From f79a9040aeaaf387ac95b1765a9ba4f66286e4c4 Mon Sep 17 00:00:00 2001 From: Luis Novo Date: Sat, 1 Nov 2025 14:40:00 -0300 Subject: [PATCH] Release 1.2 (#242) * chore: improve podcast transcripts * fix: remove date from insight - fixes #241 * fix: improve scrolling on source and insights - fixes #237 * chore: update esperanto to fix: #234 * chore: update esperanto to fix #226 * fix: process vectorization as subcommands to handle larger documents more gracefully - fix: #229 * feat: enable background job retry capabilities * feat: reenable content types that were disabled during alpha version * fix: remove unnecessary model caching causing many issues. * feat: support multiple azure endpoints and keys just like openai compatible. Fixes #215 * docs: update azure variables * chore: bump and update dependencies --- .env.example | 79 +++- api/routers/embedding.py | 14 +- api/routers/models.py | 64 ++- commands/embedding_commands.py | 245 +++++++++- docs/deployment/index.md | 7 + docs/deployment/retry-configuration.md | 345 ++++++++++++++ docs/features/ai-models.md | 60 ++- docs/getting-started/installation.md | 12 +- docs/index.md | 1 + .../components/source/SourceDetailContent.tsx | 15 - .../src/components/source/SourceDialog.tsx | 4 +- .../components/source/SourceInsightDialog.tsx | 4 +- .../sources/steps/SourceTypeStep.tsx | 4 +- open_notebook/database/repository.py | 1 - open_notebook/domain/models.py | 88 ++-- open_notebook/domain/notebook.py | 103 ++--- open_notebook/graphs/source.py | 15 + pyproject.toml | 4 +- tests/test_domain.py | 13 +- uv.lock | 434 +++++++----------- 20 files changed, 1077 insertions(+), 435 deletions(-) create mode 100644 docs/deployment/retry-configuration.md diff --git a/.env.example b/.env.example index bb049fc..ef1d647 100644 --- a/.env.example +++ b/.env.example @@ -143,10 +143,28 @@ API_URL=http://localhost:5055 # OPENAI_COMPATIBLE_API_KEY_TTS= # AZURE OPENAI +# Generic configuration (applies to all modalities: language, embedding, STT, TTS) # AZURE_OPENAI_API_KEY= # AZURE_OPENAI_ENDPOINT= -# AZURE_OPENAI_API_VERSION="2024-12-01-preview" -# AZURE_OPENAI_DEPLOYMENT_NAME= +# AZURE_OPENAI_API_VERSION=2024-12-01-preview + +# Mode-specific configuration (overrides generic if set) +# Use these when you want different deployments for different AI capabilities +# AZURE_OPENAI_API_KEY_LLM= +# AZURE_OPENAI_ENDPOINT_LLM= +# AZURE_OPENAI_API_VERSION_LLM= + +# AZURE_OPENAI_API_KEY_EMBEDDING= +# AZURE_OPENAI_ENDPOINT_EMBEDDING= +# AZURE_OPENAI_API_VERSION_EMBEDDING= + +# AZURE_OPENAI_API_KEY_STT= +# AZURE_OPENAI_ENDPOINT_STT= +# AZURE_OPENAI_API_VERSION_STT= + +# AZURE_OPENAI_API_KEY_TTS= +# AZURE_OPENAI_ENDPOINT_TTS= +# AZURE_OPENAI_API_VERSION_TTS= # USE THIS IF YOU WANT TO DEBUG THE APP ON LANGSMITH # LANGCHAIN_TRACING_V2=true @@ -162,6 +180,63 @@ SURREAL_PASSWORD="root" SURREAL_NAMESPACE="open_notebook" SURREAL_DATABASE="staging" +# RETRY CONFIGURATION (surreal-commands v1.2.0+) +# Global defaults for all background commands unless explicitly overridden at command level +# These settings help commands automatically recover from transient failures like: +# - Database transaction conflicts during concurrent operations +# - Network timeouts when calling external APIs +# - Rate limits from LLM/embedding providers +# - Temporary resource unavailability + +# Enable/disable retry globally (default: true) +# Set to false to disable retries for all commands (useful for debugging) +SURREAL_COMMANDS_RETRY_ENABLED=true + +# Maximum retry attempts before giving up (default: 3) +# Database operations use 5 attempts (defined per-command) +# API calls use 3 attempts (defined per-command) +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 + +# Wait strategy between retry attempts (default: exponential_jitter) +# Options: exponential_jitter, exponential, fixed, random +# - exponential_jitter: Recommended - prevents thundering herd during DB conflicts +# - exponential: Good for API rate limits (predictable backoff) +# - fixed: Use for quick recovery scenarios +# - random: Use when you want unpredictable retry timing +SURREAL_COMMANDS_RETRY_WAIT_STRATEGY=exponential_jitter + +# Minimum wait time between retries in seconds (default: 1) +# Database conflicts: 1 second (fast retry for transient issues) +# API rate limits: 5 seconds (wait for quota reset) +SURREAL_COMMANDS_RETRY_WAIT_MIN=1 + +# Maximum wait time between retries in seconds (default: 30) +# Database conflicts: 30 seconds maximum +# API rate limits: 120 seconds maximum (defined per-command) +# Total retry time won't exceed max_attempts * wait_max +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 + +# WORKER CONCURRENCY +# Maximum number of concurrent tasks in the worker pool (default: 5) +# This affects the likelihood of database transaction conflicts during batch operations +# +# Tuning guidelines based on deployment size: +# - Resource-constrained (low CPU/memory): 1-2 workers +# Reduces conflicts and resource usage, but slower processing +# +# - Normal deployment (balanced): 5 workers (RECOMMENDED) +# Good balance between throughput and conflict rate +# Retry logic handles occasional conflicts gracefully +# +# - Large instances (high CPU/memory): 10-20 workers +# Higher throughput but more frequent DB conflicts +# Relies heavily on retry logic with jittered backoff +# +# Note: Higher concurrency increases vectorization speed but also increases +# SurrealDB transaction conflicts. The retry logic with exponential-jitter +# backoff ensures operations complete successfully even at high concurrency. +SURREAL_COMMANDS_MAX_TASKS=5 + # OPEN_NOTEBOOK_PASSWORD= # FIRECRAWL - Get a key at https://firecrawl.dev/ diff --git a/api/routers/embedding.py b/api/routers/embedding.py index ecee428..01613ae 100644 --- a/api/routers/embedding.py +++ b/api/routers/embedding.py @@ -62,18 +62,22 @@ async def embed_content(embed_request: EmbedRequest): ) else: - # SYNC PATH: Execute synchronously (existing behavior) + # SYNC PATH: Submit job (returns immediately with command_id) + # NOTE: "sync" here means "submit and return command_id" - actual processing + # still happens asynchronously in the worker pool logger.info(f"Using sync processing for {item_type} {item_id}") + command_id = None + # Get the item and embed it if item_type == "source": source_item = await Source.get(item_id) if not source_item: raise HTTPException(status_code=404, detail="Source not found") - # Perform embedding (vectorize is now idempotent - safe to call multiple times) - await source_item.vectorize() - message = "Source embedded successfully" + # Submit vectorization job (returns command_id for tracking) + command_id = await source_item.vectorize() + message = "Source vectorization job submitted" elif item_type == "note": note_item = await Note.get(item_id) @@ -84,7 +88,7 @@ async def embed_content(embed_request: EmbedRequest): message = "Note embedded successfully" return EmbedResponse( - success=True, message=message, item_id=item_id, item_type=item_type, command_id=None + success=True, message=message, item_id=item_id, item_type=item_type, command_id=command_id ) except HTTPException: diff --git a/api/routers/models.py b/api/routers/models.py index 853dd98..261a4ba 100644 --- a/api/routers/models.py +++ b/api/routers/models.py @@ -32,6 +32,33 @@ def _check_openai_compatible_support(mode: str) -> bool: return generic or specific +def _check_azure_support(mode: str) -> bool: + """ + Check if Azure OpenAI provider is available for a specific mode. + + Args: + mode: One of 'LLM', 'EMBEDDING', 'STT', 'TTS' + + Returns: + bool: True if either generic or mode-specific env vars are set + """ + # Check generic configuration (applies to all modes) + generic = ( + os.environ.get("AZURE_OPENAI_API_KEY") is not None + and os.environ.get("AZURE_OPENAI_ENDPOINT") is not None + and os.environ.get("AZURE_OPENAI_API_VERSION") is not None + ) + + # Check mode-specific configuration (takes precedence) + specific = ( + os.environ.get(f"AZURE_OPENAI_API_KEY_{mode}") is not None + and os.environ.get(f"AZURE_OPENAI_ENDPOINT_{mode}") is not None + and os.environ.get(f"AZURE_OPENAI_API_VERSION_{mode}") is not None + ) + + return generic or specific + + @router.get("/models", response_model=List[ModelResponse]) async def get_models( type: Optional[str] = Query(None, description="Filter by model type") @@ -168,11 +195,9 @@ async def update_default_models(defaults_data: DefaultModelsResponse): defaults.default_tools_model = defaults_data.default_tools_model # type: ignore[attr-defined] await defaults.update() - - # Refresh the model manager cache - from open_notebook.domain.models import model_manager - await model_manager.refresh_defaults() - + + # No cache refresh needed - next access will fetch fresh data from DB + return DefaultModelsResponse( default_chat_model=defaults.default_chat_model, # type: ignore[attr-defined] default_transformation_model=defaults.default_transformation_model, # type: ignore[attr-defined] @@ -213,10 +238,10 @@ async def get_provider_availability(): "elevenlabs": os.environ.get("ELEVENLABS_API_KEY") is not None, "voyage": os.environ.get("VOYAGE_API_KEY") is not None, "azure": ( - os.environ.get("AZURE_OPENAI_API_KEY") is not None - and os.environ.get("AZURE_OPENAI_ENDPOINT") is not None - and os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME") is not None - and os.environ.get("AZURE_OPENAI_API_VERSION") is not None + _check_azure_support("LLM") + or _check_azure_support("EMBEDDING") + or _check_azure_support("STT") + or _check_azure_support("TTS") ), "mistral": os.environ.get("MISTRAL_API_KEY") is not None, "deepseek": os.environ.get("DEEPSEEK_API_KEY") is not None, @@ -239,19 +264,26 @@ async def get_provider_availability(): for provider in available_providers: supported_types[provider] = [] + # Map Esperanto model types to our environment variable modes + mode_mapping = { + "language": "LLM", + "embedding": "EMBEDDING", + "speech_to_text": "STT", + "text_to_speech": "TTS", + } + # Special handling for openai-compatible to check mode-specific availability if provider == "openai-compatible": - # Map Esperanto model types to our environment variable modes - mode_mapping = { - "language": "LLM", - "embedding": "EMBEDDING", - "speech_to_text": "STT", - "text_to_speech": "TTS", - } for model_type, mode in mode_mapping.items(): if model_type in esperanto_available and provider in esperanto_available[model_type]: if _check_openai_compatible_support(mode): supported_types[provider].append(model_type) + # Special handling for azure to check mode-specific availability + elif provider == "azure": + for model_type, mode in mode_mapping.items(): + if model_type in esperanto_available and provider in esperanto_available[model_type]: + if _check_azure_support(mode): + supported_types[provider].append(model_type) else: # Standard provider detection for model_type, providers in esperanto_available.items(): diff --git a/commands/embedding_commands.py b/commands/embedding_commands.py index 055e632..6e0445f 100644 --- a/commands/embedding_commands.py +++ b/commands/embedding_commands.py @@ -3,11 +3,12 @@ from typing import Dict, List, Literal, Optional from loguru import logger from pydantic import BaseModel -from surreal_commands import CommandInput, CommandOutput, command +from surreal_commands import CommandInput, CommandOutput, command, submit_command from open_notebook.database.repository import ensure_record_id, repo_query from open_notebook.domain.models import model_manager from open_notebook.domain.notebook import Note, Source, SourceInsight +from open_notebook.utils.text_utils import split_text def full_model_dump(model): @@ -35,6 +36,32 @@ class EmbedSingleItemOutput(CommandOutput): error_message: Optional[str] = None +class EmbedChunkInput(CommandInput): + source_id: str + chunk_index: int + chunk_text: str + + +class EmbedChunkOutput(CommandOutput): + success: bool + source_id: str + chunk_index: int + error_message: Optional[str] = None + + +class VectorizeSourceInput(CommandInput): + source_id: str + + +class VectorizeSourceOutput(CommandOutput): + success: bool + source_id: str + total_chunks: int + jobs_submitted: int + processing_time: float + error_message: Optional[str] = None + + class RebuildEmbeddingsInput(CommandInput): mode: Literal["existing", "all"] include_sources: bool = True @@ -159,6 +186,215 @@ async def embed_single_item_command( ) +@command( + "embed_chunk", + app="open_notebook", + retry={ + "max_attempts": 5, + "wait_strategy": "exponential_jitter", + "wait_min": 1, + "wait_max": 30, + "retry_on": [RuntimeError, ConnectionError, TimeoutError], + }, +) +async def embed_chunk_command( + input_data: EmbedChunkInput, +) -> EmbedChunkOutput: + """ + Process a single text chunk for embedding as part of source vectorization. + + This command is designed to be submitted as a background job for each chunk + of a source document, allowing natural concurrency control through the worker pool. + + Retry Strategy: + - Retries up to 5 times for transient failures: + * RuntimeError: SurrealDB transaction conflicts ("read or write conflict") + * ConnectionError: Network failures when calling embedding provider + * TimeoutError: Request timeouts to embedding provider + - Uses exponential-jitter backoff (1-30s) to prevent thundering herd during concurrent operations + - Does NOT retry permanent failures (ValueError, authentication errors, invalid input) + + Exception Handling: + - RuntimeError, ConnectionError, TimeoutError: Re-raised to trigger retry mechanism + - ValueError and other exceptions: Caught and returned as permanent failures (no retry) + """ + try: + logger.debug( + f"Processing chunk {input_data.chunk_index} for source {input_data.source_id}" + ) + + # Get embedding model + EMBEDDING_MODEL = await model_manager.get_embedding_model() + if not EMBEDDING_MODEL: + raise ValueError( + "No embedding model configured. Please configure one in the Models section." + ) + + # Generate embedding for the chunk + embedding = (await EMBEDDING_MODEL.aembed([input_data.chunk_text]))[0] + + # Insert chunk embedding into database + await repo_query( + """ + CREATE source_embedding CONTENT { + "source": $source_id, + "order": $order, + "content": $content, + "embedding": $embedding, + }; + """, + { + "source_id": ensure_record_id(input_data.source_id), + "order": input_data.chunk_index, + "content": input_data.chunk_text, + "embedding": embedding, + }, + ) + + logger.debug( + f"Successfully embedded chunk {input_data.chunk_index} for source {input_data.source_id}" + ) + + return EmbedChunkOutput( + success=True, + source_id=input_data.source_id, + chunk_index=input_data.chunk_index, + ) + + except RuntimeError: + # Re-raise RuntimeError to allow retry mechanism to handle DB transaction conflicts + logger.warning( + f"Transaction conflict for chunk {input_data.chunk_index} - will be retried by retry mechanism" + ) + raise + except (ConnectionError, TimeoutError) as e: + # Re-raise network/timeout errors to allow retry mechanism to handle transient provider failures + logger.warning( + f"Network/timeout error for chunk {input_data.chunk_index} ({type(e).__name__}: {e}) - will be retried by retry mechanism" + ) + raise + except Exception as e: + # Catch other exceptions (ValueError, etc.) as permanent failures + logger.error( + f"Failed to embed chunk {input_data.chunk_index} for source {input_data.source_id}: {e}" + ) + logger.exception(e) + + return EmbedChunkOutput( + success=False, + source_id=input_data.source_id, + chunk_index=input_data.chunk_index, + error_message=str(e), + ) + + +@command("vectorize_source", app="open_notebook", retry=None) +async def vectorize_source_command( + input_data: VectorizeSourceInput, +) -> VectorizeSourceOutput: + """ + Orchestrate source vectorization by splitting text into chunks and submitting + individual embed_chunk jobs to the worker queue. + + This command: + 1. Deletes existing embeddings (idempotency) + 2. Splits source text into chunks + 3. Submits each chunk as a separate embed_chunk job + 4. Returns immediately (jobs run in background) + + Natural concurrency control is provided by the worker pool size. + + Retry Strategy: + - Retries disabled (retry=None) - fails fast on job submission errors + - This ensures immediate visibility when orchestration fails + - Individual embed_chunk jobs have their own retry logic for DB conflicts + """ + start_time = time.time() + + try: + logger.info(f"Starting vectorization orchestration for source {input_data.source_id}") + + # 1. Load source + source = await Source.get(input_data.source_id) + if not source: + raise ValueError(f"Source '{input_data.source_id}' not found") + + if not source.full_text: + raise ValueError(f"Source {input_data.source_id} has no text to vectorize") + + # 2. Delete existing embeddings (idempotency) + logger.info(f"Deleting existing embeddings for source {input_data.source_id}") + delete_result = await repo_query( + "DELETE source_embedding WHERE source = $source_id", + {"source_id": ensure_record_id(input_data.source_id)} + ) + deleted_count = len(delete_result) if delete_result else 0 + if deleted_count > 0: + logger.info(f"Deleted {deleted_count} existing embeddings") + + # 3. Split text into chunks + logger.info(f"Splitting text into chunks for source {input_data.source_id}") + chunks = split_text(source.full_text) + total_chunks = len(chunks) + logger.info(f"Split into {total_chunks} chunks") + + if total_chunks == 0: + raise ValueError("No chunks created after splitting text") + + # 4. Submit each chunk as a separate job + logger.info(f"Submitting {total_chunks} chunk jobs to worker queue") + jobs_submitted = 0 + + for idx, chunk_text in enumerate(chunks): + try: + job_id = submit_command( + "open_notebook", # app name + "embed_chunk", # command name + { + "source_id": input_data.source_id, + "chunk_index": idx, + "chunk_text": chunk_text, + } + ) + jobs_submitted += 1 + + if (idx + 1) % 100 == 0: + logger.info(f" Submitted {idx + 1}/{total_chunks} chunk jobs") + + except Exception as e: + logger.error(f"Failed to submit chunk job {idx}: {e}") + # Continue submitting other chunks even if one fails + + processing_time = time.time() - start_time + + logger.info( + f"Vectorization orchestration complete for source {input_data.source_id}: " + f"{jobs_submitted}/{total_chunks} jobs submitted in {processing_time:.2f}s" + ) + + return VectorizeSourceOutput( + success=True, + source_id=input_data.source_id, + total_chunks=total_chunks, + jobs_submitted=jobs_submitted, + processing_time=processing_time, + ) + + except Exception as e: + processing_time = time.time() - start_time + logger.error(f"Vectorization orchestration failed for source {input_data.source_id}: {e}") + logger.exception(e) + + return VectorizeSourceOutput( + success=False, + source_id=input_data.source_id, + total_chunks=0, + jobs_submitted=0, + processing_time=processing_time, + error_message=str(e), + ) + + async def collect_items_for_rebuild( mode: str, include_sources: bool, @@ -226,12 +462,17 @@ async def collect_items_for_rebuild( return items -@command("rebuild_embeddings", app="open_notebook") +@command("rebuild_embeddings", app="open_notebook", retry=None) async def rebuild_embeddings_command( input_data: RebuildEmbeddingsInput, ) -> RebuildEmbeddingsOutput: """ Rebuild embeddings for sources, notes, and/or insights + + Retry Strategy: + - Retries disabled (retry=None) - batch failures are immediately reported + - This ensures immediate visibility when batch operations fail + - Allows operators to quickly identify and resolve issues """ start_time = time.time() diff --git a/docs/deployment/index.md b/docs/deployment/index.md index 60506c4..221fc8d 100644 --- a/docs/deployment/index.md +++ b/docs/deployment/index.md @@ -43,6 +43,13 @@ This section provides comprehensive guides for deploying Open Notebook in differ - Production deployment considerations - Troubleshooting security issues +### 6. [Retry Configuration](retry-configuration.md) +**For reliable background job processing** +- Automatic retry for transient failures +- Database transaction conflict handling +- Embedding provider failure recovery +- Performance tuning and monitoring + ## 🎯 Choose Your Deployment Method ### Use Docker Setup if: diff --git a/docs/deployment/retry-configuration.md b/docs/deployment/retry-configuration.md new file mode 100644 index 0000000..397ef61 --- /dev/null +++ b/docs/deployment/retry-configuration.md @@ -0,0 +1,345 @@ +# Retry Configuration Guide + +Open Notebook includes automatic retry capabilities for background commands to handle transient failures gracefully. This guide explains how retry works and how to configure it for your deployment. + +## Overview + +The retry system (powered by surreal-commands v1.2.0+) automatically retries failed commands when they encounter transient errors like: + +- **Database transaction conflicts** during concurrent operations +- **Network failures** when calling external APIs (embedding providers, LLMs) +- **Request timeouts** to external services +- **Rate limits** from third-party APIs + +Permanent errors (invalid input, authentication failures, etc.) are **not** retried and fail immediately. + +## How It Works + +### Architecture + +``` +Command Execution + ↓ +Try to execute + ↓ +Success? β†’ Done + ↓ +Transient Error? (RuntimeError, ConnectionError, TimeoutError) + ↓ +Retry with backoff + ↓ +Max attempts reached? + ↓ +Final failure β†’ Report error +``` + +### Retry Strategies + +**Exponential Jitter** (default, recommended): +- Waits: 1s β†’ ~2s β†’ ~4s β†’ ~8s β†’ ~16s (with randomization) +- Prevents "thundering herd" when many workers retry simultaneously +- Best for: Database conflicts, concurrent operations + +**Exponential**: +- Waits: 1s β†’ 2s β†’ 4s β†’ 8s β†’ 16s (predictable) +- Good for: API rate limits (predictable backoff helps with quota reset) + +**Fixed**: +- Waits: 2s β†’ 2s β†’ 2s β†’ 2s β†’ 2s (constant) +- Best for: Quick recovery scenarios + +**Random**: +- Waits: Random between min and max +- Use when: You want unpredictable retry timing + +## Global Configuration + +Configure default retry behavior for **all** commands via environment variables in your `.env` file: + +```bash +# Enable/disable retry globally (default: true) +SURREAL_COMMANDS_RETRY_ENABLED=true + +# Maximum retry attempts before giving up (default: 3) +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 + +# Wait strategy between retry attempts (default: exponential_jitter) +# Options: exponential_jitter, exponential, fixed, random +SURREAL_COMMANDS_RETRY_WAIT_STRATEGY=exponential_jitter + +# Minimum wait time between retries in seconds (default: 1) +SURREAL_COMMANDS_RETRY_WAIT_MIN=1 + +# Maximum wait time between retries in seconds (default: 30) +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 + +# Worker concurrency (affects likelihood of DB conflicts) +# Higher concurrency = more conflicts but faster processing +# Lower concurrency = fewer conflicts but slower processing +SURREAL_COMMANDS_MAX_TASKS=5 +``` + +### Tuning Global Defaults + +**For resource-constrained deployments** (low CPU/memory): +```bash +SURREAL_COMMANDS_MAX_TASKS=2 +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 +SURREAL_COMMANDS_RETRY_WAIT_MAX=20 +``` +- Fewer concurrent tasks reduce conflict likelihood +- Lower max wait since conflicts are rare + +**For high-performance deployments** (powerful servers): +```bash +SURREAL_COMMANDS_MAX_TASKS=10 +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=5 +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 +``` +- More concurrent tasks for faster processing +- More retries to handle increased conflicts + +**For debugging** (disable retries to see immediate errors): +```bash +SURREAL_COMMANDS_RETRY_ENABLED=false +``` + +## Per-Command Configuration + +Individual commands can override global defaults. Open Notebook uses custom retry strategies for specific operations: + +### embed_chunk (Database Operations) + +Handles concurrent chunk embedding with retry for transaction conflicts: + +```python +@command( + "embed_chunk", + app="open_notebook", + retry={ + "max_attempts": 5, + "wait_strategy": "exponential_jitter", + "wait_min": 1, + "wait_max": 30, + "retry_on": [RuntimeError, ConnectionError, TimeoutError], + }, +) +``` + +**What it retries**: +- SurrealDB transaction conflicts (`RuntimeError`) +- Network failures to embedding provider (`ConnectionError`) +- Request timeouts (`TimeoutError`) + +**What it doesn't retry**: +- Invalid input (`ValueError`) +- Authentication errors +- Missing embedding model + +**Why 5 attempts?** +Database conflicts are cheap to retry (local operation), so we retry more aggressively. + +### vectorize_source & rebuild_embeddings (Orchestration) + +Orchestration commands that coordinate other jobs **disable retries** to fail fast: + +```python +@command("vectorize_source", app="open_notebook", retry=None) +``` + +**Why no retries?** +- Job submission failures should be immediately visible +- Allows quick debugging of orchestration issues +- Individual child jobs (`embed_chunk`) have their own retry logic + +## Common Scenarios + +### Issue: Vectorization fails with "transaction conflict" errors + +**Symptoms**: +``` +RuntimeError: Failed to commit transaction due to a read or write conflict +``` + +**Solution 1 - Reduce concurrency** (fewer conflicts): +```bash +SURREAL_COMMANDS_MAX_TASKS=3 +``` + +**Solution 2 - Increase retry attempts**: +```bash +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=7 +``` + +**Solution 3 - Longer backoff** (give more time between retries): +```bash +SURREAL_COMMANDS_RETRY_WAIT_MAX=60 +``` + +### Issue: Embedding provider rate limits (429 errors) + +**Symptoms**: +``` +HTTP 429: Rate limit exceeded +``` + +**Solution - Configure longer waits**: +```bash +SURREAL_COMMANDS_RETRY_WAIT_MIN=5 +SURREAL_COMMANDS_RETRY_WAIT_MAX=120 +SURREAL_COMMANDS_RETRY_WAIT_STRATEGY=exponential +``` + +This gives the API quota time to reset between retries. + +### Issue: Slow/unstable network to embedding provider + +**Symptoms**: +``` +TimeoutError: Request timed out +ConnectionError: Failed to establish connection +``` + +**Solution - More retries with longer waits**: +```bash +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=5 +SURREAL_COMMANDS_RETRY_WAIT_MAX=60 +``` + +### Issue: Want to see errors immediately (debugging) + +**Solution - Disable retries temporarily**: +```bash +SURREAL_COMMANDS_RETRY_ENABLED=false +``` + +Remember to re-enable after debugging! + +## Monitoring Retry Behavior + +### Check Worker Logs + +Retry attempts are logged automatically: + +``` +Transaction conflict for chunk 42 - will be retried by retry mechanism +[Retry] Attempt 2/5 for embed_chunk, waiting 2.3s +[Retry] Attempt 3/5 for embed_chunk, waiting 5.1s +Successfully embedded chunk 42 +``` + +### Look for Retry Patterns + +**High retry rate** (many retries happening): +- Consider reducing `SURREAL_COMMANDS_MAX_TASKS` +- Check if external services are slow/unstable +- May need to increase `SURREAL_COMMANDS_RETRY_WAIT_MAX` + +**Retries exhausted** (commands failing after all retries): +- Check if issue is actually permanent (auth error, invalid config) +- May need to increase `SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS` +- Check external service status + +**No retries** (operations always succeed first try): +- Your retry configuration is working well! +- Could potentially increase `SURREAL_COMMANDS_MAX_TASKS` for better performance + +## Best Practices + +### βœ… Do + +- **Use exponential_jitter for concurrent operations** (prevents thundering herd) +- **Set reasonable max_attempts** (3-5 for most operations) +- **Monitor retry rates** to tune configuration +- **Test retry behavior** with large documents after config changes +- **Document custom retry strategies** in your deployment notes + +### ❌ Don't + +- **Don't set max_attempts too high** (>10) - may mask real issues +- **Don't use fixed strategy for concurrent operations** - causes thundering herd +- **Don't disable retries in production** unless debugging +- **Don't set wait_max too low** (<5s) - may exhaust retries too quickly +- **Don't forget to re-enable retries** after debugging + +## Advanced: Custom Retry Logic + +If you're developing custom commands, you can configure retry behavior: + +```python +from surreal_commands import command + +@command( + "my_custom_command", + app="my_app", + retry={ + "max_attempts": 3, + "wait_strategy": "exponential_jitter", + "wait_min": 1, + "wait_max": 30, + "retry_on": [RuntimeError, ConnectionError, TimeoutError], + }, +) +async def my_custom_command(input_data): + try: + # Your command logic + result = await some_operation() + return result + + except RuntimeError: + # Re-raise to trigger retry + raise + + except ValueError: + # Don't retry - permanent error + return {"success": False, "error": str(e)} +``` + +**Key points**: +- Exceptions in `retry_on` must be **re-raised** to trigger retries +- Other exceptions should be caught and returned as failures +- Transient errors: RuntimeError, ConnectionError, TimeoutError +- Permanent errors: ValueError, AuthenticationError, etc. + +## Troubleshooting + +### Retries not working + +**Check 1**: Is retry enabled? +```bash +grep SURREAL_COMMANDS_RETRY_ENABLED .env +# Should show: SURREAL_COMMANDS_RETRY_ENABLED=true +``` + +**Check 2**: Is the exception being re-raised? +Check your command code - exceptions must be re-raised to trigger retries. + +**Check 3**: Is the exception in `retry_on` list? +Only exceptions listed in `retry_on` are retried. + +### Worker crashing on errors + +**Issue**: Worker crashes instead of retrying + +**Cause**: Exception is not being caught by retry mechanism + +**Solution**: Check that the exception type is in the `retry_on` list and is being re-raised in the command. + +### Retries taking too long + +**Issue**: Commands retry forever + +**Cause**: `wait_max` is too high or `max_attempts` is too high + +**Solution**: Reduce retry parameters: +```bash +SURREAL_COMMANDS_RETRY_MAX_ATTEMPTS=3 +SURREAL_COMMANDS_RETRY_WAIT_MAX=30 +``` + +## References + +- [surreal-commands v1.2.0 Release](https://github.com/lfnovo/surreal-commands/releases/tag/v1.2.0) +- [surreal-commands Retry Documentation](https://github.com/lfnovo/surreal-commands#retry-configuration) +- [Issue #229: Batch Vectorization Transaction Conflicts](https://github.com/lfnovo/open-notebook/issues/229) +- [Exponential Backoff Best Practices](https://en.wikipedia.org/wiki/Exponential_backoff) diff --git a/docs/features/ai-models.md b/docs/features/ai-models.md index b0ed875..4942e96 100644 --- a/docs/features/ai-models.md +++ b/docs/features/ai-models.md @@ -362,6 +362,55 @@ export OPENAI_COMPATIBLE_BASE_URL_TTS=http://localhost:9000/v1 > **πŸ“– Need detailed setup help?** Check our comprehensive [OpenAI-Compatible Setup Guide](openai-compatible.md) for LM Studio, Text Generation WebUI, vLLM, and other configurations. +--- + +### ☁️ Azure OpenAI +**Best for**: Enterprise deployments with Microsoft Azure infrastructure + +**Environment Setup** +```bash +# Generic configuration (applies to all modalities) +export AZURE_OPENAI_API_KEY=your_key +export AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/ +export AZURE_OPENAI_API_VERSION=2024-12-01-preview + +# Mode-specific configuration (for different deployments per modality) +# Use these when you have separate Azure deployments for different capabilities +export AZURE_OPENAI_API_KEY_LLM=your_llm_key +export AZURE_OPENAI_ENDPOINT_LLM=https://llm-resource.openai.azure.com/ +export AZURE_OPENAI_API_VERSION_LLM=2024-12-01-preview + +export AZURE_OPENAI_API_KEY_EMBEDDING=your_embedding_key +export AZURE_OPENAI_ENDPOINT_EMBEDDING=https://embedding-resource.openai.azure.com/ +export AZURE_OPENAI_API_VERSION_EMBEDDING=2024-12-01-preview + +# STT and TTS also supported with _STT and _TTS suffixes +``` + +**Recommended Models** +- **Language**: `gpt-4o`, `gpt-4o-mini`, `gpt-35-turbo` +- **Embedding**: `text-embedding-3-small`, `text-embedding-ada-002` + +**Strengths** +- Enterprise-grade security and compliance +- **NEW**: Full support for modality-specific deployments +- Configure different Azure resources for different capabilities +- Integration with Azure ecosystem +- SLA guarantees and dedicated support +- Regional deployment options + +**Use Cases** +- **Single Deployment**: Use generic configuration when all models are in one Azure resource +- **Multi-Deployment**: Use mode-specific configuration for separate resources (e.g., production LLM in one region, embeddings in another) +- **Cost Optimization**: Different Azure subscriptions or resources for different workloads +- **Compliance**: Separate deployments for different data residency requirements + +**Considerations** +- Requires Azure subscription and resource setup +- More complex configuration than standard OpenAI +- Limited to Azure OpenAI service capabilities +- Deployment-based model access (not all models available) + ## 🧠 Reasoning Models Open Notebook fully supports **reasoning models** that show their transparent thinking process. These models output their internal reasoning within `` tags, which Open Notebook automatically handles. @@ -525,10 +574,19 @@ export VOYAGE_API_KEY=your_key export OLLAMA_API_BASE=http://localhost:11434 # Azure OpenAI +# Generic configuration (applies to all modalities) export AZURE_OPENAI_API_KEY=your_key export AZURE_OPENAI_ENDPOINT=your_endpoint export AZURE_OPENAI_API_VERSION=2024-12-01-preview -export AZURE_OPENAI_DEPLOYMENT_NAME=your_deployment + +# Mode-specific configuration (for different deployments per modality) +export AZURE_OPENAI_API_KEY_LLM=your_llm_key +export AZURE_OPENAI_ENDPOINT_LLM=your_llm_endpoint +export AZURE_OPENAI_API_VERSION_LLM=2024-12-01-preview + +export AZURE_OPENAI_API_KEY_EMBEDDING=your_embedding_key +export AZURE_OPENAI_ENDPOINT_EMBEDDING=your_embedding_endpoint +export AZURE_OPENAI_API_VERSION_EMBEDDING=2024-12-01-preview # Vertex AI export VERTEX_PROJECT=your_project diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index c641d4f..a4a5be4 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -191,10 +191,18 @@ OPENROUTER_BASE_URL="https://openrouter.ai/api/v1" OPENROUTER_API_KEY=your-openrouter-key-here # Azure OpenAI +# Generic configuration (applies to all modalities) AZURE_OPENAI_API_KEY=your-azure-key-here AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/ -AZURE_OPENAI_API_VERSION="2024-12-01-preview" -AZURE_OPENAI_DEPLOYMENT_NAME=your-deployment-name +AZURE_OPENAI_API_VERSION=2024-12-01-preview + +# Mode-specific configuration (for different deployments per modality) +# AZURE_OPENAI_API_KEY_LLM=your-llm-key +# AZURE_OPENAI_ENDPOINT_LLM=https://llm-endpoint.openai.azure.com/ +# AZURE_OPENAI_API_VERSION_LLM=2024-12-01-preview +# AZURE_OPENAI_API_KEY_EMBEDDING=your-embedding-key +# AZURE_OPENAI_ENDPOINT_EMBEDDING=https://embedding-endpoint.openai.azure.com/ +# AZURE_OPENAI_API_VERSION_EMBEDDING=2024-12-01-preview # OpenAI Compatible (LM Studio, etc.) OPENAI_COMPATIBLE_BASE_URL=http://localhost:1234/v1 diff --git a/docs/index.md b/docs/index.md index df8d745..bd6d143 100644 --- a/docs/index.md +++ b/docs/index.md @@ -58,6 +58,7 @@ Complete deployment guides for all scenarios. - **[Single Container](deployment/single-container.md)** - Simplified deployment - **[Development](deployment/development.md)** - Source code setup - **[Security](deployment/security.md)** - Production security +- **[Retry Configuration](deployment/retry-configuration.md)** - Background job reliability --- diff --git a/frontend/src/components/source/SourceDetailContent.tsx b/frontend/src/components/source/SourceDetailContent.tsx index e7d82ea..91312c5 100644 --- a/frontend/src/components/source/SourceDetailContent.tsx +++ b/frontend/src/components/source/SourceDetailContent.tsx @@ -557,21 +557,6 @@ export function SourceDetailContent({ {insight.insight_type} - {insight.created && ( - - {(() => { - try { - const date = new Date(insight.created) - if (isNaN(date.getTime())) { - return 'Unknown date' - } - return formatDistanceToNow(date, { addSuffix: true }) - } catch { - return 'Unknown date' - } - })()} - - )}

{insight.content.slice(0, 180)}{insight.content.length > 180 ? '…' : ''} diff --git a/frontend/src/components/source/SourceDialog.tsx b/frontend/src/components/source/SourceDialog.tsx index bfa2fbe..9654df9 100644 --- a/frontend/src/components/source/SourceDialog.tsx +++ b/frontend/src/components/source/SourceDialog.tsx @@ -38,12 +38,12 @@ export function SourceDialog({ open, onOpenChange, sourceId }: SourceDialogProps return (

- + {/* Accessibility title (hidden visually but read by screen readers) */} Source Details {/* Source detail content */} -
+
- + Source Insight @@ -41,7 +41,7 @@ export function SourceInsightDialog({ open, onOpenChange, insight }: SourceInsig -
+
{isLoading ? (
Loading insight… diff --git a/frontend/src/components/sources/steps/SourceTypeStep.tsx b/frontend/src/components/sources/steps/SourceTypeStep.tsx index 6fae755..b049e9f 100644 --- a/frontend/src/components/sources/steps/SourceTypeStep.tsx +++ b/frontend/src/components/sources/steps/SourceTypeStep.tsx @@ -105,10 +105,10 @@ export function SourceTypeStep({ control, register, errors }: SourceTypeStepProp id="file" type="file" {...register('file')} - accept=".pdf,.doc,.docx,.txt,.md,.epub" + accept=".pdf,.doc,.docx,.pptx,.ppt,.xlsx,.xls,.txt,.md,.epub,.mp4,.avi,.mov,.wmv,.mp3,.wav,.m4a,.aac,.jpg,.jpeg,.png,.tiff,.zip,.tar,.gz,.html" />

- Supported formats: PDF, DOC, DOCX, TXT, MD, EPUB + Supported: Documents (PDF, DOC, DOCX, PPT, XLS, EPUB, TXT, MD), Media (MP4, MP3, WAV, M4A), Images (JPG, PNG), Archives (ZIP)

{errors.file && (

{errors.file.message}

diff --git a/open_notebook/database/repository.py b/open_notebook/database/repository.py index 1b241f5..968a097 100644 --- a/open_notebook/database/repository.py +++ b/open_notebook/database/repository.py @@ -74,7 +74,6 @@ async def repo_query( raise RuntimeError(result) return result except Exception as e: - logger.error(f"Query: {query_str[:200]} vars: {vars}") logger.exception(e) raise diff --git a/open_notebook/domain/models.py b/open_notebook/domain/models.py index 85ad92f..fef4e83 100644 --- a/open_notebook/domain/models.py +++ b/open_notebook/domain/models.py @@ -9,7 +9,7 @@ from esperanto import ( ) from loguru import logger -from open_notebook.database.repository import repo_query +from open_notebook.database.repository import ensure_record_id, repo_query from open_notebook.domain.base import ObjectModel, RecordModel ModelType = Union[LanguageModel, EmbeddingModel, SpeechToTextModel, TextToSpeechModel] @@ -40,38 +40,40 @@ class DefaultModels(RecordModel): default_embedding_model: Optional[str] = None default_tools_model: Optional[str] = None + @classmethod + async def get_instance(cls) -> "DefaultModels": + """Always fetch fresh defaults from database (override parent caching behavior)""" + result = await repo_query( + "SELECT * FROM ONLY $record_id", + {"record_id": ensure_record_id(cls.record_id)}, + ) + + if result: + if isinstance(result, list) and len(result) > 0: + data = result[0] + elif isinstance(result, dict): + data = result + else: + data = {} + else: + data = {} + + # Create new instance with fresh data (bypass singleton cache) + instance = object.__new__(cls) + object.__setattr__(instance, "__dict__", {}) + super(RecordModel, instance).__init__(**data) + return instance + class ModelManager: - _instance = None - - def __new__(cls): - if cls._instance is None: - cls._instance = super(ModelManager, cls).__new__(cls) - return cls._instance - def __init__(self): - if not hasattr(self, "_initialized"): - self._initialized = True - self._model_cache: Dict[str, ModelType] = {} - self._default_models = None + pass # No caching needed async def get_model(self, model_id: str, **kwargs) -> Optional[ModelType]: + """Get a model by ID. Esperanto will cache the actual model instance.""" if not model_id: return None - cache_key = f"{model_id}:{str(kwargs)}" - - if cache_key in self._model_cache: - cached_model = self._model_cache[cache_key] - if not isinstance( - cached_model, - (LanguageModel, EmbeddingModel, SpeechToTextModel, TextToSpeechModel), - ): - raise TypeError( - f"Cached model is of unexpected type: {type(cached_model)}" - ) - return cached_model - try: model: Model = await Model.get(model_id) except Exception: @@ -85,27 +87,27 @@ class ModelManager: ]: raise ValueError(f"Invalid model type: {model.type}") - model_instance: ModelType + # Create model based on type (Esperanto will cache the instance) if model.type == "language": - model_instance = AIFactory.create_language( + return AIFactory.create_language( model_name=model.name, provider=model.provider, config=kwargs, ) elif model.type == "embedding": - model_instance = AIFactory.create_embedding( + return AIFactory.create_embedding( model_name=model.name, provider=model.provider, config=kwargs, ) elif model.type == "speech_to_text": - model_instance = AIFactory.create_speech_to_text( + return AIFactory.create_speech_to_text( model_name=model.name, provider=model.provider, config=kwargs, ) elif model.type == "text_to_speech": - model_instance = AIFactory.create_text_to_speech( + return AIFactory.create_text_to_speech( model_name=model.name, provider=model.provider, config=kwargs, @@ -113,28 +115,12 @@ class ModelManager: else: raise ValueError(f"Invalid model type: {model.type}") - self._model_cache[cache_key] = model_instance - return model_instance - - def clear_cache(self): - """Clear all cached model instances""" - self._model_cache.clear() - logger.info("Model cache cleared") - - async def refresh_defaults(self): - """Refresh the default models from the database and clear model cache""" - self._default_models = await DefaultModels.get_instance() - # Clear the model cache to ensure we use fresh instances with the new defaults - self.clear_cache() - async def get_defaults(self) -> DefaultModels: - """Get the default models configuration (always fetches fresh from DB)""" - # Always refresh to ensure we have the latest defaults - # This is important when embedding models are changed - await self.refresh_defaults() - if not self._default_models: - raise RuntimeError("Failed to initialize default models configuration") - return self._default_models + """Get the default models configuration from database""" + defaults = await DefaultModels.get_instance() + if not defaults: + raise RuntimeError("Failed to load default models configuration") + return defaults async def get_speech_to_text(self, **kwargs) -> Optional[SpeechToTextModel]: """Get the default speech-to-text model""" diff --git a/open_notebook/domain/notebook.py b/open_notebook/domain/notebook.py index 8e160c6..cf096bd 100644 --- a/open_notebook/domain/notebook.py +++ b/open_notebook/domain/notebook.py @@ -3,6 +3,7 @@ from typing import Any, ClassVar, Dict, List, Literal, Optional, Tuple, Union from loguru import logger from pydantic import BaseModel, Field, field_validator +from surreal_commands import submit_command from surrealdb import RecordID from open_notebook.database.repository import ensure_record_id, repo_query @@ -262,83 +263,49 @@ class Source(ObjectModel): raise InvalidInputError("Notebook ID must be provided") return await self.relate("reference", notebook_id) - async def vectorize(self) -> None: - logger.info(f"Starting vectorization for source {self.id}") - EMBEDDING_MODEL = await model_manager.get_embedding_model() + async def vectorize(self) -> str: + """ + Submit vectorization as a background job using the vectorize_source command. + + This method now leverages the job-based architecture to prevent HTTP connection + pool exhaustion when processing large documents. The actual chunk processing + happens in the background worker pool, with natural concurrency control. + + Returns: + str: The command/job ID that can be used to track progress via the commands API + + Raises: + ValueError: If source has no text to vectorize + DatabaseOperationError: If job submission fails + """ + logger.info(f"Submitting vectorization job for source {self.id}") try: - # DELETE EXISTING EMBEDDINGS FIRST - Makes vectorize() idempotent - delete_result = await repo_query( - "DELETE source_embedding WHERE source = $source_id", - {"source_id": ensure_record_id(self.id)} - ) - deleted_count = len(delete_result) if delete_result else 0 - if deleted_count > 0: - logger.info(f"Deleted {deleted_count} existing embeddings for source {self.id}") - else: - logger.debug(f"No existing embeddings found for source {self.id}") - if not self.full_text: - logger.warning(f"No text to vectorize for source {self.id}") - return + raise ValueError(f"Source {self.id} has no text to vectorize") - chunks = split_text( - self.full_text, + # Submit the vectorize_source command which will: + # 1. Delete existing embeddings (idempotency) + # 2. Split text into chunks + # 3. Submit each chunk as an embed_chunk job + command_id = submit_command( + "open_notebook", # app name + "vectorize_source", # command name + { + "source_id": str(self.id), + } ) - chunk_count = len(chunks) - logger.info(f"Split into {chunk_count} chunks for source {self.id}") - if chunk_count == 0: - logger.warning("No chunks created after splitting") - return + command_id_str = str(command_id) + logger.info( + f"Vectorization job submitted for source {self.id}: " + f"command_id={command_id_str}" + ) - # Process chunks concurrently using async gather - logger.info("Starting concurrent processing of chunks") - - async def process_chunk( - idx: int, chunk: str - ) -> Tuple[int, List[float], str]: - logger.debug(f"Processing chunk {idx}/{chunk_count}") - try: - if EMBEDDING_MODEL is None: - raise ValueError("EMBEDDING_MODEL is not configured") - embedding = (await EMBEDDING_MODEL.aembed([chunk]))[0] - cleaned_content = chunk - logger.debug(f"Successfully processed chunk {idx}") - return (idx, embedding, cleaned_content) - except Exception as e: - logger.error(f"Error processing chunk {idx}: {str(e)}") - raise - - # Create tasks for all chunks and process them concurrently - tasks = [process_chunk(idx, chunk) for idx, chunk in enumerate(chunks)] - results = await asyncio.gather(*tasks) - - logger.info(f"Parallel processing complete. Got {len(results)} results") - - # Insert results in order (they're already ordered by index) - for idx, embedding, content in results: - logger.debug(f"Inserting chunk {idx} into database") - await repo_query( - """ - CREATE source_embedding CONTENT { - "source": $source_id, - "order": $order, - "content": $content, - "embedding": $embedding, - };""", - { - "source_id": ensure_record_id(self.id), - "order": idx, - "content": content, - "embedding": embedding, - }, - ) - - logger.info(f"Vectorization complete for source {self.id}") + return command_id_str except Exception as e: - logger.error(f"Error vectorizing source {self.id}: {str(e)}") + logger.error(f"Failed to submit vectorization job for source {self.id}: {e}") logger.exception(e) raise DatabaseOperationError(e) diff --git a/open_notebook/graphs/source.py b/open_notebook/graphs/source.py index 09e30aa..da0b3d6 100644 --- a/open_notebook/graphs/source.py +++ b/open_notebook/graphs/source.py @@ -10,6 +10,7 @@ from loguru import logger from typing_extensions import Annotated, TypedDict from open_notebook.domain.content_settings import ContentSettings +from open_notebook.domain.models import Model, ModelManager from open_notebook.domain.notebook import Asset, Source from open_notebook.domain.transformation import Transformation from open_notebook.graphs.transformation import graph as transform_graph @@ -48,6 +49,20 @@ async def content_process(state: SourceState) -> dict: ) content_state["output_format"] = "markdown" + # Add speech-to-text model configuration from Default Models + try: + model_manager = ModelManager() + defaults = await model_manager.get_defaults() + if defaults.default_speech_to_text_model: + stt_model = await Model.get(defaults.default_speech_to_text_model) + if stt_model: + content_state["audio_provider"] = stt_model.provider + content_state["audio_model"] = stt_model.name + logger.debug(f"Using speech-to-text model: {stt_model.provider}/{stt_model.name}") + except Exception as e: + logger.warning(f"Failed to retrieve speech-to-text model configuration: {e}") + # Continue without custom audio model (content-core will use its default) + processed_state = await extract_content(content_state) return {"content_state": processed_state} diff --git a/pyproject.toml b/pyproject.toml index c2b1c25..10e9fad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "open-notebook" -version = "1.1.1" +version = "1.2.0" description = "An open source implementation of a research assistant, inspired by Google Notebook LM" authors = [ {name = "Luis Novo", email = "lfnovo@gmail.com"} @@ -38,8 +38,8 @@ dependencies = [ "esperanto>=2.4.1", "langchain-google-vertexai>=2.0.28", "surrealdb>=1.0.4", - "surreal-commands>=1.0.13", "podcast-creator>=0.7.0", + "surreal-commands>=1.2.0", ] [tool.setuptools] diff --git a/tests/test_domain.py b/tests/test_domain.py index 0048f5e..0c10ab4 100644 --- a/tests/test_domain.py +++ b/tests/test_domain.py @@ -48,20 +48,21 @@ class TestRecordModelSingleton: # ============================================================================ -# TEST SUITE 2: ModelManager Singleton +# TEST SUITE 2: ModelManager Instance Isolation # ============================================================================ class TestModelManager: - """Test suite for ModelManager singleton pattern.""" + """Test suite for ModelManager instance behavior.""" - def test_model_manager_singleton(self): - """Test ModelManager implements singleton pattern correctly.""" + def test_model_manager_instance_isolation(self): + """Test that each ModelManager instance is independent (not a singleton).""" manager1 = ModelManager() manager2 = ModelManager() - assert manager1 is manager2 - assert id(manager1) == id(manager2) + # Each instance should be independent (not a singleton) + assert manager1 is not manager2 + assert id(manager1) != id(manager2) # ============================================================================ diff --git a/uv.lock b/uv.lock index 7347376..3ad0e4f 100644 --- a/uv.lock +++ b/uv.lock @@ -31,7 +31,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.1" +version = "3.13.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -42,42 +42,42 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ba/fa/3ae643cd525cf6844d3dc810481e5748107368eb49563c15a5fb9f680750/aiohttp-3.13.1.tar.gz", hash = "sha256:4b7ee9c355015813a6aa085170b96ec22315dabc3d866fd77d147927000e9464", size = 7835344, upload-time = "2025-10-17T14:03:29.337Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/2c/739d03730ffce57d2093e2e611e1541ac9a4b3bb88288c33275058b9ffc2/aiohttp-3.13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eefa0a891e85dca56e2d00760945a6325bd76341ec386d3ad4ff72eb97b7e64", size = 742004, upload-time = "2025-10-17T13:59:29.73Z" }, - { url = "https://files.pythonhosted.org/packages/fc/f8/7f5b7f7184d7c80e421dbaecbd13e0b2a0bb8663fd0406864f9a167a438c/aiohttp-3.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c20eb646371a5a57a97de67e52aac6c47badb1564e719b3601bbb557a2e8fd0", size = 495601, upload-time = "2025-10-17T13:59:31.312Z" }, - { url = "https://files.pythonhosted.org/packages/3e/af/fb78d028b9642dd33ff127d9a6a151586f33daff631b05250fecd0ab23f8/aiohttp-3.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfc28038cd86fb1deed5cc75c8fda45c6b0f5c51dfd76f8c63d3d22dc1ab3d1b", size = 491790, upload-time = "2025-10-17T13:59:33.304Z" }, - { url = "https://files.pythonhosted.org/packages/1e/ae/e40e422ee995e4f91f7f087b86304e3dd622d3a5b9ca902a1e94ebf9a117/aiohttp-3.13.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b22eeffca2e522451990c31a36fe0e71079e6112159f39a4391f1c1e259a795", size = 1746350, upload-time = "2025-10-17T13:59:35.158Z" }, - { url = "https://files.pythonhosted.org/packages/28/a5/fe6022bb869bf2d2633b155ed8348d76358c22d5ff9692a15016b2d1019f/aiohttp-3.13.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:65782b2977c05ebd78787e3c834abe499313bf69d6b8be4ff9c340901ee7541f", size = 1703046, upload-time = "2025-10-17T13:59:37.077Z" }, - { url = "https://files.pythonhosted.org/packages/5a/a5/c4ef3617d7cdc49f2d5af077f19794946f0f2d94b93c631ace79047361a2/aiohttp-3.13.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dacba54f9be3702eb866b0b9966754b475e1e39996e29e442c3cd7f1117b43a9", size = 1806161, upload-time = "2025-10-17T13:59:38.837Z" }, - { url = "https://files.pythonhosted.org/packages/ad/45/b87d2430aee7e7d00b24e3dff2c5bd69f21017f6edb19cfd91e514664fc8/aiohttp-3.13.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa878da718e8235302c365e376b768035add36b55177706d784a122cb822a6a4", size = 1894546, upload-time = "2025-10-17T13:59:40.741Z" }, - { url = "https://files.pythonhosted.org/packages/e8/a2/79eb466786a7f11a0292c353a8a9b95e88268c48c389239d7531d66dbb48/aiohttp-3.13.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e4b4e607fbd4964d65945a7b9d1e7f98b0d5545736ea613f77d5a2a37ff1e46", size = 1745683, upload-time = "2025-10-17T13:59:42.59Z" }, - { url = "https://files.pythonhosted.org/packages/93/1a/153b0ad694f377e94eacc85338efe03ed4776a396c8bb47bd9227135792a/aiohttp-3.13.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0c3db2d0e5477ad561bf7ba978c3ae5f8f78afda70daa05020179f759578754f", size = 1605418, upload-time = "2025-10-17T13:59:45.229Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4e/18605b1bfeb4b00d3396d833647cdb213118e2a96862e5aebee62ad065b4/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9739d34506fdf59bf2c092560d502aa728b8cdb33f34ba15fb5e2852c35dd829", size = 1722379, upload-time = "2025-10-17T13:59:46.969Z" }, - { url = "https://files.pythonhosted.org/packages/72/13/0a38ad385d547fb283e0e1fe1ff1dff8899bd4ed0aaceeb13ec14abbf136/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:b902e30a268a85d50197b4997edc6e78842c14c0703450f632c2d82f17577845", size = 1716693, upload-time = "2025-10-17T13:59:49.217Z" }, - { url = "https://files.pythonhosted.org/packages/55/65/7029d7573ab9009adde380052c6130d02c8db52195fda112db35e914fe7b/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1bbfc04c8de7def6504cce0a97f9885a5c805fd2395a0634bc10f9d6ecb42524", size = 1784174, upload-time = "2025-10-17T13:59:51.439Z" }, - { url = "https://files.pythonhosted.org/packages/2d/36/fd46e39cb85418e45b0e4a8bfc39651ee0b8f08ea006adf217a221cdb269/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:6941853405a38a5eeb7d9776db77698df373ff7fa8c765cb81ea14a344fccbeb", size = 1593716, upload-time = "2025-10-17T13:59:53.367Z" }, - { url = "https://files.pythonhosted.org/packages/85/b8/188e0cb1be37b4408373171070fda17c3bf9c67c0d3d4fd5ee5b1fa108e1/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:7764adcd2dc8bd21c8228a53dda2005428498dc4d165f41b6086f0ac1c65b1c9", size = 1799254, upload-time = "2025-10-17T13:59:55.352Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/fdf768764eb427b0cc9ebb2cebddf990f94d98b430679f8383c35aa114be/aiohttp-3.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c09e08d38586fa59e5a2f9626505a0326fadb8e9c45550f029feeb92097a0afc", size = 1738122, upload-time = "2025-10-17T13:59:57.263Z" }, - { url = "https://files.pythonhosted.org/packages/94/84/fce7a4d575943394d7c0e632273838eb6f39de8edf25386017bf5f0de23b/aiohttp-3.13.1-cp311-cp311-win32.whl", hash = "sha256:ce1371675e74f6cf271d0b5530defb44cce713fd0ab733713562b3a2b870815c", size = 430491, upload-time = "2025-10-17T13:59:59.466Z" }, - { url = "https://files.pythonhosted.org/packages/ac/d2/d21b8ab6315a5d588c550ab285b4f02ae363edf012920e597904c5a56608/aiohttp-3.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:77a2f5cc28cf4704cc157be135c6a6cfb38c9dea478004f1c0fd7449cf445c28", size = 454808, upload-time = "2025-10-17T14:00:01.247Z" }, - { url = "https://files.pythonhosted.org/packages/1a/72/d463a10bf29871f6e3f63bcf3c91362dc4d72ed5917a8271f96672c415ad/aiohttp-3.13.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0760bd9a28efe188d77b7c3fe666e6ef74320d0f5b105f2e931c7a7e884c8230", size = 736218, upload-time = "2025-10-17T14:00:03.51Z" }, - { url = "https://files.pythonhosted.org/packages/26/13/f7bccedbe52ea5a6eef1e4ebb686a8d7765319dfd0a5939f4238cb6e79e6/aiohttp-3.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7129a424b441c3fe018a414401bf1b9e1d49492445f5676a3aecf4f74f67fcdb", size = 491251, upload-time = "2025-10-17T14:00:05.756Z" }, - { url = "https://files.pythonhosted.org/packages/0c/7c/7ea51b5aed6cc69c873f62548da8345032aa3416336f2d26869d4d37b4a2/aiohttp-3.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e1cb04ae64a594f6ddf5cbb024aba6b4773895ab6ecbc579d60414f8115e9e26", size = 490394, upload-time = "2025-10-17T14:00:07.504Z" }, - { url = "https://files.pythonhosted.org/packages/31/05/1172cc4af4557f6522efdee6eb2b9f900e1e320a97e25dffd3c5a6af651b/aiohttp-3.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:782d656a641e755decd6bd98d61d2a8ea062fd45fd3ff8d4173605dd0d2b56a1", size = 1737455, upload-time = "2025-10-17T14:00:09.403Z" }, - { url = "https://files.pythonhosted.org/packages/24/3d/ce6e4eca42f797d6b1cd3053cf3b0a22032eef3e4d1e71b9e93c92a3f201/aiohttp-3.13.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f92ad8169767429a6d2237331726c03ccc5f245222f9373aa045510976af2b35", size = 1699176, upload-time = "2025-10-17T14:00:11.314Z" }, - { url = "https://files.pythonhosted.org/packages/25/04/7127ba55653e04da51477372566b16ae786ef854e06222a1c96b4ba6c8ef/aiohttp-3.13.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e778f634ca50ec005eefa2253856921c429581422d887be050f2c1c92e5ce12", size = 1767216, upload-time = "2025-10-17T14:00:13.668Z" }, - { url = "https://files.pythonhosted.org/packages/b8/3b/43bca1e75847e600f40df829a6b2f0f4e1d4c70fb6c4818fdc09a462afd5/aiohttp-3.13.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9bc36b41cf4aab5d3b34d22934a696ab83516603d1bc1f3e4ff9930fe7d245e5", size = 1865870, upload-time = "2025-10-17T14:00:15.852Z" }, - { url = "https://files.pythonhosted.org/packages/9e/69/b204e5d43384197a614c88c1717c324319f5b4e7d0a1b5118da583028d40/aiohttp-3.13.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3fd4570ea696aee27204dd524f287127ed0966d14d309dc8cc440f474e3e7dbd", size = 1751021, upload-time = "2025-10-17T14:00:18.297Z" }, - { url = "https://files.pythonhosted.org/packages/1c/af/845dc6b6fdf378791d720364bf5150f80d22c990f7e3a42331d93b337cc7/aiohttp-3.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7bda795f08b8a620836ebfb0926f7973972a4bf8c74fdf9145e489f88c416811", size = 1561448, upload-time = "2025-10-17T14:00:20.152Z" }, - { url = "https://files.pythonhosted.org/packages/7a/91/d2ab08cd77ed76a49e4106b1cfb60bce2768242dd0c4f9ec0cb01e2cbf94/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:055a51d90e351aae53dcf324d0eafb2abe5b576d3ea1ec03827d920cf81a1c15", size = 1698196, upload-time = "2025-10-17T14:00:22.131Z" }, - { url = "https://files.pythonhosted.org/packages/5e/d1/082f0620dc428ecb8f21c08a191a4694915cd50f14791c74a24d9161cc50/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d4131df864cbcc09bb16d3612a682af0db52f10736e71312574d90f16406a867", size = 1719252, upload-time = "2025-10-17T14:00:24.453Z" }, - { url = "https://files.pythonhosted.org/packages/fc/78/2af2f44491be7b08e43945b72d2b4fd76f0a14ba850ba9e41d28a7ce716a/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:163d3226e043f79bf47c87f8dfc89c496cc7bc9128cb7055ce026e435d551720", size = 1736529, upload-time = "2025-10-17T14:00:26.567Z" }, - { url = "https://files.pythonhosted.org/packages/b0/34/3e919ecdc93edaea8d140138049a0d9126141072e519535e2efa38eb7a02/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:a2370986a3b75c1a5f3d6f6d763fc6be4b430226577b0ed16a7c13a75bf43d8f", size = 1553723, upload-time = "2025-10-17T14:00:28.592Z" }, - { url = "https://files.pythonhosted.org/packages/21/4b/d8003aeda2f67f359b37e70a5a4b53fee336d8e89511ac307ff62aeefcdb/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d7c14de0c7c9f1e6e785ce6cbe0ed817282c2af0012e674f45b4e58c6d4ea030", size = 1763394, upload-time = "2025-10-17T14:00:31.051Z" }, - { url = "https://files.pythonhosted.org/packages/4c/7b/1dbe6a39e33af9baaafc3fc016a280663684af47ba9f0e5d44249c1f72ec/aiohttp-3.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb611489cf0db10b99beeb7280bd39e0ef72bc3eb6d8c0f0a16d8a56075d1eb7", size = 1718104, upload-time = "2025-10-17T14:00:33.407Z" }, - { url = "https://files.pythonhosted.org/packages/5c/88/bd1b38687257cce67681b9b0fa0b16437be03383fa1be4d1a45b168bef25/aiohttp-3.13.1-cp312-cp312-win32.whl", hash = "sha256:f90fe0ee75590f7428f7c8b5479389d985d83c949ea10f662ab928a5ed5cf5e6", size = 425303, upload-time = "2025-10-17T14:00:35.829Z" }, - { url = "https://files.pythonhosted.org/packages/0e/e3/4481f50dd6f27e9e58c19a60cff44029641640237e35d32b04aaee8cf95f/aiohttp-3.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:3461919a9dca272c183055f2aab8e6af0adc810a1b386cce28da11eb00c859d9", size = 452071, upload-time = "2025-10-17T14:00:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/35/74/b321e7d7ca762638cdf8cdeceb39755d9c745aff7a64c8789be96ddf6e96/aiohttp-3.13.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0", size = 743409, upload-time = "2025-10-28T20:56:00.354Z" }, + { url = "https://files.pythonhosted.org/packages/99/3d/91524b905ec473beaf35158d17f82ef5a38033e5809fe8742e3657cdbb97/aiohttp-3.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb", size = 497006, upload-time = "2025-10-28T20:56:01.85Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d3/7f68bc02a67716fe80f063e19adbd80a642e30682ce74071269e17d2dba1/aiohttp-3.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9", size = 493195, upload-time = "2025-10-28T20:56:03.314Z" }, + { url = "https://files.pythonhosted.org/packages/98/31/913f774a4708775433b7375c4f867d58ba58ead833af96c8af3621a0d243/aiohttp-3.13.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613", size = 1747759, upload-time = "2025-10-28T20:56:04.904Z" }, + { url = "https://files.pythonhosted.org/packages/e8/63/04efe156f4326f31c7c4a97144f82132c3bb21859b7bb84748d452ccc17c/aiohttp-3.13.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead", size = 1704456, upload-time = "2025-10-28T20:56:06.986Z" }, + { url = "https://files.pythonhosted.org/packages/8e/02/4e16154d8e0a9cf4ae76f692941fd52543bbb148f02f098ca73cab9b1c1b/aiohttp-3.13.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780", size = 1807572, upload-time = "2025-10-28T20:56:08.558Z" }, + { url = "https://files.pythonhosted.org/packages/34/58/b0583defb38689e7f06798f0285b1ffb3a6fb371f38363ce5fd772112724/aiohttp-3.13.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a", size = 1895954, upload-time = "2025-10-28T20:56:10.545Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/083907ee3437425b4e376aa58b2c915eb1a33703ec0dc30040f7ae3368c6/aiohttp-3.13.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592", size = 1747092, upload-time = "2025-10-28T20:56:12.118Z" }, + { url = "https://files.pythonhosted.org/packages/ac/61/98a47319b4e425cc134e05e5f3fc512bf9a04bf65aafd9fdcda5d57ec693/aiohttp-3.13.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab", size = 1606815, upload-time = "2025-10-28T20:56:14.191Z" }, + { url = "https://files.pythonhosted.org/packages/97/4b/e78b854d82f66bb974189135d31fce265dee0f5344f64dd0d345158a5973/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30", size = 1723789, upload-time = "2025-10-28T20:56:16.101Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fc/9d2ccc794fc9b9acd1379d625c3a8c64a45508b5091c546dea273a41929e/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40", size = 1718104, upload-time = "2025-10-28T20:56:17.655Z" }, + { url = "https://files.pythonhosted.org/packages/66/65/34564b8765ea5c7d79d23c9113135d1dd3609173da13084830f1507d56cf/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948", size = 1785584, upload-time = "2025-10-28T20:56:19.238Z" }, + { url = "https://files.pythonhosted.org/packages/30/be/f6a7a426e02fc82781afd62016417b3948e2207426d90a0e478790d1c8a4/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf", size = 1595126, upload-time = "2025-10-28T20:56:20.836Z" }, + { url = "https://files.pythonhosted.org/packages/e5/c7/8e22d5d28f94f67d2af496f14a83b3c155d915d1fe53d94b66d425ec5b42/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782", size = 1800665, upload-time = "2025-10-28T20:56:22.922Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/91133c8b68b1da9fc16555706aa7276fdf781ae2bb0876c838dd86b8116e/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8", size = 1739532, upload-time = "2025-10-28T20:56:25.924Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/3747644d26a998774b21a616016620293ddefa4d63af6286f389aedac844/aiohttp-3.13.2-cp311-cp311-win32.whl", hash = "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec", size = 431876, upload-time = "2025-10-28T20:56:27.524Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/688462108c1a00eb9f05765331c107f95ae86f6b197b865d29e930b7e462/aiohttp-3.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c", size = 456205, upload-time = "2025-10-28T20:56:29.062Z" }, + { url = "https://files.pythonhosted.org/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" }, + { url = "https://files.pythonhosted.org/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" }, + { url = "https://files.pythonhosted.org/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" }, + { url = "https://files.pythonhosted.org/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" }, + { url = "https://files.pythonhosted.org/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" }, + { url = "https://files.pythonhosted.org/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" }, + { url = "https://files.pythonhosted.org/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" }, + { url = "https://files.pythonhosted.org/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" }, + { url = "https://files.pythonhosted.org/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" }, + { url = "https://files.pythonhosted.org/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" }, + { url = "https://files.pythonhosted.org/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" }, ] [[package]] @@ -125,7 +125,7 @@ wheels = [ [[package]] name = "anthropic" -version = "0.71.0" +version = "0.72.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -137,9 +137,9 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/4f/70682b068d897841f43223df82d96ec1d617435a8b759c4a2d901a50158b/anthropic-0.71.0.tar.gz", hash = "sha256:eb8e6fa86d049061b3ef26eb4cbae0174ebbff21affa6de7b3098da857d8de6a", size = 489102, upload-time = "2025-10-16T15:54:40.08Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/07/61f3ca8e69c5dcdaec31b36b79a53ea21c5b4ca5e93c7df58c71f43bf8d8/anthropic-0.72.0.tar.gz", hash = "sha256:8971fe76dcffc644f74ac3883069beb1527641115ae0d6eb8fa21c1ce4082f7a", size = 493721, upload-time = "2025-10-28T19:13:01.755Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/77/073e8ac488f335aec7001952825275582fb8f433737e90f24eeef9d878f6/anthropic-0.71.0-py3-none-any.whl", hash = "sha256:85c5015fcdbdc728390f11b17642a65a4365d03b12b799b18b6cc57e71fdb327", size = 355035, upload-time = "2025-10-16T15:54:38.238Z" }, + { url = "https://files.pythonhosted.org/packages/7b/b7/160d4fb30080395b4143f1d1a4f6c646ba9105561108d2a434b606c03579/anthropic-0.72.0-py3-none-any.whl", hash = "sha256:0e9f5a7582f038cab8efbb4c959e49ef654a56bfc7ba2da51b5a7b8a84de2e4d", size = 357464, upload-time = "2025-10-28T19:13:00.215Z" }, ] [[package]] @@ -215,11 +215,11 @@ wheels = [ [[package]] name = "beartype" -version = "0.22.3" +version = "0.22.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/51/97f0d11d613d3b9650bd75588ff5206a408afcdc337ab7108dafb4c8d1ec/beartype-0.22.3.tar.gz", hash = "sha256:391c457bd6463d6fb0ec5d7e28ad44c336ae02dbaaae0fc55c053b071554855b", size = 1571548, upload-time = "2025-10-23T06:20:03.783Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/09/9003e5662691056e0e8b2e6f57c799e71875fac0be0e785d8cb11557cd2a/beartype-0.22.5.tar.gz", hash = "sha256:516a9096cc77103c96153474fa35c3ebcd9d36bd2ec8d0e3a43307ced0fa6341", size = 1586256, upload-time = "2025-11-01T05:49:20.771Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/03/1faffcbda0c872a299f0c54a5be91a738e2f6cee6ff8143c481fa51f1f0a/beartype-0.22.3-py3-none-any.whl", hash = "sha256:2f36eb8ea8d5eb693d2307639756c43db73c3d1153dbba62261d8c08dbe2946d", size = 1312115, upload-time = "2025-10-23T06:20:01.136Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f6/073d19f7b571c08327fbba3f8e011578da67ab62a11f98911274ff80653f/beartype-0.22.5-py3-none-any.whl", hash = "sha256:d9743dd7cd6d193696eaa1e025f8a70fb09761c154675679ff236e61952dfba0", size = 1321700, upload-time = "2025-11-01T05:49:18.436Z" }, ] [[package]] @@ -426,7 +426,7 @@ wheels = [ [[package]] name = "content-core" -version = "1.5.0" +version = "1.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ai-prompter" }, @@ -454,9 +454,9 @@ dependencies = [ { name = "validators" }, { name = "youtube-transcript-api" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dd/34/0802726b2bf8098b965460c5050bfbffc7a68ec22f2b0118e853dba3f6d2/content_core-1.5.0.tar.gz", hash = "sha256:24a527a1d5a3b9ab05d0d6fd51e1ba3e4e13a91a5b6c55017a4c6ecee56af4f1", size = 20619815, upload-time = "2025-10-14T10:59:43.095Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/81/33a16ff0f4caa227c0f9569cbd196baaf45a296e1d172d30cd3215eb91f2/content_core-1.7.0.tar.gz", hash = "sha256:e7954de3a7aa2718863d5ab7ba9c5b29617ed5193e3a792cb0a62bc30816dfa5", size = 20656892, upload-time = "2025-11-01T15:03:46.289Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/93/e4d227665640683f252ef4296865d31706762b968cf16ae46de20e7b2c0b/content_core-1.5.0-py3-none-any.whl", hash = "sha256:e41a41776a2ffff3394a6325d9518e9989af15f2af4d019415425167b44a8d26", size = 171346, upload-time = "2025-10-14T10:59:40.493Z" }, + { url = "https://files.pythonhosted.org/packages/d8/9c/857c0fb5798d8e45f17249fc1513c197a8fd2f6d9a0b537aa176fffdf700/content_core-1.7.0-py3-none-any.whl", hash = "sha256:b51991a6498483b6e5f47cdcad36af19d5cffa770ff140ff773f0c9e886b7129", size = 173198, upload-time = "2025-11-01T15:03:43.084Z" }, ] [[package]] @@ -517,7 +517,7 @@ wheels = [ [[package]] name = "cyclopts" -version = "4.0.0" +version = "4.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -525,9 +525,9 @@ dependencies = [ { name = "rich" }, { name = "rich-rst" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/d1/2f2b99ec5ea54ac18baadfc4a011e2a1743c1eaae1e39838ca520dcf4811/cyclopts-4.0.0.tar.gz", hash = "sha256:0dae712085e91d32cc099ea3d78f305b0100a3998b1dec693be9feb0b1be101f", size = 143546, upload-time = "2025-10-20T18:33:01.456Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/51/a67b17fac2530d22216a335bd10f48631412dd824013ea559ec236668f76/cyclopts-4.2.1.tar.gz", hash = "sha256:49bb4c35644e7a9658f706ade4cf1a9958834b2dca4425e2fafecf8a0537fac7", size = 148693, upload-time = "2025-10-31T14:30:58.681Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/0e/0a22e076944600aeb06f40b7e03bbd762a42d56d43a2f5f4ab954aed9005/cyclopts-4.0.0-py3-none-any.whl", hash = "sha256:e64801a2c86b681f08323fd50110444ee961236a0bae402a66d2cc3feda33da7", size = 178837, upload-time = "2025-10-20T18:33:00.191Z" }, + { url = "https://files.pythonhosted.org/packages/4d/1d/2b313e157c9c7bba319e42f464d15073d32a81ac4827bdc5b7de38832b3e/cyclopts-4.2.1-py3-none-any.whl", hash = "sha256:17a801faa814988b0307385ef8aaeb6b14b4d64473015a2d66bde9ea13f14d9c", size = 184333, upload-time = "2025-10-31T14:30:57.581Z" }, ] [[package]] @@ -656,15 +656,15 @@ wheels = [ [[package]] name = "esperanto" -version = "2.7.1" +version = "2.8.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/54/8c/a2a9c1e7428d700963e7450aba591b2f4fbcfa61bad88654af8d92df3a00/esperanto-2.7.1.tar.gz", hash = "sha256:a18abc38d30d38c496eac62f252a9c12d243fc49fef7cc92d9d23c5b5faee741", size = 554840, upload-time = "2025-10-19T02:30:45.251Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/d8/1504c1d615be245b78fd440c1908a3b2237dbb54fddd75795ac1fa707316/esperanto-2.8.2.tar.gz", hash = "sha256:b4316eff0e01cffa8ace1c3c5a73fddecfe0118ffac1bd1a76c391cb1adbc718", size = 734199, upload-time = "2025-11-01T13:53:37.625Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/91/a2c43a4eb3c56f349d59c656783cdd8cd13149a8e521e75f77e84dcd5ac0/esperanto-2.7.1-py3-none-any.whl", hash = "sha256:ea81e531085e32828b2ecd02680088801222dd21e7a73012efdb9b68fa627ed4", size = 129593, upload-time = "2025-10-19T02:30:44.149Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f3/8e08a16274734afd8e7d988dc8ca9637a14e8857a3a0b20673a3640ed3b4/esperanto-2.8.2-py3-none-any.whl", hash = "sha256:83cc351a67003718c51b92d1f6e1417f81c6a0a007dba513fbce46905925e2c4", size = 144045, upload-time = "2025-11-01T13:53:35.896Z" }, ] [[package]] @@ -699,7 +699,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.120.0" +version = "0.120.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -707,22 +707,22 @@ dependencies = [ { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f7/0e/7f29e8f7219e4526747db182e1afb5a4b6abc3201768fb38d81fa2536241/fastapi-0.120.0.tar.gz", hash = "sha256:6ce2c1cfb7000ac14ffd8ddb2bc12e62d023a36c20ec3710d09d8e36fab177a0", size = 337603, upload-time = "2025-10-23T20:56:34.743Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/3a/0bf90d5189d7f62dc2bd0523899629ca59b58ff4290d631cd3bb5c8889d4/fastapi-0.120.4.tar.gz", hash = "sha256:2d856bc847893ca4d77896d4504ffdec0fb04312b705065fca9104428eca3868", size = 339716, upload-time = "2025-10-31T18:37:28.81Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/60/7a639ceaba54aec4e1d5676498c568abc654b95762d456095b6cb529b1ca/fastapi-0.120.0-py3-none-any.whl", hash = "sha256:84009182e530c47648da2f07eb380b44b69889a4acfd9e9035ee4605c5cfc469", size = 108243, upload-time = "2025-10-23T20:56:33.281Z" }, + { url = "https://files.pythonhosted.org/packages/ed/47/14a76b926edc3957c8a8258423db789d3fa925d2fed800102fce58959413/fastapi-0.120.4-py3-none-any.whl", hash = "sha256:9bdf192308676480d3593e10fd05094e56d6fdc7d9283db26053d8104d5f82a0", size = 108235, upload-time = "2025-10-31T18:37:27.038Z" }, ] [[package]] name = "fastmcp" -version = "2.13.0" +version = "2.13.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, { name = "cyclopts" }, { name = "exceptiongroup" }, { name = "httpx" }, + { name = "jsonschema-path" }, { name = "mcp" }, - { name = "openapi-core" }, { name = "openapi-pydantic" }, { name = "platformdirs" }, { name = "py-key-value-aio", extra = ["disk", "keyring", "memory"] }, @@ -732,9 +732,9 @@ dependencies = [ { name = "rich" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bc/3b/c30af894db2c3ec439d0e4168ba7ce705474cabdd0a599033ad9a19ad977/fastmcp-2.13.0.tar.gz", hash = "sha256:57f7b7503363e1babc0d1a13af18252b80366a409e1de85f1256cce66a4bee35", size = 7767346, upload-time = "2025-10-25T12:54:10.957Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/74/584a152bcd174c99ddf3cfdd7e86ec4a6c696fb190a907c2a2ec9056bda2/fastmcp-2.13.0.2.tar.gz", hash = "sha256:d35386561b6f3cde195ba2b5892dc89b8919a721e6b39b98e7a16f9a7c0b8e8b", size = 7762083, upload-time = "2025-10-28T13:56:21.702Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/7f/09942135f506953fc61bb81b9e5eaf50a8eea923b83d9135bd959168ef2d/fastmcp-2.13.0-py3-none-any.whl", hash = "sha256:bdff1399d3b7ebb79286edfd43eb660182432514a5ab8e4cbfb45f1d841d2aa0", size = 367134, upload-time = "2025-10-25T12:54:09.284Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c6/95eacd687cfab64fec13bfb64e6c6e7da13d01ecd4cb7d7e991858a08119/fastmcp-2.13.0.2-py3-none-any.whl", hash = "sha256:eb381eb073a101aabbc0ac44b05e23fef0cd1619344b7703115c825c8755fa1c", size = 367511, upload-time = "2025-10-28T13:56:18.83Z" }, ] [[package]] @@ -816,11 +816,11 @@ wheels = [ [[package]] name = "fsspec" -version = "2025.9.0" +version = "2025.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/e0/bab50af11c2d75c9c4a2a26a5254573c0bd97cea152254401510950486fa/fsspec-2025.9.0.tar.gz", hash = "sha256:19fd429483d25d28b65ec68f9f4adc16c17ea2c7c7bf54ec61360d478fb19c19", size = 304847, upload-time = "2025-09-02T19:10:49.215Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/7f/2747c0d332b9acfa75dc84447a066fdf812b5a6b8d30472b74d309bfe8cb/fsspec-2025.10.0.tar.gz", hash = "sha256:b6789427626f068f9a83ca4e8a3cc050850b6c0f71f99ddb4f542b8266a26a59", size = 309285, upload-time = "2025-10-30T14:58:44.036Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" }, + { url = "https://files.pythonhosted.org/packages/eb/02/a6b21098b1d5d6249b7c5ab69dde30108a71e4e819d4a9778f1de1d5b70d/fsspec-2025.10.0-py3-none-any.whl", hash = "sha256:7c7712353ae7d875407f97715f0e1ffcc21e33d5b24556cb1e090ae9409ec61d", size = 200966, upload-time = "2025-10-30T14:58:42.53Z" }, ] [[package]] @@ -841,7 +841,7 @@ wheels = [ [[package]] name = "google-api-core" -version = "2.27.0" +version = "2.28.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-auth" }, @@ -850,9 +850,9 @@ dependencies = [ { name = "protobuf" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/99/6c8b44ecc28026fd9441d7fcc5434ee1b3976c491f2f810b464c4702c975/google_api_core-2.27.0.tar.gz", hash = "sha256:d32e2f5dd0517e91037169e75bf0a9783b255aff1d11730517c0b2b29e9db06a", size = 168851, upload-time = "2025-10-22T23:54:14.195Z" } +sdist = { url = "https://files.pythonhosted.org/packages/61/da/83d7043169ac2c8c7469f0e375610d78ae2160134bf1b80634c482fa079c/google_api_core-2.28.1.tar.gz", hash = "sha256:2b405df02d68e68ce0fbc138559e6036559e685159d148ae5861013dc201baf8", size = 176759, upload-time = "2025-10-28T21:34:51.529Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/93/ecf9f7caa99c71e969091e9a78789f11b2dea5c684917eab7c54a8d13560/google_api_core-2.27.0-py3-none-any.whl", hash = "sha256:779a380db4e21a4ee3d717cf8efbf324e53900bf37e1ffb273e5348a9916dd42", size = 167110, upload-time = "2025-10-22T23:54:12.805Z" }, + { url = "https://files.pythonhosted.org/packages/ed/d4/90197b416cb61cefd316964fd9e7bd8324bcbafabf40eef14a9f20b81974/google_api_core-2.28.1-py3-none-any.whl", hash = "sha256:4021b0f8ceb77a6fb4de6fde4502cecab45062e66ff4f2895169e0b35bc9466c", size = 173706, upload-time = "2025-10-28T21:34:50.151Z" }, ] [package.optional-dependencies] @@ -863,21 +863,21 @@ grpc = [ [[package]] name = "google-auth" -version = "2.41.1" +version = "2.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cachetools" }, { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/af/5129ce5b2f9688d2fa49b463e544972a7c82b0fdb50980dafee92e121d9f/google_auth-2.41.1.tar.gz", hash = "sha256:b76b7b1f9e61f0cb7e88870d14f6a94aeef248959ef6992670efee37709cbfd2", size = 292284, upload-time = "2025-09-30T22:51:26.363Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/6b/22a77135757c3a7854c9f008ffed6bf4e8851616d77faf13147e9ab5aae6/google_auth-2.42.1.tar.gz", hash = "sha256:30178b7a21aa50bffbdc1ffcb34ff770a2f65c712170ecd5446c4bef4dc2b94e", size = 295541, upload-time = "2025-10-30T16:42:19.381Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/a4/7319a2a8add4cc352be9e3efeff5e2aacee917c85ca2fa1647e29089983c/google_auth-2.41.1-py2.py3-none-any.whl", hash = "sha256:754843be95575b9a19c604a848a41be03f7f2afd8c019f716dc1f51ee41c639d", size = 221302, upload-time = "2025-09-30T22:51:24.212Z" }, + { url = "https://files.pythonhosted.org/packages/92/05/adeb6c495aec4f9d93f9e2fc29eeef6e14d452bba11d15bdb874ce1d5b10/google_auth-2.42.1-py2.py3-none-any.whl", hash = "sha256:eb73d71c91fc95dbd221a2eb87477c278a355e7367a35c0d84e6b0e5f9b4ad11", size = 222550, upload-time = "2025-10-30T16:42:17.878Z" }, ] [[package]] name = "google-cloud-aiplatform" -version = "1.122.0" +version = "1.124.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docstring-parser" }, @@ -894,9 +894,9 @@ dependencies = [ { name = "shapely" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/49/98fc0ee254f8d3ca199e87de2ce2734cfe1da27b6852b753e438d3db771b/google_cloud_aiplatform-1.122.0.tar.gz", hash = "sha256:949361abdf4ba60911661ac3acb5a139e9b97b603d83aac1d4932dcdaba0a748", size = 9730613, upload-time = "2025-10-22T00:31:30.994Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ad/a3da0cbb78a933544ef2ca3db3da242a2217a52d823beb3ea129995c00df/google_cloud_aiplatform-1.124.0.tar.gz", hash = "sha256:cf565f2ce3dac19c6502a65d89c89760000fde1d531be54949c6232ba2a168fd", size = 9755170, upload-time = "2025-10-30T19:59:22.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/0a/6ad76f2fcc7ed7049729f9cabf3c46f2143e2a8dd69bfbf1daf853a2559b/google_cloud_aiplatform-1.122.0-py2.py3-none-any.whl", hash = "sha256:389bc24c5f710b7c58df2b95f598ef7c6e90c116608484a171f4da03bf6ea249", size = 8084071, upload-time = "2025-10-22T00:31:28.167Z" }, + { url = "https://files.pythonhosted.org/packages/c5/46/c20db72a9389c5b6595c2c3fed9abe2b05d3658fe2c07657f7324623cb63/google_cloud_aiplatform-1.124.0-py2.py3-none-any.whl", hash = "sha256:047685f0ee0ab7346ba7d437904357077e3362b32a951c5038a9ac789c5f9148", size = 8112493, upload-time = "2025-10-30T19:59:19.42Z" }, ] [[package]] @@ -919,15 +919,15 @@ wheels = [ [[package]] name = "google-cloud-core" -version = "2.4.3" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "google-api-core" }, { name = "google-auth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d6/b8/2b53838d2acd6ec6168fd284a990c76695e84c65deee79c9f3a4276f6b4f/google_cloud_core-2.4.3.tar.gz", hash = "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", size = 35861, upload-time = "2025-03-10T21:05:38.948Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/03/ef0bc99d0e0faf4fdbe67ac445e18cdaa74824fd93cd069e7bb6548cb52d/google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963", size = 36027, upload-time = "2025-10-29T23:17:39.513Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/86/bda7241a8da2d28a754aad2ba0f6776e35b67e37c36ae0c45d49370f1014/google_cloud_core-2.4.3-py2.py3-none-any.whl", hash = "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e", size = 29348, upload-time = "2025-03-10T21:05:37.785Z" }, + { url = "https://files.pythonhosted.org/packages/89/20/bfa472e327c8edee00f04beecc80baeddd2ab33ee0e86fd7654da49d45e9/google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", size = 29469, upload-time = "2025-10-29T23:17:38.548Z" }, ] [[package]] @@ -986,7 +986,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.46.0" +version = "1.47.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -998,9 +998,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c7/2d/d5907af6a46fb0b660291a09bb62f9cbc1365899f7d64a74e7d8d2e056c2/google_genai-1.46.0.tar.gz", hash = "sha256:6824c31149fe3b1c7285b25f79b924c5f89fd52466f62e30f76954f8104fe3a7", size = 239561, upload-time = "2025-10-21T22:55:04.241Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/97/784fba9bc6c41263ff90cb9063eadfdd755dde79cfa5a8d0e397b067dcf9/google_genai-1.47.0.tar.gz", hash = "sha256:ecece00d0a04e6739ea76cc8dad82ec9593d9380aaabef078990e60574e5bf59", size = 241471, upload-time = "2025-10-29T22:01:02.88Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/79/8993ec6cbf56e5c8f88c165380e55de34ec74f7b928bc302ff5c370f9c4e/google_genai-1.46.0-py3-none-any.whl", hash = "sha256:879c4a260d630db0dcedb5cc84a9d7b47acd29e43e9dc63541b511b757ea7296", size = 239445, upload-time = "2025-10-21T22:55:03.072Z" }, + { url = "https://files.pythonhosted.org/packages/89/ef/e080e8d67c270ea320956bb911a9359664fc46d3b87d1f029decd33e5c4c/google_genai-1.47.0-py3-none-any.whl", hash = "sha256:e3851237556cbdec96007d8028b4b1f2425cdc5c099a8dc36b72a57e42821b60", size = 241506, upload-time = "2025-10-29T22:01:00.982Z" }, ] [[package]] @@ -1202,21 +1202,23 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "0.36.0" +version = "1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "fsspec" }, - { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "httpx" }, { name = "packaging" }, { name = "pyyaml" }, - { name = "requests" }, + { name = "shellingham" }, { name = "tqdm" }, + { name = "typer-slim" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/98/63/4910c5fa9128fdadf6a9c5ac138e8b1b6cee4ca44bf7915bbfbce4e355ee/huggingface_hub-0.36.0.tar.gz", hash = "sha256:47b3f0e2539c39bf5cde015d63b72ec49baff67b6931c3d97f3f84532e2b8d25", size = 463358, upload-time = "2025-10-23T12:12:01.413Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/e0/308849e8ff9590505815f4a300cb8941a21c5889fb94c955d992539b5bef/huggingface_hub-1.0.1.tar.gz", hash = "sha256:87b506d5b45f0d1af58df7cf8bab993ded25d6077c2e959af58444df8b9589f3", size = 419291, upload-time = "2025-10-28T12:48:43.526Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/bd/1a875e0d592d447cbc02805fd3fe0f497714d6a2583f59d14fa9ebad96eb/huggingface_hub-0.36.0-py3-none-any.whl", hash = "sha256:7bcc9ad17d5b3f07b57c78e79d527102d08313caa278a641993acddcb894548d", size = 566094, upload-time = "2025-10-23T12:11:59.557Z" }, + { url = "https://files.pythonhosted.org/packages/db/fb/d71f914bc69e6357cbde04db62ef15497cd27926d95f03b4930997c4c390/huggingface_hub-1.0.1-py3-none-any.whl", hash = "sha256:7e255cd9b3432287a34a86933057abb1b341d20b97fb01c40cbd4e053764ae13", size = 503841, upload-time = "2025-10-28T12:48:41.821Z" }, ] [[package]] @@ -1296,7 +1298,7 @@ wheels = [ [[package]] name = "ipykernel" -version = "7.0.1" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "appnope", marker = "sys_platform == 'darwin'" }, @@ -1313,9 +1315,9 @@ dependencies = [ { name = "tornado" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/4c/9f0024c8457286c6bfd5405a15d650ec5ea36f420ef9bbc58b301f66cfc5/ipykernel-7.0.1.tar.gz", hash = "sha256:2d3fd7cdef22071c2abbad78f142b743228c5d59cd470d034871ae0ac359533c", size = 171460, upload-time = "2025-10-14T16:17:07.325Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/a4/4948be6eb88628505b83a1f2f40d90254cab66abf2043b3c40fa07dfce0f/ipykernel-7.1.0.tar.gz", hash = "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db", size = 174579, upload-time = "2025-10-27T09:46:39.471Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/f7/761037905ffdec673533bfa43af8d4c31c859c778dfc3bbb71899875ec18/ipykernel-7.0.1-py3-none-any.whl", hash = "sha256:87182a8305e28954b6721087dec45b171712610111d494c17bb607befa1c4000", size = 118157, upload-time = "2025-10-14T16:17:05.606Z" }, + { url = "https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl", hash = "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c", size = 117968, upload-time = "2025-10-27T09:46:37.805Z" }, ] [[package]] @@ -1368,15 +1370,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl", hash = "sha256:764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb", size = 139806, upload-time = "2025-05-05T12:41:56.833Z" }, ] -[[package]] -name = "isodate" -version = "0.7.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705, upload-time = "2024-10-08T23:04:11.5Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" }, -] - [[package]] name = "jaraco-classes" version = "3.4.0" @@ -1609,30 +1602,30 @@ wheels = [ [[package]] name = "langchain" -version = "1.0.2" +version = "1.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/d6/bdf9ea27a92ed4685497c2659b5c7f703ba63bac4bd92351ca09bab3b924/langchain-1.0.2.tar.gz", hash = "sha256:22f814c7b4f5f76e945c35924ff288f6dfbe33747db2a029162ef1d4f8566493", size = 473869, upload-time = "2025-10-21T21:08:26.44Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/08/1708495e03eadbeef5d51e6b7cdcae4752a113a9b6313f46c70e165149c4/langchain-1.0.3.tar.gz", hash = "sha256:f96d8d185cb8cbba9793f5c648e7d5eeec688f8e3778f700d75d89d6570ae11e", size = 444810, upload-time = "2025-10-29T23:15:10.74Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/06/0e03587da37173c29a58bf17312793c2453df9ca2912e9adfe869c120437/langchain-1.0.2-py3-none-any.whl", hash = "sha256:e0c5647ea47cde7feb9534f56f4496c7f86a45084ad9bd152e7b19739f210ead", size = 107831, upload-time = "2025-10-21T21:08:25.009Z" }, + { url = "https://files.pythonhosted.org/packages/68/c8/b5dcfdde8b96369e5445f0fbac52fe8495bbd11b23ca83691d90d464eb15/langchain-1.0.3-py3-none-any.whl", hash = "sha256:a7d57964ed16278c991de4ab15516a81937a58c5ac7d7aadccb18431ad8179b2", size = 91970, upload-time = "2025-10-29T23:15:09.198Z" }, ] [[package]] name = "langchain-anthropic" -version = "1.0.0" +version = "1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anthropic" }, { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/65/89ea83fe8e89381d31e8137b294f1858dea27f82c535553928783f8e669c/langchain_anthropic-1.0.0.tar.gz", hash = "sha256:a4f1168d119fb620f9c36e3db5c9fe632d1a0daee026d1c99234820cea714f32", size = 700946, upload-time = "2025-10-17T14:07:20.021Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/12/f622dccb2886a9a016e149b74df2a2d9f7f6d6fafee087a010aa7415227e/langchain_anthropic-1.0.1.tar.gz", hash = "sha256:cd4c2f5d5d85d3aba290ea7b9976371d3e25fd58f6d70cfd0ef3323787862edc", size = 667647, upload-time = "2025-10-30T20:22:58.585Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/59/96b4edcca672875af4e60c3cafc2b6bbd6e9656a965dfb3543c758c0fbce/langchain_anthropic-1.0.0-py3-none-any.whl", hash = "sha256:455094c91d5c1d573830d023c964e1f2f8232e9c6c95df20468c8f9dc4ff9a50", size = 46403, upload-time = "2025-10-17T14:07:19.04Z" }, + { url = "https://files.pythonhosted.org/packages/46/2c/2dcbf58526fa59b5464f79b5369a3abd81460ad3b737399cc3fd55bfb0cb/langchain_anthropic-1.0.1-py3-none-any.whl", hash = "sha256:a883f1030c50c2422a57985c0a89b1f49e9e0abe3117d212e510e3b838df7417", size = 46421, upload-time = "2025-10-30T20:22:57.198Z" }, ] [[package]] @@ -1655,7 +1648,7 @@ wheels = [ [[package]] name = "langchain-community" -version = "0.4" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -1671,14 +1664,14 @@ dependencies = [ { name = "sqlalchemy" }, { name = "tenacity" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/30/be/07ad676e0e8c2afa96584ee5624967fa08f64efd04930cbb5d48eba6d693/langchain_community-0.4.tar.gz", hash = "sha256:11ff08c3d923641cecbe17379cfeeb1258eed1b51bbf1784362d69bb5fe38bf2", size = 33242918, upload-time = "2025-10-17T19:05:40.878Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/97/a03585d42b9bdb6fbd935282d6e3348b10322a24e6ce12d0c99eb461d9af/langchain_community-0.4.1.tar.gz", hash = "sha256:f3b211832728ee89f169ddce8579b80a085222ddb4f4ed445a46e977d17b1e85", size = 33241144, upload-time = "2025-10-27T15:20:32.504Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/5e/8101e972895ba2732d1a59ba93da47aa394f02455f018d339fb94f45b08c/langchain_community-0.4-py3-none-any.whl", hash = "sha256:79034e7bd4ba3a67ae9d7dd7fcef63ef4ed44673480fea0405ab45295985d56d", size = 2533111, upload-time = "2025-10-17T19:05:38.61Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a4/c4fde67f193401512337456cabc2148f2c43316e445f5decd9f8806e2992/langchain_community-0.4.1-py3-none-any.whl", hash = "sha256:2135abb2c7748a35c84613108f7ebf30f8505b18c3c18305ffaecfc7651f6c6a", size = 2533285, upload-time = "2025-10-27T15:20:30.767Z" }, ] [[package]] name = "langchain-core" -version = "1.0.1" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -1689,9 +1682,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/37/1bc4badb93eaa32406a7afdef011336b21719d21ce5ecebf35409a524f8c/langchain_core-1.0.1.tar.gz", hash = "sha256:d769e8d25854466abb672a721143a01bea11cc6ee2d7dae776aa092556db0a26", size = 764566, upload-time = "2025-10-24T16:39:35.495Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/96/b298cb46643bb235240de7ec8d87d3b4ccefead6bf41ca3c48c7d5397e01/langchain_core-1.0.2.tar.gz", hash = "sha256:9aae1908cc00d50b88e812305e980e7fd06d07375590ce8da01c04037bdccd72", size = 769167, upload-time = "2025-10-29T23:13:02.732Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/54/3cdbe9d151d06cd689b5aa937ac11403b64bbfe76486fda6431a24061721/langchain_core-1.0.1-py3-none-any.whl", hash = "sha256:c7ce58fc487359c44166e255cc0009ef30290da0b6307b75091152847919661e", size = 467122, upload-time = "2025-10-24T16:39:33.788Z" }, + { url = "https://files.pythonhosted.org/packages/52/54/3aed89938a42cf7115575c333647551e35adc380feed651105d2d86c22f5/langchain_core-1.0.2-py3-none-any.whl", hash = "sha256:1f4ab4a41fc2e135e5dd4b97a89af123bbdc535af8f1f0644e8e8801bc288a12", size = 469251, upload-time = "2025-10-29T23:13:00.864Z" }, ] [[package]] @@ -1822,7 +1815,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/0e/72/a3add0e4eec4eb9e2 [[package]] name = "langgraph" -version = "1.0.1" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -1832,9 +1825,9 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/20/7c/a0f4211f751b8b37aae2d88c6243ceb14027ca9ebf00ac8f3b210657af6a/langgraph-1.0.1.tar.gz", hash = "sha256:4985b32ceabb046a802621660836355dfcf2402c5876675dc353db684aa8f563", size = 480245, upload-time = "2025-10-20T18:51:59.839Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/25/18e6e056ee1a8af64fcab441b4a3f2e158399935b08f148c7718fc42ecdb/langgraph-1.0.2.tar.gz", hash = "sha256:dae1af08d6025cb1fcaed68f502c01af7d634d9044787c853a46c791cfc52f67", size = 482660, upload-time = "2025-10-29T18:38:28.374Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/3c/acc0956a0da96b25a2c5c1a85168eacf1253639a04ed391d7a7bcaae5d6c/langgraph-1.0.1-py3-none-any.whl", hash = "sha256:892f04f64f4889abc80140265cc6bd57823dd8e327a5eef4968875f2cd9013bd", size = 155415, upload-time = "2025-10-20T18:51:58.321Z" }, + { url = "https://files.pythonhosted.org/packages/d7/b1/9f4912e13d4ed691f2685c8a4b764b5a9237a30cca0c5782bc213d9f0a9a/langgraph-1.0.2-py3-none-any.whl", hash = "sha256:b3d56b8c01de857b5fb1da107e8eab6e30512a377685eeedb4f76456724c9729", size = 156751, upload-time = "2025-10-29T18:38:26.577Z" }, ] [[package]] @@ -1866,15 +1859,15 @@ wheels = [ [[package]] name = "langgraph-prebuilt" -version = "1.0.1" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/b6/2bcb992acf67713a3557e51c1955854672ec6c1abe6ba51173a87eb8d825/langgraph_prebuilt-1.0.1.tar.gz", hash = "sha256:ecbfb9024d9d7ed9652dde24eef894650aaab96bf79228e862c503e2a060b469", size = 119918, upload-time = "2025-10-20T18:49:55.991Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/2f/b940590436e07b3450fe6d791aad5e581363ad536c4f1771e3ba46530268/langgraph_prebuilt-1.0.2.tar.gz", hash = "sha256:9896dbabf04f086eb59df4294f54ab5bdb21cd78e27e0a10e695dffd1cc6097d", size = 142075, upload-time = "2025-10-29T18:29:00.401Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/47/9ffd10882403020ea866e381de7f8e504a78f606a914af7f8244456c7783/langgraph_prebuilt-1.0.1-py3-none-any.whl", hash = "sha256:8c02e023538f7ef6ad5ed76219ba1ab4f6de0e31b749e4d278f57a8a95eec9f7", size = 28458, upload-time = "2025-10-20T18:49:54.723Z" }, + { url = "https://files.pythonhosted.org/packages/27/2f/9a7d00d4afa036e65294059c7c912002fb72ba5dbbd5c2a871ca06360278/langgraph_prebuilt-1.0.2-py3-none-any.whl", hash = "sha256:d9499f7c449fb637ee7b87e3f6a3b74095f4202053c74d33894bd839ea4c57c7", size = 34286, upload-time = "2025-10-29T18:28:59.26Z" }, ] [[package]] @@ -1892,7 +1885,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.4.38" +version = "0.4.39" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -1903,30 +1896,9 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/21/f1ba48412c64bf3bb8feb532fc9d247b396935b5d8242332d44a4195ec2d/langsmith-0.4.38.tar.gz", hash = "sha256:3aa57f9c16a5880256cd1eab0452533c1fb5ee14ec5250e23ed919cc2b07f6d3", size = 942789, upload-time = "2025-10-23T22:28:20.458Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/67/cf7c22d2744286f872aacee2ac13928c46e2ba5d486514d60cd4ab59f58d/langsmith-0.4.39.tar.gz", hash = "sha256:8f2e6bae5cba88f86d8df2a4f95b20a319c65e9945be639302876ab6ef2f13e0", size = 943095, upload-time = "2025-11-01T00:06:18.59Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/2b/7e0248f65e35800ea8e4e3dbb3bcc36c61b81f5b8abeddaceec8320ab491/langsmith-0.4.38-py3-none-any.whl", hash = "sha256:326232a24b1c6dd308a3188557cc023adf8fb14144263b2982c115a6be5141e7", size = 397341, upload-time = "2025-10-23T22:28:18.333Z" }, -] - -[[package]] -name = "lazy-object-proxy" -version = "1.12.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/a2/69df9c6ba6d316cfd81fe2381e464db3e6de5db45f8c43c6a23504abf8cb/lazy_object_proxy-1.12.0.tar.gz", hash = "sha256:1f5a462d92fd0cfb82f1fab28b51bfb209fabbe6aabf7f0d51472c0c124c0c61", size = 43681, upload-time = "2025-08-22T13:50:06.783Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/01/b3/4684b1e128a87821e485f5a901b179790e6b5bc02f89b7ee19c23be36ef3/lazy_object_proxy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1cf69cd1a6c7fe2dbcc3edaa017cf010f4192e53796538cc7d5e1fedbfa4bcff", size = 26656, upload-time = "2025-08-22T13:42:30.605Z" }, - { url = "https://files.pythonhosted.org/packages/3a/03/1bdc21d9a6df9ff72d70b2ff17d8609321bea4b0d3cffd2cea92fb2ef738/lazy_object_proxy-1.12.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efff4375a8c52f55a145dc8487a2108c2140f0bec4151ab4e1843e52eb9987ad", size = 68832, upload-time = "2025-08-22T13:42:31.675Z" }, - { url = "https://files.pythonhosted.org/packages/3d/4b/5788e5e8bd01d19af71e50077ab020bc5cce67e935066cd65e1215a09ff9/lazy_object_proxy-1.12.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1192e8c2f1031a6ff453ee40213afa01ba765b3dc861302cd91dbdb2e2660b00", size = 69148, upload-time = "2025-08-22T13:42:32.876Z" }, - { url = "https://files.pythonhosted.org/packages/79/0e/090bf070f7a0de44c61659cb7f74c2fe02309a77ca8c4b43adfe0b695f66/lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3605b632e82a1cbc32a1e5034278a64db555b3496e0795723ee697006b980508", size = 67800, upload-time = "2025-08-22T13:42:34.054Z" }, - { url = "https://files.pythonhosted.org/packages/cf/d2/b320325adbb2d119156f7c506a5fbfa37fcab15c26d13cf789a90a6de04e/lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a61095f5d9d1a743e1e20ec6d6db6c2ca511961777257ebd9b288951b23b44fa", size = 68085, upload-time = "2025-08-22T13:42:35.197Z" }, - { url = "https://files.pythonhosted.org/packages/6a/48/4b718c937004bf71cd82af3713874656bcb8d0cc78600bf33bb9619adc6c/lazy_object_proxy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:997b1d6e10ecc6fb6fe0f2c959791ae59599f41da61d652f6c903d1ee58b7370", size = 26535, upload-time = "2025-08-22T13:42:36.521Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1b/b5f5bd6bda26f1e15cd3232b223892e4498e34ec70a7f4f11c401ac969f1/lazy_object_proxy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ee0d6027b760a11cc18281e702c0309dd92da458a74b4c15025d7fc490deede", size = 26746, upload-time = "2025-08-22T13:42:37.572Z" }, - { url = "https://files.pythonhosted.org/packages/55/64/314889b618075c2bfc19293ffa9153ce880ac6153aacfd0a52fcabf21a66/lazy_object_proxy-1.12.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4ab2c584e3cc8be0dfca422e05ad30a9abe3555ce63e9ab7a559f62f8dbc6ff9", size = 71457, upload-time = "2025-08-22T13:42:38.743Z" }, - { url = "https://files.pythonhosted.org/packages/11/53/857fc2827fc1e13fbdfc0ba2629a7d2579645a06192d5461809540b78913/lazy_object_proxy-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14e348185adbd03ec17d051e169ec45686dcd840a3779c9d4c10aabe2ca6e1c0", size = 71036, upload-time = "2025-08-22T13:42:40.184Z" }, - { url = "https://files.pythonhosted.org/packages/2b/24/e581ffed864cd33c1b445b5763d617448ebb880f48675fc9de0471a95cbc/lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4fcbe74fb85df8ba7825fa05eddca764138da752904b378f0ae5ab33a36c308", size = 69329, upload-time = "2025-08-22T13:42:41.311Z" }, - { url = "https://files.pythonhosted.org/packages/78/be/15f8f5a0b0b2e668e756a152257d26370132c97f2f1943329b08f057eff0/lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:563d2ec8e4d4b68ee7848c5ab4d6057a6d703cb7963b342968bb8758dda33a23", size = 70690, upload-time = "2025-08-22T13:42:42.51Z" }, - { url = "https://files.pythonhosted.org/packages/5d/aa/f02be9bbfb270e13ee608c2b28b8771f20a5f64356c6d9317b20043c6129/lazy_object_proxy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:53c7fd99eb156bbb82cbc5d5188891d8fdd805ba6c1e3b92b90092da2a837073", size = 26563, upload-time = "2025-08-22T13:42:43.685Z" }, - { url = "https://files.pythonhosted.org/packages/41/a0/b91504515c1f9a299fc157967ffbd2f0321bce0516a3d5b89f6f4cad0355/lazy_object_proxy-1.12.0-pp39.pp310.pp311.graalpy311-none-any.whl", hash = "sha256:c3b2e0af1f7f77c4263759c4824316ce458fabe0fceadcd24ef8ca08b2d1e402", size = 15072, upload-time = "2025-08-22T13:50:05.498Z" }, + { url = "https://files.pythonhosted.org/packages/1f/38/9a97f650b8cdb2ba0356d65aef9239f4a30db69ae44c30daa2cf8dd3f350/langsmith-0.4.39-py3-none-any.whl", hash = "sha256:48872eaaa449fc10781b5251f4fc05bc7d5c2d1d733a734566a96dd9166108b4", size = 397767, upload-time = "2025-11-01T00:06:16.433Z" }, ] [[package]] @@ -2075,7 +2047,7 @@ wheels = [ [[package]] name = "mcp" -version = "1.19.0" +version = "1.20.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2084,15 +2056,16 @@ dependencies = [ { name = "jsonschema" }, { name = "pydantic" }, { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, { name = "python-multipart" }, { name = "pywin32", marker = "sys_platform == 'win32'" }, { name = "sse-starlette" }, { name = "starlette" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/2b/916852a5668f45d8787378461eaa1244876d77575ffef024483c94c0649c/mcp-1.19.0.tar.gz", hash = "sha256:213de0d3cd63f71bc08ffe9cc8d4409cc87acffd383f6195d2ce0457c021b5c1", size = 444163, upload-time = "2025-10-24T01:11:15.839Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/22/fae38092e6c2995c03232635028510d77e7decff31b4ae79dfa0ba99c635/mcp-1.20.0.tar.gz", hash = "sha256:9ccc09eaadbfbcbbdab1c9723cfe2e0d1d9e324d7d3ce7e332ef90b09ed35177", size = 451377, upload-time = "2025-10-30T22:14:53.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/a3/3e71a875a08b6a830b88c40bc413bff01f1650f1efe8a054b5e90a9d4f56/mcp-1.19.0-py3-none-any.whl", hash = "sha256:f5907fe1c0167255f916718f376d05f09a830a215327a3ccdd5ec8a519f2e572", size = 170105, upload-time = "2025-10-24T01:11:14.151Z" }, + { url = "https://files.pythonhosted.org/packages/df/00/76fc92f4892d47fecb37131d0e95ea69259f077d84c68f6793a0d96cfe80/mcp-1.20.0-py3-none-any.whl", hash = "sha256:d0dc06f93653f7432ff89f694721c87f79876b6f93741bf628ad1e48f7ac5e5d", size = 173136, upload-time = "2025-10-30T22:14:51.078Z" }, ] [[package]] @@ -2324,7 +2297,7 @@ wheels = [ [[package]] name = "open-notebook" -version = "1.1.1" +version = "1.2.0" source = { editable = "." } dependencies = [ { name = "ai-prompter" }, @@ -2404,7 +2377,7 @@ requires-dist = [ { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" }, { name = "python-dotenv", specifier = ">=1.0.1" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.5.5" }, - { name = "surreal-commands", specifier = ">=1.0.13" }, + { name = "surreal-commands", specifier = ">=1.2.0" }, { name = "surrealdb", specifier = ">=1.0.4" }, { name = "tiktoken", specifier = ">=0.8.0" }, { name = "tomli", specifier = ">=2.0.2" }, @@ -2439,26 +2412,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/0e/331df43df633e6105ff9cf45e0ce57762bd126a45ac16b25a43f6738d8a2/openai-2.6.1-py3-none-any.whl", hash = "sha256:904e4b5254a8416746a2f05649594fa41b19d799843cd134dac86167e094edef", size = 1005551, upload-time = "2025-10-24T13:29:50.973Z" }, ] -[[package]] -name = "openapi-core" -version = "0.19.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "isodate" }, - { name = "jsonschema" }, - { name = "jsonschema-path" }, - { name = "more-itertools" }, - { name = "openapi-schema-validator" }, - { name = "openapi-spec-validator" }, - { name = "parse" }, - { name = "typing-extensions" }, - { name = "werkzeug" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b1/35/1acaa5f2fcc6e54eded34a2ec74b479439c4e469fc4e8d0e803fda0234db/openapi_core-0.19.5.tar.gz", hash = "sha256:421e753da56c391704454e66afe4803a290108590ac8fa6f4a4487f4ec11f2d3", size = 103264, upload-time = "2025-03-20T20:17:28.193Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/6f/83ead0e2e30a90445ee4fc0135f43741aebc30cca5b43f20968b603e30b6/openapi_core-0.19.5-py3-none-any.whl", hash = "sha256:ef7210e83a59394f46ce282639d8d26ad6fc8094aa904c9c16eb1bac8908911f", size = 106595, upload-time = "2025-03-20T20:17:26.77Z" }, -] - [[package]] name = "openapi-pydantic" version = "0.5.1" @@ -2471,35 +2424,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, ] -[[package]] -name = "openapi-schema-validator" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema" }, - { name = "jsonschema-specifications" }, - { name = "rfc3339-validator" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8b/f3/5507ad3325169347cd8ced61c232ff3df70e2b250c49f0fe140edb4973c6/openapi_schema_validator-0.6.3.tar.gz", hash = "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee", size = 11550, upload-time = "2025-01-10T18:08:22.268Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/21/c6/ad0fba32775ae749016829dace42ed80f4407b171da41313d1a3a5f102e4/openapi_schema_validator-0.6.3-py3-none-any.whl", hash = "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3", size = 8755, upload-time = "2025-01-10T18:08:19.758Z" }, -] - -[[package]] -name = "openapi-spec-validator" -version = "0.7.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema" }, - { name = "jsonschema-path" }, - { name = "lazy-object-proxy" }, - { name = "openapi-schema-validator" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/82/af/fe2d7618d6eae6fb3a82766a44ed87cd8d6d82b4564ed1c7cfb0f6378e91/openapi_spec_validator-0.7.2.tar.gz", hash = "sha256:cc029309b5c5dbc7859df0372d55e9d1ff43e96d678b9ba087f7c56fc586f734", size = 36855, upload-time = "2025-06-07T14:48:56.299Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/dd/b3fd642260cb17532f66cc1e8250f3507d1e580483e209dc1e9d13bd980d/openapi_spec_validator-0.7.2-py3-none-any.whl", hash = "sha256:4bbdc0894ec85f1d1bea1d6d9c8b2c3c8d7ccaa13577ef40da9c006c9fd0eb60", size = 39713, upload-time = "2025-06-07T14:48:54.077Z" }, -] - [[package]] name = "openpyxl" version = "3.1.5" @@ -2613,15 +2537,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, ] -[[package]] -name = "parse" -version = "1.20.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/78/d9b09ba24bb36ef8b83b71be547e118d46214735b6dfb39e4bfde0e9b9dd/parse-1.20.2.tar.gz", hash = "sha256:b41d604d16503c79d81af5165155c0b20f6c8d6c559efa66b4b695c3e5a0a0ce", size = 29391, upload-time = "2024-06-11T04:41:57.34Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/31/ba45bf0b2aa7898d81cbbfac0e88c267befb59ad91a19e36e1bc5578ddb1/parse-1.20.2-py2.py3-none-any.whl", hash = "sha256:967095588cb802add9177d0c0b6133b5ba33b1ea9007ca800e526f42a85af558", size = 20126, upload-time = "2024-06-11T04:41:55.057Z" }, -] - [[package]] name = "parso" version = "0.8.5" @@ -3093,6 +3008,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] +[[package]] +name = "pyjwt" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + [[package]] name = "pymupdf" version = "1.26.5" @@ -3173,11 +3102,11 @@ wheels = [ [[package]] name = "python-dotenv" -version = "1.1.1" +version = "1.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, + { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, ] [[package]] @@ -3402,18 +3331,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] -[[package]] -name = "rfc3339-validator" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, -] - [[package]] name = "rich" version = "14.2.0" @@ -3504,28 +3421,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.14.2" +version = "0.14.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/34/8218a19b2055b80601e8fd201ec723c74c7fe1ca06d525a43ed07b6d8e85/ruff-0.14.2.tar.gz", hash = "sha256:98da787668f239313d9c902ca7c523fe11b8ec3f39345553a51b25abc4629c96", size = 5539663, upload-time = "2025-10-23T19:37:00.956Z" } +sdist = { url = "https://files.pythonhosted.org/packages/75/62/50b7727004dfe361104dfbf898c45a9a2fdfad8c72c04ae62900224d6ecf/ruff-0.14.3.tar.gz", hash = "sha256:4ff876d2ab2b161b6de0aa1f5bd714e8e9b4033dc122ee006925fbacc4f62153", size = 5558687, upload-time = "2025-10-31T00:26:26.878Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/dd/23eb2db5ad9acae7c845700493b72d3ae214dce0b226f27df89216110f2b/ruff-0.14.2-py3-none-linux_armv6l.whl", hash = "sha256:7cbe4e593505bdec5884c2d0a4d791a90301bc23e49a6b1eb642dd85ef9c64f1", size = 12533390, upload-time = "2025-10-23T19:36:18.044Z" }, - { url = "https://files.pythonhosted.org/packages/5a/8c/5f9acff43ddcf3f85130d0146d0477e28ccecc495f9f684f8f7119b74c0d/ruff-0.14.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8d54b561729cee92f8d89c316ad7a3f9705533f5903b042399b6ae0ddfc62e11", size = 12887187, upload-time = "2025-10-23T19:36:22.664Z" }, - { url = "https://files.pythonhosted.org/packages/99/fa/047646491479074029665022e9f3dc6f0515797f40a4b6014ea8474c539d/ruff-0.14.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5c8753dfa44ebb2cde10ce5b4d2ef55a41fb9d9b16732a2c5df64620dbda44a3", size = 11925177, upload-time = "2025-10-23T19:36:24.778Z" }, - { url = "https://files.pythonhosted.org/packages/15/8b/c44cf7fe6e59ab24a9d939493a11030b503bdc2a16622cede8b7b1df0114/ruff-0.14.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d0bbeffb8d9f4fccf7b5198d566d0bad99a9cb622f1fc3467af96cb8773c9e3", size = 12358285, upload-time = "2025-10-23T19:36:26.979Z" }, - { url = "https://files.pythonhosted.org/packages/45/01/47701b26254267ef40369aea3acb62a7b23e921c27372d127e0f3af48092/ruff-0.14.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7047f0c5a713a401e43a88d36843d9c83a19c584e63d664474675620aaa634a8", size = 12303832, upload-time = "2025-10-23T19:36:29.192Z" }, - { url = "https://files.pythonhosted.org/packages/2d/5c/ae7244ca4fbdf2bee9d6405dcd5bc6ae51ee1df66eb7a9884b77b8af856d/ruff-0.14.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bf8d2f9aa1602599217d82e8e0af7fd33e5878c4d98f37906b7c93f46f9a839", size = 13036995, upload-time = "2025-10-23T19:36:31.861Z" }, - { url = "https://files.pythonhosted.org/packages/27/4c/0860a79ce6fd4c709ac01173f76f929d53f59748d0dcdd662519835dae43/ruff-0.14.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1c505b389e19c57a317cf4b42db824e2fca96ffb3d86766c1c9f8b96d32048a7", size = 14512649, upload-time = "2025-10-23T19:36:33.915Z" }, - { url = "https://files.pythonhosted.org/packages/7f/7f/d365de998069720a3abfc250ddd876fc4b81a403a766c74ff9bde15b5378/ruff-0.14.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a307fc45ebd887b3f26b36d9326bb70bf69b01561950cdcc6c0bdf7bb8e0f7cc", size = 14088182, upload-time = "2025-10-23T19:36:36.983Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ea/d8e3e6b209162000a7be1faa41b0a0c16a133010311edc3329753cc6596a/ruff-0.14.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61ae91a32c853172f832c2f40bd05fd69f491db7289fb85a9b941ebdd549781a", size = 13599516, upload-time = "2025-10-23T19:36:39.208Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ea/c7810322086db68989fb20a8d5221dd3b79e49e396b01badca07b433ab45/ruff-0.14.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1967e40286f63ee23c615e8e7e98098dedc7301568bd88991f6e544d8ae096", size = 13272690, upload-time = "2025-10-23T19:36:41.453Z" }, - { url = "https://files.pythonhosted.org/packages/a9/39/10b05acf8c45786ef501d454e00937e1b97964f846bf28883d1f9619928a/ruff-0.14.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2877f02119cdebf52a632d743a2e302dea422bfae152ebe2f193d3285a3a65df", size = 13496497, upload-time = "2025-10-23T19:36:43.61Z" }, - { url = "https://files.pythonhosted.org/packages/59/a1/1f25f8301e13751c30895092485fada29076e5e14264bdacc37202e85d24/ruff-0.14.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e681c5bc777de5af898decdcb6ba3321d0d466f4cb43c3e7cc2c3b4e7b843a05", size = 12266116, upload-time = "2025-10-23T19:36:45.625Z" }, - { url = "https://files.pythonhosted.org/packages/5c/fa/0029bfc9ce16ae78164e6923ef392e5f173b793b26cc39aa1d8b366cf9dc/ruff-0.14.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e21be42d72e224736f0c992cdb9959a2fa53c7e943b97ef5d081e13170e3ffc5", size = 12281345, upload-time = "2025-10-23T19:36:47.618Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ab/ece7baa3c0f29b7683be868c024f0838770c16607bea6852e46b202f1ff6/ruff-0.14.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b8264016f6f209fac16262882dbebf3f8be1629777cf0f37e7aff071b3e9b92e", size = 12629296, upload-time = "2025-10-23T19:36:49.789Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7f/638f54b43f3d4e48c6a68062794e5b367ddac778051806b9e235dfb7aa81/ruff-0.14.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5ca36b4cb4db3067a3b24444463ceea5565ea78b95fe9a07ca7cb7fd16948770", size = 13371610, upload-time = "2025-10-23T19:36:51.882Z" }, - { url = "https://files.pythonhosted.org/packages/8d/35/3654a973ebe5b32e1fd4a08ed2d46755af7267da7ac710d97420d7b8657d/ruff-0.14.2-py3-none-win32.whl", hash = "sha256:41775927d287685e08f48d8eb3f765625ab0b7042cc9377e20e64f4eb0056ee9", size = 12415318, upload-time = "2025-10-23T19:36:53.961Z" }, - { url = "https://files.pythonhosted.org/packages/71/30/3758bcf9e0b6a4193a6f51abf84254aba00887dfa8c20aba18aa366c5f57/ruff-0.14.2-py3-none-win_amd64.whl", hash = "sha256:0df3424aa5c3c08b34ed8ce099df1021e3adaca6e90229273496b839e5a7e1af", size = 13565279, upload-time = "2025-10-23T19:36:56.578Z" }, - { url = "https://files.pythonhosted.org/packages/2e/5d/aa883766f8ef9ffbe6aa24f7192fb71632f31a30e77eb39aa2b0dc4290ac/ruff-0.14.2-py3-none-win_arm64.whl", hash = "sha256:ea9d635e83ba21569fbacda7e78afbfeb94911c9434aff06192d9bc23fd5495a", size = 12554956, upload-time = "2025-10-23T19:36:58.714Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8e/0c10ff1ea5d4360ab8bfca4cb2c9d979101a391f3e79d2616c9bf348cd26/ruff-0.14.3-py3-none-linux_armv6l.whl", hash = "sha256:876b21e6c824f519446715c1342b8e60f97f93264012de9d8d10314f8a79c371", size = 12535613, upload-time = "2025-10-31T00:25:44.302Z" }, + { url = "https://files.pythonhosted.org/packages/d3/c8/6724f4634c1daf52409fbf13fefda64aa9c8f81e44727a378b7b73dc590b/ruff-0.14.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6fd8c79b457bedd2abf2702b9b472147cd860ed7855c73a5247fa55c9117654", size = 12855812, upload-time = "2025-10-31T00:25:47.793Z" }, + { url = "https://files.pythonhosted.org/packages/de/03/db1bce591d55fd5f8a08bb02517fa0b5097b2ccabd4ea1ee29aa72b67d96/ruff-0.14.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:71ff6edca490c308f083156938c0c1a66907151263c4abdcb588602c6e696a14", size = 11944026, upload-time = "2025-10-31T00:25:49.657Z" }, + { url = "https://files.pythonhosted.org/packages/0b/75/4f8dbd48e03272715d12c87dc4fcaaf21b913f0affa5f12a4e9c6f8a0582/ruff-0.14.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:786ee3ce6139772ff9272aaf43296d975c0217ee1b97538a98171bf0d21f87ed", size = 12356818, upload-time = "2025-10-31T00:25:51.949Z" }, + { url = "https://files.pythonhosted.org/packages/ec/9b/506ec5b140c11d44a9a4f284ea7c14ebf6f8b01e6e8917734a3325bff787/ruff-0.14.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cd6291d0061811c52b8e392f946889916757610d45d004e41140d81fb6cd5ddc", size = 12336745, upload-time = "2025-10-31T00:25:54.248Z" }, + { url = "https://files.pythonhosted.org/packages/c7/e1/c560d254048c147f35e7f8131d30bc1f63a008ac61595cf3078a3e93533d/ruff-0.14.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a497ec0c3d2c88561b6d90f9c29f5ae68221ac00d471f306fa21fa4264ce5fcd", size = 13101684, upload-time = "2025-10-31T00:25:56.253Z" }, + { url = "https://files.pythonhosted.org/packages/a5/32/e310133f8af5cd11f8cc30f52522a3ebccc5ea5bff4b492f94faceaca7a8/ruff-0.14.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e231e1be58fc568950a04fbe6887c8e4b85310e7889727e2b81db205c45059eb", size = 14535000, upload-time = "2025-10-31T00:25:58.397Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a1/7b0470a22158c6d8501eabc5e9b6043c99bede40fa1994cadf6b5c2a61c7/ruff-0.14.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:469e35872a09c0e45fecf48dd960bfbce056b5db2d5e6b50eca329b4f853ae20", size = 14156450, upload-time = "2025-10-31T00:26:00.889Z" }, + { url = "https://files.pythonhosted.org/packages/0a/96/24bfd9d1a7f532b560dcee1a87096332e461354d3882124219bcaff65c09/ruff-0.14.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d6bc90307c469cb9d28b7cfad90aaa600b10d67c6e22026869f585e1e8a2db0", size = 13568414, upload-time = "2025-10-31T00:26:03.291Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e7/138b883f0dfe4ad5b76b58bf4ae675f4d2176ac2b24bdd81b4d966b28c61/ruff-0.14.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2f8a0bbcffcfd895df39c9a4ecd59bb80dca03dc43f7fb63e647ed176b741e", size = 13315293, upload-time = "2025-10-31T00:26:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/f4/c09bb898be97b2eb18476b7c950df8815ef14cf956074177e9fbd40b7719/ruff-0.14.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:678fdd7c7d2d94851597c23ee6336d25f9930b460b55f8598e011b57c74fd8c5", size = 13539444, upload-time = "2025-10-31T00:26:08.09Z" }, + { url = "https://files.pythonhosted.org/packages/9c/aa/b30a1db25fc6128b1dd6ff0741fa4abf969ded161599d07ca7edd0739cc0/ruff-0.14.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1ec1ac071e7e37e0221d2f2dbaf90897a988c531a8592a6a5959f0603a1ecf5e", size = 12252581, upload-time = "2025-10-31T00:26:10.297Z" }, + { url = "https://files.pythonhosted.org/packages/da/13/21096308f384d796ffe3f2960b17054110a9c3828d223ca540c2b7cc670b/ruff-0.14.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afcdc4b5335ef440d19e7df9e8ae2ad9f749352190e96d481dc501b753f0733e", size = 12307503, upload-time = "2025-10-31T00:26:12.646Z" }, + { url = "https://files.pythonhosted.org/packages/cb/cc/a350bac23f03b7dbcde3c81b154706e80c6f16b06ff1ce28ed07dc7b07b0/ruff-0.14.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7bfc42f81862749a7136267a343990f865e71fe2f99cf8d2958f684d23ce3dfa", size = 12675457, upload-time = "2025-10-31T00:26:15.044Z" }, + { url = "https://files.pythonhosted.org/packages/cb/76/46346029fa2f2078826bc88ef7167e8c198e58fe3126636e52f77488cbba/ruff-0.14.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a65e448cfd7e9c59fae8cf37f9221585d3354febaad9a07f29158af1528e165f", size = 13403980, upload-time = "2025-10-31T00:26:17.81Z" }, + { url = "https://files.pythonhosted.org/packages/9f/a4/35f1ef68c4e7b236d4a5204e3669efdeefaef21f0ff6a456792b3d8be438/ruff-0.14.3-py3-none-win32.whl", hash = "sha256:f3d91857d023ba93e14ed2d462ab62c3428f9bbf2b4fbac50a03ca66d31991f7", size = 12500045, upload-time = "2025-10-31T00:26:20.503Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/51960ae340823c9859fb60c63301d977308735403e2134e17d1d2858c7fb/ruff-0.14.3-py3-none-win_amd64.whl", hash = "sha256:d7b7006ac0756306db212fd37116cce2bd307e1e109375e1c6c106002df0ae5f", size = 13594005, upload-time = "2025-10-31T00:26:22.533Z" }, + { url = "https://files.pythonhosted.org/packages/b7/73/4de6579bac8e979fca0a77e54dec1f1e011a0d268165eb8a9bc0982a6564/ruff-0.14.3-py3-none-win_arm64.whl", hash = "sha256:26eb477ede6d399d898791d01961e16b86f02bc2486d0d1a7a9bb2379d055dc1", size = 12590017, upload-time = "2025-10-31T00:26:24.52Z" }, ] [[package]] @@ -3656,14 +3573,14 @@ wheels = [ [[package]] name = "sse-starlette" -version = "3.0.2" +version = "3.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/6f/22ed6e33f8a9e76ca0a412405f31abb844b779d52c5f96660766edcd737c/sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a", size = 20985, upload-time = "2025-07-27T09:07:44.565Z" } +sdist = { url = "https://files.pythonhosted.org/packages/db/3c/fa6517610dc641262b77cc7bf994ecd17465812c1b0585fe33e11be758ab/sse_starlette-3.0.3.tar.gz", hash = "sha256:88cfb08747e16200ea990c8ca876b03910a23b547ab3bd764c0d8eb81019b971", size = 21943, upload-time = "2025-10-30T18:44:20.117Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/10/c78f463b4ef22eef8491f218f692be838282cd65480f6e423d7730dfd1fb/sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", size = 11297, upload-time = "2025-07-27T09:07:43.268Z" }, + { url = "https://files.pythonhosted.org/packages/23/a0/984525d19ca5c8a6c33911a0c164b11490dd0f90ff7fd689f704f84e9a11/sse_starlette-3.0.3-py3-none-any.whl", hash = "sha256:af5bf5a6f3933df1d9c7f8539633dc8444ca6a97ab2e2a7cd3b6e431ac03a431", size = 11765, upload-time = "2025-10-30T18:44:18.834Z" }, ] [[package]] @@ -3682,35 +3599,35 @@ wheels = [ [[package]] name = "starlette" -version = "0.48.0" +version = "0.49.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a7/a5/d6f429d43394057b67a6b5bbe6eae2f77a6bf7459d961fdb224bf206eee6/starlette-0.48.0.tar.gz", hash = "sha256:7e8cee469a8ab2352911528110ce9088fdc6a37d9876926e73da7ce4aa4c7a46", size = 2652949, upload-time = "2025-09-13T08:41:05.699Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1a/608df0b10b53b0beb96a37854ee05864d182ddd4b1156a22f1ad3860425a/starlette-0.49.3.tar.gz", hash = "sha256:1c14546f299b5901a1ea0e34410575bc33bbd741377a10484a54445588d00284", size = 2655031, upload-time = "2025-11-01T15:12:26.13Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/72/2db2f49247d0a18b4f1bb9a5a39a0162869acf235f3a96418363947b3d46/starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659", size = 73736, upload-time = "2025-09-13T08:41:03.869Z" }, + { url = "https://files.pythonhosted.org/packages/a3/e0/021c772d6a662f43b63044ab481dc6ac7592447605b5b35a957785363122/starlette-0.49.3-py3-none-any.whl", hash = "sha256:b579b99715fdc2980cf88c8ec96d3bf1ce16f5a8051a7c2b84ef9b1cdecaea2f", size = 74340, upload-time = "2025-11-01T15:12:24.387Z" }, ] [[package]] name = "surreal-commands" -version = "1.1.1" +version = "1.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "humanize" }, { name = "langchain-core" }, - { name = "langgraph" }, { name = "loguru" }, { name = "pydantic" }, { name = "python-dotenv" }, { name = "rich" }, { name = "surrealdb" }, + { name = "tenacity" }, { name = "typer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7f/89/c0234679e93c619583e1b8552079114f59ae77c31013001113a80bd6216a/surreal_commands-1.1.1.tar.gz", hash = "sha256:6994f65d3a7574f965fea887dc2ad3797177260b3a07aba07246bf4d61926574", size = 156443, upload-time = "2025-07-09T14:01:01.245Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/63/71d018478b1843f1e02ae3dd426faa4d1c9810c920167ac3719c85ef017e/surreal_commands-1.2.0.tar.gz", hash = "sha256:1fed8631485e4063fe62163cdce59a65ff38a2e76732320071b65d9f6ee2b3ed", size = 194102, upload-time = "2025-11-01T14:48:11.849Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/fe/a69762f6eacf14ec3b97eb16f97fc2fd276679caace36168adadc3264df2/surreal_commands-1.1.1-py3-none-any.whl", hash = "sha256:d4be9ee5bfbcfe9d3d962d161b2639dd9fdc8dcde0ce8fe0e3b4444c646fe421", size = 28960, upload-time = "2025-07-09T14:00:59.766Z" }, + { url = "https://files.pythonhosted.org/packages/60/7d/c849b9e4b92914681f37d64bd09684671df5daf0ec1fd2d5aa79fcacfc77/surreal_commands-1.2.0-py3-none-any.whl", hash = "sha256:534cd037058efcf3d619a5c3147e74e24916394428158f835d2c640927035a1a", size = 34106, upload-time = "2025-11-01T14:48:10.641Z" }, ] [[package]] @@ -3869,6 +3786,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl", hash = "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a", size = 47028, upload-time = "2025-10-20T17:03:47.617Z" }, ] +[[package]] +name = "typer-slim" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/45/81b94a52caed434b94da65729c03ad0fb7665fab0f7db9ee54c94e541403/typer_slim-0.20.0.tar.gz", hash = "sha256:9fc6607b3c6c20f5c33ea9590cbeb17848667c51feee27d9e314a579ab07d1a3", size = 106561, upload-time = "2025-10-20T17:03:46.642Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/dd/5cbf31f402f1cc0ab087c94d4669cfa55bd1e818688b910631e131d74e75/typer_slim-0.20.0-py3-none-any.whl", hash = "sha256:f42a9b7571a12b97dddf364745d29f12221865acef7a2680065f9bb29c7dc89d", size = 47087, upload-time = "2025-10-20T17:03:44.546Z" }, +] + [[package]] name = "types-requests" version = "2.32.4.20250913" @@ -3957,16 +3887,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.35.3" +version = "20.35.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/d5/b0ccd381d55c8f45d46f77df6ae59fbc23d19e901e2d523395598e5f4c93/virtualenv-20.35.3.tar.gz", hash = "sha256:4f1a845d131133bdff10590489610c98c168ff99dc75d6c96853801f7f67af44", size = 6002907, upload-time = "2025-10-10T21:23:33.178Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl", hash = "sha256:63d106565078d8c8d0b206d48080f938a8b25361e19432d2c9db40d2899c810a", size = 5981061, upload-time = "2025-10-10T21:23:30.433Z" }, + { url = "https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" }, ] [[package]] @@ -4009,18 +3939,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] -[[package]] -name = "werkzeug" -version = "3.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/32/af/d4502dc713b4ccea7175d764718d5183caf8d0867a4f0190d5d4a45cea49/werkzeug-3.1.1.tar.gz", hash = "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4", size = 806453, upload-time = "2024-11-01T16:40:45.462Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/ea/c67e1dee1ba208ed22c06d1d547ae5e293374bfc43e0eb0ef5e262b68561/werkzeug-3.1.1-py3-none-any.whl", hash = "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5", size = 224371, upload-time = "2024-11-01T16:40:43.994Z" }, -] - [[package]] name = "widgetsnbextension" version = "4.0.14"