Diomedes Git
commited on
Commit
·
d5af2c0
1
Parent(s):
de7bf4b
refactoring characters to use fallback inference to protect against rate limits, etc
Browse files- pyproject.toml +1 -0
- src/characters/check_char_init.py +34 -12
- src/characters/raven.py +114 -34
- uv.lock +89 -0
pyproject.toml
CHANGED
|
@@ -15,6 +15,7 @@ dependencies = [
|
|
| 15 |
"mcp>=1.20.0",
|
| 16 |
"newsapi>=0.1.1",
|
| 17 |
"newsapi-python>=0.2.7",
|
|
|
|
| 18 |
"openaq>=0.5.0",
|
| 19 |
"python-dotenv>=1.2.1",
|
| 20 |
"pytrends>=4.9.2",
|
|
|
|
| 15 |
"mcp>=1.20.0",
|
| 16 |
"newsapi>=0.1.1",
|
| 17 |
"newsapi-python>=0.2.7",
|
| 18 |
+
"openai>=2.8.1",
|
| 19 |
"openaq>=0.5.0",
|
| 20 |
"python-dotenv>=1.2.1",
|
| 21 |
"pytrends>=4.9.2",
|
src/characters/check_char_init.py
CHANGED
|
@@ -27,29 +27,51 @@ characters = {
|
|
| 27 |
print("--- Initializing Characters ---")
|
| 28 |
|
| 29 |
# Set a dummy GROQ_API_KEY for testing purposes if it's not already set
|
| 30 |
-
# This allows the use_groq=True path to be tested without an actual key,
|
| 31 |
-
# but it will still raise an error if the key is explicitly checked for existence
|
| 32 |
-
# in the character's __init__ method (which is good, as it tests that check).
|
| 33 |
if "GROQ_API_KEY" not in os.environ:
|
| 34 |
os.environ["GROQ_API_KEY"] = "dummy_key_for_testing"
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
for name, char_class in characters.items():
|
| 37 |
print(f"Testing {name}...")
|
| 38 |
|
| 39 |
-
# Test with
|
| 40 |
try:
|
| 41 |
-
instance = char_class(
|
| 42 |
-
print(f" ✅ {name} (
|
| 43 |
except ValueError as e:
|
| 44 |
-
print(f" ❌ {name} (
|
| 45 |
except Exception as e:
|
| 46 |
-
print(f" ❌ {name} (
|
| 47 |
|
| 48 |
-
# Test with
|
| 49 |
try:
|
| 50 |
-
instance = char_class(
|
| 51 |
-
print(f" ✅ {name} (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
except Exception as e:
|
| 53 |
-
print(f" ❌ {name} (
|
| 54 |
|
| 55 |
print("--- Character Initialization Test Complete ---")
|
|
|
|
| 27 |
print("--- Initializing Characters ---")
|
| 28 |
|
| 29 |
# Set a dummy GROQ_API_KEY for testing purposes if it's not already set
|
|
|
|
|
|
|
|
|
|
| 30 |
if "GROQ_API_KEY" not in os.environ:
|
| 31 |
os.environ["GROQ_API_KEY"] = "dummy_key_for_testing"
|
| 32 |
|
| 33 |
+
# Define test configurations
|
| 34 |
+
cloud_config = {
|
| 35 |
+
"primary": "groq",
|
| 36 |
+
"fallback": ["nebius"],
|
| 37 |
+
"models": {
|
| 38 |
+
"groq": "llama-3.1-70b-versatile",
|
| 39 |
+
"nebius": "meta-llama/Meta-Llama-3.1-70B-Instruct"
|
| 40 |
+
},
|
| 41 |
+
"timeout": 30,
|
| 42 |
+
"use_cloud": True
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
ollama_config = {
|
| 46 |
+
"use_cloud": False
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
for name, char_class in characters.items():
|
| 50 |
print(f"Testing {name}...")
|
| 51 |
|
| 52 |
+
# Test with cloud providers (use_cloud=True)
|
| 53 |
try:
|
| 54 |
+
instance = char_class(provider_config=cloud_config)
|
| 55 |
+
print(f" ✅ {name} (cloud providers) initialized successfully.")
|
| 56 |
except ValueError as e:
|
| 57 |
+
print(f" ❌ {name} (cloud providers) failed to initialize: {e} (Expected if API keys are missing)")
|
| 58 |
except Exception as e:
|
| 59 |
+
print(f" ❌ {name} (cloud providers) failed with unexpected error: {e}")
|
| 60 |
|
| 61 |
+
# Test with Ollama (use_cloud=False)
|
| 62 |
try:
|
| 63 |
+
instance = char_class(provider_config=ollama_config)
|
| 64 |
+
print(f" ✅ {name} (Ollama) initialized successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f" ❌ {name} (Ollama) failed to initialize: {e}")
|
| 67 |
+
|
| 68 |
+
# Test with default config (None - should use defaults)
|
| 69 |
+
try:
|
| 70 |
+
instance = char_class()
|
| 71 |
+
print(f" ✅ {name} (default config) initialized successfully.")
|
| 72 |
+
except ValueError as e:
|
| 73 |
+
print(f" ⚠️ {name} (default config) failed: {e} (Expected if no API keys configured)")
|
| 74 |
except Exception as e:
|
| 75 |
+
print(f" ❌ {name} (default config) failed with unexpected error: {e}")
|
| 76 |
|
| 77 |
print("--- Character Initialization Test Complete ---")
|
src/characters/raven.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
import asyncio
|
|
|
|
| 4 |
from typing import Optional, List, Dict, Any
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
from groq import Groq
|
|
|
|
| 7 |
from src.cluas_mcp.news.news_search import search_news
|
| 8 |
from src.cluas_mcp.web.web_search import search_web
|
| 9 |
from src.cluas_mcp.web.trending import fetch_trends
|
|
@@ -11,12 +13,13 @@ from src.cluas_mcp.common.paper_memory import PaperMemory
|
|
| 11 |
from src.cluas_mcp.common.observation_memory import ObservationMemory
|
| 12 |
|
| 13 |
load_dotenv()
|
|
|
|
|
|
|
| 14 |
|
| 15 |
class Raven:
|
| 16 |
-
def __init__(self,
|
| 17 |
self.name = "Raven"
|
| 18 |
self.location = location
|
| 19 |
-
self.use_groq = use_groq
|
| 20 |
self.tools = ["search_news", "search_web", "fetch_trends"]
|
| 21 |
self.paper_memory = PaperMemory()
|
| 22 |
self.observation_memory = ObservationMemory(location=location)
|
|
@@ -26,14 +29,52 @@ class Raven:
|
|
| 26 |
"fetch_trends": fetch_trends,
|
| 27 |
}
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
else:
|
|
|
|
| 36 |
self.model = "llama3.1:8b"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
def get_system_prompt(self) -> str:
|
| 39 |
return """You are Raven, a passionate activist and truth-seeker.
|
|
@@ -59,24 +100,9 @@ TOOLS AVAILABLE:
|
|
| 59 |
|
| 60 |
When you need to verify information or find current news, use your tools!"""
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
"""Generate a response."""
|
| 66 |
-
if self.use_groq:
|
| 67 |
-
return await self._respond_groq(message, conversation_history)
|
| 68 |
-
return self._respond_ollama(message, conversation_history)
|
| 69 |
-
|
| 70 |
-
async def _respond_groq(self, message: str, history: Optional[List[Dict]] = None) -> str:
|
| 71 |
-
"""Use Groq with tool calling for Raven's investigative workflow."""
|
| 72 |
-
messages = [{"role": "system", "content": self.get_system_prompt()}]
|
| 73 |
-
|
| 74 |
-
if history:
|
| 75 |
-
messages.extend(history[-5:])
|
| 76 |
-
|
| 77 |
-
messages.append({"role": "user", "content": message})
|
| 78 |
-
|
| 79 |
-
tools = [
|
| 80 |
{
|
| 81 |
"type": "function",
|
| 82 |
"function": {
|
|
@@ -134,17 +160,72 @@ When you need to verify information or find current news, use your tools!"""
|
|
| 134 |
}
|
| 135 |
]
|
| 136 |
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
messages=messages,
|
| 140 |
tools=tools,
|
| 141 |
-
tool_choice="auto",
|
| 142 |
temperature=0.8,
|
| 143 |
max_tokens=150
|
| 144 |
)
|
| 145 |
|
| 146 |
choice = first_response.choices[0]
|
| 147 |
|
|
|
|
| 148 |
if choice.finish_reason == "tool_calls" and choice.message.tool_calls:
|
| 149 |
tool_call = choice.message.tool_calls[0]
|
| 150 |
tool_name = tool_call.function.name
|
|
@@ -157,6 +238,7 @@ When you need to verify information or find current news, use your tools!"""
|
|
| 157 |
|
| 158 |
formatted = self._format_tool_result(tool_name, tool_result)
|
| 159 |
|
|
|
|
| 160 |
messages.append({
|
| 161 |
"role": "assistant",
|
| 162 |
"content": None,
|
|
@@ -175,8 +257,8 @@ When you need to verify information or find current news, use your tools!"""
|
|
| 175 |
"content": formatted
|
| 176 |
})
|
| 177 |
|
| 178 |
-
|
| 179 |
-
|
| 180 |
messages=messages,
|
| 181 |
temperature=0.8,
|
| 182 |
max_tokens=200
|
|
@@ -237,7 +319,6 @@ When you need to verify information or find current news, use your tools!"""
|
|
| 237 |
"""Placeholder for local inference without tool calls."""
|
| 238 |
prompt = self._build_prompt(message, history)
|
| 239 |
|
| 240 |
-
# requests import has to be at the top of the file
|
| 241 |
import requests
|
| 242 |
|
| 243 |
response = requests.post('http://localhost:11434/api/generate', json={
|
|
@@ -271,5 +352,4 @@ When you need to verify information or find current news, use your tools!"""
|
|
| 271 |
transcript.append(f"Raven: {content}")
|
| 272 |
transcript.append(f"User: {message}")
|
| 273 |
transcript.append("Raven:")
|
| 274 |
-
return "\n\n".join(transcript)
|
| 275 |
-
|
|
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
import asyncio
|
| 4 |
+
import logging
|
| 5 |
from typing import Optional, List, Dict, Any
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
from groq import Groq
|
| 8 |
+
from openai import OpenAI
|
| 9 |
from src.cluas_mcp.news.news_search import search_news
|
| 10 |
from src.cluas_mcp.web.web_search import search_web
|
| 11 |
from src.cluas_mcp.web.trending import fetch_trends
|
|
|
|
| 13 |
from src.cluas_mcp.common.observation_memory import ObservationMemory
|
| 14 |
|
| 15 |
load_dotenv()
|
| 16 |
+
logging.basicConfig(level=logging.INFO)
|
| 17 |
+
logger = logging.getLogger(__name__)
|
| 18 |
|
| 19 |
class Raven:
|
| 20 |
+
def __init__(self, provider_config=None, location="Seattle, WA"):
|
| 21 |
self.name = "Raven"
|
| 22 |
self.location = location
|
|
|
|
| 23 |
self.tools = ["search_news", "search_web", "fetch_trends"]
|
| 24 |
self.paper_memory = PaperMemory()
|
| 25 |
self.observation_memory = ObservationMemory(location=location)
|
|
|
|
| 29 |
"fetch_trends": fetch_trends,
|
| 30 |
}
|
| 31 |
|
| 32 |
+
# Default provider priority
|
| 33 |
+
if provider_config is None:
|
| 34 |
+
provider_config = {
|
| 35 |
+
"primary": "groq",
|
| 36 |
+
"fallback": ["nebius"],
|
| 37 |
+
"models": {
|
| 38 |
+
"groq": "llama-3.1-70b-versatile",
|
| 39 |
+
"nebius": "meta-llama/Meta-Llama-3.1-70B-Instruct"
|
| 40 |
+
},
|
| 41 |
+
"timeout": 30,
|
| 42 |
+
"use_cloud": True
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
self.provider_config = provider_config
|
| 46 |
+
self.use_cloud = provider_config.get("use_cloud", True)
|
| 47 |
+
|
| 48 |
+
if self.use_cloud:
|
| 49 |
+
self._init_clients()
|
| 50 |
else:
|
| 51 |
+
# Local ollama fallback
|
| 52 |
self.model = "llama3.1:8b"
|
| 53 |
+
|
| 54 |
+
def _init_clients(self):
|
| 55 |
+
"""Initialize all available provider clients"""
|
| 56 |
+
self.clients = {}
|
| 57 |
+
|
| 58 |
+
# Groq
|
| 59 |
+
if os.getenv("GROQ_API_KEY"):
|
| 60 |
+
self.clients["groq"] = Groq(
|
| 61 |
+
api_key=os.getenv("GROQ_API_KEY"),
|
| 62 |
+
timeout=self.provider_config.get("timeout", 30)
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
# Nebius Token Factory (OpenAI-compatible)
|
| 66 |
+
if os.getenv("NEBIUS_API_KEY"):
|
| 67 |
+
self.clients["nebius"] = OpenAI(
|
| 68 |
+
api_key=os.getenv("NEBIUS_API_KEY"),
|
| 69 |
+
base_url="https://api.tokenfactory.nebius.com/v1",
|
| 70 |
+
timeout=self.provider_config.get("timeout", 30)
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
# Log which providers are available
|
| 74 |
+
available = list(self.clients.keys())
|
| 75 |
+
if not available:
|
| 76 |
+
raise ValueError(f"{self.name}: No LLM provider API keys found in environment")
|
| 77 |
+
logger.info(f"{self.name} initialized with providers: {available}")
|
| 78 |
|
| 79 |
def get_system_prompt(self) -> str:
|
| 80 |
return """You are Raven, a passionate activist and truth-seeker.
|
|
|
|
| 100 |
|
| 101 |
When you need to verify information or find current news, use your tools!"""
|
| 102 |
|
| 103 |
+
def _get_tool_definitions(self) -> List[Dict]:
|
| 104 |
+
"""Return tool definitions for function calling"""
|
| 105 |
+
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
{
|
| 107 |
"type": "function",
|
| 108 |
"function": {
|
|
|
|
| 160 |
}
|
| 161 |
]
|
| 162 |
|
| 163 |
+
def _call_llm(self, messages: List[Dict], tools: Optional[List[Dict]] = None,
|
| 164 |
+
temperature: float = 0.8, max_tokens: int = 150) -> tuple:
|
| 165 |
+
"""Call LLM with automatic fallback"""
|
| 166 |
+
providers = [self.provider_config["primary"]] + self.provider_config["fallback"]
|
| 167 |
+
last_error = None
|
| 168 |
+
|
| 169 |
+
for provider in providers:
|
| 170 |
+
if provider not in self.clients:
|
| 171 |
+
logger.debug(f"{self.name}: Skipping {provider} - not configured")
|
| 172 |
+
continue
|
| 173 |
+
|
| 174 |
+
try:
|
| 175 |
+
model = self.provider_config["models"][provider]
|
| 176 |
+
logger.debug(f"{self.name} trying {provider} with model {model}")
|
| 177 |
+
|
| 178 |
+
# Both Groq and OpenAI clients have same interface
|
| 179 |
+
response = self.clients[provider].chat.completions.create(
|
| 180 |
+
model=model,
|
| 181 |
+
messages=messages,
|
| 182 |
+
tools=tools,
|
| 183 |
+
tool_choice="auto" if tools else None,
|
| 184 |
+
temperature=temperature,
|
| 185 |
+
max_tokens=max_tokens
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
logger.info(f"{self.name} successfully used {provider}")
|
| 189 |
+
return response, provider
|
| 190 |
+
|
| 191 |
+
except Exception as e:
|
| 192 |
+
last_error = e
|
| 193 |
+
logger.warning(f"{self.name}: {provider} failed - {str(e)[:100]}")
|
| 194 |
+
continue
|
| 195 |
+
|
| 196 |
+
# If we get here, all providers failed
|
| 197 |
+
raise Exception(f"All LLM providers failed for {self.name}. Last error: {last_error}")
|
| 198 |
+
|
| 199 |
+
async def respond(self,
|
| 200 |
+
message: str,
|
| 201 |
+
conversation_history: Optional[List[Dict]] = None) -> str:
|
| 202 |
+
"""Generate a response."""
|
| 203 |
+
if self.use_cloud:
|
| 204 |
+
return await self._respond_cloud(message, conversation_history)
|
| 205 |
+
return self._respond_ollama(message, conversation_history)
|
| 206 |
+
|
| 207 |
+
async def _respond_cloud(self, message: str, history: Optional[List[Dict]] = None) -> str:
|
| 208 |
+
"""Use cloud providers with tool calling for Raven's investigative workflow."""
|
| 209 |
+
messages = [{"role": "system", "content": self.get_system_prompt()}]
|
| 210 |
+
|
| 211 |
+
if history:
|
| 212 |
+
messages.extend(history[-5:])
|
| 213 |
+
|
| 214 |
+
messages.append({"role": "user", "content": message})
|
| 215 |
+
|
| 216 |
+
tools = self._get_tool_definitions()
|
| 217 |
+
|
| 218 |
+
# First LLM call - may trigger tool use
|
| 219 |
+
first_response, provider = self._call_llm(
|
| 220 |
messages=messages,
|
| 221 |
tools=tools,
|
|
|
|
| 222 |
temperature=0.8,
|
| 223 |
max_tokens=150
|
| 224 |
)
|
| 225 |
|
| 226 |
choice = first_response.choices[0]
|
| 227 |
|
| 228 |
+
# Check if LLM wants to use tools
|
| 229 |
if choice.finish_reason == "tool_calls" and choice.message.tool_calls:
|
| 230 |
tool_call = choice.message.tool_calls[0]
|
| 231 |
tool_name = tool_call.function.name
|
|
|
|
| 238 |
|
| 239 |
formatted = self._format_tool_result(tool_name, tool_result)
|
| 240 |
|
| 241 |
+
# Add tool call and result to messages
|
| 242 |
messages.append({
|
| 243 |
"role": "assistant",
|
| 244 |
"content": None,
|
|
|
|
| 257 |
"content": formatted
|
| 258 |
})
|
| 259 |
|
| 260 |
+
# Second LLM call with tool results
|
| 261 |
+
second_response, _ = self._call_llm(
|
| 262 |
messages=messages,
|
| 263 |
temperature=0.8,
|
| 264 |
max_tokens=200
|
|
|
|
| 319 |
"""Placeholder for local inference without tool calls."""
|
| 320 |
prompt = self._build_prompt(message, history)
|
| 321 |
|
|
|
|
| 322 |
import requests
|
| 323 |
|
| 324 |
response = requests.post('http://localhost:11434/api/generate', json={
|
|
|
|
| 352 |
transcript.append(f"Raven: {content}")
|
| 353 |
transcript.append(f"User: {message}")
|
| 354 |
transcript.append("Raven:")
|
| 355 |
+
return "\n\n".join(transcript)
|
|
|
uv.lock
CHANGED
|
@@ -342,6 +342,7 @@ dependencies = [
|
|
| 342 |
{ name = "mcp" },
|
| 343 |
{ name = "newsapi" },
|
| 344 |
{ name = "newsapi-python" },
|
|
|
|
| 345 |
{ name = "openaq" },
|
| 346 |
{ name = "python-dotenv" },
|
| 347 |
{ name = "pytrends" },
|
|
@@ -367,6 +368,7 @@ requires-dist = [
|
|
| 367 |
{ name = "mcp", specifier = ">=1.20.0" },
|
| 368 |
{ name = "newsapi", specifier = ">=0.1.1" },
|
| 369 |
{ name = "newsapi-python", specifier = ">=0.2.7" },
|
|
|
|
| 370 |
{ name = "openaq", specifier = ">=0.5.0" },
|
| 371 |
{ name = "python-dotenv", specifier = ">=1.2.1" },
|
| 372 |
{ name = "pytrends", specifier = ">=4.9.2" },
|
|
@@ -889,6 +891,74 @@ wheels = [
|
|
| 889 |
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
| 890 |
]
|
| 891 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 892 |
[[package]]
|
| 893 |
name = "jsonschema"
|
| 894 |
version = "4.25.1"
|
|
@@ -1233,6 +1303,25 @@ wheels = [
|
|
| 1233 |
{ url = "https://files.pythonhosted.org/packages/2d/fd/4b5eb0b3e888d86aee4d198c23acec7d214baaf17ea93c1adec94c9518b9/numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42", size = 10545459, upload-time = "2025-11-16T22:52:20.55Z" },
|
| 1234 |
]
|
| 1235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1236 |
[[package]]
|
| 1237 |
name = "openapi-pydantic"
|
| 1238 |
version = "0.5.1"
|
|
|
|
| 342 |
{ name = "mcp" },
|
| 343 |
{ name = "newsapi" },
|
| 344 |
{ name = "newsapi-python" },
|
| 345 |
+
{ name = "openai" },
|
| 346 |
{ name = "openaq" },
|
| 347 |
{ name = "python-dotenv" },
|
| 348 |
{ name = "pytrends" },
|
|
|
|
| 368 |
{ name = "mcp", specifier = ">=1.20.0" },
|
| 369 |
{ name = "newsapi", specifier = ">=0.1.1" },
|
| 370 |
{ name = "newsapi-python", specifier = ">=0.2.7" },
|
| 371 |
+
{ name = "openai", specifier = ">=2.8.1" },
|
| 372 |
{ name = "openaq", specifier = ">=0.5.0" },
|
| 373 |
{ name = "python-dotenv", specifier = ">=1.2.1" },
|
| 374 |
{ name = "pytrends", specifier = ">=4.9.2" },
|
|
|
|
| 891 |
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
| 892 |
]
|
| 893 |
|
| 894 |
+
[[package]]
|
| 895 |
+
name = "jiter"
|
| 896 |
+
version = "0.12.0"
|
| 897 |
+
source = { registry = "https://pypi.org/simple" }
|
| 898 |
+
sdist = { url = "https://files.pythonhosted.org/packages/45/9d/e0660989c1370e25848bb4c52d061c71837239738ad937e83edca174c273/jiter-0.12.0.tar.gz", hash = "sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b", size = 168294, upload-time = "2025-11-09T20:49:23.302Z" }
|
| 899 |
+
wheels = [
|
| 900 |
+
{ url = "https://files.pythonhosted.org/packages/92/c9/5b9f7b4983f1b542c64e84165075335e8a236fa9e2ea03a0c79780062be8/jiter-0.12.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:305e061fa82f4680607a775b2e8e0bcb071cd2205ac38e6ef48c8dd5ebe1cf37", size = 314449, upload-time = "2025-11-09T20:47:22.999Z" },
|
| 901 |
+
{ url = "https://files.pythonhosted.org/packages/98/6e/e8efa0e78de00db0aee82c0cf9e8b3f2027efd7f8a71f859d8f4be8e98ef/jiter-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c1860627048e302a528333c9307c818c547f214d8659b0705d2195e1a94b274", size = 319855, upload-time = "2025-11-09T20:47:24.779Z" },
|
| 902 |
+
{ url = "https://files.pythonhosted.org/packages/20/26/894cd88e60b5d58af53bec5c6759d1292bd0b37a8b5f60f07abf7a63ae5f/jiter-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df37577a4f8408f7e0ec3205d2a8f87672af8f17008358063a4d6425b6081ce3", size = 350171, upload-time = "2025-11-09T20:47:26.469Z" },
|
| 903 |
+
{ url = "https://files.pythonhosted.org/packages/f5/27/a7b818b9979ac31b3763d25f3653ec3a954044d5e9f5d87f2f247d679fd1/jiter-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fdd787356c1c13a4f40b43c2156276ef7a71eb487d98472476476d803fb2cf", size = 365590, upload-time = "2025-11-09T20:47:27.918Z" },
|
| 904 |
+
{ url = "https://files.pythonhosted.org/packages/ba/7e/e46195801a97673a83746170b17984aa8ac4a455746354516d02ca5541b4/jiter-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1eb5db8d9c65b112aacf14fcd0faae9913d07a8afea5ed06ccdd12b724e966a1", size = 479462, upload-time = "2025-11-09T20:47:29.654Z" },
|
| 905 |
+
{ url = "https://files.pythonhosted.org/packages/ca/75/f833bfb009ab4bd11b1c9406d333e3b4357709ed0570bb48c7c06d78c7dd/jiter-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73c568cc27c473f82480abc15d1301adf333a7ea4f2e813d6a2c7d8b6ba8d0df", size = 378983, upload-time = "2025-11-09T20:47:31.026Z" },
|
| 906 |
+
{ url = "https://files.pythonhosted.org/packages/71/b3/7a69d77943cc837d30165643db753471aff5df39692d598da880a6e51c24/jiter-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4321e8a3d868919bcb1abb1db550d41f2b5b326f72df29e53b2df8b006eb9403", size = 361328, upload-time = "2025-11-09T20:47:33.286Z" },
|
| 907 |
+
{ url = "https://files.pythonhosted.org/packages/b0/ac/a78f90caf48d65ba70d8c6efc6f23150bc39dc3389d65bbec2a95c7bc628/jiter-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a51bad79f8cc9cac2b4b705039f814049142e0050f30d91695a2d9a6611f126", size = 386740, upload-time = "2025-11-09T20:47:34.703Z" },
|
| 908 |
+
{ url = "https://files.pythonhosted.org/packages/39/b6/5d31c2cc8e1b6a6bcf3c5721e4ca0a3633d1ab4754b09bc7084f6c4f5327/jiter-0.12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2a67b678f6a5f1dd6c36d642d7db83e456bc8b104788262aaefc11a22339f5a9", size = 520875, upload-time = "2025-11-09T20:47:36.058Z" },
|
| 909 |
+
{ url = "https://files.pythonhosted.org/packages/30/b5/4df540fae4e9f68c54b8dab004bd8c943a752f0b00efd6e7d64aa3850339/jiter-0.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efe1a211fe1fd14762adea941e3cfd6c611a136e28da6c39272dbb7a1bbe6a86", size = 511457, upload-time = "2025-11-09T20:47:37.932Z" },
|
| 910 |
+
{ url = "https://files.pythonhosted.org/packages/07/65/86b74010e450a1a77b2c1aabb91d4a91dd3cd5afce99f34d75fd1ac64b19/jiter-0.12.0-cp312-cp312-win32.whl", hash = "sha256:d779d97c834b4278276ec703dc3fc1735fca50af63eb7262f05bdb4e62203d44", size = 204546, upload-time = "2025-11-09T20:47:40.47Z" },
|
| 911 |
+
{ url = "https://files.pythonhosted.org/packages/1c/c7/6659f537f9562d963488e3e55573498a442503ced01f7e169e96a6110383/jiter-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e8269062060212b373316fe69236096aaf4c49022d267c6736eebd66bbbc60bb", size = 205196, upload-time = "2025-11-09T20:47:41.794Z" },
|
| 912 |
+
{ url = "https://files.pythonhosted.org/packages/21/f4/935304f5169edadfec7f9c01eacbce4c90bb9a82035ac1de1f3bd2d40be6/jiter-0.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:06cb970936c65de926d648af0ed3d21857f026b1cf5525cb2947aa5e01e05789", size = 186100, upload-time = "2025-11-09T20:47:43.007Z" },
|
| 913 |
+
{ url = "https://files.pythonhosted.org/packages/3d/a6/97209693b177716e22576ee1161674d1d58029eb178e01866a0422b69224/jiter-0.12.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e", size = 313658, upload-time = "2025-11-09T20:47:44.424Z" },
|
| 914 |
+
{ url = "https://files.pythonhosted.org/packages/06/4d/125c5c1537c7d8ee73ad3d530a442d6c619714b95027143f1b61c0b4dfe0/jiter-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1", size = 318605, upload-time = "2025-11-09T20:47:45.973Z" },
|
| 915 |
+
{ url = "https://files.pythonhosted.org/packages/99/bf/a840b89847885064c41a5f52de6e312e91fa84a520848ee56c97e4fa0205/jiter-0.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf", size = 349803, upload-time = "2025-11-09T20:47:47.535Z" },
|
| 916 |
+
{ url = "https://files.pythonhosted.org/packages/8a/88/e63441c28e0db50e305ae23e19c1d8fae012d78ed55365da392c1f34b09c/jiter-0.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44", size = 365120, upload-time = "2025-11-09T20:47:49.284Z" },
|
| 917 |
+
{ url = "https://files.pythonhosted.org/packages/0a/7c/49b02714af4343970eb8aca63396bc1c82fa01197dbb1e9b0d274b550d4e/jiter-0.12.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45", size = 479918, upload-time = "2025-11-09T20:47:50.807Z" },
|
| 918 |
+
{ url = "https://files.pythonhosted.org/packages/69/ba/0a809817fdd5a1db80490b9150645f3aae16afad166960bcd562be194f3b/jiter-0.12.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87", size = 379008, upload-time = "2025-11-09T20:47:52.211Z" },
|
| 919 |
+
{ url = "https://files.pythonhosted.org/packages/5f/c3/c9fc0232e736c8877d9e6d83d6eeb0ba4e90c6c073835cc2e8f73fdeef51/jiter-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed", size = 361785, upload-time = "2025-11-09T20:47:53.512Z" },
|
| 920 |
+
{ url = "https://files.pythonhosted.org/packages/96/61/61f69b7e442e97ca6cd53086ddc1cf59fb830549bc72c0a293713a60c525/jiter-0.12.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9", size = 386108, upload-time = "2025-11-09T20:47:54.893Z" },
|
| 921 |
+
{ url = "https://files.pythonhosted.org/packages/e9/2e/76bb3332f28550c8f1eba3bf6e5efe211efda0ddbbaf24976bc7078d42a5/jiter-0.12.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626", size = 519937, upload-time = "2025-11-09T20:47:56.253Z" },
|
| 922 |
+
{ url = "https://files.pythonhosted.org/packages/84/d6/fa96efa87dc8bff2094fb947f51f66368fa56d8d4fc9e77b25d7fbb23375/jiter-0.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c", size = 510853, upload-time = "2025-11-09T20:47:58.32Z" },
|
| 923 |
+
{ url = "https://files.pythonhosted.org/packages/8a/28/93f67fdb4d5904a708119a6ab58a8f1ec226ff10a94a282e0215402a8462/jiter-0.12.0-cp313-cp313-win32.whl", hash = "sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de", size = 204699, upload-time = "2025-11-09T20:47:59.686Z" },
|
| 924 |
+
{ url = "https://files.pythonhosted.org/packages/c4/1f/30b0eb087045a0abe2a5c9c0c0c8da110875a1d3be83afd4a9a4e548be3c/jiter-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a", size = 204258, upload-time = "2025-11-09T20:48:01.01Z" },
|
| 925 |
+
{ url = "https://files.pythonhosted.org/packages/2c/f4/2b4daf99b96bce6fc47971890b14b2a36aef88d7beb9f057fafa032c6141/jiter-0.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60", size = 185503, upload-time = "2025-11-09T20:48:02.35Z" },
|
| 926 |
+
{ url = "https://files.pythonhosted.org/packages/39/ca/67bb15a7061d6fe20b9b2a2fd783e296a1e0f93468252c093481a2f00efa/jiter-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6", size = 317965, upload-time = "2025-11-09T20:48:03.783Z" },
|
| 927 |
+
{ url = "https://files.pythonhosted.org/packages/18/af/1788031cd22e29c3b14bc6ca80b16a39a0b10e611367ffd480c06a259831/jiter-0.12.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4", size = 345831, upload-time = "2025-11-09T20:48:05.55Z" },
|
| 928 |
+
{ url = "https://files.pythonhosted.org/packages/05/17/710bf8472d1dff0d3caf4ced6031060091c1320f84ee7d5dcbed1f352417/jiter-0.12.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb", size = 361272, upload-time = "2025-11-09T20:48:06.951Z" },
|
| 929 |
+
{ url = "https://files.pythonhosted.org/packages/fb/f1/1dcc4618b59761fef92d10bcbb0b038b5160be653b003651566a185f1a5c/jiter-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7", size = 204604, upload-time = "2025-11-09T20:48:08.328Z" },
|
| 930 |
+
{ url = "https://files.pythonhosted.org/packages/d9/32/63cb1d9f1c5c6632a783c0052cde9ef7ba82688f7065e2f0d5f10a7e3edb/jiter-0.12.0-cp313-cp313t-win_arm64.whl", hash = "sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3", size = 185628, upload-time = "2025-11-09T20:48:09.572Z" },
|
| 931 |
+
{ url = "https://files.pythonhosted.org/packages/a8/99/45c9f0dbe4a1416b2b9a8a6d1236459540f43d7fb8883cff769a8db0612d/jiter-0.12.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c46d927acd09c67a9fb1416df45c5a04c27e83aae969267e98fba35b74e99525", size = 312478, upload-time = "2025-11-09T20:48:10.898Z" },
|
| 932 |
+
{ url = "https://files.pythonhosted.org/packages/4c/a7/54ae75613ba9e0f55fcb0bc5d1f807823b5167cc944e9333ff322e9f07dd/jiter-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:774ff60b27a84a85b27b88cd5583899c59940bcc126caca97eb2a9df6aa00c49", size = 318706, upload-time = "2025-11-09T20:48:12.266Z" },
|
| 933 |
+
{ url = "https://files.pythonhosted.org/packages/59/31/2aa241ad2c10774baf6c37f8b8e1f39c07db358f1329f4eb40eba179c2a2/jiter-0.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5433fab222fb072237df3f637d01b81f040a07dcac1cb4a5c75c7aa9ed0bef1", size = 351894, upload-time = "2025-11-09T20:48:13.673Z" },
|
| 934 |
+
{ url = "https://files.pythonhosted.org/packages/54/4f/0f2759522719133a9042781b18cc94e335b6d290f5e2d3e6899d6af933e3/jiter-0.12.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8c593c6e71c07866ec6bfb790e202a833eeec885022296aff6b9e0b92d6a70e", size = 365714, upload-time = "2025-11-09T20:48:15.083Z" },
|
| 935 |
+
{ url = "https://files.pythonhosted.org/packages/dc/6f/806b895f476582c62a2f52c453151edd8a0fde5411b0497baaa41018e878/jiter-0.12.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90d32894d4c6877a87ae00c6b915b609406819dce8bc0d4e962e4de2784e567e", size = 478989, upload-time = "2025-11-09T20:48:16.706Z" },
|
| 936 |
+
{ url = "https://files.pythonhosted.org/packages/86/6c/012d894dc6e1033acd8db2b8346add33e413ec1c7c002598915278a37f79/jiter-0.12.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:798e46eed9eb10c3adbbacbd3bdb5ecd4cf7064e453d00dbef08802dae6937ff", size = 378615, upload-time = "2025-11-09T20:48:18.614Z" },
|
| 937 |
+
{ url = "https://files.pythonhosted.org/packages/87/30/d718d599f6700163e28e2c71c0bbaf6dace692e7df2592fd793ac9276717/jiter-0.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3f1368f0a6719ea80013a4eb90ba72e75d7ea67cfc7846db2ca504f3df0169a", size = 364745, upload-time = "2025-11-09T20:48:20.117Z" },
|
| 938 |
+
{ url = "https://files.pythonhosted.org/packages/8f/85/315b45ce4b6ddc7d7fceca24068543b02bdc8782942f4ee49d652e2cc89f/jiter-0.12.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65f04a9d0b4406f7e51279710b27484af411896246200e461d80d3ba0caa901a", size = 386502, upload-time = "2025-11-09T20:48:21.543Z" },
|
| 939 |
+
{ url = "https://files.pythonhosted.org/packages/74/0b/ce0434fb40c5b24b368fe81b17074d2840748b4952256bab451b72290a49/jiter-0.12.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:fd990541982a24281d12b67a335e44f117e4c6cbad3c3b75c7dea68bf4ce3a67", size = 519845, upload-time = "2025-11-09T20:48:22.964Z" },
|
| 940 |
+
{ url = "https://files.pythonhosted.org/packages/e8/a3/7a7a4488ba052767846b9c916d208b3ed114e3eb670ee984e4c565b9cf0d/jiter-0.12.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:b111b0e9152fa7df870ecaebb0bd30240d9f7fff1f2003bcb4ed0f519941820b", size = 510701, upload-time = "2025-11-09T20:48:24.483Z" },
|
| 941 |
+
{ url = "https://files.pythonhosted.org/packages/c3/16/052ffbf9d0467b70af24e30f91e0579e13ded0c17bb4a8eb2aed3cb60131/jiter-0.12.0-cp314-cp314-win32.whl", hash = "sha256:a78befb9cc0a45b5a5a0d537b06f8544c2ebb60d19d02c41ff15da28a9e22d42", size = 205029, upload-time = "2025-11-09T20:48:25.749Z" },
|
| 942 |
+
{ url = "https://files.pythonhosted.org/packages/e4/18/3cf1f3f0ccc789f76b9a754bdb7a6977e5d1d671ee97a9e14f7eb728d80e/jiter-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:e1fe01c082f6aafbe5c8faf0ff074f38dfb911d53f07ec333ca03f8f6226debf", size = 204960, upload-time = "2025-11-09T20:48:27.415Z" },
|
| 943 |
+
{ url = "https://files.pythonhosted.org/packages/02/68/736821e52ecfdeeb0f024b8ab01b5a229f6b9293bbdb444c27efade50b0f/jiter-0.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:d72f3b5a432a4c546ea4bedc84cce0c3404874f1d1676260b9c7f048a9855451", size = 185529, upload-time = "2025-11-09T20:48:29.125Z" },
|
| 944 |
+
{ url = "https://files.pythonhosted.org/packages/30/61/12ed8ee7a643cce29ac97c2281f9ce3956eb76b037e88d290f4ed0d41480/jiter-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e6ded41aeba3603f9728ed2b6196e4df875348ab97b28fc8afff115ed42ba7a7", size = 318974, upload-time = "2025-11-09T20:48:30.87Z" },
|
| 945 |
+
{ url = "https://files.pythonhosted.org/packages/2d/c6/f3041ede6d0ed5e0e79ff0de4c8f14f401bbf196f2ef3971cdbe5fd08d1d/jiter-0.12.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a947920902420a6ada6ad51892082521978e9dd44a802663b001436e4b771684", size = 345932, upload-time = "2025-11-09T20:48:32.658Z" },
|
| 946 |
+
{ url = "https://files.pythonhosted.org/packages/d5/5d/4d94835889edd01ad0e2dbfc05f7bdfaed46292e7b504a6ac7839aa00edb/jiter-0.12.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:add5e227e0554d3a52cf390a7635edaffdf4f8fce4fdbcef3cc2055bb396a30c", size = 367243, upload-time = "2025-11-09T20:48:34.093Z" },
|
| 947 |
+
{ url = "https://files.pythonhosted.org/packages/fd/76/0051b0ac2816253a99d27baf3dda198663aff882fa6ea7deeb94046da24e/jiter-0.12.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f9b1cda8fcb736250d7e8711d4580ebf004a46771432be0ae4796944b5dfa5d", size = 479315, upload-time = "2025-11-09T20:48:35.507Z" },
|
| 948 |
+
{ url = "https://files.pythonhosted.org/packages/70/ae/83f793acd68e5cb24e483f44f482a1a15601848b9b6f199dacb970098f77/jiter-0.12.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deeb12a2223fe0135c7ff1356a143d57f95bbf1f4a66584f1fc74df21d86b993", size = 380714, upload-time = "2025-11-09T20:48:40.014Z" },
|
| 949 |
+
{ url = "https://files.pythonhosted.org/packages/b1/5e/4808a88338ad2c228b1126b93fcd8ba145e919e886fe910d578230dabe3b/jiter-0.12.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c596cc0f4cb574877550ce4ecd51f8037469146addd676d7c1a30ebe6391923f", size = 365168, upload-time = "2025-11-09T20:48:41.462Z" },
|
| 950 |
+
{ url = "https://files.pythonhosted.org/packages/0c/d4/04619a9e8095b42aef436b5aeb4c0282b4ff1b27d1db1508df9f5dc82750/jiter-0.12.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ab4c823b216a4aeab3fdbf579c5843165756bd9ad87cc6b1c65919c4715f783", size = 387893, upload-time = "2025-11-09T20:48:42.921Z" },
|
| 951 |
+
{ url = "https://files.pythonhosted.org/packages/17/ea/d3c7e62e4546fdc39197fa4a4315a563a89b95b6d54c0d25373842a59cbe/jiter-0.12.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e427eee51149edf962203ff8db75a7514ab89be5cb623fb9cea1f20b54f1107b", size = 520828, upload-time = "2025-11-09T20:48:44.278Z" },
|
| 952 |
+
{ url = "https://files.pythonhosted.org/packages/cc/0b/c6d3562a03fd767e31cb119d9041ea7958c3c80cb3d753eafb19b3b18349/jiter-0.12.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:edb868841f84c111255ba5e80339d386d937ec1fdce419518ce1bd9370fac5b6", size = 511009, upload-time = "2025-11-09T20:48:45.726Z" },
|
| 953 |
+
{ url = "https://files.pythonhosted.org/packages/aa/51/2cb4468b3448a8385ebcd15059d325c9ce67df4e2758d133ab9442b19834/jiter-0.12.0-cp314-cp314t-win32.whl", hash = "sha256:8bbcfe2791dfdb7c5e48baf646d37a6a3dcb5a97a032017741dea9f817dca183", size = 205110, upload-time = "2025-11-09T20:48:47.033Z" },
|
| 954 |
+
{ url = "https://files.pythonhosted.org/packages/b2/c5/ae5ec83dec9c2d1af805fd5fe8f74ebded9c8670c5210ec7820ce0dbeb1e/jiter-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2fa940963bf02e1d8226027ef461e36af472dea85d36054ff835aeed944dd873", size = 205223, upload-time = "2025-11-09T20:48:49.076Z" },
|
| 955 |
+
{ url = "https://files.pythonhosted.org/packages/97/9a/3c5391907277f0e55195550cf3fa8e293ae9ee0c00fb402fec1e38c0c82f/jiter-0.12.0-cp314-cp314t-win_arm64.whl", hash = "sha256:506c9708dd29b27288f9f8f1140c3cb0e3d8ddb045956d7757b1fa0e0f39a473", size = 185564, upload-time = "2025-11-09T20:48:50.376Z" },
|
| 956 |
+
{ url = "https://files.pythonhosted.org/packages/cb/f5/12efb8ada5f5c9edc1d4555fe383c1fb2eac05ac5859258a72d61981d999/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e8547883d7b96ef2e5fe22b88f8a4c8725a56e7f4abafff20fd5272d634c7ecb", size = 309974, upload-time = "2025-11-09T20:49:17.187Z" },
|
| 957 |
+
{ url = "https://files.pythonhosted.org/packages/85/15/d6eb3b770f6a0d332675141ab3962fd4a7c270ede3515d9f3583e1d28276/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:89163163c0934854a668ed783a2546a0617f71706a2551a4a0666d91ab365d6b", size = 304233, upload-time = "2025-11-09T20:49:18.734Z" },
|
| 958 |
+
{ url = "https://files.pythonhosted.org/packages/8c/3e/e7e06743294eea2cf02ced6aa0ff2ad237367394e37a0e2b4a1108c67a36/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d96b264ab7d34bbb2312dedc47ce07cd53f06835eacbc16dde3761f47c3a9e7f", size = 338537, upload-time = "2025-11-09T20:49:20.317Z" },
|
| 959 |
+
{ url = "https://files.pythonhosted.org/packages/2f/9c/6753e6522b8d0ef07d3a3d239426669e984fb0eba15a315cdbc1253904e4/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c", size = 346110, upload-time = "2025-11-09T20:49:21.817Z" },
|
| 960 |
+
]
|
| 961 |
+
|
| 962 |
[[package]]
|
| 963 |
name = "jsonschema"
|
| 964 |
version = "4.25.1"
|
|
|
|
| 1303 |
{ url = "https://files.pythonhosted.org/packages/2d/fd/4b5eb0b3e888d86aee4d198c23acec7d214baaf17ea93c1adec94c9518b9/numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42", size = 10545459, upload-time = "2025-11-16T22:52:20.55Z" },
|
| 1304 |
]
|
| 1305 |
|
| 1306 |
+
[[package]]
|
| 1307 |
+
name = "openai"
|
| 1308 |
+
version = "2.8.1"
|
| 1309 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1310 |
+
dependencies = [
|
| 1311 |
+
{ name = "anyio" },
|
| 1312 |
+
{ name = "distro" },
|
| 1313 |
+
{ name = "httpx" },
|
| 1314 |
+
{ name = "jiter" },
|
| 1315 |
+
{ name = "pydantic" },
|
| 1316 |
+
{ name = "sniffio" },
|
| 1317 |
+
{ name = "tqdm" },
|
| 1318 |
+
{ name = "typing-extensions" },
|
| 1319 |
+
]
|
| 1320 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d5/e4/42591e356f1d53c568418dc7e30dcda7be31dd5a4d570bca22acb0525862/openai-2.8.1.tar.gz", hash = "sha256:cb1b79eef6e809f6da326a7ef6038719e35aa944c42d081807bfa1be8060f15f", size = 602490, upload-time = "2025-11-17T22:39:59.549Z" }
|
| 1321 |
+
wheels = [
|
| 1322 |
+
{ url = "https://files.pythonhosted.org/packages/55/4f/dbc0c124c40cb390508a82770fb9f6e3ed162560181a85089191a851c59a/openai-2.8.1-py3-none-any.whl", hash = "sha256:c6c3b5a04994734386e8dad3c00a393f56d3b68a27cd2e8acae91a59e4122463", size = 1022688, upload-time = "2025-11-17T22:39:57.675Z" },
|
| 1323 |
+
]
|
| 1324 |
+
|
| 1325 |
[[package]]
|
| 1326 |
name = "openapi-pydantic"
|
| 1327 |
version = "0.5.1"
|