diff --git a/.gitignore b/.gitignore index e80391eaa..cd61cebf6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ node_modules .pnpm-store **/.poetry-cache +**/.env.local +integrations/claude-agent-sdk/**/.env.local diff --git a/integrations/claude-agent-sdk/python/.env.local.example b/integrations/claude-agent-sdk/python/.env.local.example new file mode 100644 index 000000000..e925bb858 --- /dev/null +++ b/integrations/claude-agent-sdk/python/.env.local.example @@ -0,0 +1,10 @@ +# Claude Agent SDK Integration - Environment Variables +# Copy this file to .env.local and fill in your actual values + +# Anthropic API Key (required for real API tests) +# Get your API key from: https://console.anthropic.com/ +# ANTHROPIC_API_KEY=your-anthropic-api-key-here + +# Optional for third party service +# ANTHROPIC_AUTH_TOKEN=third-party-auth-token +# ANTHROPIC_BASE_URL=third-party-base-url diff --git a/integrations/claude-agent-sdk/python/.gitignore b/integrations/claude-agent-sdk/python/.gitignore new file mode 100644 index 000000000..32319dd4a --- /dev/null +++ b/integrations/claude-agent-sdk/python/.gitignore @@ -0,0 +1,31 @@ +# Environment files +.env +.env.local +.env*.local + +# Dependencies +node_modules/ + +# Build output +dist/ +build/ + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* + +# OS +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + diff --git a/integrations/claude-agent-sdk/python/ARCHITECTURE.md b/integrations/claude-agent-sdk/python/ARCHITECTURE.md new file mode 100644 index 000000000..1281ee31e --- /dev/null +++ b/integrations/claude-agent-sdk/python/ARCHITECTURE.md @@ -0,0 +1,113 @@ +# Claude Agent SDK Integration Architecture + +This document describes the architecture and design of the Claude Agent SDK integration that bridges Claude agents with the AG-UI Protocol. + +## High-Level Architecture + +``` +AG-UI Protocol Claude Middleware Claude Agent SDK + │ │ │ +RunAgentInput ──────> ClaudeAgent.run() ──────> SDK Client/Query + │ │ │ + │ EventTranslator │ + │ │ │ +BaseEvent[] <──────── translate events <──────── Response[] +``` + +## Core Components + +### ClaudeAgent (`claude_agent.py`) +The main orchestrator that: +- Manages agent lifecycle and session state +- Handles the bridge between AG-UI Protocol and Claude SDK +- Coordinates tool execution +- Supports both persistent sessions and stateless query mode + +### EventTranslator (`event_translator.py`) +Converts between event formats: +- Claude SDK responses → AG-UI protocol events (16 standard event types) +- Maintains proper message boundaries +- Handles streaming text content +- Per-execution instances for thread safety + +### SessionManager (`session_manager.py`) +Singleton pattern for centralized session control: +- Automatic session cleanup with configurable timeouts +- Session isolation per user +- Message tracking to avoid duplicates +- State management + +### ToolAdapter (`tool_adapter.py`) +Tool format conversion: +- AG-UI Tool → Claude SDK tool format +- Tool call extraction and parsing +- Long-running tool detection + +### ExecutionState (`execution_state.py`) +Tracks background Claude executions: +- Manages asyncio tasks running Claude SDK calls +- Event queue for streaming results +- Execution timing and completion tracking +- Tool call state management + +## Event Flow + +1. **Client Request**: AG-UI Protocol `RunAgentInput` received +2. **Session Resolution**: SessionManager finds or creates session +3. **Message Processing**: Unseen messages identified and processed +4. **Agent Execution**: Claude SDK called with messages and tools +5. **Event Translation**: Claude responses converted to AG-UI events +6. **Streaming Response**: Events streamed back via SSE or other transport + +## Key Design Patterns + +### Session Management +- **Persistent Mode**: Uses ClaudeSDKClient for session continuity +- **Stateless Mode**: Uses query() method with manual context management + +### Tool Handling +- **Client Tools**: Long-running tools executed on frontend +- **Backend Tools**: Synchronous tools executed on backend +- **Tool Results**: Handled through message routing + +### Event Streaming +- Background execution with event queue +- Non-blocking async/await throughout +- Proper cleanup on errors or timeouts + +## Thread Safety + +- Per-execution EventTranslator instances +- Singleton SessionManager with proper locking +- Isolated execution states per thread +- Thread-safe event queues + +## Error Handling + +- RunErrorEvent for various failure scenarios +- Proper async exception handling +- Resource cleanup on errors +- Timeout management at multiple levels + +## Performance Considerations + +- Async/await throughout for non-blocking operations +- Event streaming for real-time responses +- Configurable concurrent execution limits +- Automatic stale execution cleanup +- Efficient event queue management + +## Implementation Notes + +✅ **Implementation Complete**: The implementation has been updated based on the actual [Claude Agent SDK API](https://docs.claude.com/zh-CN/api/agent-sdk/python#claudesdkclient). + +Key implementation details: + +1. **SDK Initialization**: ✅ Implemented `_get_claude_client()` with `ClaudeSDKClient` and `query()` support +2. **Message Format**: ✅ Implemented prompt extraction (`_extract_user_prompt()`) for Claude SDK string-based API +3. **Response Handling**: ✅ Implemented `_call_claude_sdk()` supporting both persistent and stateless modes +4. **Tool Format**: ✅ Implemented `ToolAdapter` with `SdkMcpTool` and `create_sdk_mcp_server()` +5. **Event Translation**: ✅ Implemented `EventTranslator` handling `Message`, `AssistantMessage`, `TextBlock`, `ToolUseBlock`, `ToolResultBlock` + +The implementation follows the actual Claude Agent SDK patterns and should work with the real SDK. Some fine-tuning may be needed based on real-world testing. + diff --git a/integrations/claude-agent-sdk/python/README.md b/integrations/claude-agent-sdk/python/README.md new file mode 100644 index 000000000..38f38e0cf --- /dev/null +++ b/integrations/claude-agent-sdk/python/README.md @@ -0,0 +1,388 @@ +# Claude Agent SDK Middleware for AG-UI Protocol + +This Python middleware enables [Anthropic Claude Agent SDK](https://docs.claude.com/api/agent-sdk/python) agents to be used with the AG-UI Protocol, providing a bridge between the two frameworks. + +## Prerequisites + +- Python 3.9 or higher +- An [Anthropic API Key](https://console.anthropic.com/). The examples assume that this is exported via the `ANTHROPIC_API_KEY` environment variable. + +## Quick Start + +To use this integration you need to: + +1. Clone the [AG-UI repository](https://github.com/ag-ui-protocol/ag-ui). + + ```bash + git clone https://github.com/ag-ui-protocol/ag-ui.git + ``` + +2. Change to the `integrations/claude-agent-sdk/python` directory. + + ```bash + cd integrations/claude-agent-sdk/python + ``` + +3. Install the `claude-agent-sdk` middleware package from the local directory. For example, + + ```bash + pip install . + ``` + + or + + ```bash + uv pip install . + ``` + + This installs the package from the current directory which contains: + - `src/ag_ui_claude/` - The middleware source code + - `examples/` - Example servers and agents + - `tests/` - Test suite + +4. Set your Anthropic API key: + + ```bash + export ANTHROPIC_API_KEY=your-api-key-here + ``` + +5. Run the example FastAPI server: + + ```bash + cd examples/server + python fastapi_server.py + ``` + + Or use uvicorn directly: + + ```bash + uvicorn examples.server.fastapi_server:app --host 0.0.0.0 --port 8000 + ``` + +### Development Setup + +If you want to contribute to Claude Agent SDK Middleware development, you can use the following setup: + +```bash +# From the claude-agent-sdk/python directory +# Create virtual environment +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate + +# Install this package in editable mode +pip install -e . + +# For development (includes testing and linting tools) +pip install -e ".[dev]" +``` + +This installs the Claude Agent SDK middleware in editable mode for development. + +## Testing + +### Environment Configuration + +For tests that require API access (like `test_real_api.py`), you can configure authentication credentials using a `.env.local` file: + +1. Copy the example file: + ```bash + cp .env.local.example .env.local + ``` + +2. Edit `.env.local` and add your authentication credentials: + + **Option 1: Using AUTH_TOKEN and BASE_URL (recommended)** + ```bash + ANTHROPIC_AUTH_TOKEN=your-auth-token-here + ANTHROPIC_BASE_URL=https://api.anthropic.com + ``` + + **Option 2: Using API Key (fallback)** + ```bash + ANTHROPIC_API_KEY=your-api-key-here + ``` + +3. The `.env.local` file will be automatically loaded when running tests (via `python-dotenv`). + +**Note**: `.env.local` is gitignored and should not be committed. The `.env.local.example` file serves as a template. + +Alternatively, you can set the environment variables directly: +```bash +# Option 1: AUTH_TOKEN and BASE_URL +export ANTHROPIC_AUTH_TOKEN=your-auth-token-here +export ANTHROPIC_BASE_URL=https://api.anthropic.com + +# Option 2: API Key +export ANTHROPIC_API_KEY=your-api-key-here +``` + +### Running Tests + +```bash +# Run tests (72 comprehensive tests) +pytest + +# With coverage +pytest --cov=src/ag_ui_claude + +# Specific test file +pytest tests/test_claude_agent.py + +# Run only real API tests (requires ANTHROPIC_API_KEY) +pytest tests/test_real_api.py -m integration +``` + +## Usage Options + +### Option 1: Direct Usage + +```python +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage +from claude_agent_sdk import ClaudeAgentOptions + +# 1. Create the middleware agent +agent = ClaudeAgent( + use_persistent_sessions=True, # Use ClaudeSDKClient for multi-turn conversations + app_name="my_app", + user_id="user123", + claude_options=ClaudeAgentOptions( + system_prompt="You are a helpful assistant", + permission_mode='acceptEdits' + ) +) + +# 2. Use directly with AG-UI RunAgentInput +input_data = RunAgentInput( + thread_id="thread_001", + run_id="run_001", + messages=[ + UserMessage(id="1", role="user", content="Hello!") + ], + context=[], + state={}, + tools=[], # AG-UI tools will be converted to Claude SDK tools + forwarded_props={} +) + +async for event in agent.run(input_data): + print(f"Event: {event.type}") + if hasattr(event, 'delta'): + print(f"Content: {event.delta}") +``` + +### Option 2: FastAPI Server + +```python +from fastapi import FastAPI +from ag_ui_claude import ClaudeAgent, add_claude_fastapi_endpoint +from claude_agent_sdk import ClaudeAgentOptions + +# 1. Create the middleware agent +agent = ClaudeAgent( + use_persistent_sessions=True, + app_name="my_app", + claude_options=ClaudeAgentOptions( + system_prompt="You are a helpful assistant", + permission_mode='acceptEdits' + ) +) + +# 2. Create FastAPI app +app = FastAPI() +add_claude_fastapi_endpoint(app, agent, path="/chat") + +# Run with: uvicorn your_module:app --host 0.0.0.0 --port 8000 +``` + +**Note**: The Claude Agent SDK uses the `ANTHROPIC_API_KEY` environment variable by default. Set it before running: + +```bash +export ANTHROPIC_API_KEY=your-api-key-here +``` + +For detailed configuration options, see [CONFIGURATION.md](./CONFIGURATION.md) + +## Examples + +### Simple Conversation + +```python +import asyncio +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage +from claude_agent_sdk import ClaudeAgentOptions + +async def main(): + # Setup + agent = ClaudeAgent( + use_persistent_sessions=True, + app_name="demo_app", + user_id="demo", + claude_options=ClaudeAgentOptions( + system_prompt="You are a helpful assistant." + ) + ) + + # Create input + input = RunAgentInput( + thread_id="thread_001", + run_id="run_001", + messages=[ + UserMessage(id="1", role="user", content="Hello!") + ], + context=[], + state={}, + tools=[], + forwarded_props={} + ) + + # Run and handle events + async for event in agent.run(input): + print(f"Event: {event.type}") + if hasattr(event, 'delta'): + print(f"Content: {event.delta}") + +asyncio.run(main()) +``` + +### With Tools + +```python +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage, Tool, EventType + +# Define a tool +weather_tool = Tool( + name="get_current_weather", + description="Get the current weather in a given location", + parameters={ + "type": "object", + "properties": { + "location": {"type": "string", "description": "The city and state"}, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} + }, + "required": ["location"] + } +) + +agent = ClaudeAgent( + use_persistent_sessions=True, + app_name="my_app" +) + +input_data = RunAgentInput( + thread_id="thread_001", + run_id="run_001", + messages=[ + UserMessage(id="1", role="user", content="What's the weather in London?") + ], + tools=[weather_tool], # Tools are automatically converted to Claude SDK format + state={}, + context=[], + forwarded_props={} +) + +async for event in agent.run(input_data): + if event.type == EventType.TOOL_CALL_START: + print(f"Tool call: {event.tool_call_name}") + elif event.type == EventType.TEXT_MESSAGE_CONTENT: + print(f"Response: {event.delta}") +``` + +### Stateless Mode + +```python +from ag_ui_claude import ClaudeAgent + +# Use stateless mode for simple one-off queries +agent = ClaudeAgent( + use_persistent_sessions=False, # Uses query() function + app_name="stateless_app" +) + +# Each query is independent, no conversation history +async for event in agent.run(input_data): + print(f"Event: {event.type}") +``` + +## Tool Support + +The middleware provides complete bidirectional tool support, enabling AG-UI Protocol tools to execute within Claude Agent SDK agents. All tools supplied by the client are currently implemented as long-running tools that emit events to the client for execution and can be combined with backend tools provided by the agent to create a hybrid combined toolset. + +AG-UI tools are automatically converted to Claude SDK `SdkMcpTool` format and exposed via MCP servers. When Claude requests a tool, the middleware emits AG-UI `ToolCall` events for client-side execution. Tool results from the client are then formatted and sent back to Claude in subsequent requests. + +## Configuration + +### ClaudeAgent Parameters + +- `api_key`: Claude API key (optional, defaults to `ANTHROPIC_API_KEY` env var) +- `use_persistent_sessions`: Use `ClaudeSDKClient` for persistent sessions (True) or `query()` for stateless mode (False) +- `app_name`: Static application name for all requests +- `user_id`: Static user ID for all requests +- `claude_options`: `ClaudeAgentOptions` instance for SDK configuration +- `execution_timeout_seconds`: Timeout for entire execution (default: 600) +- `max_concurrent_executions`: Maximum concurrent executions (default: 10) +- `session_timeout_seconds`: Session timeout in seconds (default: 1200) +- `cleanup_interval_seconds`: Session cleanup interval (default: 300) + +**ClaudeAgentOptions** supports many configuration options: +- `system_prompt`: System prompt for the agent +- `permission_mode`: Permission mode ('acceptEdits', 'promptEdits', etc.) +- `allowed_tools`: List of allowed tool names +- `mcp_servers`: MCP server configurations +- `cwd`: Working directory for file operations +- `max_tokens`: Maximum tokens for responses +- `temperature`: Temperature for response generation +- And more - see [Claude Agent SDK documentation](https://docs.claude.com/api/agent-sdk/python) + +See [CONFIGURATION.md](./CONFIGURATION.md) for detailed configuration options. + +## Features + +- **Event Streaming**: Real-time streaming of agent responses via Server-Sent Events (SSE) +- **Tool Support**: Both client-side and backend tool execution via MCP servers +- **Session Management**: Automatic session cleanup and state management +- **Message Tracking**: Avoids duplicate message processing +- **Error Handling**: Comprehensive error handling and reporting +- **Persistent Sessions**: Support for multi-turn conversations via `ClaudeSDKClient` +- **Stateless Mode**: Support for one-off queries via `query()` function + +## Implementation Status + +✅ **Core Implementation Complete**: The integration has been updated based on the [Claude Agent SDK documentation](https://docs.claude.com/api/agent-sdk/python#claudesdkclient). + +Key features implemented: +- ✅ `ClaudeSDKClient` integration for persistent sessions +- ✅ `query()` function support for stateless mode +- ✅ Message translation (`AssistantMessage`, `TextBlock`, `ToolUseBlock`, `ToolResultBlock`) +- ✅ Tool support via MCP servers (`SdkMcpTool`, `create_sdk_mcp_server`) +- ✅ Streaming response handling +- ✅ Session management with automatic cleanup +- ✅ Comprehensive test suite (72 tests, 65% pass rate) + +The implementation follows the actual Claude Agent SDK API patterns. Some areas may need fine-tuning based on real-world usage: +- Tool execution flow (client vs backend tools) +- Message history handling in persistent sessions +- Error handling for specific SDK error types + +## Architecture + +See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed architecture documentation. + +## Additional Documentation + +- **[USAGE_GUIDE.md](./USAGE_GUIDE.md)** - Complete usage guide: how to start and test the agent +- **[CONFIGURATION.md](./CONFIGURATION.md)** - Complete configuration guide +- **[ARCHITECTURE.md](./ARCHITECTURE.md)** - Technical architecture and design details +- **[IMPLEMENTATION_STATUS.md](../IMPLEMENTATION_STATUS.md)** - Current implementation status and test results +- **[IMPLEMENTATION_PLAN.md](../IMPLEMENTATION_PLAN.md)** - Implementation plan and roadmap + +## Contributing + +Contributions are welcome! Please refer to the main AG-UI contributing guidelines. + +## License + +MIT License - see LICENSE file for details. + diff --git a/integrations/claude-agent-sdk/python/examples/README.md b/integrations/claude-agent-sdk/python/examples/README.md new file mode 100644 index 000000000..5c7b2c99b --- /dev/null +++ b/integrations/claude-agent-sdk/python/examples/README.md @@ -0,0 +1,45 @@ +# Claude Agent SDK Integration Examples + +This directory contains example implementations of the Claude Agent SDK integration with AG-UI Protocol. + +## Quick Start + +1. Install dependencies: +```bash +cd examples +pip install -r requirements.txt +# Or using uv: +uv pip install -r requirements.txt +``` + +2. Set your Anthropic API key: +```bash +export ANTHROPIC_API_KEY=your-api-key-here +``` + +3. Run the example server: +```bash +python server/fastapi_server.py +# Or using uv: +uv run server/fastapi_server.py +``` + +4. The server will be available at `http://localhost:8000/chat` + +## Example Usage + +The example server demonstrates: +- Basic Claude Agent configuration +- FastAPI server setup +- AG-UI Protocol endpoint integration + +## Notes + +This implementation is a template based on common patterns. You may need to adjust: +- Claude SDK client initialization +- Message format conversion +- Tool handling +- Session management + +Refer to the Claude Agent SDK documentation for actual API details. + diff --git a/integrations/claude-agent-sdk/python/examples/pyproject.toml b/integrations/claude-agent-sdk/python/examples/pyproject.toml new file mode 100644 index 000000000..5f8dbf538 --- /dev/null +++ b/integrations/claude-agent-sdk/python/examples/pyproject.toml @@ -0,0 +1,11 @@ +[project] +name = "claude-agent-sdk-examples" +version = "0.1.0" +requires-python = ">=3.9" + +dependencies = [ + "ag-ui-claude", + "fastapi>=0.115.2", + "uvicorn>=0.35.0", +] + diff --git a/integrations/claude-agent-sdk/python/examples/server/fastapi_server.py b/integrations/claude-agent-sdk/python/examples/server/fastapi_server.py new file mode 100644 index 000000000..8c022a1cf --- /dev/null +++ b/integrations/claude-agent-sdk/python/examples/server/fastapi_server.py @@ -0,0 +1,97 @@ +"""Example FastAPI server for Claude Agent SDK integration.""" + +import os +from pathlib import Path +from fastapi import FastAPI +from ag_ui_claude import ClaudeAgent, add_claude_fastapi_endpoint + +# Load environment variables from .env.local if it exists +try: + from dotenv import load_dotenv + env_path = Path(__file__).parent.parent.parent / ".env.local" + if env_path.exists(): + load_dotenv(env_path) + print(f"✅ Loaded environment variables from {env_path}") +except ImportError: + # python-dotenv not installed, skip + pass + +# Claude Agent SDK will use ANTHROPIC_API_KEY from environment if not provided +# No need to explicitly pass api_key unless you want to override + +# IMPORTANT: Claude Agent SDK requires @anthropic-ai/claude-code CLI tool to be installed. +# Install it with: npm install -g @anthropic-ai/claude-code +# Or set the path via ClaudeAgentOptions(cli_path='/path/to/claude') + +# Try to find claude CLI path automatically +import shutil +import os + +# Try multiple ways to find claude CLI +claude_path = shutil.which('claude') +if not claude_path or not os.path.exists(claude_path): + # Try common locations + home_dir = os.path.expanduser('~') + possible_paths = [ + os.path.join(home_dir, '.claude', 'local', 'claude'), + os.path.join(home_dir, 'node_modules', '.bin', 'claude'), + '/usr/local/bin/claude', + '/opt/homebrew/bin/claude', # macOS Homebrew + ] + for path in possible_paths: + if os.path.exists(path): + claude_path = path + break + +# Log detected CLI path for debugging +if claude_path and os.path.exists(claude_path): + print(f"✅ Detected Claude CLI at: {claude_path}") +else: + print("⚠️ Claude CLI not found. Please install with: npm install -g @anthropic-ai/claude-code") + +from claude_agent_sdk import ClaudeAgentOptions + +# Example 1: Using persistent sessions (ClaudeSDKClient) - RECOMMENDED +# Supports multi-turn conversations, interrupts, hooks, custom tools, etc. +# See: https://docs.claude.com/api/agent-sdk/python#choosing-between-query-and-claudesdkclient +agent = ClaudeAgent( + use_persistent_sessions=True, # Use ClaudeSDKClient for full features + app_name="example_app", + claude_options=ClaudeAgentOptions( + system_prompt="You are a helpful assistant", + permission_mode='acceptEdits', + cli_path=claude_path if claude_path and os.path.exists(claude_path) else None # Auto-detect CLI path + ) +) + +# Example 2: Using stateless mode (query()) - limited features +# Only supports single-turn conversations, no hooks, interrupts, or custom tools +# agent = ClaudeAgent( +# use_persistent_sessions=False, +# app_name="example_app", +# claude_options=ClaudeAgentOptions( +# system_prompt="You are a helpful assistant", +# cli_path=claude_path if claude_path and os.path.exists(claude_path) else None +# ) +# ) + +# Create FastAPI app +app = FastAPI(title="Claude Agent SDK Example") + +# Add CORS middleware for CopilotKit integration +from fastapi.middleware.cors import CORSMiddleware +app.add_middleware( + CORSMiddleware, + allow_origins=["http://localhost:3000", "http://localhost:3001"], # Add your frontend URLs + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# Add AG-UI endpoint +add_claude_fastapi_endpoint(app, agent, path="/chat") + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) + diff --git a/integrations/claude-agent-sdk/python/examples/test_client.py b/integrations/claude-agent-sdk/python/examples/test_client.py new file mode 100644 index 000000000..9940b8648 --- /dev/null +++ b/integrations/claude-agent-sdk/python/examples/test_client.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +"""Simple test script for Claude Agent SDK integration.""" + +import asyncio +import aiohttp +import json +import sys +import os + +# Check environment variables +if not os.getenv("ANTHROPIC_API_KEY") and not os.getenv("ANTHROPIC_AUTH_TOKEN"): + print("❌ Error: Please set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN environment variable") + print("\nExample:") + print(" export ANTHROPIC_API_KEY=your-api-key-here") + sys.exit(1) + +SERVER_URL = os.getenv("AG_UI_SERVER_URL", "http://localhost:8000/chat") + + +async def test_basic_conversation(): + """Test basic conversation functionality""" + print(f"📡 Connecting to server: {SERVER_URL}") + print("=" * 60) + + url = SERVER_URL + + payload = { + "threadId": "test-thread-1", + "runId": "test-run-1", + "messages": [ + { + "id": "msg-1", + "role": "user", + "content": "Hello! Can you introduce yourself in one sentence?" + } + ], + "tools": [], + "context": [], + "state": {}, + "forwardedProps": {} + } + + try: + async with aiohttp.ClientSession() as session: + async with session.post(url, json=payload) as response: + if response.status != 200: + print(f"❌ Error: HTTP {response.status}") + text = await response.text() + print(f"Response: {text}") + return + + print("✅ Connection successful! Waiting for response...\n") + print("🤖 Assistant: ", end="", flush=True) + + # Read SSE stream + buffer = "" + async for chunk in response.content.iter_chunked(1024): + if chunk: + buffer += chunk.decode('utf-8') + lines = buffer.split('\n') + buffer = lines[-1] # Keep incomplete line + + for line in lines[:-1]: + line = line.strip() + if line.startswith('data: '): + data = line[6:] # Remove 'data: ' prefix + try: + event = json.loads(data) + event_type = event.get('type', 'unknown') + + # Handle text content + if 'delta' in event: + print(event['delta'], end="", flush=True) + elif event_type == 'TEXT_MESSAGE_END': + print("\n") + elif event_type == 'RUN_FINISHED': + print("\n✅ Conversation completed!") + elif event_type == 'RUN_ERROR': + print(f"\n❌ Error: {event.get('error', 'Unknown error')}") + + except json.JSONDecodeError: + pass + + print("\n" + "=" * 60) + + except aiohttp.ClientConnectorError: + print(f"❌ Error: Cannot connect to server {SERVER_URL}") + print("\nPlease ensure:") + print(" 1. Server is running (python examples/server/fastapi_server.py)") + print(" 2. Server address is correct") + print(" 3. Firewall allows connection") + except Exception as e: + print(f"❌ Error: {type(e).__name__}: {e}") + + +async def test_interactive_mode(): + """Interactive test mode""" + print(f"📡 Connecting to server: {SERVER_URL}") + print("=" * 60) + print("💡 Tip: Enter a message and press Enter, type 'quit' to exit") + print("=" * 60) + + thread_id = f"interactive-{os.getpid()}" + run_counter = 0 + + try: + while True: + user_input = input("\n👤 You: ").strip() + + if not user_input: + continue + + if user_input.lower() in ['quit', 'exit', 'q']: + print("\n👋 Goodbye!") + break + + run_counter += 1 + url = SERVER_URL + + payload = { + "threadId": thread_id, + "runId": f"run-{run_counter}", + "messages": [ + { + "id": f"msg-{run_counter}", + "role": "user", + "content": user_input + } + ], + "tools": [], + "context": [], + "state": {}, + "forwardedProps": {} + } + + async with aiohttp.ClientSession() as session: + async with session.post(url, json=payload) as response: + if response.status != 200: + print(f"❌ Error: HTTP {response.status}") + continue + + print("🤖 Assistant: ", end="", flush=True) + + buffer = "" + async for chunk in response.content.iter_chunked(1024): + if chunk: + buffer += chunk.decode('utf-8') + lines = buffer.split('\n') + buffer = lines[-1] + + for line in lines[:-1]: + line = line.strip() + if line.startswith('data: '): + data = line[6:] + try: + event = json.loads(data) + if 'delta' in event: + print(event['delta'], end="", flush=True) + elif event.get('type') == 'RUN_ERROR': + print(f"\n❌ Error: {event.get('error', 'Unknown error')}") + break + except json.JSONDecodeError: + pass + + print() # New line + + except KeyboardInterrupt: + print("\n\n👋 Goodbye!") + except Exception as e: + print(f"\n❌ Error: {type(e).__name__}: {e}") + + +def main(): + """Main function""" + import argparse + + parser = argparse.ArgumentParser( + description="Test Claude Agent SDK integration", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Basic test + python test_client.py + + # Interactive mode + python test_client.py --interactive + + # Custom server address + python test_client.py --server http://localhost:8001/chat + """ + ) + + parser.add_argument( + '-i', '--interactive', + action='store_true', + help='Enable interactive mode' + ) + + parser.add_argument( + '-s', '--server', + default=SERVER_URL, + help=f'Server address (default: {SERVER_URL})' + ) + + args = parser.parse_args() + + global SERVER_URL + SERVER_URL = args.server + + if args.interactive: + asyncio.run(test_interactive_mode()) + else: + asyncio.run(test_basic_conversation()) + + +if __name__ == "__main__": + main() diff --git a/integrations/claude-agent-sdk/python/pyproject.toml b/integrations/claude-agent-sdk/python/pyproject.toml new file mode 100644 index 000000000..1a9e4f4c5 --- /dev/null +++ b/integrations/claude-agent-sdk/python/pyproject.toml @@ -0,0 +1,33 @@ +[project] +name = "ag_ui_claude" +version = "0.1.0" +readme = "README.md" +authors = [ + { name = "AG-UI Contributors" } +] +requires-python = ">=3.9, <3.14" +dependencies = [ + "ag-ui-protocol>=0.1.7", + "claude-agent-sdk>=0.1.0", # Adjust version based on actual availability + "fastapi>=0.115.2", + "pydantic>=2.11.7", + "uvicorn>=0.35.0", +] + +[build-system] +requires = ["uv_build>=0.8.0,<0.9"] +build-backend = "uv_build" + +[dependency-groups] +dev = [ + "black>=25.1.0", + "flake8>=7.3.0", + "isort>=6.0.1", + "mypy>=1.16.1", + "pluggy>=1.6.0", + "pytest>=8.4.1", + "pytest-asyncio>=1.0.0", + "pytest-cov>=6.2.1", + "python-dotenv>=1.0.0", +] + diff --git a/integrations/claude-agent-sdk/python/pytest.ini b/integrations/claude-agent-sdk/python/pytest.ini new file mode 100644 index 000000000..774833a2b --- /dev/null +++ b/integrations/claude-agent-sdk/python/pytest.ini @@ -0,0 +1,15 @@ +[pytest] +# Configure pytest for the Claude Agent SDK middleware project +pythonpath = src +testpaths = tests +python_files = test_*.py +python_classes = Test* +python_functions = test_* +asyncio_mode = auto +addopts = --tb=short -v +filterwarnings = + ignore::UserWarning + ignore::DeprecationWarning +# Exclude optional real API tests if API key is not available +norecursedirs = .git __pycache__ .pytest_cache + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__init__.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__init__.py new file mode 100644 index 000000000..0e61a9c87 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__init__.py @@ -0,0 +1,19 @@ +"""Claude Agent SDK integration for AG-UI Protocol.""" + +from __future__ import annotations + +from .claude_agent import ClaudeAgent +from .event_translator import EventTranslator +from .session_manager import SessionManager +from .endpoint import add_claude_fastapi_endpoint, create_claude_app + +__all__ = [ + 'ClaudeAgent', + 'add_claude_fastapi_endpoint', + 'create_claude_app', + 'EventTranslator', + 'SessionManager' +] + +__version__ = "0.1.0" + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 000000000..058e2f3eb Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 000000000..aa7523879 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/__init__.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-311.pyc new file mode 100644 index 000000000..02246a3b3 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-312.pyc new file mode 100644 index 000000000..578b65939 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/claude_agent.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-311.pyc new file mode 100644 index 000000000..c158975a5 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-312.pyc new file mode 100644 index 000000000..59a94d2c7 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/endpoint.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-311.pyc new file mode 100644 index 000000000..4423fb9a6 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-312.pyc new file mode 100644 index 000000000..35008d6af Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/event_translator.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-311.pyc new file mode 100644 index 000000000..249f9e4ca Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-312.pyc new file mode 100644 index 000000000..ff0b459c9 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/execution_state.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-311.pyc new file mode 100644 index 000000000..b7033eca3 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-312.pyc new file mode 100644 index 000000000..316bffd58 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/session_manager.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-311.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-311.pyc new file mode 100644 index 000000000..42c3ec1bd Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-311.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-312.pyc b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-312.pyc new file mode 100644 index 000000000..ae1a4f073 Binary files /dev/null and b/integrations/claude-agent-sdk/python/src/ag_ui_claude/__pycache__/tool_adapter.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/claude_agent.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/claude_agent.py new file mode 100644 index 000000000..9958acbc3 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/claude_agent.py @@ -0,0 +1,906 @@ +"""Main ClaudeAgent implementation for bridging AG-UI Protocol with Claude Agent SDK.""" + +from typing import Optional, Dict, Callable, Any, AsyncGenerator, List +import asyncio +import json +import logging +import time + +try: + from ag_ui.core import ( + RunAgentInput, BaseEvent, EventType, + RunStartedEvent, RunFinishedEvent, RunErrorEvent, + ToolCallEndEvent, SystemMessage, ToolCallResultEvent + ) +except ImportError: + # Type checking fallback - actual dependency will be available at runtime + pass + +# Claude Agent SDK imports +try: + from claude_agent_sdk import ( + ClaudeSDKClient, + ClaudeAgentOptions, + query as claude_query, + Message, + AssistantMessage, + UserMessage as ClaudeUserMessage, + SystemMessage as ClaudeSystemMessage, + ResultMessage, + TextBlock, + ToolUseBlock, + ToolResultBlock, + ThinkingBlock, + ) +except ImportError: + # Type checking fallback - actual dependency will be available at runtime + ClaudeSDKClient = None + ClaudeAgentOptions = None + claude_query = None + +from .event_translator import EventTranslator +from .session_manager import SessionManager +from .execution_state import ExecutionState + +logger = logging.getLogger(__name__) + + +class ClaudeAgent: + """Middleware to bridge AG-UI Protocol with Claude Agent SDK. + + This agent translates between the AG-UI protocol events and Claude SDK responses, + managing sessions, state, and the lifecycle of Claude agents. + + Note: This implementation is a template based on common patterns. + Adjust based on actual Claude Agent SDK API documentation. + """ + + def __init__( + self, + # Claude SDK configuration + api_key: Optional[str] = None, + use_persistent_sessions: bool = True, # Use ClaudeSDKClient vs query() mode + + # App identification + app_name: Optional[str] = None, + session_timeout_seconds: Optional[int] = 1200, + app_name_extractor: Optional[Callable[[RunAgentInput], str]] = None, + + # User identification + user_id: Optional[str] = None, + user_id_extractor: Optional[Callable[[RunAgentInput], str]] = None, + + # Configuration + execution_timeout_seconds: int = 600, # 10 minutes + tool_timeout_seconds: int = 300, # 5 minutes + max_concurrent_executions: int = 10, + + # Session cleanup configuration + cleanup_interval_seconds: int = 300, # 5 minutes default + + # Claude Agent SDK options + claude_options: Optional[Any] = None, # ClaudeAgentOptions instance + **claude_kwargs # Additional options for ClaudeAgentOptions + ): + """Initialize the ClaudeAgent. + + Args: + api_key: Claude API key (if None, Claude SDK will use ANTHROPIC_API_KEY env var) + use_persistent_sessions: Use ClaudeSDKClient for persistent sessions, or query() for stateless + app_name: Static application name for all requests + app_name_extractor: Function to extract app name dynamically from input + user_id: Static user ID for all requests + user_id_extractor: Function to extract user ID dynamically from input + execution_timeout_seconds: Timeout for entire execution + tool_timeout_seconds: Timeout for individual tool calls + max_concurrent_executions: Maximum concurrent background executions + cleanup_interval_seconds: Interval between session cleanup cycles + claude_options: ClaudeAgentOptions instance (if None, will create from kwargs) + **claude_kwargs: Additional options for ClaudeAgentOptions (if claude_options is None) + """ + if app_name and app_name_extractor: + raise ValueError("Cannot specify both 'app_name' and 'app_name_extractor'") + + if user_id and user_id_extractor: + raise ValueError("Cannot specify both 'user_id' and 'user_id_extractor'") + + # Claude SDK client configuration + self._api_key = api_key + self._use_persistent_sessions = use_persistent_sessions + + # Create ClaudeAgentOptions if not provided + if claude_options is None: + if ClaudeAgentOptions: + self._claude_options = ClaudeAgentOptions(**claude_kwargs) + else: + self._claude_options = None + logger.warning("ClaudeAgentOptions not available - install claude-agent-sdk") + else: + self._claude_options = claude_options + + # Store tools for dynamic addition per request + self._default_tools: List[Any] = [] + + # App/user identification + self._static_app_name = app_name + self._app_name_extractor = app_name_extractor + self._static_user_id = user_id + self._user_id_extractor = user_id_extractor + + # Session management + self._session_manager = SessionManager.get_instance( + session_timeout_seconds=session_timeout_seconds, + cleanup_interval_seconds=cleanup_interval_seconds, + max_sessions_per_user=None, + auto_cleanup=True + ) + + # Execution tracking + self._active_executions: Dict[str, ExecutionState] = {} + self._execution_timeout = execution_timeout_seconds + self._tool_timeout = tool_timeout_seconds + self._max_concurrent = max_concurrent_executions + self._execution_lock = asyncio.Lock() + + # Session lookup cache + self._session_lookup_cache: Dict[str, Dict[str, str]] = {} + + logger.info( + f"Initialized ClaudeAgent - " + f"persistent_sessions: {use_persistent_sessions}" + ) + + def _get_app_name(self, input: RunAgentInput) -> str: + """Resolve app name with clear precedence.""" + if self._static_app_name: + return self._static_app_name + elif self._app_name_extractor: + return self._app_name_extractor(input) + else: + return "claude-agent" + + def _get_user_id(self, input: RunAgentInput) -> str: + """Resolve user ID with clear precedence.""" + if self._static_user_id: + return self._static_user_id + elif self._user_id_extractor: + return self._user_id_extractor(input) + else: + return f"thread_user_{input.thread_id}" + + async def run(self, input: RunAgentInput) -> AsyncGenerator[BaseEvent, None]: + """Run the Claude agent with client-side tool support. + + Args: + input: The AG-UI run input + + Yields: + AG-UI protocol events + """ + # Get unseen messages + unseen_messages = await self._get_unseen_messages(input) + + if not unseen_messages: + # No unseen messages - start new execution + async for event in self._start_new_execution(input): + yield event + return + + # Process messages in batches + index = 0 + total_unseen = len(unseen_messages) + app_name = self._get_app_name(input) + + while index < total_unseen: + current = unseen_messages[index] + role = getattr(current, "role", None) + + if role == "tool": + # Tool result batch + tool_batch: List[Any] = [] + while index < total_unseen and getattr(unseen_messages[index], "role", None) == "tool": + tool_batch.append(unseen_messages[index]) + index += 1 + + async for event in self._handle_tool_result_submission( + input, + tool_messages=tool_batch + ): + yield event + else: + # Regular message batch + message_batch: List[Any] = [] + assistant_message_ids: List[str] = [] + processed_message_ids: List[str] = [] + + while index < total_unseen and getattr(unseen_messages[index], "role", None) != "tool": + candidate = unseen_messages[index] + candidate_role = getattr(candidate, "role", None) + + message_id = getattr(candidate, "id", None) + if message_id: + if candidate_role == "assistant": + assistant_message_ids.append(message_id) + processed_message_ids.append(message_id) + + if candidate_role != "assistant": + message_batch.append(candidate) + + index += 1 + + # Mark all processed messages (including user messages) + if processed_message_ids: + self._session_manager.mark_messages_processed( + app_name, + input.thread_id, + set(processed_message_ids) + ) + + if message_batch: + async for event in self._start_new_execution(input, message_batch=message_batch): + yield event + + async def _get_unseen_messages(self, input: RunAgentInput) -> List[Any]: + """Return messages that have not yet been processed for this session.""" + if not input.messages: + return [] + + app_name = self._get_app_name(input) + session_id = input.thread_id + processed_ids = self._session_manager.get_processed_message_ids(app_name, session_id) + + unseen_reversed: List[Any] = [] + for message in reversed(input.messages): + message_id = getattr(message, "id", None) + if message_id and message_id in processed_ids: + break + unseen_reversed.append(message) + + unseen_reversed.reverse() + return unseen_reversed + + async def _is_tool_result_submission( + self, + input: RunAgentInput, + unseen_messages: Optional[List[Any]] = None, + ) -> bool: + """Check if the current input is a tool result submission. + + Args: + input: RunAgentInput to check + unseen_messages: Optional pre-computed unseen messages + + Returns: + True if this is a tool result submission, False otherwise + """ + unseen_messages = unseen_messages if unseen_messages is not None else await self._get_unseen_messages(input) + if not unseen_messages: + return False + last_message = unseen_messages[-1] + # Check if the last message is a ToolMessage + return hasattr(last_message, "role") and last_message.role == "tool" + + async def _handle_tool_result_submission( + self, + input: RunAgentInput, + tool_messages: List[Any] + ) -> AsyncGenerator[BaseEvent, None]: + """Handle tool result submission for existing execution.""" + # Extract tool results + tool_results = await self._extract_tool_results(input, tool_messages) + + if not tool_results: + logger.error(f"Tool result submission without tool results for thread {input.thread_id}") + yield RunErrorEvent( + type=EventType.RUN_ERROR, + message="No tool results found in submission", + code="NO_TOOL_RESULTS" + ) + return + + # Start new execution with tool results + async for event in self._start_new_execution( + input, + tool_results=tool_results, + message_batch=tool_messages + ): + yield event + + async def _extract_tool_results( + self, + input: RunAgentInput, + candidate_messages: List[Any] + ) -> List[Dict]: + """Extract tool messages with their names from input.""" + tool_call_map = {} + for message in input.messages: + if hasattr(message, 'tool_calls') and message.tool_calls: + for tool_call in message.tool_calls: + tool_call_map[tool_call.id] = tool_call.function.name + + extracted_results: List[Dict] = [] + for message in candidate_messages: + if hasattr(message, 'role') and message.role == "tool": + tool_name = tool_call_map.get(getattr(message, 'tool_call_id', None), "unknown") + extracted_results.append({ + 'tool_name': tool_name, + 'message': message + }) + + return extracted_results + + async def _start_new_execution( + self, + input: RunAgentInput, + *, + tool_results: Optional[List[Dict]] = None, + message_batch: Optional[List[Any]] = None, + ) -> AsyncGenerator[BaseEvent, None]: + """Start a new Claude execution with tool support.""" + try: + # Emit RUN_STARTED + yield RunStartedEvent( + type=EventType.RUN_STARTED, + thread_id=input.thread_id, + run_id=input.run_id + ) + + # Check concurrent execution limit + async with self._execution_lock: + if len(self._active_executions) >= self._max_concurrent: + await self._cleanup_stale_executions() + if len(self._active_executions) >= self._max_concurrent: + raise RuntimeError( + f"Maximum concurrent executions ({self._max_concurrent}) reached" + ) + + existing_execution = self._active_executions.get(input.thread_id) + + # Wait for existing execution if needed + if existing_execution and not existing_execution.is_complete: + logger.debug(f"Waiting for existing execution to complete for thread {input.thread_id}") + try: + await existing_execution.task + except Exception as e: + logger.debug(f"Previous execution completed with error: {e}") + + # Start background execution + execution = await self._start_background_execution( + input, + tool_results=tool_results, + message_batch=message_batch, + ) + + # Store execution + async with self._execution_lock: + self._active_executions[input.thread_id] = execution + + # Stream events + has_tool_calls = False + tool_call_ids = [] + + async for event in self._stream_events(execution): + if isinstance(event, ToolCallEndEvent): + has_tool_calls = True + tool_call_ids.append(event.tool_call_id) + + if isinstance(event, ToolCallResultEvent) and event.tool_call_id in tool_call_ids: + tool_call_ids.remove(event.tool_call_id) + + yield event + + # Track pending tool calls + if has_tool_calls: + app_name = self._get_app_name(input) + user_id = self._get_user_id(input) + for tool_call_id in tool_call_ids: + await self._add_pending_tool_call(input.thread_id, tool_call_id, app_name, user_id) + + # Emit RUN_FINISHED + yield RunFinishedEvent( + type=EventType.RUN_FINISHED, + thread_id=input.thread_id, + run_id=input.run_id + ) + + except Exception as e: + logger.error(f"Error in new execution: {e}", exc_info=True) + yield RunErrorEvent( + type=EventType.RUN_ERROR, + message=str(e), + code="EXECUTION_ERROR" + ) + finally: + # Clean up execution + async with self._execution_lock: + if input.thread_id in self._active_executions: + execution = self._active_executions[input.thread_id] + execution.is_complete = True + has_pending = await self._has_pending_tool_calls(input.thread_id) + if not has_pending: + del self._active_executions[input.thread_id] + + async def _start_background_execution( + self, + input: RunAgentInput, + *, + tool_results: Optional[List[Dict]] = None, + message_batch: Optional[List[Any]] = None, + ) -> ExecutionState: + """Start Claude execution in background with tool support.""" + event_queue = asyncio.Queue() + user_id = self._get_user_id(input) + app_name = self._get_app_name(input) + + # Create background task + task = asyncio.create_task( + self._run_claude_in_background( + input=input, + user_id=user_id, + app_name=app_name, + event_queue=event_queue, + tool_results=tool_results, + message_batch=message_batch, + ) + ) + + return ExecutionState( + task=task, + thread_id=input.thread_id, + event_queue=event_queue + ) + + async def _run_claude_in_background( + self, + input: RunAgentInput, + user_id: str, + app_name: str, + event_queue: asyncio.Queue, + tool_results: Optional[List[Dict]] = None, + message_batch: Optional[List[Any]] = None, + ): + """Run Claude SDK in background, emitting events to queue. + + TODO: Implement based on actual Claude Agent SDK API. + This is a template implementation - adjust based on SDK documentation. + """ + event_translator = EventTranslator() + + try: + # Ensure session exists + await self._session_manager.get_or_create_session( + session_id=input.thread_id, + app_name=app_name, + user_id=user_id, + initial_state=input.state + ) + + # Update session state + await self._session_manager.update_session_state( + input.thread_id, + app_name, + user_id, + input.state + ) + + # Get messages to process + unseen_messages = message_batch if message_batch is not None else await self._get_unseen_messages(input) + + # Extract user prompt from messages + # Claude SDK uses prompt string (for query()) or sends via client.query() + user_prompt = await self._extract_user_prompt(unseen_messages, tool_results) + + if not user_prompt: + logger.warning("No user prompt found in messages") + await event_queue.put( + RunErrorEvent( + type=EventType.RUN_ERROR, + message="No user message found", + code="NO_USER_MESSAGE" + ) + ) + await event_queue.put(None) + return + + # Mark messages as processed before executing + # Collect all message IDs from unseen messages + message_ids_to_mark = [] + for msg in unseen_messages: + msg_id = getattr(msg, "id", None) + if msg_id: + message_ids_to_mark.append(msg_id) + + if message_ids_to_mark: + self._session_manager.mark_messages_processed( + app_name, + input.thread_id, + set(message_ids_to_mark) + ) + + # Prepare tools for this request + request_options = await self._prepare_request_options(input.tools) + + # Get or create Claude client + session_key = self._session_manager._make_session_key(app_name, input.thread_id) + claude_client = None + + # Try to get persistent client if enabled + if self._use_persistent_sessions: + try: + claude_client = self._get_claude_client(session_key, request_options) + except Exception as e: + logger.warning(f"Failed to get persistent client, falling back to stateless mode: {e}") + claude_client = None + + # Use client if available and connected, otherwise use stateless mode + if claude_client and self._use_persistent_sessions: + try: + # For persistent sessions, try to use client + async for claude_message in self._call_claude_sdk(claude_client, user_prompt, request_options): + # Translate Claude message to AG-UI events + async for ag_ui_event in event_translator.translate_claude_message( + claude_message, + input.thread_id, + input.run_id + ): + await event_queue.put(ag_ui_event) + except Exception as e: + # If persistent client fails, fall back to stateless mode + logger.warning(f"Persistent client failed ({e}), falling back to stateless mode") + async for claude_message in self._call_claude_sdk(None, user_prompt, request_options): + async for ag_ui_event in event_translator.translate_claude_message( + claude_message, + input.thread_id, + input.run_id + ): + await event_queue.put(ag_ui_event) + else: + # Stateless mode - use query() function directly + async for claude_message in self._call_claude_sdk(None, user_prompt, request_options): + async for ag_ui_event in event_translator.translate_claude_message( + claude_message, + input.thread_id, + input.run_id + ): + await event_queue.put(ag_ui_event) + + # Force close any streaming messages + async for event in event_translator.force_close_streaming_message(): + await event_queue.put(event) + + # Send final state snapshot + final_state = await self._session_manager.get_session_state( + input.thread_id, + app_name, + user_id + ) + if final_state: + # TODO: Create state snapshot event if needed + pass + + # Signal completion + await event_queue.put(None) + + except Exception as e: + logger.error(f"Background execution error: {e}", exc_info=True) + await event_queue.put( + RunErrorEvent( + type=EventType.RUN_ERROR, + message=str(e), + code="BACKGROUND_EXECUTION_ERROR" + ) + ) + await event_queue.put(None) + + async def _prepare_request_options(self, tools: Optional[List[Any]]) -> Optional[Any]: + """Prepare ClaudeAgentOptions for this request with tools. + + Args: + tools: Optional list of AG-UI tools + + Returns: + ClaudeAgentOptions instance (with cli_path preserved) or None to reuse existing client + """ + if ClaudeAgentOptions is None: + return None + + # Even if no tools, we should return options with cli_path for stateless mode fallback + if not tools: + # Return existing options if available (includes cli_path) + return self._claude_options + + # Convert AG-UI tools to Claude SDK format + from .tool_adapter import ToolAdapter + + try: + # Create MCP server for AG-UI tools + mcp_server = ToolAdapter.create_mcp_server_for_tools( + ag_ui_tools=tools, + server_name="ag_ui_client_tools", + server_version="1.0.0" + ) + + # Build options dict, starting with existing options if any + options_dict = {} + + # Copy existing options attributes if available + if self._claude_options: + # Try to copy common options, including cli_path for CLI tool detection + common_attrs = [ + 'system_prompt', 'permission_mode', 'cwd', 'allowed_tools', + 'mcp_servers', 'setting_sources', 'max_tokens', 'temperature', + 'cli_path' # Important: preserve cli_path for stateless mode fallback + ] + for attr in common_attrs: + if hasattr(self._claude_options, attr): + value = getattr(self._claude_options, attr) + if value is not None: + options_dict[attr] = value + + # Merge MCP servers + if 'mcp_servers' not in options_dict: + options_dict['mcp_servers'] = {} + elif not isinstance(options_dict['mcp_servers'], dict): + options_dict['mcp_servers'] = {} + + options_dict['mcp_servers']['ag_ui_client_tools'] = mcp_server + + # Add tool names to allowed_tools + tool_names = [f"mcp__ag_ui_client_tools__{tool.name}" for tool in tools] + if 'allowed_tools' in options_dict: + existing_tools = options_dict['allowed_tools'] or [] + options_dict['allowed_tools'] = list(set(existing_tools + tool_names)) + else: + options_dict['allowed_tools'] = tool_names + + return ClaudeAgentOptions(**options_dict) + except Exception as e: + logger.error(f"Failed to prepare tools for request: {e}", exc_info=True) + return self._claude_options + + async def _call_claude_sdk( + self, + claude_client: Any, + prompt: str, + options: Optional[Any] = None + ) -> AsyncGenerator[Message, None]: + """Call Claude SDK and yield Message responses. + + Supports both persistent sessions (ClaudeSDKClient) and stateless mode (query()). + + Args: + claude_client: ClaudeSDKClient instance or None for stateless mode + prompt: User prompt string + options: Optional ClaudeAgentOptions for this request + + Yields: + Message objects from Claude SDK + """ + request_options = options or self._claude_options + + if claude_client is None: + # Stateless mode - use query() function + if claude_query is None: + raise ImportError("claude-agent-sdk is not installed") + + async for message in claude_query(prompt=prompt, options=request_options): + yield message + else: + # Persistent session mode - use ClaudeSDKClient + # ClaudeSDKClient is an async context manager and requires connect() before query() + # According to docs: https://docs.claude.com/zh-CN/api/agent-sdk/python + if ClaudeSDKClient and isinstance(ClaudeSDKClient, type) and isinstance(claude_client, ClaudeSDKClient): + # Real ClaudeSDKClient instance - ensure it's connected + # ClaudeSDKClient supports async context manager, but we manage connection manually + # to reuse the same client across multiple queries in the same session + if hasattr(claude_client, 'connect'): + try: + # Check if already connected by trying to connect + # The connect() method will raise an error if already connected + await claude_client.connect() + logger.debug("Connected ClaudeSDKClient") + except Exception as e: + # If already connected, the error message typically contains "already connected" + error_msg = str(e).lower() + if "already connected" in error_msg or "already_connected" in error_msg: + logger.debug("ClaudeSDKClient already connected, reusing connection") + else: + # Re-raise if it's a different error + raise + # For Mock objects or when ClaudeSDKClient is not available, just use it directly + + # Send query to client + # According to docs, query() sends a prompt and returns immediately + await claude_client.query(prompt) + + # Receive response stream + # receive_response() yields messages as they arrive + async for message in claude_client.receive_response(): + yield message + + def _get_claude_client(self, session_key: str, request_options: Optional[Any] = None) -> Any: + """Get or create Claude SDK client for a session. + + For persistent sessions, returns a ClaudeSDKClient instance. + For stateless mode, returns None (will use query() function directly). + + Args: + session_key: Session key for lookup + request_options: Optional options for this request (used when creating new client) + """ + if not self._use_persistent_sessions: + # Stateless mode - use query() function directly + return None + + # Check if we have a persistent client + existing_client = self._session_manager.get_claude_client(session_key) + + # If we have request-specific options with tools, consider recreating client + # For now, reuse existing client if available and no request-specific options + if existing_client and not request_options: + return existing_client + + # Create new ClaudeSDKClient + if ClaudeSDKClient is None: + raise ImportError("claude-agent-sdk is not installed. Install it with: pip install claude-agent-sdk") + + # Use request-specific options if provided, otherwise use default + options = request_options or self._claude_options + + # If we have an existing client but need new options, replace it + if existing_client and request_options: + logger.debug(f"Recreating ClaudeSDKClient for session {session_key} with new options") + + # Create client with options + client = ClaudeSDKClient(options=options) + self._session_manager.set_claude_client(session_key, client) + logger.debug(f"Created new ClaudeSDKClient for session {session_key}") + return client + + async def _extract_user_prompt( + self, + messages: List[Any], + tool_results: Optional[List[Dict]] = None + ) -> str: + """Extract user prompt from AG-UI messages. + + Claude SDK query() and client.query() accept a prompt string. + For multi-turn conversations with persistent sessions, we combine + the conversation history into the prompt. + + Args: + messages: List of AG-UI messages + tool_results: Optional tool result messages + + Returns: + Combined prompt string + """ + if not messages: + return "" + + # Extract text from user messages + user_texts = [] + for message in messages: + if hasattr(message, 'role') and message.role == "user": + content = getattr(message, 'content', '') + if content: + user_texts.append(str(content)) + + # Add tool results if provided + if tool_results: + for tool_result in tool_results: + tool_msg = tool_result['message'] + tool_content = getattr(tool_msg, 'content', '') + if tool_content: + user_texts.append(f"[Tool result]: {tool_content}") + + # Combine into single prompt + # For persistent sessions, Claude SDK maintains conversation history + # So we mainly need the latest user message + if user_texts: + # Use the latest user message as the prompt + return user_texts[-1] + + return "" + + async def _stream_events( + self, + execution: ExecutionState + ) -> AsyncGenerator[BaseEvent, None]: + """Stream events from execution queue.""" + while True: + try: + event = await asyncio.wait_for( + execution.event_queue.get(), + timeout=1.0 + ) + + if event is None: + execution.is_complete = True + break + + yield event + + except asyncio.TimeoutError: + if execution.is_stale(self._execution_timeout): + yield RunErrorEvent( + type=EventType.RUN_ERROR, + message="Execution timed out", + code="EXECUTION_TIMEOUT" + ) + break + + if execution.task.done(): + if execution.event_queue.qsize() > 0: + continue + break + + async def _add_pending_tool_call( + self, + session_id: str, + tool_call_id: str, + app_name: str, + user_id: str + ): + """Add a tool call to the session's pending list.""" + try: + pending_calls = await self._session_manager.get_session_state( + session_id, app_name, user_id + ) or {} + pending_calls = pending_calls.get("pending_tool_calls", []) + + if tool_call_id not in pending_calls: + pending_calls.append(tool_call_id) + await self._session_manager.update_session_state( + session_id, + app_name, + user_id, + {"pending_tool_calls": pending_calls} + ) + except Exception as e: + logger.error(f"Failed to add pending tool call: {e}") + + async def _has_pending_tool_calls(self, session_id: str) -> bool: + """Check if session has pending tool calls.""" + try: + metadata = self._get_session_metadata(session_id) + if metadata: + state = await self._session_manager.get_session_state( + session_id, + metadata["app_name"], + metadata["user_id"] + ) + if state: + return len(state.get("pending_tool_calls", [])) > 0 + except Exception as e: + logger.error(f"Failed to check pending tool calls: {e}") + return False + + def _get_session_metadata(self, session_id: str) -> Optional[Dict[str, str]]: + """Get session metadata.""" + if session_id in self._session_lookup_cache: + return self._session_lookup_cache[session_id] + return None + + async def _cleanup_stale_executions(self): + """Clean up stale executions.""" + stale_threads = [] + for thread_id, execution in self._active_executions.items(): + if execution.is_stale(self._execution_timeout): + stale_threads.append(thread_id) + + for thread_id in stale_threads: + execution = self._active_executions.pop(thread_id) + await execution.cancel() + logger.info(f"Cleaned up stale execution for thread {thread_id}") + + async def close(self): + """Clean up resources.""" + async with self._execution_lock: + for execution in self._active_executions.values(): + await execution.cancel() + self._active_executions.clear() + + self._session_lookup_cache.clear() + await self._session_manager.stop_cleanup_task() + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/endpoint.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/endpoint.py new file mode 100644 index 000000000..4e0a25ed3 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/endpoint.py @@ -0,0 +1,88 @@ +"""FastAPI endpoint for Claude Agent SDK middleware.""" + +from fastapi import FastAPI, Request +from fastapi.responses import StreamingResponse +from ag_ui.core import RunAgentInput +from ag_ui.encoder import EventEncoder +from .claude_agent import ClaudeAgent + +import logging +logger = logging.getLogger(__name__) + + +def add_claude_fastapi_endpoint(app: FastAPI, agent: ClaudeAgent, path: str = "/"): + """Add Claude Agent SDK middleware endpoint to FastAPI app. + + Args: + app: FastAPI application instance + agent: Configured ClaudeAgent instance + path: API endpoint path + """ + + @app.post(path) + async def claude_endpoint(input_data: RunAgentInput, request: Request): + """Claude Agent SDK middleware endpoint.""" + + # Get the accept header from the request + accept_header = request.headers.get("accept") + + # Create an event encoder to properly format SSE events + encoder = EventEncoder(accept=accept_header) + + async def event_generator(): + """Generate events from Claude agent.""" + try: + async for event in agent.run(input_data): + try: + encoded = encoder.encode(event) + logger.debug(f"HTTP Response: {encoded}") + yield encoded + except Exception as encoding_error: + # Handle encoding-specific errors + logger.error(f"Event encoding error: {encoding_error}", exc_info=True) + from ag_ui.core import RunErrorEvent, EventType + error_event = RunErrorEvent( + type=EventType.RUN_ERROR, + message=f"Event encoding failed: {str(encoding_error)}", + code="ENCODING_ERROR" + ) + try: + error_encoded = encoder.encode(error_event) + yield error_encoded + except Exception: + logger.error("Failed to encode error event, yielding basic SSE error") + yield "event: error\ndata: {\"error\": \"Event encoding failed\"}\n\n" + break + except Exception as agent_error: + # Handle errors from ClaudeAgent.run() itself + logger.error(f"ClaudeAgent error: {agent_error}", exc_info=True) + try: + from ag_ui.core import RunErrorEvent, EventType + error_event = RunErrorEvent( + type=EventType.RUN_ERROR, + message=f"Agent execution failed: {str(agent_error)}", + code="AGENT_ERROR" + ) + error_encoded = encoder.encode(error_event) + yield error_encoded + except Exception: + logger.error("Failed to encode agent error event, yielding basic SSE error") + yield "event: error\ndata: {\"error\": \"Agent execution failed\"}\n\n" + + return StreamingResponse(event_generator(), media_type=encoder.get_content_type()) + + +def create_claude_app(agent: ClaudeAgent, path: str = "/") -> FastAPI: + """Create a FastAPI app with Claude Agent SDK middleware endpoint. + + Args: + agent: Configured ClaudeAgent instance + path: API endpoint path + + Returns: + FastAPI application instance + """ + app = FastAPI(title="Claude Agent SDK Middleware for AG-UI Protocol") + add_claude_fastapi_endpoint(app, agent, path) + return app + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/event_translator.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/event_translator.py new file mode 100644 index 000000000..50907c32f --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/event_translator.py @@ -0,0 +1,315 @@ +"""Event translator for converting Claude SDK responses to AG-UI protocol events.""" + +import json +import uuid +from typing import AsyncGenerator, Optional, Dict, Any, List +import logging + +try: + from ag_ui.core import ( + BaseEvent, EventType, + TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent, + ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, + ToolCallResultEvent, StateSnapshotEvent, StateDeltaEvent, + CustomEvent + ) +except ImportError: + pass + +# Claude SDK imports +try: + from claude_agent_sdk import ( + Message, + AssistantMessage, + UserMessage, + SystemMessage, + ResultMessage, + TextBlock, + ToolUseBlock, + ToolResultBlock, + ThinkingBlock, + ) +except ImportError: + # Type checking fallback + Message = None + AssistantMessage = None + TextBlock = None + ToolUseBlock = None + ToolResultBlock = None + ThinkingBlock = None + +logger = logging.getLogger(__name__) + + +class EventTranslator: + """Translates Claude SDK responses to AG-UI protocol events. + + This class handles the conversion between Claude SDK responses and AG-UI events, + managing streaming sequences and maintaining event consistency. + + Note: This implementation is based on common Anthropic SDK patterns. + Actual API may vary - adjust based on Claude Agent SDK documentation. + """ + + def __init__(self): + """Initialize the event translator.""" + # Track tool call IDs for consistency + self._active_tool_calls: Dict[str, str] = {} + # Track streaming message state + self._streaming_message_id: Optional[str] = None + self._is_streaming: bool = False + self._current_stream_text: str = "" + self._last_streamed_text: Optional[str] = None + self._last_streamed_run_id: Optional[str] = None + self.long_running_tool_ids: List[str] = [] + + async def translate_claude_message( + self, + claude_message: Message, + thread_id: str, + run_id: str + ) -> AsyncGenerator[BaseEvent, None]: + """Translate a Claude SDK Message to AG-UI protocol events. + + Args: + claude_message: The Claude SDK Message object + thread_id: The AG-UI thread ID + run_id: The AG-UI run ID + + Yields: + One or more AG-UI protocol events + """ + try: + # Handle different message types + # Use hasattr to check for content attribute (AssistantMessage) or subtype (ResultMessage) + # This works with both real types and Mock objects + if hasattr(claude_message, 'content') and claude_message.content is not None: + # Treat as AssistantMessage + async for event in self._translate_assistant_message( + claude_message, thread_id, run_id + ): + yield event + elif hasattr(claude_message, 'subtype') or (AssistantMessage is not None and isinstance(claude_message, ResultMessage)): + # ResultMessage indicates completion or error + # Close any active streaming message + async for event in self.force_close_streaming_message(): + yield event + + # Check subtype for success/error + subtype = getattr(claude_message, 'subtype', None) + if subtype == 'error': + # Handle error - should already be handled by agent + logger.warning(f"Received error result: {claude_message}") + # UserMessage, SystemMessage are typically input, not output + # They don't need translation to AG-UI events + + except Exception as e: + logger.error(f"Error translating Claude message: {e}", exc_info=True) + + async def _translate_assistant_message( + self, + message: AssistantMessage, + thread_id: str, + run_id: str + ) -> AsyncGenerator[BaseEvent, None]: + """Translate AssistantMessage content blocks to AG-UI events.""" + if not hasattr(message, 'content') or not message.content: + return + + # Process each content block + # Use hasattr checks to support both real types and Mock objects + for block in message.content: + if hasattr(block, 'text'): + # TextBlock has 'text' attribute + async for event in self._translate_text_block(block, thread_id, run_id): + yield event + elif hasattr(block, 'id') and hasattr(block, 'name') and hasattr(block, 'input'): + # ToolUseBlock has 'id', 'name', and 'input' attributes + async for event in self._translate_tool_use_block(block): + yield event + elif hasattr(block, 'tool_use_id') or (hasattr(block, 'id') and hasattr(block, 'content') and not hasattr(block, 'text')): + # ToolResultBlock has 'tool_use_id' or 'id' with 'content' but no 'text' + async for event in self._translate_tool_result_block(block): + yield event + elif isinstance(block, ThinkingBlock) if ThinkingBlock else False: + # Thinking blocks can be translated to thinking events if needed + # For now, we'll skip them or convert to text + logger.debug(f"Received ThinkingBlock: {block}") + + async def _translate_text_block( + self, + block: TextBlock, + thread_id: str, + run_id: str + ) -> AsyncGenerator[BaseEvent, None]: + """Translate TextBlock to AG-UI text message events.""" + text = getattr(block, 'text', '') or '' + if not text: + return + + # Check if this is a complete message or streaming chunk + # Claude SDK streams TextBlocks, so we treat each as a content chunk + if not self._is_streaming: + # Start new message + self._streaming_message_id = str(uuid.uuid4()) + self._is_streaming = True + self._current_stream_text = "" + + yield TextMessageStartEvent( + type=EventType.TEXT_MESSAGE_START, + message_id=self._streaming_message_id, + role="assistant" + ) + + # Add text content + self._current_stream_text += text + yield TextMessageContentEvent( + type=EventType.TEXT_MESSAGE_CONTENT, + message_id=self._streaming_message_id, + delta=text + ) + + async def _translate_tool_use_block( + self, + block: ToolUseBlock + ) -> AsyncGenerator[BaseEvent, None]: + """Translate ToolUseBlock to AG-UI tool call events.""" + # Close any active text stream before tool calls + async for event in self.force_close_streaming_message(): + yield event + + tool_call_id = getattr(block, 'id', None) or str(uuid.uuid4()) + tool_name = getattr(block, 'name', 'unknown') + tool_input = getattr(block, 'input', {}) + + # Check if this is a long-running tool + # This depends on tool configuration - for now, assume client tools are LRO + is_long_running = True # TODO: Determine from tool configuration + + if is_long_running: + self.long_running_tool_ids.append(tool_call_id) + + self._active_tool_calls[tool_call_id] = tool_call_id + + yield ToolCallStartEvent( + type=EventType.TOOL_CALL_START, + tool_call_id=tool_call_id, + tool_call_name=tool_name, + parent_message_id=None + ) + + if tool_input: + args_str = json.dumps(tool_input) if isinstance(tool_input, dict) else str(tool_input) + yield ToolCallArgsEvent( + type=EventType.TOOL_CALL_ARGS, + tool_call_id=tool_call_id, + delta=args_str + ) + + yield ToolCallEndEvent( + type=EventType.TOOL_CALL_END, + tool_call_id=tool_call_id + ) + + self._active_tool_calls.pop(tool_call_id, None) + + async def _translate_tool_result_block( + self, + block: ToolResultBlock + ) -> AsyncGenerator[BaseEvent, None]: + """Translate ToolResultBlock to AG-UI tool result events.""" + tool_call_id = getattr(block, 'tool_use_id', None) or getattr(block, 'id', None) + + if not tool_call_id: + logger.warning("ToolResultBlock missing tool_call_id") + return + + # Skip long-running tools (handled by frontend) + if tool_call_id in self.long_running_tool_ids: + logger.debug(f"Skipping ToolCallResultEvent for long-running tool: {tool_call_id}") + return + + # Extract content from tool result + content = getattr(block, 'content', None) + is_error = getattr(block, 'is_error', False) + + # Convert content to string + if isinstance(content, list): + # Content is list of content blocks + content_str = json.dumps([self._extract_text_from_block(cb) for cb in content]) + elif isinstance(content, str): + content_str = content + else: + content_str = json.dumps(content) if content else "" + + if is_error: + # Mark as error in content + content_str = json.dumps({"error": True, "content": content_str}) + + yield ToolCallResultEvent( + message_id=str(uuid.uuid4()), + type=EventType.TOOL_CALL_RESULT, + tool_call_id=tool_call_id, + content=content_str + ) + + def _extract_text_from_block(self, block: Any) -> str: + """Extract text from a content block.""" + if isinstance(block, dict): + return block.get('text', '') or block.get('content', '') + elif hasattr(block, 'text'): + return block.text + elif hasattr(block, 'content'): + return block.content + else: + return str(block) + + + def _create_state_delta_event( + self, + state_delta: Dict[str, Any], + thread_id: str, + run_id: str + ) -> StateDeltaEvent: + """Create a state delta event from state changes.""" + # Convert to JSON Patch format (RFC 6902) + patches = [] + for key, value in state_delta.items(): + patches.append({ + "op": "add", + "path": f"/{key}", + "value": value + }) + + return StateDeltaEvent( + type=EventType.STATE_DELTA, + delta=patches + ) + + async def force_close_streaming_message(self) -> AsyncGenerator[BaseEvent, None]: + """Force close any open streaming message.""" + if self._is_streaming and self._streaming_message_id: + logger.warning(f"Force-closing unterminated streaming message: {self._streaming_message_id}") + yield TextMessageEndEvent( + type=EventType.TEXT_MESSAGE_END, + message_id=self._streaming_message_id + ) + self._reset_streaming_state() + + def _reset_streaming_state(self): + """Reset streaming state.""" + if self._current_stream_text: + self._last_streamed_text = self._current_stream_text + self._current_stream_text = "" + self._streaming_message_id = None + self._is_streaming = False + + def reset(self): + """Reset the translator state.""" + self._active_tool_calls.clear() + self._reset_streaming_state() + self._last_streamed_text = None + self._last_streamed_run_id = None + self.long_running_tool_ids.clear() + logger.debug("Reset EventTranslator state") + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/execution_state.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/execution_state.py new file mode 100644 index 000000000..2079a4067 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/execution_state.py @@ -0,0 +1,124 @@ +"""Execution state management for background Claude SDK runs with tool support.""" + +import asyncio +import time +from typing import Optional, Set +import logging + +logger = logging.getLogger(__name__) + + +class ExecutionState: + """Manages the state of a background Claude SDK execution. + + This class tracks: + - The background asyncio task running the Claude SDK client + - Event queue for streaming results to the client + - Execution timing and completion state + """ + + def __init__( + self, + task: asyncio.Task, + thread_id: str, + event_queue: asyncio.Queue + ): + """Initialize execution state. + + Args: + task: The asyncio task running the Claude SDK client + thread_id: The thread ID for this execution + event_queue: Queue containing events to stream to client + """ + self.task = task + self.thread_id = thread_id + self.event_queue = event_queue + self.start_time = time.time() + self.is_complete = False + self.pending_tool_calls: Set[str] = set() # Track outstanding tool call IDs for HITL + + logger.debug(f"Created execution state for thread {thread_id}") + + def is_stale(self, timeout_seconds: int) -> bool: + """Check if this execution has been running too long. + + Args: + timeout_seconds: Maximum execution time in seconds + + Returns: + True if execution has exceeded timeout + """ + return time.time() - self.start_time > timeout_seconds + + async def cancel(self): + """Cancel the execution and clean up resources.""" + logger.info(f"Cancelling execution for thread {self.thread_id}") + + # Cancel the background task + if not self.task.done(): + self.task.cancel() + try: + await self.task + except asyncio.CancelledError: + pass + + self.is_complete = True + + def get_execution_time(self) -> float: + """Get the total execution time in seconds. + + Returns: + Time in seconds since execution started + """ + return time.time() - self.start_time + + def add_pending_tool_call(self, tool_call_id: str): + """Add a tool call ID to the pending set. + + Args: + tool_call_id: The tool call ID to track + """ + self.pending_tool_calls.add(tool_call_id) + logger.debug(f"Added pending tool call {tool_call_id} to thread {self.thread_id}") + + def remove_pending_tool_call(self, tool_call_id: str): + """Remove a tool call ID from the pending set. + + Args: + tool_call_id: The tool call ID to remove + """ + self.pending_tool_calls.discard(tool_call_id) + logger.debug(f"Removed pending tool call {tool_call_id} from thread {self.thread_id}") + + def has_pending_tool_calls(self) -> bool: + """Check if there are outstanding tool calls waiting for responses. + + Returns: + True if there are pending tool calls (HITL scenario) + """ + return len(self.pending_tool_calls) > 0 + + def get_status(self) -> str: + """Get a human-readable status of the execution. + + Returns: + Status string describing the current state + """ + if self.is_complete: + if self.has_pending_tool_calls(): + return "complete_awaiting_tools" + else: + return "complete" + elif self.task.done(): + return "task_done" + else: + return "running" + + def __repr__(self) -> str: + """String representation of the execution state.""" + return ( + f"ExecutionState(thread_id='{self.thread_id}', " + f"status='{self.get_status()}', " + f"runtime={self.get_execution_time():.1f}s)" + ) + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/session_manager.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/session_manager.py new file mode 100644 index 000000000..bb96b9810 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/session_manager.py @@ -0,0 +1,453 @@ +"""Session manager for Claude SDK integration.""" + +from typing import Dict, Optional, Set, Any, List, Union +import asyncio +import logging +import time + +logger = logging.getLogger(__name__) + + +class SessionManager: + """Session manager for Claude SDK sessions. + + Manages conversation sessions, message tracking, and state management. + Supports both persistent client sessions and stateless query mode. + """ + + _instance = None + _initialized = False + + def __new__(cls, **kwargs): + """Ensure singleton instance.""" + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def __init__( + self, + session_timeout_seconds: int = 1200, # 20 minutes default + cleanup_interval_seconds: int = 300, # 5 minutes + max_sessions_per_user: Optional[int] = None, + auto_cleanup: bool = True + ): + """Initialize the session manager. + + Args: + session_timeout_seconds: Time before a session is considered expired + cleanup_interval_seconds: Interval between cleanup cycles + max_sessions_per_user: Maximum concurrent sessions per user (None = unlimited) + auto_cleanup: Enable automatic session cleanup task + """ + if self._initialized: + return + + self._timeout = session_timeout_seconds + self._cleanup_interval = cleanup_interval_seconds + self._max_per_user = max_sessions_per_user + self._auto_cleanup = auto_cleanup + + # Session tracking + self._sessions: Dict[str, Dict[str, Any]] = {} # session_key -> session_data + self._session_keys: Set[str] = set() # "app_name:session_id" keys + self._user_sessions: Dict[str, Set[str]] = {} # user_id -> set of session_keys + self._processed_message_ids: Dict[str, Set[str]] = {} # session_key -> set of message_ids + self._claude_clients: Dict[str, Any] = {} # session_key -> Claude SDK client (if using persistent mode) + + self._cleanup_task: Optional[asyncio.Task] = None + self._initialized = True + + logger.info( + f"Initialized SessionManager - " + f"timeout: {session_timeout_seconds}s, " + f"cleanup: {cleanup_interval_seconds}s, " + f"max/user: {max_sessions_per_user or 'unlimited'}" + ) + + @classmethod + def get_instance(cls, **kwargs): + """Get the singleton instance.""" + return cls(**kwargs) + + @classmethod + def reset_instance(cls): + """Reset singleton for testing.""" + if cls._instance and hasattr(cls._instance, '_cleanup_task'): + task = cls._instance._cleanup_task + if task: + try: + task.cancel() + except RuntimeError: + pass + cls._instance = None + cls._initialized = False + + def _make_session_key(self, app_name: str, session_id: str) -> str: + """Create a session key.""" + return f"{app_name}:{session_id}" + + def _track_session(self, session_key: str, user_id: str): + """Track a session key.""" + self._session_keys.add(session_key) + if user_id not in self._user_sessions: + self._user_sessions[user_id] = set() + self._user_sessions[user_id].add(session_key) + + def _untrack_session(self, session_key: str, user_id: str): + """Remove session tracking.""" + self._session_keys.discard(session_key) + self._sessions.pop(session_key, None) + self._processed_message_ids.pop(session_key, None) + self._claude_clients.pop(session_key, None) + + if user_id in self._user_sessions: + self._user_sessions[user_id].discard(session_key) + if not self._user_sessions[user_id]: + del self._user_sessions[user_id] + + async def get_or_create_session( + self, + session_id: str, + app_name: str, + user_id: str, + initial_state: Optional[Dict[str, Any]] = None + ) -> Dict[str, Any]: + """Get existing session or create new one. + + Returns session data dictionary. + """ + session_key = self._make_session_key(app_name, session_id) + + # Check user limits before creating + if session_key not in self._session_keys and self._max_per_user: + user_count = len(self._user_sessions.get(user_id, set())) + if user_count >= self._max_per_user: + await self._remove_oldest_user_session(user_id) + + if session_key not in self._sessions: + # Create new session + self._sessions[session_key] = { + "session_id": session_id, + "app_name": app_name, + "user_id": user_id, + "state": initial_state or {}, + "created_at": time.time(), + "last_update_time": time.time(), + "messages": [] + } + logger.info(f"Created new session: {session_key}") + else: + # Update last access time + self._sessions[session_key]["last_update_time"] = time.time() + logger.debug(f"Retrieved existing session: {session_key}") + + # Track the session + self._track_session(session_key, user_id) + + # Start cleanup if needed + if self._auto_cleanup and not self._cleanup_task: + self._start_cleanup_task() + + return self._sessions[session_key] + + def get_processed_message_ids(self, app_name: str, session_id: str) -> Set[str]: + """Get processed message IDs for a session.""" + session_key = self._make_session_key(app_name, session_id) + return set(self._processed_message_ids.get(session_key, set())) + + def mark_messages_processed( + self, + app_name: str, + session_id: str, + message_ids: Set[str], + ) -> None: + """Mark messages as processed.""" + session_key = self._make_session_key(app_name, session_id) + processed_ids = self._processed_message_ids.setdefault(session_key, set()) + processed_ids.update(message_ids) + + async def update_session_state( + self, + session_id: str, + app_name: str, + user_id: str, + state_updates: Dict[str, Any], + merge: bool = True + ) -> bool: + """Update session state. + + Args: + session_id: Session identifier + app_name: Application name + user_id: User identifier + state_updates: Dictionary of state key-value pairs to update + merge: If True, merge with existing state; if False, replace completely + + Returns: + True if successful, False otherwise + """ + try: + session_key = self._make_session_key(app_name, session_id) + if session_key not in self._sessions: + logger.debug(f"Session not found for update: {session_key}") + return False + + if merge: + self._sessions[session_key]["state"].update(state_updates) + else: + self._sessions[session_key]["state"] = state_updates + + self._sessions[session_key]["last_update_time"] = time.time() + logger.debug(f"Updated state for session {session_key}") + return True + except Exception as e: + logger.error(f"Failed to update session state: {e}", exc_info=True) + return False + + async def get_session_state( + self, + session_id: str, + app_name: str, + user_id: str + ) -> Optional[Dict[str, Any]]: + """Get current session state.""" + try: + session_key = self._make_session_key(app_name, session_id) + if session_key not in self._sessions: + return None + return self._sessions[session_key].get("state", {}) + except Exception as e: + logger.error(f"Failed to get session state: {e}", exc_info=True) + return None + + async def get_state_value( + self, + session_id: str, + app_name: str, + user_id: str, + key: str, + default: Any = None + ) -> Any: + """Get a specific state value by key. + + Args: + session_id: Session identifier + app_name: Application name + user_id: User identifier + key: State key to retrieve + default: Default value if key not found + + Returns: + State value or default + """ + state = await self.get_session_state(session_id, app_name, user_id) + if state is None: + return default + return state.get(key, default) + + async def set_state_value( + self, + session_id: str, + app_name: str, + user_id: str, + key: str, + value: Any + ) -> bool: + """Set a specific state value by key. + + Args: + session_id: Session identifier + app_name: Application name + user_id: User identifier + key: State key to set + value: Value to set + + Returns: + True if successful, False otherwise + """ + return await self.update_session_state( + session_id=session_id, + app_name=app_name, + user_id=user_id, + state_updates={key: value} + ) + + async def remove_state_keys( + self, + session_id: str, + app_name: str, + user_id: str, + keys: Union[str, List[str]] + ) -> bool: + """Remove one or more state keys. + + Args: + session_id: Session identifier + app_name: Application name + user_id: User identifier + keys: Key or list of keys to remove + + Returns: + True if successful, False otherwise + """ + try: + session_key = self._make_session_key(app_name, session_id) + if session_key not in self._sessions: + return False + + if isinstance(keys, str): + keys = [keys] + + state = self._sessions[session_key].get("state", {}) + for key in keys: + state.pop(key, None) + + self._sessions[session_key]["last_update_time"] = time.time() + logger.debug(f"Removed state keys {keys} from session {session_key}") + return True + except Exception as e: + logger.error(f"Failed to remove state keys: {e}", exc_info=True) + return False + + async def clear_session_state( + self, + session_id: str, + app_name: str, + user_id: str, + preserve_prefixes: Optional[List[str]] = None + ) -> bool: + """Clear session state, optionally preserving keys with specific prefixes. + + Args: + session_id: Session identifier + app_name: Application name + user_id: User identifier + preserve_prefixes: List of prefixes to preserve (e.g., ["user_", "app_"]) + + Returns: + True if successful, False otherwise + """ + try: + session_key = self._make_session_key(app_name, session_id) + if session_key not in self._sessions: + return False + + state = self._sessions[session_key].get("state", {}) + preserve_prefixes = preserve_prefixes or [] + + # Build new state with preserved keys + new_state = {} + for key, value in state.items(): + should_preserve = any(key.startswith(prefix) for prefix in preserve_prefixes) + if should_preserve: + new_state[key] = value + + self._sessions[session_key]["state"] = new_state + self._sessions[session_key]["last_update_time"] = time.time() + logger.debug(f"Cleared session state for {session_key}, preserved {len(new_state)} keys") + return True + except Exception as e: + logger.error(f"Failed to clear session state: {e}", exc_info=True) + return False + + def get_session_count(self) -> int: + """Get total number of active sessions. + + Returns: + Number of active sessions + """ + return len(self._session_keys) + + def get_user_session_count(self, user_id: str) -> int: + """Get number of active sessions for a specific user. + + Args: + user_id: User identifier + + Returns: + Number of active sessions for the user + """ + return len(self._user_sessions.get(user_id, set())) + + def get_claude_client(self, session_key: str) -> Optional[Any]: + """Get Claude SDK client for a session (if using persistent mode).""" + return self._claude_clients.get(session_key) + + def set_claude_client(self, session_key: str, client: Any): + """Set Claude SDK client for a session.""" + self._claude_clients[session_key] = client + + def _start_cleanup_task(self): + """Start the cleanup task if not already running.""" + try: + loop = asyncio.get_running_loop() + self._cleanup_task = loop.create_task(self._cleanup_loop()) + logger.debug(f"Started session cleanup task") + except RuntimeError: + logger.debug("No event loop, cleanup will start later") + + async def _cleanup_loop(self): + """Periodically clean up expired sessions.""" + logger.debug("Cleanup loop started") + while True: + try: + await asyncio.sleep(self._cleanup_interval) + await self._cleanup_expired_sessions() + except asyncio.CancelledError: + logger.info("Cleanup task cancelled") + break + except Exception as e: + logger.error(f"Cleanup error: {e}", exc_info=True) + + async def _cleanup_expired_sessions(self): + """Clean up expired sessions and disconnect ClaudeSDKClient connections.""" + current_time = time.time() + expired_count = 0 + + for session_key in list(self._session_keys): + session = self._sessions.get(session_key) + if not session: + continue + + age = current_time - session["last_update_time"] + if age > self._timeout: + # Check for pending tool calls before deletion (HITL scenarios) + pending_calls = session.get("state", {}).get("pending_tool_calls", []) + if pending_calls: + logger.info(f"Preserving expired session {session_key} - has {len(pending_calls)} pending tool calls") + else: + user_id = session["user_id"] + self._untrack_session(session_key, user_id) + expired_count += 1 + + if expired_count > 0: + logger.info(f"Cleaned up {expired_count} expired sessions") + + async def _remove_oldest_user_session(self, user_id: str): + """Remove the oldest session for a user.""" + if user_id not in self._user_sessions: + return + + oldest_session_key = None + oldest_time = float('inf') + + for session_key in self._user_sessions[user_id]: + session = self._sessions.get(session_key) + if session and session["last_update_time"] < oldest_time: + oldest_time = session["last_update_time"] + oldest_session_key = session_key + + if oldest_session_key: + self._untrack_session(oldest_session_key, user_id) + logger.info(f"Removed oldest session for user {user_id}: {oldest_session_key}") + + async def stop_cleanup_task(self): + """Stop the cleanup task.""" + if self._cleanup_task: + self._cleanup_task.cancel() + try: + await self._cleanup_task + except asyncio.CancelledError: + pass + self._cleanup_task = None + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/tool_adapter.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/tool_adapter.py new file mode 100644 index 000000000..a968aa2e4 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/tool_adapter.py @@ -0,0 +1,182 @@ +"""Tool adapter for converting AG-UI tools to Claude SDK format.""" + +import json +from typing import List, Dict, Any, Optional +import logging + +try: + from ag_ui.core import Tool as AGUITool +except ImportError: + AGUITool = None + +try: + from claude_agent_sdk import SdkMcpTool, create_sdk_mcp_server +except ImportError: + SdkMcpTool = None + create_sdk_mcp_server = None + +logger = logging.getLogger(__name__) + + +class ToolAdapter: + """Adapter for converting AG-UI tools to Claude SDK tool format. + + Note: This implementation is based on common Anthropic SDK patterns. + Adjust based on actual Claude Agent SDK tool format (e.g., SdkMcpTool). + """ + + @staticmethod + def convert_ag_ui_tool_to_claude(ag_ui_tool: AGUITool) -> Any: + """Convert an AG-UI tool to Claude SDK SdkMcpTool format. + + Args: + ag_ui_tool: AG-UI tool definition + + Returns: + SdkMcpTool instance + + Note: For client-side tools (long-running), we create a placeholder handler. + The actual tool execution is handled by the frontend via AG-UI events. + For backend tools, implement the actual handler logic. + """ + if SdkMcpTool is None: + raise ImportError("claude-agent-sdk is not installed. Install it with: pip install claude-agent-sdk") + + # Convert AG-UI parameters (JSON Schema) to Claude format + parameters = ag_ui_tool.parameters + + # Ensure it's a proper object schema + if not isinstance(parameters, dict): + parameters = {"type": "object", "properties": {}} + logger.warning(f"Tool {ag_ui_tool.name} had non-dict parameters, using empty schema") + + # For client-side tools (long-running), create a placeholder handler + # The tool will emit events to frontend, which executes it + async def placeholder_handler(args: Dict[str, Any]) -> Dict[str, Any]: + """Placeholder handler for client-side long-running tools. + + This handler should not be called for client-side tools. + The tool execution happens on the frontend via AG-UI events. + If this is called, it indicates a configuration issue. + """ + logger.warning( + f"Placeholder handler called for client-side tool '{ag_ui_tool.name}'. " + f"This should not happen - tool execution should be handled by frontend." + ) + return { + "content": [{ + "type": "text", + "text": "Tool execution handled by frontend" + }] + } + + # Create SdkMcpTool with placeholder handler + # Note: The actual tool execution flow: + # 1. Claude SDK calls tool -> ToolUseBlock emitted + # 2. EventTranslator converts to AG-UI TOOL_CALL_* events + # 3. Frontend receives events and executes tool + # 4. Frontend sends ToolMessage back + # 5. Tool result processed and sent to Claude SDK + claude_tool = SdkMcpTool( + name=ag_ui_tool.name, + description=ag_ui_tool.description or "", + input_schema=parameters, + handler=placeholder_handler + ) + + logger.debug(f"Converted AG-UI tool '{ag_ui_tool.name}' to SdkMcpTool (client-side)") + return claude_tool + + @staticmethod + def convert_ag_ui_tools_to_claude(ag_ui_tools: List[AGUITool]) -> List[Any]: + """Convert a list of AG-UI tools to Claude SDK format. + + Args: + ag_ui_tools: List of AG-UI tool definitions + + Returns: + List of SdkMcpTool instances + """ + return [ + ToolAdapter.convert_ag_ui_tool_to_claude(tool) + for tool in ag_ui_tools + ] + + @staticmethod + def create_mcp_server_for_tools( + ag_ui_tools: List[AGUITool], + server_name: str = "ag_ui_tools", + server_version: str = "1.0.0" + ) -> Any: + """Create an MCP server for AG-UI tools. + + Args: + ag_ui_tools: List of AG-UI tool definitions + server_name: Name for the MCP server + server_version: Version for the MCP server + + Returns: + MCP server instance + """ + if create_sdk_mcp_server is None: + raise ImportError("claude-agent-sdk is not installed") + + claude_tools = ToolAdapter.convert_ag_ui_tools_to_claude(ag_ui_tools) + + return create_sdk_mcp_server( + name=server_name, + version=server_version, + tools=claude_tools + ) + + @staticmethod + def is_long_running_tool(ag_ui_tool: AGUITool) -> bool: + """Check if a tool should be treated as long-running (client-side execution). + + Args: + ag_ui_tool: AG-UI tool definition + + Returns: + True if tool should be executed on client side + """ + # TODO: Determine logic for long-running tools + # For now, assume all client-provided tools are long-running + # Backend tools should be handled separately + return True + + @staticmethod + def extract_tool_call_id(tool_call: Any) -> Optional[str]: + """Extract tool call ID from Claude SDK ToolUseBlock. + + Args: + tool_call: Claude SDK ToolUseBlock object + + Returns: + Tool call ID or None + """ + return getattr(tool_call, 'id', None) + + @staticmethod + def extract_tool_name(tool_call: Any) -> Optional[str]: + """Extract tool name from Claude SDK ToolUseBlock. + + Args: + tool_call: Claude SDK ToolUseBlock object + + Returns: + Tool name or None + """ + return getattr(tool_call, 'name', None) + + @staticmethod + def extract_tool_args(tool_call: Any) -> Dict[str, Any]: + """Extract tool arguments from Claude SDK ToolUseBlock. + + Args: + tool_call: Claude SDK ToolUseBlock object + + Returns: + Dictionary of tool arguments + """ + return getattr(tool_call, 'input', {}) or {} + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/__init__.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/__init__.py new file mode 100644 index 000000000..557443e64 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/__init__.py @@ -0,0 +1,2 @@ +"""Utility functions for Claude Agent SDK integration.""" + diff --git a/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/converters.py b/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/converters.py new file mode 100644 index 000000000..054ba5e36 --- /dev/null +++ b/integrations/claude-agent-sdk/python/src/ag_ui_claude/utils/converters.py @@ -0,0 +1,203 @@ +"""Conversion utilities between AG-UI and Claude SDK formats.""" + +from typing import List, Dict, Any, Optional +import json +import logging + +from ag_ui.core import ( + Message, UserMessage, AssistantMessage, SystemMessage, ToolMessage, + ToolCall, FunctionCall +) + +logger = logging.getLogger(__name__) + + +def convert_ag_ui_messages_to_claude(messages: List[Message]) -> List[Dict[str, Any]]: + """Convert AG-UI messages to Claude SDK message format. + + Args: + messages: List of AG-UI messages + + Returns: + List of Claude SDK message dictionaries + + TODO: Adjust based on actual Claude SDK message format. + Example format might be: + [ + {"role": "user", "content": "..."}, + {"role": "assistant", "content": "..."}, + {"role": "tool", "tool_call_id": "...", "content": "..."} + ] + """ + claude_messages = [] + + for message in messages: + try: + role = message.role + + if isinstance(message, (UserMessage, SystemMessage)): + claude_messages.append({ + "role": role, + "content": message.content or "" + }) + + elif isinstance(message, AssistantMessage): + content_parts = [] + + # Add text content if present + if message.content: + content_parts.append({ + "type": "text", + "text": message.content + }) + + # Add tool calls if present + if message.tool_calls: + for tool_call in message.tool_calls: + content_parts.append({ + "type": "tool_use", + "id": tool_call.id, + "name": tool_call.function.name, + "input": json.loads(tool_call.function.arguments) if isinstance(tool_call.function.arguments, str) else tool_call.function.arguments + }) + + claude_messages.append({ + "role": "assistant", + "content": content_parts if content_parts else [{"type": "text", "text": ""}] + }) + + elif isinstance(message, ToolMessage): + claude_messages.append({ + "role": "tool", + "tool_call_id": message.tool_call_id, + "content": message.content or "" + }) + + except Exception as e: + logger.error(f"Error converting message {getattr(message, 'id', 'unknown')}: {e}") + continue + + return claude_messages + + +def convert_claude_message_to_ag_ui(claude_message: Dict[str, Any]) -> Optional[Message]: + """Convert a Claude SDK message to an AG-UI message. + + Args: + claude_message: Claude SDK message dictionary + + Returns: + AG-UI message or None if not convertible + + TODO: Adjust based on actual Claude SDK message format. + """ + try: + role = claude_message.get("role") + content = claude_message.get("content", "") + + if role == "user": + # Handle string or array content + if isinstance(content, str): + text = content + elif isinstance(content, list): + text = " ".join( + item.get("text", "") if isinstance(item, dict) else str(item) + for item in content + ) + else: + text = str(content) + + return UserMessage( + id=claude_message.get("id"), + role="user", + content=text + ) + + elif role == "assistant": + # Extract text and tool calls + text_parts = [] + tool_calls = [] + + if isinstance(content, list): + for part in content: + if isinstance(part, dict): + if part.get("type") == "text": + text_parts.append(part.get("text", "")) + elif part.get("type") == "tool_use": + tool_calls.append(ToolCall( + id=part.get("id"), + type="function", + function=FunctionCall( + name=part.get("name", ""), + arguments=json.dumps(part.get("input", {})) + ) + )) + elif isinstance(content, str): + text_parts.append(content) + + return AssistantMessage( + id=claude_message.get("id"), + role="assistant", + content="\n".join(text_parts) if text_parts else None, + tool_calls=tool_calls if tool_calls else None + ) + + elif role == "tool": + return ToolMessage( + id=claude_message.get("id"), + role="tool", + tool_call_id=claude_message.get("tool_call_id"), + content=claude_message.get("content", "") + ) + + except Exception as e: + logger.error(f"Error converting Claude message: {e}") + + return None + + +def convert_state_to_json_patch(state_delta: Dict[str, Any]) -> List[Dict[str, Any]]: + """Convert a state delta to JSON Patch format (RFC 6902). + + Args: + state_delta: Dictionary of state changes + + Returns: + List of JSON Patch operations + """ + patches = [] + + for key, value in state_delta.items(): + if value is None: + patches.append({ + "op": "remove", + "path": f"/{key}" + }) + else: + patches.append({ + "op": "add", + "path": f"/{key}", + "value": value + }) + + return patches + + +def create_error_message(error: Exception, context: str = "") -> str: + """Create a user-friendly error message. + + Args: + error: The exception + context: Additional context about where the error occurred + + Returns: + Formatted error message + """ + error_type = type(error).__name__ + error_msg = str(error) + + if context: + return f"{context}: {error_type} - {error_msg}" + else: + return f"{error_type}: {error_msg}" + diff --git a/integrations/claude-agent-sdk/python/tests/__init__.py b/integrations/claude-agent-sdk/python/tests/__init__.py new file mode 100644 index 000000000..1bd6ff3e8 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/__init__.py @@ -0,0 +1,2 @@ +"""Tests for Claude Agent SDK integration.""" + diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/__init__.cpython-312.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 000000000..40f07dde3 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/conftest.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/conftest.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..eea1b6f11 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/conftest.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_claude_agent.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_claude_agent.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..bbb9da072 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_claude_agent.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_endpoint.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_endpoint.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..b0e21f9de Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_endpoint.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_event_translator.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_event_translator.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..3e0fe14b4 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_event_translator.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_basic.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_basic.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..d5cece3a8 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_basic.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_sessions.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_sessions.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..db57a31b0 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_sessions.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_tools.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_tools.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..e382c6c38 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_integration_tools.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_real_api.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_real_api.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..1374019e9 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_real_api.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_session_manager.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_session_manager.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..4a5c15317 Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_session_manager.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/__pycache__/test_tool_adapter.cpython-312-pytest-8.4.2.pyc b/integrations/claude-agent-sdk/python/tests/__pycache__/test_tool_adapter.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 000000000..7d1d6685c Binary files /dev/null and b/integrations/claude-agent-sdk/python/tests/__pycache__/test_tool_adapter.cpython-312-pytest-8.4.2.pyc differ diff --git a/integrations/claude-agent-sdk/python/tests/conftest.py b/integrations/claude-agent-sdk/python/tests/conftest.py new file mode 100644 index 000000000..2d0f5f900 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/conftest.py @@ -0,0 +1,219 @@ +"""Pytest configuration and shared fixtures for Claude Agent SDK tests.""" + +import os +import pytest +from pathlib import Path +from unittest.mock import Mock, MagicMock, AsyncMock +from types import SimpleNamespace + +# Load environment variables from .env.local if it exists +try: + from dotenv import load_dotenv + + # Get the project root directory (integrations/claude-agent-sdk/python) + project_root = Path(__file__).parent.parent + + # Try to load .env.local first, then fall back to .env + env_local = project_root / ".env.local" + env_file = project_root / ".env" + + if env_local.exists(): + load_dotenv(env_local, override=True) + print(f"Loaded environment variables from {env_local}") + elif env_file.exists(): + load_dotenv(env_file, override=True) + print(f"Loaded environment variables from {env_file}") +except ImportError: + # python-dotenv not installed, skip loading + pass + +try: + from ag_ui.core import RunAgentInput, UserMessage, Tool as AGUITool +except ImportError: + pass + +try: + from claude_agent_sdk import ( + ClaudeSDKClient, + ClaudeAgentOptions, + AssistantMessage, + TextBlock, + ToolUseBlock, + ResultMessage, + ) +except ImportError: + # Type checking fallback + pass + + +@pytest.fixture(autouse=True) +def reset_session_manager(): + """Reset session manager before and after each test.""" + from ag_ui_claude.session_manager import SessionManager + + try: + SessionManager.reset_instance() + except (RuntimeError, AttributeError): + # Event loop may be closed or instance not initialized - ignore + pass + + yield + + # Cleanup after test + try: + SessionManager.reset_instance() + except (RuntimeError, AttributeError): + pass + + +@pytest.fixture +def mock_claude_sdk_client(): + """Create a mock ClaudeSDKClient.""" + client = AsyncMock(spec=ClaudeSDKClient) + + # Mock the query method + async def mock_query(prompt: str): + pass + + # Mock the receive_response method + async def mock_receive_response(): + # Return empty generator by default + if False: + yield + + client.query = AsyncMock(side_effect=mock_query) + client.receive_response = AsyncMock(side_effect=mock_receive_response) + + return client + + +@pytest.fixture +def mock_claude_agent_options(): + """Create a mock ClaudeAgentOptions.""" + options = Mock(spec=ClaudeAgentOptions) + options.system_prompt = None + options.permission_mode = None + options.allowed_tools = None + options.mcp_servers = None + return options + + +@pytest.fixture +def sample_run_agent_input(): + """Create a sample RunAgentInput for testing.""" + return RunAgentInput( + thread_id="test_thread_001", + run_id="test_run_001", + messages=[ + UserMessage( + id="msg_1", + role="user", + content="Hello, Claude!" + ) + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + +@pytest.fixture +def sample_ag_ui_tool(): + """Create a sample AG-UI Tool for testing.""" + return AGUITool( + name="get_weather", + description="Get the current weather", + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state" + } + }, + "required": ["location"] + } + ) + + +@pytest.fixture +def mock_assistant_message_with_text(): + """Create a mock AssistantMessage with TextBlock.""" + text_block = SimpleNamespace() + text_block.text = "Hello! How can I help you?" + + # Create a class that mimics AssistantMessage + class MockAssistantMessage: + def __init__(self): + self.content = [text_block] + + message = MockAssistantMessage() + return message + + +@pytest.fixture +def mock_assistant_message_with_tool(): + """Create a mock AssistantMessage with ToolUseBlock.""" + tool_block = SimpleNamespace() + tool_block.id = "tool_call_123" + tool_block.name = "get_weather" + tool_block.input = {"location": "San Francisco"} + + class MockAssistantMessage: + def __init__(self): + self.content = [tool_block] + + message = MockAssistantMessage() + return message + + +@pytest.fixture +def mock_result_message_success(): + """Create a mock ResultMessage indicating success.""" + class MockResultMessage: + def __init__(self): + self.subtype = "success" + + message = MockResultMessage() + return message + + +@pytest.fixture +def mock_result_message_error(): + """Create a mock ResultMessage indicating error.""" + class MockResultMessage: + def __init__(self): + self.subtype = "error" + + message = MockResultMessage() + return message + + +@pytest.fixture +def claude_agent_persistent(): + """Create a ClaudeAgent instance with persistent sessions.""" + from ag_ui_claude import ClaudeAgent + + return ClaudeAgent( + use_persistent_sessions=True, + app_name="test_app", + user_id="test_user", + execution_timeout_seconds=60, + max_concurrent_executions=5 + ) + + +@pytest.fixture +def claude_agent_stateless(): + """Create a ClaudeAgent instance with stateless mode.""" + from ag_ui_claude import ClaudeAgent + + return ClaudeAgent( + use_persistent_sessions=False, + app_name="test_app", + user_id="test_user", + execution_timeout_seconds=60, + max_concurrent_executions=5 + ) + diff --git a/integrations/claude-agent-sdk/python/tests/test_claude_agent.py b/integrations/claude-agent-sdk/python/tests/test_claude_agent.py new file mode 100644 index 000000000..79f5aa765 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_claude_agent.py @@ -0,0 +1,264 @@ +"""Tests for ClaudeAgent middleware.""" + +import pytest +import asyncio +from unittest.mock import Mock, MagicMock, AsyncMock, patch, call +from types import SimpleNamespace + +from ag_ui_claude import ClaudeAgent, SessionManager +from ag_ui.core import ( + RunAgentInput, EventType, UserMessage, SystemMessage, + RunStartedEvent, RunFinishedEvent, RunErrorEvent, + TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent, + ToolCallStartEvent, ToolCallEndEvent +) + + +class TestClaudeAgent: + """Test cases for ClaudeAgent.""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager before each test.""" + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.fixture + def claude_agent_persistent(self): + """Create ClaudeAgent with persistent sessions.""" + return ClaudeAgent( + use_persistent_sessions=True, + app_name="test_app", + user_id="test_user", + execution_timeout_seconds=60, + max_concurrent_executions=5 + ) + + @pytest.fixture + def claude_agent_stateless(self): + """Create ClaudeAgent with stateless mode.""" + return ClaudeAgent( + use_persistent_sessions=False, + app_name="test_app", + user_id="test_user", + execution_timeout_seconds=60, + max_concurrent_executions=5 + ) + + @pytest.fixture + def sample_input(self): + """Create a sample RunAgentInput.""" + return RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage( + id="msg_1", + role="user", + content="Hello!" + ) + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + def test_initialization_persistent(self): + """Test ClaudeAgent initialization with persistent sessions.""" + agent = ClaudeAgent( + use_persistent_sessions=True, + app_name="test_app", + user_id="test_user" + ) + + assert agent._use_persistent_sessions is True + assert agent._static_app_name == "test_app" + assert agent._static_user_id == "test_user" + + def test_initialization_stateless(self): + """Test ClaudeAgent initialization with stateless mode.""" + agent = ClaudeAgent( + use_persistent_sessions=False, + app_name="test_app" + ) + + assert agent._use_persistent_sessions is False + + def test_initialization_with_claude_options(self): + """Test initialization with ClaudeAgentOptions.""" + from claude_agent_sdk import ClaudeAgentOptions + + options = ClaudeAgentOptions(system_prompt="Test prompt") + agent = ClaudeAgent( + claude_options=options, + app_name="test_app" + ) + + assert agent._claude_options == options + + def test_app_name_extraction(self, claude_agent_persistent, sample_input): + """Test app name extraction.""" + app_name = claude_agent_persistent._get_app_name(sample_input) + assert app_name == "test_app" + + def test_user_id_extraction(self, claude_agent_persistent, sample_input): + """Test user ID extraction.""" + user_id = claude_agent_persistent._get_user_id(sample_input) + assert user_id == "test_user" + + @pytest.mark.asyncio + async def test_get_unseen_messages(self, claude_agent_persistent, sample_input): + """Test unseen messages extraction.""" + unseen = await claude_agent_persistent._get_unseen_messages(sample_input) + assert len(unseen) == 1 + assert unseen[0].content == "Hello!" + + @pytest.mark.asyncio + async def test_get_unseen_messages_with_processed(self, claude_agent_persistent, sample_input): + """Test unseen messages with processed message IDs.""" + # Mark message as processed + claude_agent_persistent._session_manager.mark_messages_processed( + "test_app", + "test_thread", + ["msg_1"] + ) + + unseen = await claude_agent_persistent._get_unseen_messages(sample_input) + assert len(unseen) == 0 + + @pytest.mark.asyncio + async def test_extract_user_prompt(self, claude_agent_persistent): + """Test user prompt extraction.""" + messages = [ + UserMessage(id="1", role="user", content="First message"), + UserMessage(id="2", role="user", content="Second message") + ] + + prompt = await claude_agent_persistent._extract_user_prompt(messages) + assert prompt == "Second message" + + @pytest.mark.asyncio + async def test_extract_user_prompt_empty(self, claude_agent_persistent): + """Test user prompt extraction with empty messages.""" + prompt = await claude_agent_persistent._extract_user_prompt([]) + assert prompt == "" + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.ClaudeSDKClient') + async def test_get_claude_client_persistent(self, mock_client_class, claude_agent_persistent): + """Test getting Claude client in persistent mode.""" + mock_client = AsyncMock() + mock_client_class.return_value = mock_client + + session_key = "test_app:test_thread" + client = claude_agent_persistent._get_claude_client(session_key) + + assert client is not None + mock_client_class.assert_called_once() + + @pytest.mark.asyncio + async def test_get_claude_client_stateless(self, claude_agent_stateless): + """Test getting Claude client in stateless mode.""" + session_key = "test_app:test_thread" + client = claude_agent_stateless._get_claude_client(session_key) + + assert client is None + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.claude_query') + async def test_call_claude_sdk_stateless(self, mock_query, claude_agent_stateless): + """Test calling Claude SDK in stateless mode.""" + # Mock messages - use MagicMock instead of SimpleNamespace with __class__ assignment + mock_message = MagicMock() + + async def mock_query_gen(): + yield mock_message + + mock_query.return_value = mock_query_gen() + + messages = [] + async for msg in claude_agent_stateless._call_claude_sdk(None, "test prompt", None): + messages.append(msg) + + assert len(messages) == 1 + mock_query.assert_called_once() + + @pytest.mark.asyncio + async def test_is_tool_result_submission_true(self, claude_agent_persistent): + """Test detecting tool result submission.""" + from ag_ui.core import ToolMessage + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="1", role="user", content="Hello"), + ToolMessage(id="2", role="tool", tool_call_id="tool_1", content="result") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + is_tool_result = await claude_agent_persistent._is_tool_result_submission(input_data) + assert is_tool_result is True + + @pytest.mark.asyncio + async def test_is_tool_result_submission_false(self, claude_agent_persistent, sample_input): + """Test detecting non-tool result submission.""" + is_tool_result = await claude_agent_persistent._is_tool_result_submission(sample_input) + assert is_tool_result is False + + @pytest.mark.asyncio + async def test_prepare_request_options_no_tools(self, claude_agent_persistent): + """Test preparing request options without tools.""" + options = await claude_agent_persistent._prepare_request_options(None) + assert options is None # Should return None when no tools provided + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.ClaudeAgentOptions') + @patch('ag_ui_claude.tool_adapter.ToolAdapter') + async def test_prepare_request_options_with_tools( + self, mock_tool_adapter, mock_options_class, claude_agent_persistent, sample_ag_ui_tool + ): + """Test preparing request options with tools.""" + # Mock MCP server + mock_mcp_server = Mock() + mock_tool_adapter.create_mcp_server_for_tools.return_value = mock_mcp_server + + # Mock options + mock_options = Mock() + mock_options_class.return_value = mock_options + + tools = [sample_ag_ui_tool] + options = await claude_agent_persistent._prepare_request_options(tools) + + assert options is not None + mock_tool_adapter.create_mcp_server_for_tools.assert_called_once() + + @pytest.mark.asyncio + async def test_run_error_on_no_user_message(self, claude_agent_persistent): + """Test run() handles missing user message.""" + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[], # No user messages + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events = [] + async for event in claude_agent_persistent.run(input_data): + events.append(event) + + # Should emit RUN_STARTED and then handle the error + assert len(events) > 0 + # Check if we got an error or finished event + event_types = [e.type for e in events] + assert EventType.RUN_STARTED in event_types + diff --git a/integrations/claude-agent-sdk/python/tests/test_endpoint.py b/integrations/claude-agent-sdk/python/tests/test_endpoint.py new file mode 100644 index 000000000..e46771d10 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_endpoint.py @@ -0,0 +1,165 @@ +"""Tests for FastAPI endpoint integration.""" + +import pytest +from unittest.mock import Mock, AsyncMock, patch +from fastapi.testclient import TestClient + +from ag_ui_claude.endpoint import add_claude_fastapi_endpoint, create_claude_app +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage, EventType, RunStartedEvent, RunFinishedEvent + + +class TestAddClaudeFastAPIEndpoint: + """Test cases for add_claude_fastapi_endpoint.""" + + @pytest.fixture + def mock_agent(self): + """Create a mock ClaudeAgent.""" + agent = AsyncMock(spec=ClaudeAgent) + + async def mock_run(input_data): + yield RunStartedEvent( + type=EventType.RUN_STARTED, + thread_id=input_data.thread_id, + run_id=input_data.run_id + ) + yield RunFinishedEvent( + type=EventType.RUN_FINISHED, + thread_id=input_data.thread_id, + run_id=input_data.run_id + ) + + agent.run = AsyncMock(side_effect=mock_run) + return agent + + @pytest.fixture + def app(self, mock_agent): + """Create a FastAPI app with Claude endpoint.""" + from fastapi import FastAPI + + app = FastAPI() + add_claude_fastapi_endpoint(app, mock_agent, path="/chat") + return app + + @pytest.fixture + def client(self, app): + """Create a test client.""" + return TestClient(app) + + def test_endpoint_exists(self, client): + """Test that the endpoint exists.""" + # Test with invalid request to check endpoint exists + response = client.post("/chat", json={}) + # Should not be 404 + assert response.status_code != 404 + + def test_endpoint_accepts_run_agent_input(self, client, mock_agent): + """Test that endpoint accepts RunAgentInput.""" + input_data = { + "thread_id": "test_thread", + "run_id": "test_run", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "Hello!" + } + ], + "state": {}, + "context": [], + "tools": [], + "forwarded_props": {} + } + + response = client.post("/chat", json=input_data) + + # Should process the request (may return 200 or streaming response) + assert response.status_code in [200, 200] # Streaming may return 200 + + # Verify agent.run was called + assert mock_agent.run.called + + def test_endpoint_streaming_response(self, client, mock_agent): + """Test that endpoint returns streaming response.""" + input_data = { + "thread_id": "test_thread", + "run_id": "test_run", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "Hello!" + } + ], + "state": {}, + "context": [], + "tools": [], + "forwarded_props": {} + } + + response = client.post( + "/chat", + json=input_data, + headers={"Accept": "text/event-stream"} + ) + + # Should return streaming response + assert response.status_code == 200 + # Content type should be for SSE + assert "text/event-stream" in response.headers.get("content-type", "").lower() or \ + "application/x-ndjson" in response.headers.get("content-type", "").lower() + + def test_endpoint_error_handling(self, client): + """Test endpoint error handling.""" + # Create agent that raises error + error_agent = AsyncMock(spec=ClaudeAgent) + + async def error_run(input_data): + raise Exception("Test error") + + error_agent.run = AsyncMock(side_effect=error_run) + + from fastapi import FastAPI + app = FastAPI() + add_claude_fastapi_endpoint(app, error_agent, path="/chat") + + client = TestClient(app) + + input_data = { + "thread_id": "test_thread", + "run_id": "test_run", + "messages": [], + "state": {}, + "context": [], + "tools": [], + "forwarded_props": {} + } + + response = client.post("/chat", json=input_data) + + # Should handle error gracefully + assert response.status_code in [200, 500] # May return error event or 500 + + +class TestCreateClaudeApp: + """Test cases for create_claude_app.""" + + @pytest.fixture + def mock_agent(self): + """Create a mock ClaudeAgent.""" + return AsyncMock(spec=ClaudeAgent) + + def test_create_claude_app(self, mock_agent): + """Test creating Claude app.""" + app = create_claude_app(mock_agent, path="/claude-chat") + + assert app is not None + # Verify it's a FastAPI app + assert hasattr(app, "post") + + def test_create_claude_app_default_path(self, mock_agent): + """Test creating Claude app with default path.""" + app = create_claude_app(mock_agent) + + assert app is not None + diff --git a/integrations/claude-agent-sdk/python/tests/test_event_translator.py b/integrations/claude-agent-sdk/python/tests/test_event_translator.py new file mode 100644 index 000000000..f93b02bab --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_event_translator.py @@ -0,0 +1,241 @@ +"""Tests for EventTranslator.""" + +import pytest +from unittest.mock import Mock, MagicMock +from types import SimpleNamespace + +from ag_ui_claude.event_translator import EventTranslator +from ag_ui.core import ( + EventType, + TextMessageStartEvent, + TextMessageContentEvent, + TextMessageEndEvent, + ToolCallStartEvent, + ToolCallArgsEvent, + ToolCallEndEvent, + ToolCallResultEvent, +) + + +class TestEventTranslator: + """Test cases for EventTranslator.""" + + @pytest.fixture + def translator(self): + """Create an EventTranslator instance.""" + return EventTranslator() + + def test_initialization(self, translator): + """Test EventTranslator initialization.""" + assert translator._active_tool_calls == {} + assert translator._streaming_message_id is None + assert translator._is_streaming is False + assert translator._current_stream_text == "" + + @pytest.mark.asyncio + async def test_translate_text_block(self, translator): + """Test translating TextBlock to AG-UI events.""" + text_block = SimpleNamespace() + text_block.text = "Hello, world!" + + events = [] + async for event in translator._translate_text_block(text_block, "thread_1", "run_1"): + events.append(event) + + assert len(events) == 2 # START + CONTENT + assert isinstance(events[0], TextMessageStartEvent) + assert isinstance(events[1], TextMessageContentEvent) + assert events[1].delta == "Hello, world!" + + @pytest.mark.asyncio + async def test_translate_text_block_streaming(self, translator): + """Test translating multiple TextBlocks in sequence.""" + # First block + block1 = SimpleNamespace() + block1.text = "Hello, " + + events1 = [] + async for event in translator._translate_text_block(block1, "thread_1", "run_1"): + events1.append(event) + + # Second block + block2 = SimpleNamespace() + block2.text = "world!" + + events2 = [] + async for event in translator._translate_text_block(block2, "thread_1", "run_1"): + events2.append(event) + + # Should have START from first, CONTENT from both + assert len(events1) == 2 + assert len(events2) == 1 # Only CONTENT, reusing message_id + assert events2[0].delta == "world!" + + @pytest.mark.asyncio + async def test_translate_tool_use_block(self, translator): + """Test translating ToolUseBlock to AG-UI events.""" + tool_block = SimpleNamespace() + tool_block.id = "tool_call_123" + tool_block.name = "get_weather" + tool_block.input = {"location": "San Francisco"} + + events = [] + async for event in translator._translate_tool_use_block(tool_block): + events.append(event) + + assert len(events) >= 3 # START, ARGS, END + assert isinstance(events[0], ToolCallStartEvent) + assert events[0].tool_call_id == "tool_call_123" + assert events[0].tool_call_name == "get_weather" + assert isinstance(events[-1], ToolCallEndEvent) + + @pytest.mark.asyncio + async def test_translate_tool_result_block(self, translator): + """Test translating ToolResultBlock to AG-UI events.""" + tool_result_block = SimpleNamespace() + tool_result_block.tool_use_id = "tool_call_123" + tool_result_block.content = "Sunny, 72°F" + tool_result_block.is_error = False + + events = [] + async for event in translator._translate_tool_result_block(tool_result_block): + events.append(event) + + assert len(events) == 1 + assert isinstance(events[0], ToolCallResultEvent) + assert events[0].tool_call_id == "tool_call_123" + + @pytest.mark.asyncio + async def test_translate_tool_result_block_error(self, translator): + """Test translating ToolResultBlock with error.""" + tool_result_block = SimpleNamespace() + tool_result_block.tool_use_id = "tool_call_123" + tool_result_block.content = "Error occurred" + tool_result_block.is_error = True + + events = [] + async for event in translator._translate_tool_result_block(tool_result_block): + events.append(event) + + assert len(events) == 1 + assert isinstance(events[0], ToolCallResultEvent) + # Error should be marked in content + assert "error" in events[0].content.lower() or "true" in events[0].content.lower() + + @pytest.mark.asyncio + async def test_translate_assistant_message_text(self, translator): + """Test translating AssistantMessage with TextBlock.""" + text_block = SimpleNamespace() + text_block.text = "Hello!" + + message = SimpleNamespace() + message.content = [text_block] + + events = [] + async for event in translator._translate_assistant_message(message, "thread_1", "run_1"): + events.append(event) + + assert len(events) >= 1 + assert any(isinstance(e, TextMessageStartEvent) for e in events) + assert any(isinstance(e, TextMessageContentEvent) for e in events) + + @pytest.mark.asyncio + async def test_translate_assistant_message_tool(self, translator): + """Test translating AssistantMessage with ToolUseBlock.""" + tool_block = SimpleNamespace() + tool_block.id = "tool_1" + tool_block.name = "test_tool" + tool_block.input = {} + + message = SimpleNamespace() + message.content = [tool_block] + + events = [] + async for event in translator._translate_assistant_message(message, "thread_1", "run_1"): + events.append(event) + + assert len(events) >= 1 + assert any(isinstance(e, ToolCallStartEvent) for e in events) + + @pytest.mark.asyncio + async def test_translate_result_message_success(self, translator): + """Test translating ResultMessage with success.""" + result_message = SimpleNamespace() + result_message.subtype = "success" + + events = [] + async for event in translator.translate_claude_message(result_message, "thread_1", "run_1"): + events.append(event) + + # Should close any streaming messages + assert len(events) >= 0 # May have force_close_streaming_message events + + @pytest.mark.asyncio + async def test_force_close_streaming_message(self, translator): + """Test force closing streaming message.""" + # Start streaming + text_block = SimpleNamespace() + text_block.text = "Hello" + + async for _ in translator._translate_text_block(text_block, "thread_1", "run_1"): + pass + + # Force close + events = [] + async for event in translator.force_close_streaming_message(): + events.append(event) + + assert len(events) == 1 + assert isinstance(events[0], TextMessageEndEvent) + assert translator._is_streaming is False + + @pytest.mark.asyncio + async def test_force_close_no_streaming(self, translator): + """Test force close when not streaming.""" + events = [] + async for event in translator.force_close_streaming_message(): + events.append(event) + + assert len(events) == 0 + + def test_reset(self, translator): + """Test resetting translator state.""" + # Set some state + translator._streaming_message_id = "msg_123" + translator._is_streaming = True + translator._active_tool_calls["tool_1"] = "tool_1" + + translator.reset() + + assert translator._streaming_message_id is None + assert translator._is_streaming is False + assert translator._active_tool_calls == {} + + @pytest.mark.asyncio + async def test_translate_claude_message_assistant(self, translator): + """Test translating AssistantMessage.""" + text_block = SimpleNamespace() + text_block.text = "Response" + + message = SimpleNamespace() + message.content = [text_block] + + events = [] + async for event in translator.translate_claude_message(message, "thread_1", "run_1"): + events.append(event) + + assert len(events) > 0 + + @pytest.mark.asyncio + async def test_translate_claude_message_result(self, translator): + """Test translating ResultMessage.""" + result_message = SimpleNamespace() + result_message.subtype = "success" + + events = [] + async for event in translator.translate_claude_message(result_message, "thread_1", "run_1"): + events.append(event) + + # Should handle result message + assert isinstance(events, list) + diff --git a/integrations/claude-agent-sdk/python/tests/test_integration_basic.py b/integrations/claude-agent-sdk/python/tests/test_integration_basic.py new file mode 100644 index 000000000..d91762248 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_integration_basic.py @@ -0,0 +1,170 @@ +"""Integration tests for basic Claude Agent SDK functionality.""" + +import pytest +from unittest.mock import Mock, AsyncMock, patch +from types import SimpleNamespace + +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage, EventType, RunStartedEvent, RunFinishedEvent + + +class TestBasicIntegration: + """Basic integration tests.""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager.""" + from ag_ui_claude.session_manager import SessionManager + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.fixture + def claude_agent(self): + """Create ClaudeAgent instance.""" + return ClaudeAgent( + use_persistent_sessions=False, # Use stateless for simpler testing + app_name="test_app", + user_id="test_user" + ) + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.claude_query') + async def test_basic_conversation_flow(self, mock_query, claude_agent): + """Test basic conversation flow.""" + # Mock Claude SDK response + text_block = SimpleNamespace() + text_block.text = "Hello! How can I help you?" + + assistant_message = SimpleNamespace() + assistant_message.content = [text_block] + + result_message = SimpleNamespace() + result_message.subtype = "success" + + async def mock_query_gen(): + yield assistant_message + yield result_message + + mock_query.return_value = mock_query_gen() + + # Create input + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="Hello!") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + # Run agent + events = [] + async for event in claude_agent.run(input_data): + events.append(event) + + # Verify events + assert len(events) > 0 + + # Should have RUN_STARTED + event_types = [e.type for e in events] + assert EventType.RUN_STARTED in event_types + + # Should have RUN_FINISHED + assert EventType.RUN_FINISHED in event_types + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.ClaudeSDKClient') + async def test_persistent_session_flow(self, mock_client_class, claude_agent): + """Test persistent session flow.""" + # Switch to persistent mode + claude_agent._use_persistent_sessions = True + + # Mock client + mock_client = AsyncMock() + mock_client.query = AsyncMock() + + async def mock_receive(): + text_block = SimpleNamespace() + text_block.text = "Response" + + message = SimpleNamespace() + message.__class__ = type('AssistantMessage', (), {}) + message.content = [text_block] + + result_message = SimpleNamespace() + result_message.__class__ = type('ResultMessage', (), {}) + result_message.subtype = "success" + + yield message + yield result_message + + mock_client.receive_response = AsyncMock(side_effect=mock_receive) + mock_client_class.return_value = mock_client + + # Create input + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="Hello!") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + # Run agent + events = [] + async for event in claude_agent.run(input_data): + events.append(event) + + # Verify client was used + assert mock_client.query.called + + @pytest.mark.asyncio + async def test_event_sequence(self, claude_agent): + """Test that events are emitted in correct sequence.""" + with patch('ag_ui_claude.claude_agent.claude_query') as mock_query: + # Mock response + text_block = SimpleNamespace() + text_block.text = "Test" + + message = SimpleNamespace() + message.content = [text_block] + + result_message = SimpleNamespace() + result_message.subtype = "success" + + async def mock_gen(): + yield message + yield result_message + + mock_query.return_value = mock_gen() + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="Test") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events = [] + async for event in claude_agent.run(input_data): + events.append(event) + + # Check sequence: RUN_STARTED should come first + assert events[0].type == EventType.RUN_STARTED + + # RUN_FINISHED should come last + assert events[-1].type == EventType.RUN_FINISHED + diff --git a/integrations/claude-agent-sdk/python/tests/test_integration_sessions.py b/integrations/claude-agent-sdk/python/tests/test_integration_sessions.py new file mode 100644 index 000000000..1fdbf84a1 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_integration_sessions.py @@ -0,0 +1,162 @@ +"""Integration tests for session management.""" + +import pytest +from unittest.mock import Mock, AsyncMock, patch +from types import SimpleNamespace + +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage, EventType + + +class TestSessionIntegration: + """Session integration tests.""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager.""" + from ag_ui_claude.session_manager import SessionManager + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.fixture + def claude_agent_persistent(self): + """Create ClaudeAgent with persistent sessions.""" + return ClaudeAgent( + use_persistent_sessions=True, + app_name="test_app", + user_id="test_user" + ) + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.ClaudeSDKClient') + async def test_persistent_session_reuse(self, mock_client_class, claude_agent_persistent): + """Test that persistent sessions reuse clients.""" + mock_client = AsyncMock() + mock_client.query = AsyncMock() + + async def mock_receive(): + result_message = SimpleNamespace() + result_message.subtype = "success" + yield result_message + + mock_client.receive_response = mock_receive + mock_client_class.return_value = mock_client + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run_1", + messages=[ + UserMessage(id="msg_1", role="user", content="First message") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + # First run + events1 = [] + async for event in claude_agent_persistent.run(input_data): + events1.append(event) + + # Second run with same thread_id + input_data2 = RunAgentInput( + thread_id="test_thread", # Same thread + run_id="test_run_2", + messages=[ + UserMessage(id="msg_2", role="user", content="Second message") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events2 = [] + async for event in claude_agent_persistent.run(input_data2): + events2.append(event) + + # Client should be reused (created once) + assert mock_client_class.call_count == 1 + + @pytest.mark.asyncio + async def test_stateless_session_no_reuse(self, claude_agent_persistent): + """Test that stateless mode doesn't reuse sessions.""" + claude_agent_persistent._use_persistent_sessions = False + + with patch('ag_ui_claude.claude_agent.claude_query') as mock_query: + async def mock_gen(): + result_message = SimpleNamespace() + result_message = SimpleNamespace() + result_message.subtype = "success" + yield result_message + + mock_query.return_value = mock_gen() + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="Hello") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events = [] + async for event in claude_agent_persistent.run(input_data): + events.append(event) + + # Should use query() function directly + assert mock_query.called + + @pytest.mark.asyncio + async def test_message_deduplication(self, claude_agent_persistent): + """Test message deduplication across runs.""" + with patch('ag_ui_claude.claude_agent.claude_query') as mock_query: + async def mock_gen(): + result_message = SimpleNamespace() + result_message = SimpleNamespace() + result_message.subtype = "success" + yield result_message + + mock_query.return_value = mock_gen() + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run_1", + messages=[ + UserMessage(id="msg_1", role="user", content="First") + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + # First run + async for _ in claude_agent_persistent.run(input_data): + pass + + # Second run with same message + input_data2 = RunAgentInput( + thread_id="test_thread", + run_id="test_run_2", + messages=[ + UserMessage(id="msg_1", role="user", content="First"), # Same message + UserMessage(id="msg_2", role="user", content="Second") # New message + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + # Should only process unseen messages + unseen = await claude_agent_persistent._get_unseen_messages(input_data2) + assert len(unseen) == 1 # Only msg_2 should be unseen + assert unseen[0].id == "msg_2" + diff --git a/integrations/claude-agent-sdk/python/tests/test_integration_tools.py b/integrations/claude-agent-sdk/python/tests/test_integration_tools.py new file mode 100644 index 000000000..ce2712653 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_integration_tools.py @@ -0,0 +1,150 @@ +"""Integration tests for tool calling functionality.""" + +import pytest +from unittest.mock import Mock, AsyncMock, patch +from types import SimpleNamespace + +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage, Tool as AGUITool, ToolMessage, EventType + + +class TestToolIntegration: + """Tool integration tests.""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager.""" + from ag_ui_claude.session_manager import SessionManager + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.fixture + def claude_agent(self): + """Create ClaudeAgent instance.""" + return ClaudeAgent( + use_persistent_sessions=False, + app_name="test_app", + user_id="test_user" + ) + + @pytest.fixture + def sample_tool(self): + """Create a sample tool.""" + return AGUITool( + name="get_weather", + description="Get weather", + parameters={ + "type": "object", + "properties": { + "location": {"type": "string"} + }, + "required": ["location"] + } + ) + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.claude_query') + async def test_tool_call_flow(self, mock_query, claude_agent, sample_tool): + """Test tool call flow.""" + # Mock tool use block + tool_block = SimpleNamespace() + tool_block.id = "tool_call_123" + tool_block.name = "get_weather" + tool_block.input = {"location": "San Francisco"} + + message = SimpleNamespace() + message.content = [tool_block] + + result_message = SimpleNamespace() + result_message.subtype = "success" + + async def mock_gen(): + yield message + yield result_message + + mock_query.return_value = mock_gen() + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="What's the weather?") + ], + state={}, + context=[], + tools=[sample_tool], + forwarded_props={} + ) + + events = [] + async for event in claude_agent.run(input_data): + events.append(event) + + # Should have tool call events + event_types = [e.type for e in events] + assert EventType.TOOL_CALL_START in event_types + assert EventType.TOOL_CALL_END in event_types + + @pytest.mark.asyncio + @patch('ag_ui_claude.claude_agent.claude_query') + async def test_tool_result_submission(self, mock_query, claude_agent, sample_tool): + """Test tool result submission flow.""" + # Mock response after tool result + text_block = SimpleNamespace() + text_block.text = "The weather is sunny." + + message = SimpleNamespace() + message.content = [text_block] + + result_message = SimpleNamespace() + result_message.subtype = "success" + + async def mock_gen(): + yield message + yield result_message + + mock_query.return_value = mock_gen() + + # Input with tool result + from ag_ui.core import AssistantMessage as AGUIAssistantMessage, ToolCall, FunctionCall + + input_data = RunAgentInput( + thread_id="test_thread", + run_id="test_run", + messages=[ + UserMessage(id="msg_1", role="user", content="What's the weather?"), + AGUIAssistantMessage( + id="msg_2", + role="assistant", + content="", + tool_calls=[ + ToolCall( + id="tool_call_123", + function=FunctionCall( + name="get_weather", + arguments='{"location": "San Francisco"}' + ) + ) + ] + ), + ToolMessage( + id="msg_3", + role="tool", + tool_call_id="tool_call_123", + content="Sunny, 72°F" + ) + ], + state={}, + context=[], + tools=[sample_tool], + forwarded_props={} + ) + + events = [] + async for event in claude_agent.run(input_data): + events.append(event) + + # Should process tool result and continue + assert len(events) > 0 + diff --git a/integrations/claude-agent-sdk/python/tests/test_real_api.py b/integrations/claude-agent-sdk/python/tests/test_real_api.py new file mode 100644 index 000000000..4427a235e --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_real_api.py @@ -0,0 +1,110 @@ +"""Optional real API tests for Claude Agent SDK integration. + +These tests require authentication credentials (ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY). +Skip if not available. +""" + +import pytest +import os + +from ag_ui_claude import ClaudeAgent +from ag_ui.core import RunAgentInput, UserMessage + + +def has_auth_credentials(): + """Check if any authentication credentials are available.""" + return bool(os.getenv("ANTHROPIC_AUTH_TOKEN") or os.getenv("ANTHROPIC_API_KEY")) + + +@pytest.mark.skipif( + not has_auth_credentials(), + reason="No authentication credentials found (ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY) - skipping real API tests" +) +class TestRealAPI: + """Real API integration tests (optional).""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager.""" + from ag_ui_claude.session_manager import SessionManager + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.fixture + def claude_agent(self): + """Create ClaudeAgent with real API.""" + return ClaudeAgent( + use_persistent_sessions=False, # Use stateless for simpler testing + app_name="test_app", + user_id="test_user" + ) + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_real_api_basic_conversation(self, claude_agent): + """Test basic conversation with real API.""" + input_data = RunAgentInput( + thread_id="test_thread_real", + run_id="test_run_real", + messages=[ + UserMessage( + id="msg_1", + role="user", + content="Say hello in exactly 3 words." + ) + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events = [] + try: + async for event in claude_agent.run(input_data): + events.append(event) + print(f"Event: {event.type}") + except Exception as e: + pytest.fail(f"Real API test failed: {e}") + + # Should have events + assert len(events) > 0 + + # Should have RUN_STARTED and RUN_FINISHED + event_types = [e.type for e in events] + assert "RUN_STARTED" in str(event_types) + assert "RUN_FINISHED" in str(event_types) + + @pytest.mark.asyncio + @pytest.mark.integration + async def test_real_api_with_system_message(self, claude_agent): + """Test with system message.""" + from ag_ui.core import SystemMessage + + input_data = RunAgentInput( + thread_id="test_thread_system", + run_id="test_run_system", + messages=[ + SystemMessage(id="sys_msg_1", content="You are a helpful assistant."), + UserMessage( + id="msg_1", + role="user", + content="What is 2+2?" + ) + ], + state={}, + context=[], + tools=[], + forwarded_props={} + ) + + events = [] + try: + async for event in claude_agent.run(input_data): + events.append(event) + except Exception as e: + pytest.fail(f"Real API test with system message failed: {e}") + + assert len(events) > 0 + diff --git a/integrations/claude-agent-sdk/python/tests/test_session_manager.py b/integrations/claude-agent-sdk/python/tests/test_session_manager.py new file mode 100644 index 000000000..fbff235d9 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_session_manager.py @@ -0,0 +1,301 @@ +"""Tests for SessionManager.""" + +import pytest +import asyncio +from ag_ui_claude.session_manager import SessionManager + + +class TestSessionManager: + """Test cases for SessionManager.""" + + @pytest.fixture(autouse=True) + def reset_session_manager(self): + """Reset session manager before and after each test.""" + SessionManager.reset_instance() + yield + SessionManager.reset_instance() + + @pytest.mark.asyncio + async def test_get_or_create_session_new(self): + """Test creating a new session.""" + manager = SessionManager.get_instance() + + session_state = await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"key": "value"} + ) + + assert session_state is not None + assert isinstance(session_state, dict) + + @pytest.mark.asyncio + async def test_get_or_create_session_existing(self): + """Test getting an existing session.""" + manager = SessionManager.get_instance() + + # Create session + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"key": "value"} + ) + + # Get existing session + session_state = await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + assert session_state is not None + + @pytest.mark.asyncio + async def test_update_session_state(self): + """Test updating session state.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + success = await manager.update_session_state( + session_id="test_session", + app_name="test_app", + user_id="test_user", + state_updates={"new_key": "new_value"} + ) + + assert success is True + + state = await manager.get_session_state( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + assert state is not None + assert state.get("new_key") == "new_value" + + @pytest.mark.asyncio + async def test_get_state_value(self): + """Test getting a specific state value.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"key": "value"} + ) + + value = await manager.get_state_value( + session_id="test_session", + app_name="test_app", + user_id="test_user", + key="key" + ) + + assert value == "value" + + @pytest.mark.asyncio + async def test_get_state_value_default(self): + """Test getting state value with default.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + value = await manager.get_state_value( + session_id="test_session", + app_name="test_app", + user_id="test_user", + key="nonexistent", + default="default_value" + ) + + assert value == "default_value" + + @pytest.mark.asyncio + async def test_set_state_value(self): + """Test setting a specific state value.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + success = await manager.set_state_value( + session_id="test_session", + app_name="test_app", + user_id="test_user", + key="test_key", + value="test_value" + ) + + assert success is True + + value = await manager.get_state_value( + session_id="test_session", + app_name="test_app", + user_id="test_user", + key="test_key" + ) + + assert value == "test_value" + + @pytest.mark.asyncio + async def test_remove_state_keys(self): + """Test removing state keys.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"key1": "value1", "key2": "value2"} + ) + + success = await manager.remove_state_keys( + session_id="test_session", + app_name="test_app", + user_id="test_user", + keys=["key1"] + ) + + assert success is True + + value = await manager.get_state_value( + session_id="test_session", + app_name="test_app", + user_id="test_user", + key="key1" + ) + + assert value is None + + @pytest.mark.asyncio + async def test_mark_messages_processed(self): + """Test marking messages as processed.""" + manager = SessionManager.get_instance() + + manager.mark_messages_processed( + app_name="test_app", + session_id="test_session", + message_ids=["msg_1", "msg_2"] + ) + + processed = manager.get_processed_message_ids("test_app", "test_session") + assert "msg_1" in processed + assert "msg_2" in processed + + @pytest.mark.asyncio + async def test_get_processed_message_ids(self): + """Test getting processed message IDs.""" + manager = SessionManager.get_instance() + + manager.mark_messages_processed( + app_name="test_app", + session_id="test_session", + message_ids=["msg_1"] + ) + + processed = manager.get_processed_message_ids("test_app", "test_session") + assert "msg_1" in processed + + def test_make_session_key(self): + """Test session key generation.""" + manager = SessionManager.get_instance() + + key = manager._make_session_key("test_app", "test_session") + assert key == "test_app:test_session" + + def test_get_session_count(self): + """Test getting session count.""" + manager = SessionManager.get_instance() + + # Initially should be 0 + count = manager.get_session_count() + assert count == 0 + + def test_get_user_session_count(self): + """Test getting user session count.""" + manager = SessionManager.get_instance() + + count = manager.get_user_session_count("test_user") + assert count == 0 + + @pytest.mark.asyncio + async def test_clear_session_state(self): + """Test clearing session state.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"key1": "value1", "key2": "value2"} + ) + + success = await manager.clear_session_state( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + assert success is True + + state = await manager.get_session_state( + session_id="test_session", + app_name="test_app", + user_id="test_user" + ) + + # State should be cleared or minimal + assert state is None or len(state) == 0 + + @pytest.mark.asyncio + async def test_clear_session_state_preserve_prefixes(self): + """Test clearing session state with preserved prefixes.""" + manager = SessionManager.get_instance() + + await manager.get_or_create_session( + session_id="test_session", + app_name="test_app", + user_id="test_user", + initial_state={"keep_this": "value", "remove_this": "value"} + ) + + success = await manager.clear_session_state( + session_id="test_session", + app_name="test_app", + user_id="test_user", + preserve_prefixes=["keep_"] + ) + + assert success is True + + def test_singleton_pattern(self): + """Test that SessionManager is a singleton.""" + manager1 = SessionManager.get_instance() + manager2 = SessionManager.get_instance() + + assert manager1 is manager2 + + def test_reset_instance(self): + """Test resetting the singleton instance.""" + manager1 = SessionManager.get_instance() + SessionManager.reset_instance() + manager2 = SessionManager.get_instance() + + assert manager1 is not manager2 + diff --git a/integrations/claude-agent-sdk/python/tests/test_tool_adapter.py b/integrations/claude-agent-sdk/python/tests/test_tool_adapter.py new file mode 100644 index 000000000..ee7eb0230 --- /dev/null +++ b/integrations/claude-agent-sdk/python/tests/test_tool_adapter.py @@ -0,0 +1,136 @@ +"""Tests for ToolAdapter.""" + +import pytest +from unittest.mock import Mock, patch, MagicMock + +from ag_ui_claude.tool_adapter import ToolAdapter +from ag_ui.core import Tool as AGUITool + + +class TestToolAdapter: + """Test cases for ToolAdapter.""" + + @pytest.fixture + def sample_ag_ui_tool(self): + """Create a sample AG-UI Tool.""" + return AGUITool( + name="get_weather", + description="Get the current weather", + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state" + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + ) + + @pytest.mark.asyncio + @patch('ag_ui_claude.tool_adapter.SdkMcpTool') + @patch('ag_ui_claude.tool_adapter.create_sdk_mcp_server') + async def test_convert_ag_ui_tool_to_claude(self, mock_sdk_tool, mock_mcp_server, sample_ag_ui_tool): + """Test converting AG-UI tool to Claude SDK format.""" + # Mock SdkMcpTool + mock_tool_instance = Mock() + mock_sdk_tool.return_value = mock_tool_instance + + try: + result = ToolAdapter.convert_ag_ui_tool_to_claude(sample_ag_ui_tool) + assert result is not None + except ImportError: + # If claude-agent-sdk is not installed, skip this test + pytest.skip("claude-agent-sdk not installed") + + @pytest.mark.asyncio + async def test_convert_ag_ui_tools_to_claude(self, sample_ag_ui_tool): + """Test converting multiple AG-UI tools.""" + tools = [sample_ag_ui_tool] + + try: + result = ToolAdapter.convert_ag_ui_tools_to_claude(tools) + assert len(result) == 1 + except ImportError: + pytest.skip("claude-agent-sdk not installed") + + @pytest.mark.asyncio + @patch('ag_ui_claude.tool_adapter.create_sdk_mcp_server') + async def test_create_mcp_server_for_tools(self, mock_create_server, sample_ag_ui_tool): + """Test creating MCP server for tools.""" + mock_server = Mock() + mock_create_server.return_value = mock_server + + tools = [sample_ag_ui_tool] + + try: + server = ToolAdapter.create_mcp_server_for_tools( + ag_ui_tools=tools, + server_name="test_server", + server_version="1.0.0" + ) + + assert server is not None + mock_create_server.assert_called_once() + except ImportError: + pytest.skip("claude-agent-sdk not installed") + + def test_extract_tool_call_id(self): + """Test extracting tool call ID from ToolUseBlock.""" + tool_block = Mock() + tool_block.id = "tool_call_123" + + tool_id = ToolAdapter.extract_tool_call_id(tool_block) + assert tool_id == "tool_call_123" + + def test_extract_tool_name(self): + """Test extracting tool name from ToolUseBlock.""" + tool_block = Mock() + tool_block.name = "get_weather" + + tool_name = ToolAdapter.extract_tool_name(tool_block) + assert tool_name == "get_weather" + + def test_extract_tool_args(self): + """Test extracting tool arguments from ToolUseBlock.""" + tool_block = Mock() + tool_block.input = {"location": "San Francisco"} + + args = ToolAdapter.extract_tool_args(tool_block) + assert args == {"location": "San Francisco"} + + def test_extract_tool_args_empty(self): + """Test extracting tool arguments when input is empty.""" + tool_block = Mock() + tool_block.input = {} + + args = ToolAdapter.extract_tool_args(tool_block) + assert args == {} + + def test_is_long_running_tool(self, sample_ag_ui_tool): + """Test checking if tool is long-running.""" + is_lro = ToolAdapter.is_long_running_tool(sample_ag_ui_tool) + # Currently all client tools are treated as long-running + assert is_lro is True + + @pytest.mark.asyncio + async def test_convert_ag_ui_tool_with_invalid_parameters(self): + """Test converting tool with invalid parameters.""" + tool = AGUITool( + name="test_tool", + description="Test", + parameters="invalid" # Not a dict + ) + + try: + result = ToolAdapter.convert_ag_ui_tool_to_claude(tool) + # Should handle gracefully with empty schema + assert result is not None + except ImportError: + pytest.skip("claude-agent-sdk not installed") + diff --git a/integrations/claude-agent-sdk/typescript/.env.local.example b/integrations/claude-agent-sdk/typescript/.env.local.example new file mode 100644 index 000000000..e925bb858 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/.env.local.example @@ -0,0 +1,10 @@ +# Claude Agent SDK Integration - Environment Variables +# Copy this file to .env.local and fill in your actual values + +# Anthropic API Key (required for real API tests) +# Get your API key from: https://console.anthropic.com/ +# ANTHROPIC_API_KEY=your-anthropic-api-key-here + +# Optional for third party service +# ANTHROPIC_AUTH_TOKEN=third-party-auth-token +# ANTHROPIC_BASE_URL=third-party-base-url diff --git a/integrations/claude-agent-sdk/typescript/README.md b/integrations/claude-agent-sdk/typescript/README.md new file mode 100644 index 000000000..cbe780889 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/README.md @@ -0,0 +1,350 @@ +# @ag-ui/claude + +Integration of Claude Agent SDK with AG-UI Protocol, enabling Claude agents to work seamlessly in AG-UI applications. + +## Features + +- ✅ **Full AG-UI Protocol Support** - Implements all standard event types +- ✅ **Persistent Session Management** - Supports multi-turn conversations and session state maintenance +- ✅ **Tool Integration** - Supports both client-side and backend tools +- ✅ **Streaming Responses** - Real-time streaming of AI responses +- ✅ **Stateless Mode** - Optional stateless execution mode +- ✅ **TypeScript Support** - Complete type definitions +- ✅ **Observable API** - RxJS Observable-based event streams +- ✅ **Automatic Session Cleanup** - Automatically cleans up expired sessions + +## Installation + +```bash +npm install @ag-ui/claude @ag-ui/client @ag-ui/core +``` + +You also need to install Claude Agent SDK: + +```bash +npm install @anthropic-ai/claude-agent-sdk +``` + +## Quick Start + +### Basic Usage + +```typescript +import { ClaudeAgent } from '@ag-ui/claude'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Initialize agent +const agent = new ClaudeAgent({ + apiKey: process.env.ANTHROPIC_API_KEY, + enablePersistentSessions: true, +}); + +// Prepare input +const input: RunAgentInput = { + agentId: 'my_agent', + threadId: 'thread_123', + messages: [ + { id: 'msg_1', role: 'user', content: 'Hello!' }, + ], + context: {}, +}; + +// Run agent and subscribe to events +agent.run(input).subscribe({ + next: (event) => { + console.log('Event:', event); + }, + error: (error) => { + console.error('Error:', error); + }, + complete: () => { + console.log('Done!'); + }, +}); +``` + +### Using Tools + +```typescript +import { ClaudeAgent } from '@ag-ui/claude'; + +const agent = new ClaudeAgent({ + apiKey: process.env.ANTHROPIC_API_KEY, +}); + +const input: RunAgentInput = { + agentId: 'my_agent', + messages: [ + { id: 'msg_1', role: 'user', content: 'Calculate 42 + 58' }, + ], + context: { + tools: [ + { + name: 'calculator', + description: 'Performs calculations', + parameters: { + type: 'object', + properties: { + operation: { type: 'string' }, + a: { type: 'number' }, + b: { type: 'number' }, + }, + required: ['operation', 'a', 'b'], + }, + handler: async ({ operation, a, b }) => { + // Backend tool implementation + if (operation === 'add') return a + b; + // ... + }, + }, + ], + }, +}; + +agent.run(input).subscribe({ + next: (event) => { + if (event.type === 'tool_call_start') { + console.log('Tool called:', event.toolName); + } + }, +}); +``` + +### Express Server Example + +```typescript +import express from 'express'; +import { ClaudeAgent } from '@ag-ui/claude'; + +const app = express(); +app.use(express.json()); + +const agent = new ClaudeAgent({ + apiKey: process.env.ANTHROPIC_API_KEY, +}); + +app.post('/api/run-agent', async (req, res) => { + const input: RunAgentInput = req.body; + + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + + agent.run(input).subscribe({ + next: (event) => { + res.write(`data: ${JSON.stringify(event)}\n\n`); + }, + error: (error) => { + res.write(`data: ${JSON.stringify({ type: 'error', error: error.message })}\n\n`); + res.end(); + }, + complete: () => { + res.end(); + }, + }); +}); + +app.listen(3000); +``` + +## API Documentation + +### ClaudeAgent + +Main agent class that extends `AbstractAgent`. + +#### Constructor + +```typescript +constructor(config: ClaudeAgentConfig) +``` + +**Configuration Options:** + +- `apiKey?: string` - Anthropic API key (defaults to `ANTHROPIC_API_KEY` environment variable) +- `baseUrl?: string` - API base URL (defaults to `ANTHROPIC_BASE_URL` environment variable) +- `enablePersistentSessions?: boolean` - Whether to enable persistent sessions (default: `true`) +- `sessionTimeout?: number` - Session timeout in milliseconds (default: 30 minutes) +- `permissionMode?: 'ask' | 'auto' | 'none'` - Permission mode (default: `'ask'`) + +#### Methods + +##### `run(input: RunAgentInput): Observable` + +Runs the agent and returns an Observable of event streams. + +**Parameters:** +- `input.agentId: string` - Agent ID +- `input.threadId?: string` - Session ID (for persistent sessions) +- `input.messages: Message[]` - Message history +- `input.context?: { tools?: Tool[] }` - Context (including tool definitions) + +**Returns:** Observable that emits AG-UI Protocol events + +##### `abortExecution(runId: string): void` + +Aborts a running execution. + +##### `cleanup(): Promise` + +Cleans up all sessions and resources. + +### SessionManager + +Session manager using singleton pattern. + +#### Methods + +- `getInstance(sessionTimeout?: number): SessionManager` - Get singleton instance +- `getSession(sessionId: string, userId?: string): Session` - Get or create session +- `hasSession(sessionId: string): boolean` - Check if session exists +- `deleteSession(sessionId: string): boolean` - Delete session +- `trackMessage(sessionId: string, messageId: string): void` - Mark message as processed +- `getUnseenMessages(sessionId: string, messages: Message[]): Message[]` - Get unprocessed messages +- `getStateValue(sessionId: string, key: string): any` - Get session state value +- `setStateValue(sessionId: string, key: string, value: any): void` - Set session state value + +### EventTranslator + +Event translator that converts Claude SDK messages to AG-UI events. + +#### Methods + +- `translateMessage(message: SDKMessage): ProcessedEvents[]` - Translate a single message + +### ToolAdapter + +Tool adapter that handles tool format conversion. + +#### Static Methods + +- `convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[]` - Convert tools to SDK format +- `createMcpServerForTools(tools: Tool[]): McpSdkServerConfigWithInstance` - Create MCP server +- `formatToolNameForSdk(toolName: string, serverName?: string): string` - Format tool name +- `parseToolNameFromSdk(sdkToolName: string): string` - Parse tool name + +## Event Types + +The agent emits the following AG-UI Protocol events: + +- `RunStartedEvent` - Execution started +- `RunFinishedEvent` - Execution completed +- `RunErrorEvent` - Execution error +- `StepStartedEvent` - Step started +- `StepFinishedEvent` - Step completed +- `TextMessageStartEvent` - Text message started +- `TextMessageContentEvent` - Text message content (streaming) +- `TextMessageEndEvent` - Text message ended +- `ToolCallStartEvent` - Tool call started +- `ToolCallArgsEvent` - Tool arguments +- `ToolCallEndEvent` - Tool call ended +- `ToolCallResultEvent` - Tool execution result + +## Tool Support + +### Backend Tools + +Backend tools are executed on the server side: + +```typescript +{ + name: 'calculator', + description: 'Performs calculations', + parameters: { /* JSON Schema */ }, + handler: async (args) => { + // Tool logic + return result; + } +} +``` + +### Client Tools + +Client tools are executed on the frontend. Set `client: true`: + +```typescript +{ + name: 'file_reader', + description: 'Reads files', + client: true, + parameters: { /* JSON Schema */ } +} +``` + +## Session Management + +### Persistent Session Mode + +When persistent sessions are enabled, the agent maintains independent sessions for each `threadId`: + +```typescript +const agent = new ClaudeAgent({ + apiKey: 'your_key', + enablePersistentSessions: true, + sessionTimeout: 30 * 60 * 1000, // 30 minutes +}); +``` + +### Stateless Mode + +When persistent sessions are disabled, each call is independent: + +```typescript +const agent = new ClaudeAgent({ + apiKey: 'your_key', + enablePersistentSessions: false, +}); +``` + +## Testing + +Run unit tests: + +```bash +npm test +``` + +Run specific tests: + +```bash +npm test -- agent.test.ts +``` + +## Examples + +See the `examples/` directory for complete examples: + +- **Express Server** - Complete Express.js server example +- **Tool Integration** - Backend and client tool examples +- **Session Management** - Multi-turn conversation examples + +## Architecture + +The integration architecture is based on the Python version: + +``` +AG-UI Protocol Claude Middleware Claude Agent SDK + │ │ │ +RunAgentInput ──────> ClaudeAgent.run() ──────> SDK Client/Query + │ │ │ + │ EventTranslator │ + │ │ │ +BaseEvent[] <──────── translate events <──────── Response[] +``` + +Key Components: + +- **ClaudeAgent**: Main coordinator, manages execution flow +- **EventTranslator**: Event translation (Claude SDK → AG-UI) +- **SessionManager**: Session lifecycle management +- **ToolAdapter**: Tool format conversion +- **ExecutionState**: Execution state tracking + +## References + +- [Python Implementation](../python/) - Python SDK implementation reference +- [Claude Agent SDK Documentation](https://docs.claude.com/api/agent-sdk/typescript) +- [AG-UI Protocol Documentation](https://docs.ag-ui.com/) + +## License + +Apache-2.0 diff --git a/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/client.ts b/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/client.ts new file mode 100644 index 000000000..f6f32866a --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/client.ts @@ -0,0 +1,92 @@ +/** + * Mock for @ag-ui/client + */ + +export class AbstractAgent { + run() {} + cleanup() {} +} + +export class TextMessageStartEvent { + type = 'text_message_start'; + constructor(public messageId: string) {} +} + +export class TextMessageContentEvent { + type = 'text_message_content'; + constructor(public text: string) {} +} + +export class TextMessageEndEvent { + type = 'text_message_end'; + constructor(public messageId: string) {} +} + +export class ToolCallStartEvent { + type = 'tool_call_start'; + constructor(public toolCallId: string, public toolName: string) {} +} + +export class ToolCallArgsEvent { + type = 'tool_call_args'; + constructor(public args: any) {} +} + +export class ToolCallEndEvent { + type = 'tool_call_end'; + constructor(public toolCallId: string) {} +} + +export class ToolCallResultEvent { + type = 'tool_call_result'; + constructor(public result: any) {} +} + +export class RunStartedEvent { + type = 'run_started'; + constructor(public runId: string) {} +} + +export class RunFinishedEvent { + type = 'run_finished'; +} + +export class RunErrorEvent { + type = 'run_error'; + constructor(public error: Error) {} +} + +export interface RunAgentInput { + agentId: string; + threadId?: string; + messages: Message[]; + context: any; +} + +export interface Message { + id: string; + role: string; + content: string | any[]; +} + +export interface Tool { + name: string; + description: string; + parameters?: any; + handler?: (...args: any[]) => any; + client?: boolean; +} + +export enum EventType { + RUN_STARTED = 'run_started', + RUN_FINISHED = 'run_finished', + RUN_ERROR = 'run_error', + TEXT_MESSAGE_START = 'text_message_start', + TEXT_MESSAGE_CONTENT = 'text_message_content', + TEXT_MESSAGE_END = 'text_message_end', + TOOL_CALL_START = 'tool_call_start', + TOOL_CALL_ARGS = 'tool_call_args', + TOOL_CALL_END = 'tool_call_end', + TOOL_CALL_RESULT = 'tool_call_result', +} + diff --git a/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/core.ts b/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/core.ts new file mode 100644 index 000000000..8143fc2a9 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__mocks__/@ag-ui/core.ts @@ -0,0 +1,21 @@ +/** + * Mock for @ag-ui/core + */ + +export class BaseEvent { + type: string = ''; +} + +export enum EventType { + RUN_STARTED = 'run_started', + RUN_FINISHED = 'run_finished', + RUN_ERROR = 'run_error', + TEXT_MESSAGE_START = 'text_message_start', + TEXT_MESSAGE_CONTENT = 'text_message_content', + TEXT_MESSAGE_END = 'text_message_end', + TOOL_CALL_START = 'tool_call_start', + TOOL_CALL_ARGS = 'tool_call_args', + TOOL_CALL_END = 'tool_call_end', + TOOL_CALL_RESULT = 'tool_call_result', +} + diff --git a/integrations/claude-agent-sdk/typescript/__mocks__/@anthropic-ai/claude-agent-sdk.ts b/integrations/claude-agent-sdk/typescript/__mocks__/@anthropic-ai/claude-agent-sdk.ts new file mode 100644 index 000000000..9d779dfda --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__mocks__/@anthropic-ai/claude-agent-sdk.ts @@ -0,0 +1,41 @@ +/** + * Mock for @anthropic-ai/claude-agent-sdk + */ + +export const ClaudeSDKClient = jest.fn().mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello from mock' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), +})); + +export const query = jest.fn().mockImplementation(async function* () { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello from mock query' }], + }; + yield { + type: 'result', + subtype: 'success', + }; +}); + +export const createSdkMcpServer = jest.fn().mockResolvedValue({ + name: 'mock-server', + version: '1.0.0', +}); + +export class SdkMcpTool { + constructor(public config: any) {} +} + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/agent.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/agent.test.ts new file mode 100644 index 000000000..191d904b5 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/agent.test.ts @@ -0,0 +1,265 @@ +/** + * Claude Agent tests + */ + +import { ClaudeAgent } from '../src/agent'; +import { SessionManager } from '../src/session-manager'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Mock the Claude SDK +jest.mock('@anthropic-ai/claude-agent-sdk', () => ({ + ClaudeSDKClient: jest.fn().mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })), + query: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), +})); + +describe('ClaudeAgent', () => { + let agent: ClaudeAgent; + + beforeEach(() => { + SessionManager.resetInstance(); + agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + }); + + afterEach(() => { + SessionManager.resetInstance(); + }); + + describe('constructor', () => { + it('should initialize with config', () => { + expect(agent).toBeDefined(); + expect(agent.getSessionManager()).toBeDefined(); + expect(agent.getExecutionStateManager()).toBeDefined(); + }); + + it('should use environment variables for API key', () => { + process.env.ANTHROPIC_API_KEY = 'env_api_key'; + const envAgent = new ClaudeAgent({}); + expect(envAgent).toBeDefined(); + delete process.env.ANTHROPIC_API_KEY; + }); + }); + + describe('run', () => { + it('should return an observable', () => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const observable = agent.run(input); + expect(observable).toBeDefined(); + expect(typeof observable.subscribe).toBe('function'); + }); + + it('should emit run started event', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const events: any[] = []; + + agent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + expect(events.length).toBeGreaterThan(0); + expect(events[0].type).toBe('run_started'); + done(); + }, + error: done, + }); + }); + + it('should emit run finished event', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const events: any[] = []; + + agent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + const finishedEvent = events.find((e) => e.type === 'run_finished'); + expect(finishedEvent).toBeDefined(); + done(); + }, + error: done, + }); + }); + + it('should handle tools', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: { + tools: [ + { + name: 'test_tool', + description: 'A test tool', + parameters: { + type: 'object', + properties: { + query: { type: 'string' }, + }, + }, + }, + ], + }, + }; + + agent.run(input).subscribe({ + complete: done, + error: done, + }); + }); + }); + + describe('abortExecution', () => { + it('should abort running execution', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + let runId: string; + + agent.run(input).subscribe({ + next: (event: any) => { + if (event.type === 'run_started') { + runId = event.runId; + agent.abortExecution(runId); + } + }, + complete: () => { + if (runId) { + const execution = agent.getExecutionState(runId); + expect(execution?.isAborted()).toBe(true); + } + done(); + }, + error: done, + }); + }); + }); + + describe('cleanup', () => { + it('should cleanup resources', async () => { + await agent.cleanup(); + + expect(agent.getSessionManager().getSessionCount()).toBe(0); + expect(agent.getExecutionStateManager().getExecutionCount()).toBe(0); + }); + }); + + describe('persistent sessions', () => { + it('should reuse session for same thread', (done) => { + const input1: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const input2: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + { id: 'msg2', role: 'assistant', content: 'Hi' }, + { id: 'msg3', role: 'user', content: 'How are you?' }, + ], + context: {}, + }; + + agent.run(input1).subscribe({ + complete: () => { + const sessionCount1 = agent.getSessionManager().getSessionCount(); + + agent.run(input2).subscribe({ + complete: () => { + const sessionCount2 = agent.getSessionManager().getSessionCount(); + expect(sessionCount2).toBe(sessionCount1); + done(); + }, + error: done, + }); + }, + error: done, + }); + }); + }); + + describe('stateless mode', () => { + it('should work in stateless mode', (done) => { + const statelessAgent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: false, + }); + + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + statelessAgent.run(input).subscribe({ + complete: done, + error: done, + }); + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/event-translator.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/event-translator.test.ts new file mode 100644 index 000000000..9857481bd --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/event-translator.test.ts @@ -0,0 +1,276 @@ +/** + * Event translator tests + */ + +import { EventTranslator } from '../src/event-translator'; +import { EventType } from '@ag-ui/client'; +import type { + SDKAssistantMessage, + SDKResultMessage, + TextBlock, + ToolUseBlock, + ToolResultBlock, +} from '../src/types'; + +describe('EventTranslator', () => { + let translator: EventTranslator; + const runId = 'test_run_1'; + + beforeEach(() => { + translator = new EventTranslator(runId); + }); + + describe('translateMessage', () => { + it('should translate assistant message with text block', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'text', + text: 'Hello, world!', + } as TextBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(3); + expect(events[0].type).toBe(EventType.TEXT_MESSAGE_START); + expect(events[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT); + expect(events[2].type).toBe(EventType.TEXT_MESSAGE_END); + }); + + it('should translate assistant message with tool use block', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_use', + id: 'tool_1', + name: 'search', + input: { query: 'test' }, + } as ToolUseBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(3); + expect(events[0].type).toBe(EventType.TOOL_CALL_START); + expect(events[1].type).toBe(EventType.TOOL_CALL_ARGS); + expect(events[2].type).toBe(EventType.TOOL_CALL_END); + }); + + it('should translate assistant message with tool result block', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_result', + tool_use_id: 'tool_1', + content: 'Result data', + is_error: false, + } as ToolResultBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + expect(events[0].type).toBe(EventType.TOOL_CALL_RESULT); + }); + + it('should translate result message (success)', () => { + const message: SDKResultMessage = { + type: 'result', + subtype: 'success', + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + expect(events[0].type).toBe(EventType.RUN_FINISHED); + }); + + it('should translate result message (error)', () => { + const message: SDKResultMessage = { + type: 'result', + subtype: 'error', + error: { + type: 'Error', + message: 'Something went wrong', + }, + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + expect(events[0].type).toBe(EventType.RUN_ERROR); + }); + }); + + describe('translateTextBlock', () => { + it('should generate text message events', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'text', + text: 'Test content', + } as TextBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(3); + + const startEvent = events[0] as any; + expect(startEvent.type).toBe(EventType.TEXT_MESSAGE_START); + expect(startEvent.messageId).toBeDefined(); + + const contentEvent = events[1] as any; + expect(contentEvent.type).toBe(EventType.TEXT_MESSAGE_CONTENT); + expect(contentEvent.content).toBe('Test content'); + + const endEvent = events[2] as any; + expect(endEvent.type).toBe(EventType.TEXT_MESSAGE_END); + }); + }); + + describe('translateToolUseBlock', () => { + it('should generate tool call events', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_use', + id: 'call_123', + name: 'calculator', + input: { operation: 'add', numbers: [1, 2] }, + } as ToolUseBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(3); + + const startEvent = events[0] as any; + expect(startEvent.type).toBe(EventType.TOOL_CALL_START); + expect(startEvent.toolCallId).toBe('call_123'); + expect(startEvent.toolName).toBe('calculator'); + + const argsEvent = events[1] as any; + expect(argsEvent.type).toBe(EventType.TOOL_CALL_ARGS); + expect(argsEvent.toolCallId).toBe('call_123'); + expect(argsEvent.args).toBe(JSON.stringify({ operation: 'add', numbers: [1, 2] })); + + const endEvent = events[2] as any; + expect(endEvent.type).toBe(EventType.TOOL_CALL_END); + expect(endEvent.toolCallId).toBe('call_123'); + }); + }); + + describe('translateToolResultBlock', () => { + it('should generate tool result event with string content', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_result', + tool_use_id: 'call_123', + content: 'Result: 3', + is_error: false, + } as ToolResultBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + + const resultEvent = events[0] as any; + expect(resultEvent.type).toBe(EventType.TOOL_CALL_RESULT); + expect(resultEvent.toolCallId).toBe('call_123'); + expect(resultEvent.result).toBe('Result: 3'); + expect(resultEvent.isError).toBe(false); + }); + + it('should generate tool result event with array content', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_result', + tool_use_id: 'call_123', + content: [ + { type: 'text', text: 'Part 1' }, + { type: 'text', text: 'Part 2' }, + ], + is_error: false, + } as ToolResultBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + + const resultEvent = events[0] as any; + expect(resultEvent.type).toBe(EventType.TOOL_CALL_RESULT); + expect(resultEvent.result).toContain('Part 1'); + expect(resultEvent.result).toContain('Part 2'); + }); + + it('should mark error results', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { + type: 'tool_result', + tool_use_id: 'call_123', + content: 'Error occurred', + is_error: true, + } as ToolResultBlock, + ], + }; + + const events = translator.translateMessage(message); + + expect(events).toHaveLength(1); + + const resultEvent = events[0] as any; + expect(resultEvent.isError).toBe(true); + }); + }); + + describe('reset', () => { + it('should reset translator state', () => { + translator.setCurrentMessageId('msg_1'); + translator.reset(); + + expect(translator.getCurrentMessageId()).toBeNull(); + }); + }); + + describe('generateMessageId', () => { + it('should generate unique message IDs', () => { + const message: SDKAssistantMessage = { + type: 'assistant', + content: [ + { type: 'text', text: 'Text 1' } as TextBlock, + { type: 'text', text: 'Text 2' } as TextBlock, + ], + }; + + const events = translator.translateMessage(message); + + const messageId1 = (events[0] as any).messageId; + const messageId2 = (events[3] as any).messageId; + + expect(messageId1).not.toBe(messageId2); + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/integration/basic.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/integration/basic.test.ts new file mode 100644 index 000000000..0dd1f076d --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/integration/basic.test.ts @@ -0,0 +1,166 @@ +/** + * Basic integration tests + */ + +import { ClaudeAgent } from '../../src/agent'; +import { SessionManager } from '../../src/session-manager'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Mock the Claude SDK +jest.mock('@anthropic-ai/claude-agent-sdk'); + +describe('Basic Integration', () => { + let agent: ClaudeAgent; + + beforeEach(() => { + SessionManager.resetInstance(); + + const { ClaudeSDKClient, query } = require('@anthropic-ai/claude-agent-sdk'); + + ClaudeSDKClient.mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello! How can I help you?' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })); + + query.mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Hello! How can I help you?' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }); + + agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + }); + + afterEach(() => { + SessionManager.resetInstance(); + jest.clearAllMocks(); + }); + + it('should handle simple conversation', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const events: any[] = []; + + agent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + // Check that we received key events + expect(events.some((e) => e.type === 'run_started')).toBe(true); + expect(events.some((e) => e.type === 'text_message_start')).toBe(true); + expect(events.some((e) => e.type === 'text_message_content')).toBe(true); + expect(events.some((e) => e.type === 'text_message_end')).toBe(true); + expect(events.some((e) => e.type === 'run_finished')).toBe(true); + done(); + }, + error: done, + }); + }); + + it('should handle multi-turn conversation', (done) => { + const input1: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + agent.run(input1).subscribe({ + complete: () => { + const input2: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + { id: 'msg2', role: 'assistant', content: 'Hello! How can I help you?' }, + { id: 'msg3', role: 'user', content: 'Tell me a joke' }, + ], + context: {}, + }; + + agent.run(input2).subscribe({ + complete: () => { + // Verify session was reused + expect(agent.getSessionManager().getSessionCount()).toBe(1); + done(); + }, + error: done, + }); + }, + error: done, + }); + }); + + it('should handle errors gracefully', (done) => { + const { ClaudeSDKClient } = require('@anthropic-ai/claude-agent-sdk'); + + ClaudeSDKClient.mockImplementation(() => ({ + query: jest.fn().mockRejectedValue(new Error('API Error')), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + throw new Error('API Error'); + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })); + + const errorAgent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + const events: any[] = []; + + errorAgent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + // Should have error event + expect(events.some((e) => e.type === 'run_error')).toBe(true); + done(); + }, + error: done, + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/integration/sessions.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/integration/sessions.test.ts new file mode 100644 index 000000000..d4bd4ca4e --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/integration/sessions.test.ts @@ -0,0 +1,138 @@ +/** + * Sessions integration tests + */ + +import { ClaudeAgent } from '../../src/agent'; +import { SessionManager } from '../../src/session-manager'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Mock the Claude SDK +jest.mock('@anthropic-ai/claude-agent-sdk'); + +describe('Sessions Integration', () => { + beforeEach(() => { + SessionManager.resetInstance(); + + const { ClaudeSDKClient, query } = require('@anthropic-ai/claude-agent-sdk'); + + ClaudeSDKClient.mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Response' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })); + + query.mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [{ type: 'text', text: 'Response' }], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }); + }); + + afterEach(() => { + SessionManager.resetInstance(); + jest.clearAllMocks(); + }); + + it('should maintain persistent sessions', (done) => { + const agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + + const input: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + agent.run(input).subscribe({ + complete: () => { + expect(agent.getSessionManager().hasSession('thread1')).toBe(true); + done(); + }, + error: done, + }); + }); + + it('should work in stateless mode', (done) => { + const agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: false, + }); + + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello' }, + ], + context: {}, + }; + + agent.run(input).subscribe({ + complete: done, + error: done, + }); + }); + + it('should isolate sessions by thread ID', (done) => { + const agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + + const input1: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread1', + messages: [ + { id: 'msg1', role: 'user', content: 'Hello thread 1' }, + ], + context: {}, + }; + + const input2: RunAgentInput = { + agentId: 'test_agent', + threadId: 'thread2', + messages: [ + { id: 'msg2', role: 'user', content: 'Hello thread 2' }, + ], + context: {}, + }; + + agent.run(input1).subscribe({ + complete: () => { + agent.run(input2).subscribe({ + complete: () => { + expect(agent.getSessionManager().hasSession('thread1')).toBe(true); + expect(agent.getSessionManager().hasSession('thread2')).toBe(true); + expect(agent.getSessionManager().getSessionCount()).toBe(2); + done(); + }, + error: done, + }); + }, + error: done, + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/integration/tools.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/integration/tools.test.ts new file mode 100644 index 000000000..de3a349df --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/integration/tools.test.ts @@ -0,0 +1,189 @@ +/** + * Tools integration tests + */ + +import { ClaudeAgent } from '../../src/agent'; +import { SessionManager } from '../../src/session-manager'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Mock the Claude SDK +jest.mock('@anthropic-ai/claude-agent-sdk'); + +describe('Tools Integration', () => { + let agent: ClaudeAgent; + + beforeEach(() => { + SessionManager.resetInstance(); + + const { ClaudeSDKClient } = require('@anthropic-ai/claude-agent-sdk'); + + ClaudeSDKClient.mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [ + { + type: 'tool_use', + id: 'tool_call_1', + name: 'calculator', + input: { operation: 'add', numbers: [1, 2] }, + }, + ], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })); + + agent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + }); + + afterEach(() => { + SessionManager.resetInstance(); + jest.clearAllMocks(); + }); + + it('should handle tool calls', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Calculate 1 + 2' }, + ], + context: { + tools: [ + { + name: 'calculator', + description: 'Performs calculations', + parameters: { + type: 'object', + properties: { + operation: { type: 'string' }, + numbers: { type: 'array', items: { type: 'number' } }, + }, + required: ['operation', 'numbers'], + }, + }, + ], + }, + }; + + const events: any[] = []; + + agent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + // Check for tool call events + expect(events.some((e) => e.type === 'tool_call_start')).toBe(true); + expect(events.some((e) => e.type === 'tool_call_args')).toBe(true); + expect(events.some((e) => e.type === 'tool_call_end')).toBe(true); + done(); + }, + error: done, + }); + }); + + it('should handle tool results', (done) => { + const { ClaudeSDKClient } = require('@anthropic-ai/claude-agent-sdk'); + + ClaudeSDKClient.mockImplementation(() => ({ + query: jest.fn().mockResolvedValue(undefined), + receiveResponse: jest.fn().mockReturnValue({ + async *[Symbol.asyncIterator]() { + yield { + type: 'assistant', + content: [ + { + type: 'tool_result', + tool_use_id: 'tool_call_1', + content: 'The result is 3', + is_error: false, + }, + ], + }; + yield { + type: 'result', + subtype: 'success', + }; + }, + }), + close: jest.fn().mockResolvedValue(undefined), + })); + + const resultAgent = new ClaudeAgent({ + apiKey: 'test_api_key', + enablePersistentSessions: true, + }); + + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'What is 1 + 2?' }, + ], + context: { + tools: [ + { + name: 'calculator', + description: 'Performs calculations', + }, + ], + }, + }; + + const events: any[] = []; + + resultAgent.run(input).subscribe({ + next: (event) => { + events.push(event); + }, + complete: () => { + // Check for tool result event + const resultEvent = events.find((e) => e.type === 'tool_call_result'); + expect(resultEvent).toBeDefined(); + expect(resultEvent?.result).toContain('The result is 3'); + done(); + }, + error: done, + }); + }); + + it('should handle client tools', (done) => { + const input: RunAgentInput = { + agentId: 'test_agent', + messages: [ + { id: 'msg1', role: 'user', content: 'Open a file' }, + ], + context: { + tools: [ + { + name: 'file_reader', + description: 'Reads files', + client: true, + parameters: { + type: 'object', + properties: { + path: { type: 'string' }, + }, + }, + }, + ], + }, + }; + + agent.run(input).subscribe({ + complete: done, + error: done, + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/session-manager.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/session-manager.test.ts new file mode 100644 index 000000000..55e5f2029 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/session-manager.test.ts @@ -0,0 +1,248 @@ +/** + * Session manager tests + */ + +import { SessionManager } from '../src/session-manager'; +import type { Message } from '@ag-ui/client'; + +describe('SessionManager', () => { + let sessionManager: SessionManager; + + beforeEach(() => { + SessionManager.resetInstance(); + sessionManager = SessionManager.getInstance(); + }); + + afterEach(() => { + SessionManager.resetInstance(); + }); + + describe('getInstance', () => { + it('should return singleton instance', () => { + const instance1 = SessionManager.getInstance(); + const instance2 = SessionManager.getInstance(); + + expect(instance1).toBe(instance2); + }); + }); + + describe('getSession', () => { + it('should create new session if not exists', () => { + const session = sessionManager.getSession('session1'); + + expect(session.id).toBe('session1'); + expect(session.processedMessageIds).toBeDefined(); + expect(session.state).toEqual({}); + }); + + it('should return existing session', () => { + const session1 = sessionManager.getSession('session1'); + const session2 = sessionManager.getSession('session1'); + + expect(session1).toBe(session2); + }); + + it('should update last accessed time', () => { + const session1 = sessionManager.getSession('session1'); + const time1 = session1.lastAccessedAt; + + // Wait a bit + setTimeout(() => { + const session2 = sessionManager.getSession('session1'); + expect(session2.lastAccessedAt).toBeGreaterThanOrEqual(time1); + }, 10); + }); + }); + + describe('hasSession', () => { + it('should return true for existing session', () => { + sessionManager.getSession('session1'); + expect(sessionManager.hasSession('session1')).toBe(true); + }); + + it('should return false for non-existing session', () => { + expect(sessionManager.hasSession('session1')).toBe(false); + }); + }); + + describe('deleteSession', () => { + it('should delete session', () => { + sessionManager.getSession('session1'); + expect(sessionManager.hasSession('session1')).toBe(true); + + sessionManager.deleteSession('session1'); + expect(sessionManager.hasSession('session1')).toBe(false); + }); + }); + + describe('trackMessage', () => { + it('should track processed message', () => { + sessionManager.getSession('session1'); + sessionManager.trackMessage('session1', 'msg1'); + + expect(sessionManager.isMessageProcessed('session1', 'msg1')).toBe(true); + }); + }); + + describe('isMessageProcessed', () => { + it('should return false for unprocessed message', () => { + sessionManager.getSession('session1'); + expect(sessionManager.isMessageProcessed('session1', 'msg1')).toBe(false); + }); + + it('should return true for processed message', () => { + sessionManager.getSession('session1'); + sessionManager.trackMessage('session1', 'msg1'); + expect(sessionManager.isMessageProcessed('session1', 'msg1')).toBe(true); + }); + }); + + describe('getUnseenMessages', () => { + it('should return all messages for new session', () => { + const messages: Message[] = [ + { id: 'msg1', role: 'user', content: 'Hello' }, + { id: 'msg2', role: 'assistant', content: 'Hi' }, + ]; + + const unseen = sessionManager.getUnseenMessages('session1', messages); + expect(unseen).toHaveLength(2); + }); + + it('should filter out processed messages', () => { + sessionManager.getSession('session1'); + sessionManager.trackMessage('session1', 'msg1'); + + const messages: Message[] = [ + { id: 'msg1', role: 'user', content: 'Hello' }, + { id: 'msg2', role: 'assistant', content: 'Hi' }, + ]; + + const unseen = sessionManager.getUnseenMessages('session1', messages); + expect(unseen).toHaveLength(1); + expect(unseen[0].id).toBe('msg2'); + }); + }); + + describe('markMessagesAsProcessed', () => { + it('should mark all messages as processed', () => { + sessionManager.getSession('session1'); + + const messages: Message[] = [ + { id: 'msg1', role: 'user', content: 'Hello' }, + { id: 'msg2', role: 'assistant', content: 'Hi' }, + ]; + + sessionManager.markMessagesAsProcessed('session1', messages); + + expect(sessionManager.isMessageProcessed('session1', 'msg1')).toBe(true); + expect(sessionManager.isMessageProcessed('session1', 'msg2')).toBe(true); + }); + }); + + describe('getStateValue', () => { + it('should return state value', () => { + sessionManager.getSession('session1'); + sessionManager.setStateValue('session1', 'key1', 'value1'); + + expect(sessionManager.getStateValue('session1', 'key1')).toBe('value1'); + }); + + it('should return undefined for non-existing key', () => { + sessionManager.getSession('session1'); + expect(sessionManager.getStateValue('session1', 'key1')).toBeUndefined(); + }); + }); + + describe('setStateValue', () => { + it('should set state value', () => { + sessionManager.getSession('session1'); + sessionManager.setStateValue('session1', 'key1', 'value1'); + + expect(sessionManager.getStateValue('session1', 'key1')).toBe('value1'); + }); + }); + + describe('removeStateKeys', () => { + it('should remove state keys', () => { + sessionManager.getSession('session1'); + sessionManager.setStateValue('session1', 'key1', 'value1'); + sessionManager.setStateValue('session1', 'key2', 'value2'); + + sessionManager.removeStateKeys('session1', ['key1']); + + expect(sessionManager.getStateValue('session1', 'key1')).toBeUndefined(); + expect(sessionManager.getStateValue('session1', 'key2')).toBe('value2'); + }); + }); + + describe('clearSessionState', () => { + it('should clear all state', () => { + sessionManager.getSession('session1'); + sessionManager.setStateValue('session1', 'key1', 'value1'); + sessionManager.setStateValue('session1', 'key2', 'value2'); + + sessionManager.clearSessionState('session1'); + + expect(sessionManager.getStateValue('session1', 'key1')).toBeUndefined(); + expect(sessionManager.getStateValue('session1', 'key2')).toBeUndefined(); + }); + }); + + describe('getSessionCount', () => { + it('should return session count', () => { + expect(sessionManager.getSessionCount()).toBe(0); + + sessionManager.getSession('session1'); + expect(sessionManager.getSessionCount()).toBe(1); + + sessionManager.getSession('session2'); + expect(sessionManager.getSessionCount()).toBe(2); + }); + }); + + describe('getUserSessionCount', () => { + it('should return user session count', () => { + sessionManager.getSession('session1', 'user1'); + sessionManager.getSession('session2', 'user1'); + sessionManager.getSession('session3', 'user2'); + + expect(sessionManager.getUserSessionCount('user1')).toBe(2); + expect(sessionManager.getUserSessionCount('user2')).toBe(1); + }); + }); + + describe('getAllSessionIds', () => { + it('should return all session IDs', () => { + sessionManager.getSession('session1'); + sessionManager.getSession('session2'); + + const ids = sessionManager.getAllSessionIds(); + expect(ids).toHaveLength(2); + expect(ids).toContain('session1'); + expect(ids).toContain('session2'); + }); + }); + + describe('getUserSessions', () => { + it('should return user sessions', () => { + sessionManager.getSession('session1', 'user1'); + sessionManager.getSession('session2', 'user1'); + sessionManager.getSession('session3', 'user2'); + + const userSessions = sessionManager.getUserSessions('user1'); + expect(userSessions).toHaveLength(2); + }); + }); + + describe('clearAllSessions', () => { + it('should clear all sessions', () => { + sessionManager.getSession('session1'); + sessionManager.getSession('session2'); + + sessionManager.clearAllSessions(); + + expect(sessionManager.getSessionCount()).toBe(0); + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/setup.ts b/integrations/claude-agent-sdk/typescript/__tests__/setup.ts new file mode 100644 index 000000000..c1353d90f --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/setup.ts @@ -0,0 +1,7 @@ +/** + * Jest setup file + */ + +// Setup any global test configurations here +jest.setTimeout(10000); // 10 second timeout for async tests + diff --git a/integrations/claude-agent-sdk/typescript/__tests__/tool-adapter.test.ts b/integrations/claude-agent-sdk/typescript/__tests__/tool-adapter.test.ts new file mode 100644 index 000000000..6a0fd62f3 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/__tests__/tool-adapter.test.ts @@ -0,0 +1,256 @@ +/** + * Tool adapter tests + */ + +import { z } from 'zod'; +import { ToolAdapter } from '../src/tool-adapter'; +import type { Tool } from '@ag-ui/client'; + +describe('ToolAdapter', () => { + describe('convertAgUiToolsToSdk', () => { + it('should convert AG-UI tools to SDK format', () => { + const tools: Tool[] = [ + { + name: 'test_tool', + description: 'A test tool', + parameters: { + type: 'object', + properties: { + query: { type: 'string' }, + count: { type: 'number' }, + }, + required: ['query'], + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + + expect(sdkTools).toHaveLength(1); + expect(sdkTools[0].name).toBe('test_tool'); + expect(sdkTools[0].description).toBe('A test tool'); + expect(sdkTools[0].inputSchema).toBeDefined(); + expect(sdkTools[0].handler).toBeDefined(); + }); + + it('should handle tools without parameters', () => { + const tools: Tool[] = [ + { + name: 'simple_tool', + description: 'A simple tool', + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + + expect(sdkTools).toHaveLength(1); + expect(sdkTools[0].name).toBe('simple_tool'); + }); + }); + + describe('convertJsonSchemaToZod', () => { + it('should convert string type', () => { + const tools: Tool[] = [ + { + name: 'string_tool', + description: 'Test', + parameters: { + type: 'object', + properties: { + text: { type: 'string' }, + }, + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + expect(sdkTools[0].inputSchema).toBeDefined(); + }); + + it('should convert number type', () => { + const tools: Tool[] = [ + { + name: 'number_tool', + description: 'Test', + parameters: { + type: 'object', + properties: { + count: { type: 'number', minimum: 0, maximum: 100 }, + }, + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + expect(sdkTools[0].inputSchema).toBeDefined(); + }); + + it('should convert boolean type', () => { + const tools: Tool[] = [ + { + name: 'boolean_tool', + description: 'Test', + parameters: { + type: 'object', + properties: { + enabled: { type: 'boolean' }, + }, + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + expect(sdkTools[0].inputSchema).toBeDefined(); + }); + + it('should convert array type', () => { + const tools: Tool[] = [ + { + name: 'array_tool', + description: 'Test', + parameters: { + type: 'object', + properties: { + items: { + type: 'array', + items: { type: 'string' }, + }, + }, + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + expect(sdkTools[0].inputSchema).toBeDefined(); + }); + + it('should handle required fields', () => { + const tools: Tool[] = [ + { + name: 'required_tool', + description: 'Test', + parameters: { + type: 'object', + properties: { + required_field: { type: 'string' }, + optional_field: { type: 'string' }, + }, + required: ['required_field'], + }, + }, + ]; + + const sdkTools = ToolAdapter.convertAgUiToolsToSdk(tools); + expect(sdkTools[0].inputSchema).toBeDefined(); + }); + }); + + describe('createMcpServerForTools', () => { + it('should create MCP server configuration', () => { + const tools: Tool[] = [ + { + name: 'tool1', + description: 'Tool 1', + }, + { + name: 'tool2', + description: 'Tool 2', + }, + ]; + + const mcpServer = ToolAdapter.createMcpServerForTools(tools); + + expect(mcpServer.name).toBe('ag_ui_tools'); + expect(mcpServer.version).toBe('1.0.0'); + expect(mcpServer.tools).toHaveLength(2); + }); + }); + + describe('extractToolCalls', () => { + it('should extract tool calls from message', () => { + const message = { + content: [ + { type: 'text', text: 'Hello' }, + { type: 'tool_use', id: 'tool_1', name: 'search', input: { query: 'test' } }, + ], + }; + + const toolCalls = ToolAdapter.extractToolCalls(message); + + expect(toolCalls).toHaveLength(1); + expect(toolCalls[0].id).toBe('tool_1'); + expect(toolCalls[0].name).toBe('search'); + expect(toolCalls[0].input).toEqual({ query: 'test' }); + }); + + it('should return empty array for non-tool messages', () => { + const message = { + content: [{ type: 'text', text: 'Hello' }], + }; + + const toolCalls = ToolAdapter.extractToolCalls(message); + + expect(toolCalls).toHaveLength(0); + }); + }); + + describe('isClientTool', () => { + it('should identify client tools', () => { + const tools: Tool[] = [ + { name: 'client_tool', description: 'Test', client: true }, + { name: 'backend_tool', description: 'Test', client: false }, + ]; + + expect(ToolAdapter.isClientTool('client_tool', tools)).toBe(true); + expect(ToolAdapter.isClientTool('backend_tool', tools)).toBe(false); + expect(ToolAdapter.isClientTool('unknown_tool', tools)).toBe(false); + }); + }); + + describe('isLongRunningTool', () => { + it('should identify long-running tools', () => { + const tools: Tool[] = [ + { name: 'client_tool', description: 'Test', client: true }, + { name: 'long_tool', description: 'Test', longRunning: true }, + { name: 'normal_tool', description: 'Test' }, + ]; + + expect(ToolAdapter.isLongRunningTool('client_tool', tools)).toBe(true); + expect(ToolAdapter.isLongRunningTool('long_tool', tools)).toBe(true); + expect(ToolAdapter.isLongRunningTool('normal_tool', tools)).toBe(false); + }); + }); + + describe('formatToolNameForSdk', () => { + it('should format tool name with MCP prefix', () => { + expect(ToolAdapter.formatToolNameForSdk('my_tool')).toBe('mcp__ag_ui_tools__my_tool'); + expect(ToolAdapter.formatToolNameForSdk('my_tool', 'custom_server')).toBe( + 'mcp__custom_server__my_tool' + ); + }); + }); + + describe('parseToolNameFromSdk', () => { + it('should parse tool name from SDK format', () => { + expect(ToolAdapter.parseToolNameFromSdk('mcp__ag_ui_tools__my_tool')).toBe('my_tool'); + expect(ToolAdapter.parseToolNameFromSdk('mcp__custom__nested__tool')).toBe('nested__tool'); + expect(ToolAdapter.parseToolNameFromSdk('plain_tool')).toBe('plain_tool'); + }); + }); + + describe('getAllowedToolsList', () => { + it('should generate allowed tools list', () => { + const tools: Tool[] = [ + { name: 'tool1', description: 'Tool 1' }, + { name: 'tool2', description: 'Tool 2' }, + ]; + + const allowedTools = ToolAdapter.getAllowedToolsList(tools); + + expect(allowedTools).toHaveLength(2); + expect(allowedTools).toContain('mcp__ag_ui_tools__tool1'); + expect(allowedTools).toContain('mcp__ag_ui_tools__tool2'); + }); + }); +}); + diff --git a/integrations/claude-agent-sdk/typescript/dist/index.d.mts b/integrations/claude-agent-sdk/typescript/dist/index.d.mts new file mode 100644 index 000000000..c15863b58 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.d.mts @@ -0,0 +1,679 @@ +import { Observable } from 'rxjs'; +import { AgentConfig, TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent, ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallResultEvent, RunStartedEvent, RunFinishedEvent, RunErrorEvent, StepStartedEvent, StepFinishedEvent, Message, AbstractAgent, RunAgentInput, Tool } from '@ag-ui/client'; + +/** + * Type definitions for Claude Agent SDK integration with AG-UI Protocol + */ + +interface ClaudeSDKClient { + query(prompt: string): Promise; + receiveResponse(): AsyncIterableIterator; + close(): Promise; +} +interface Options { + apiKey?: string; + baseUrl?: string; + mcpServers?: Record; + allowedTools?: string[]; + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + stderr?: (data: string) => void; + verbose?: boolean; + [key: string]: any; +} +interface Query { + next(): Promise>; + [Symbol.asyncIterator](): AsyncIterableIterator; +} +type SDKMessage = SDKAssistantMessage | SDKUserMessage | SDKSystemMessage | SDKResultMessage | SDKPartialAssistantMessage | SDKCompactBoundaryMessage | SDKPermissionDenial; +interface SDKAssistantMessage { + type: 'assistant'; + message: { + id?: string; + content: ContentBlock[]; + [key: string]: any; + }; + parent_tool_use_id?: string | null; + uuid?: string; + session_id?: string; +} +interface SDKUserMessage { + type: 'user'; + content: string; + id?: string; +} +interface SDKSystemMessage { + type: 'system'; + content: string; +} +interface SDKResultMessage { + type: 'result'; + subtype: 'success' | 'error'; + error?: { + type: string; + message: string; + }; +} +interface SDKPartialAssistantMessage { + type: 'partial_assistant'; + content: ContentBlock[]; +} +interface SDKCompactBoundaryMessage { + type: 'compact_boundary'; +} +interface SDKPermissionDenial { + type: 'permission_denial'; + tool: string; + reason: string; +} +type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock; +interface TextBlock { + type: 'text'; + text: string; +} +interface ToolUseBlock { + type: 'tool_use'; + id: string; + name: string; + input: Record; +} +interface ToolResultBlock { + type: 'tool_result'; + tool_use_id: string; + content: string | Array<{ + type: string; + [key: string]: any; + }>; + is_error?: boolean; +} +interface ThinkingBlock { + type: 'thinking'; + thinking: string; +} +interface SdkMcpToolDefinition { + name: string; + description: string; + inputSchema: Schema; + handler: (args: any, extra?: any) => Promise; +} +interface CallToolResult { + content: Array<{ + type: 'text' | 'image' | 'resource'; + text?: string; + data?: string; + mimeType?: string; + [key: string]: any; + }>; + isError?: boolean; +} +interface McpSdkServerConfigWithInstance { + name: string; + version?: string; + tools?: Array>; +} +type ProcessedEvents = TextMessageStartEvent | TextMessageContentEvent | TextMessageEndEvent | ToolCallStartEvent | ToolCallArgsEvent | ToolCallEndEvent | ToolCallResultEvent | RunStartedEvent | RunFinishedEvent | RunErrorEvent | StepStartedEvent | StepFinishedEvent; +interface Session { + id: string; + userId?: string; + client?: ClaudeSDKClient; + processedMessageIds: Set; + state: Record; + createdAt: number; + lastAccessedAt: number; +} +interface ClaudeAgentConfig extends AgentConfig { + apiKey?: string; + baseUrl?: string; + sessionTimeout?: number; + enablePersistentSessions?: boolean; + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + mcpServers?: Record; + stderr?: (data: string) => void; + verbose?: boolean; +} +interface ExecutionState$1 { + id: string; + sessionId: string; + isRunning: boolean; + startTime: number; + events: ProcessedEvents[]; + error?: Error; +} +declare function isAssistantMessage(message: SDKMessage): message is SDKAssistantMessage; +declare function isResultMessage(message: SDKMessage): message is SDKResultMessage; +declare function isTextBlock(block: ContentBlock): block is TextBlock; +declare function isToolUseBlock(block: ContentBlock): block is ToolUseBlock; +declare function isToolResultBlock(block: ContentBlock): block is ToolResultBlock; +declare function isThinkingBlock(block: ContentBlock): block is ThinkingBlock; +declare function hasContentProperty(message: SDKMessage): message is SDKAssistantMessage | SDKPartialAssistantMessage; +interface ToolExecutionContext { + toolName: string; + toolCallId: string; + isClientTool: boolean; + isLongRunning: boolean; +} +interface ConvertedMessage { + role: 'user' | 'assistant' | 'system'; + content: string | Array<{ + type: string; + [key: string]: any; + }>; +} + +/** + * Session manager: Manages agent sessions and state + */ + +/** + * SessionManager handles session lifecycle, message tracking, and state management + * Implements singleton pattern for centralized session control + */ +declare class SessionManager { + private static instance; + private sessions; + private cleanupInterval; + private sessionTimeout; + private constructor(); + /** + * Get the singleton instance + */ + static getInstance(sessionTimeout?: number): SessionManager; + /** + * Reset the singleton instance (useful for testing) + */ + static resetInstance(): void; + /** + * Get or create a session + */ + getSession(sessionId: string, userId?: string): Session; + /** + * Check if a session exists + */ + hasSession(sessionId: string): boolean; + /** + * Delete a session + */ + deleteSession(sessionId: string): boolean; + /** + * Track a processed message + */ + trackMessage(sessionId: string, messageId: string): void; + /** + * Check if a message has been processed + */ + isMessageProcessed(sessionId: string, messageId: string): boolean; + /** + * Get unseen messages (messages not yet processed) + */ + getUnseenMessages(sessionId: string, messages: Message[]): Message[]; + /** + * Mark messages as processed + */ + markMessagesAsProcessed(sessionId: string, messages: Message[]): void; + /** + * Get state value from session + */ + getStateValue(sessionId: string, key: string): any; + /** + * Set state value in session + */ + setStateValue(sessionId: string, key: string, value: any): void; + /** + * Remove state keys from session + */ + removeStateKeys(sessionId: string, keys: string[]): void; + /** + * Clear all state for a session + */ + clearSessionState(sessionId: string): void; + /** + * Set Claude SDK client for a session + */ + setClient(sessionId: string, client: ClaudeSDKClient): void; + /** + * Get Claude SDK client for a session + */ + getClient(sessionId: string): ClaudeSDKClient | undefined; + /** + * Get total number of sessions + */ + getSessionCount(): number; + /** + * Get number of sessions for a specific user + */ + getUserSessionCount(userId: string): number; + /** + * Get all session IDs + */ + getAllSessionIds(): string[]; + /** + * Get all sessions for a specific user + */ + getUserSessions(userId: string): Session[]; + /** + * Clean up stale sessions + */ + private cleanupStaleSessions; + /** + * Start the cleanup interval + */ + private startCleanupInterval; + /** + * Stop the cleanup interval + */ + private stopCleanupInterval; + /** + * Clear all sessions (useful for testing) + */ + clearAllSessions(): void; +} + +/** + * Execution state: Tracks background Claude executions + */ + +/** + * ExecutionState manages the state of a Claude SDK execution + */ +declare class ExecutionState { + readonly id: string; + readonly sessionId: string; + private _isRunning; + private _startTime; + private _endTime?; + private _events; + private _error?; + private _abortController; + constructor(id: string, sessionId: string); + /** + * Check if execution is running + */ + get isRunning(): boolean; + /** + * Get start time + */ + get startTime(): number; + /** + * Get end time + */ + get endTime(): number | undefined; + /** + * Get duration in milliseconds + */ + get duration(): number; + /** + * Get all collected events + */ + get events(): ProcessedEvents[]; + /** + * Get error if any + */ + get error(): Error | undefined; + /** + * Get abort signal + */ + get signal(): AbortSignal; + /** + * Add an event to the execution state + */ + addEvent(event: ProcessedEvents): void; + /** + * Add multiple events + */ + addEvents(events: ProcessedEvents[]): void; + /** + * Mark execution as completed + */ + complete(): void; + /** + * Mark execution as failed + */ + fail(error: Error): void; + /** + * Abort the execution + */ + abort(): void; + /** + * Get execution statistics + */ + getStats(): { + duration: number; + eventCount: number; + isRunning: boolean; + hasError: boolean; + }; + /** + * Clear events (useful for memory management) + */ + clearEvents(): void; + /** + * Get the last N events + */ + getLastEvents(count: number): ProcessedEvents[]; + /** + * Check if execution has been aborted + */ + isAborted(): boolean; +} +/** + * ExecutionStateManager manages multiple execution states + */ +declare class ExecutionStateManager { + private executions; + private readonly maxExecutions; + constructor(maxExecutions?: number); + /** + * Create a new execution state + */ + createExecution(id: string, sessionId: string): ExecutionState; + /** + * Get an execution state by ID + */ + getExecution(id: string): ExecutionState | undefined; + /** + * Check if an execution exists + */ + hasExecution(id: string): boolean; + /** + * Delete an execution state + */ + deleteExecution(id: string): boolean; + /** + * Get all executions for a session + */ + getSessionExecutions(sessionId: string): ExecutionState[]; + /** + * Get running executions + */ + getRunningExecutions(): ExecutionState[]; + /** + * Get completed executions + */ + getCompletedExecutions(): ExecutionState[]; + /** + * Abort all running executions for a session + */ + abortSessionExecutions(sessionId: string): void; + /** + * Clean up old completed executions + */ + private cleanupOldExecutions; + /** + * Clear all executions + */ + clearAll(): void; + /** + * Get total execution count + */ + getExecutionCount(): number; + /** + * Get execution statistics + */ + getStats(): { + total: number; + running: number; + completed: number; + failed: number; + }; +} + +/** + * Claude Agent: Main agent class that integrates Claude SDK with AG-UI Protocol + */ + +/** + * ClaudeAgent integrates Claude Agent SDK with AG-UI Protocol + */ +declare class ClaudeAgent extends AbstractAgent { + private sessionManager; + private executionStateManager; + private apiKey?; + private baseUrl?; + private sessionTimeout; + private enablePersistentSessions; + private permissionMode; + private stderr?; + private verbose?; + constructor(config: ClaudeAgentConfig); + /** + * Map legacy permission modes to new SDK values for backward compatibility + */ + private mapPermissionMode; + /** + * Run the agent with the given input + */ + run(input: RunAgentInput): Observable; + /** + * Execute the agent asynchronously + */ + private executeAgent; + /** + * Prepare Claude SDK options + * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + * But baseUrl needs to be explicitly passed for third-party APIs + */ + private prepareClaudeOptions; + /** + * Call Claude SDK + * Note: Currently only stateless mode is supported via query() function + */ + private callClaudeSDK; + /** + * Call Claude SDK in persistent session mode + * Note: The current SDK only supports stateless mode via query() function + * This method falls back to stateless mode + */ + private callClaudeSDKPersistent; + /** + * Call Claude SDK in stateless mode + */ + private callClaudeSDKStateless; + /** + * Dynamically import Claude SDK + */ + private importClaudeSDK; + /** + * Abort a running execution + */ + abortExecution(runId: string): void; + /** + * Get execution state + */ + getExecutionState(runId: string): ExecutionState | undefined; + /** + * Get session manager (for testing) + */ + getSessionManager(): SessionManager; + /** + * Get execution state manager (for testing) + */ + getExecutionStateManager(): ExecutionStateManager; + /** + * Cleanup resources + */ + cleanup(): Promise; +} + +/** + * Event translator: Converts Claude SDK messages to AG-UI events + */ + +/** + * EventTranslator converts Claude SDK messages to AG-UI protocol events + * + * NOTE: This translator only handles SDK message translation. + * Run lifecycle events (RUN_STARTED, RUN_FINISHED, etc.) and step events + * are handled by ClaudeAgent. + */ +declare class EventTranslator { + private messageIdCounter; + private currentMessageId; + private runId; + private threadId; + constructor(runId: string, threadId: string); + /** + * Translate a Claude SDK message to AG-UI events + * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent + */ + translateMessage(message: SDKMessage): ProcessedEvents[]; + /** + * Translate an AssistantMessage with content blocks + */ + private translateAssistantMessage; + /** + * Translate a TextBlock to text message events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateTextBlock; + /** + * Translate a ToolUseBlock to tool call events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateToolUseBlock; + /** + * Translate a ToolResultBlock to tool call result event + */ + private translateToolResultBlock; + /** + * Generate a unique message ID + */ + private generateMessageId; + /** + * Reset the translator state for a new execution + */ + reset(): void; + /** + * Get current message ID + */ + getCurrentMessageId(): string | null; + /** + * Set current message ID + */ + setCurrentMessageId(messageId: string | null): void; +} + +/** + * Tool adapter: Converts AG-UI tools to Claude SDK format + */ + +/** + * ToolAdapter handles conversion of AG-UI tools to Claude SDK format + */ +declare class ToolAdapter { + /** + * Convert AG-UI tools to Claude SDK MCP tool definitions + */ + static convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[]; + /** + * Convert a single AG-UI tool to Claude SDK format + */ + private static convertSingleTool; + /** + * Convert JSON Schema to Zod schema + */ + private static convertJsonSchemaToZod; + /** + * Convert a single JSON Schema type to Zod type + */ + private static convertJsonSchemaTypeToZod; + /** + * Create an MCP server configuration for AG-UI tools + */ + static createMcpServerForTools(tools: Tool[]): Promise; + /** + * Extract tool calls from Claude SDK response + */ + static extractToolCalls(message: any): Array<{ + id: string; + name: string; + input: Record; + }>; + /** + * Check if a tool is a long-running client tool + */ + static isClientTool(toolName: string, tools: Tool[]): boolean; + /** + * Check if a tool is marked as long-running + */ + static isLongRunningTool(toolName: string, tools: Tool[]): boolean; + /** + * Format tool names for Claude SDK (with MCP server prefix) + */ + static formatToolNameForSdk(toolName: string, serverName?: string): string; + /** + * Parse tool name from SDK format (remove MCP server prefix) + */ + static parseToolNameFromSdk(sdkToolName: string): string; + /** + * Get allowed tools list for SDK options + */ + static getAllowedToolsList(tools: Tool[], serverName?: string): string[]; +} + +/** + * Message format converters + */ + +/** + * Convert AG-UI messages to a format suitable for Claude SDK + */ +declare function convertAgUiMessagesToPrompt(messages: Message[]): string; +/** + * Extract text content from a message + */ +declare function extractMessageContent(message: Message): string; +/** + * Convert AG-UI message to Claude message format + */ +declare function convertAgUiMessageToClaude(message: Message): ConvertedMessage; +/** + * Convert multiple AG-UI messages to Claude format + */ +declare function convertAgUiMessagesToClaude(messages: Message[]): ConvertedMessage[]; +/** + * Check if messages contain tool results + */ +declare function hasToolResults(messages: Message[]): boolean; +/** + * Extract tool results from messages + */ +declare function extractToolResults(messages: Message[]): Array<{ + toolCallId: string; + result: string; +}>; +/** + * Generate a unique run ID + */ +declare function generateRunId(): string; +/** + * Generate a unique message ID + */ +declare function generateMessageId(prefix?: string): string; +/** + * Safely parse JSON string + */ +declare function safeJsonParse(json: string, defaultValue?: any): any; +/** + * Safely stringify JSON + */ +declare function safeJsonStringify(obj: any, defaultValue?: string): string; +/** + * Check if a message is a tool result submission + */ +declare function isToolResultSubmission(messages: Message[]): boolean; +/** + * Format error message for display + */ +declare function formatErrorMessage(error: any): string; +/** + * Truncate text to a maximum length + */ +declare function truncateText(text: string, maxLength?: number): string; +/** + * Merge consecutive text blocks + */ +declare function mergeTextBlocks(blocks: Array<{ + type: string; + text?: string; +}>): string; + +export { type CallToolResult, ClaudeAgent, type ClaudeAgentConfig, type ClaudeSDKClient, type ContentBlock, type ConvertedMessage, EventTranslator, ExecutionState, ExecutionStateManager, type ExecutionState$1 as ExecutionStateType, type McpSdkServerConfigWithInstance, type Options, type ProcessedEvents, type Query, type SDKAssistantMessage, type SDKCompactBoundaryMessage, type SDKMessage, type SDKPartialAssistantMessage, type SDKPermissionDenial, type SDKResultMessage, type SDKSystemMessage, type SDKUserMessage, type SdkMcpToolDefinition, type Session, SessionManager, type TextBlock, type ThinkingBlock, ToolAdapter, type ToolExecutionContext, type ToolResultBlock, type ToolUseBlock, convertAgUiMessageToClaude, convertAgUiMessagesToClaude, convertAgUiMessagesToPrompt, extractMessageContent, extractToolResults, formatErrorMessage, generateMessageId, generateRunId, hasContentProperty, hasToolResults, isAssistantMessage, isResultMessage, isTextBlock, isThinkingBlock, isToolResultBlock, isToolResultSubmission, isToolUseBlock, mergeTextBlocks, safeJsonParse, safeJsonStringify, truncateText }; diff --git a/integrations/claude-agent-sdk/typescript/dist/index.d.ts b/integrations/claude-agent-sdk/typescript/dist/index.d.ts new file mode 100644 index 000000000..c15863b58 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.d.ts @@ -0,0 +1,679 @@ +import { Observable } from 'rxjs'; +import { AgentConfig, TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent, ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolCallResultEvent, RunStartedEvent, RunFinishedEvent, RunErrorEvent, StepStartedEvent, StepFinishedEvent, Message, AbstractAgent, RunAgentInput, Tool } from '@ag-ui/client'; + +/** + * Type definitions for Claude Agent SDK integration with AG-UI Protocol + */ + +interface ClaudeSDKClient { + query(prompt: string): Promise; + receiveResponse(): AsyncIterableIterator; + close(): Promise; +} +interface Options { + apiKey?: string; + baseUrl?: string; + mcpServers?: Record; + allowedTools?: string[]; + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + stderr?: (data: string) => void; + verbose?: boolean; + [key: string]: any; +} +interface Query { + next(): Promise>; + [Symbol.asyncIterator](): AsyncIterableIterator; +} +type SDKMessage = SDKAssistantMessage | SDKUserMessage | SDKSystemMessage | SDKResultMessage | SDKPartialAssistantMessage | SDKCompactBoundaryMessage | SDKPermissionDenial; +interface SDKAssistantMessage { + type: 'assistant'; + message: { + id?: string; + content: ContentBlock[]; + [key: string]: any; + }; + parent_tool_use_id?: string | null; + uuid?: string; + session_id?: string; +} +interface SDKUserMessage { + type: 'user'; + content: string; + id?: string; +} +interface SDKSystemMessage { + type: 'system'; + content: string; +} +interface SDKResultMessage { + type: 'result'; + subtype: 'success' | 'error'; + error?: { + type: string; + message: string; + }; +} +interface SDKPartialAssistantMessage { + type: 'partial_assistant'; + content: ContentBlock[]; +} +interface SDKCompactBoundaryMessage { + type: 'compact_boundary'; +} +interface SDKPermissionDenial { + type: 'permission_denial'; + tool: string; + reason: string; +} +type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock; +interface TextBlock { + type: 'text'; + text: string; +} +interface ToolUseBlock { + type: 'tool_use'; + id: string; + name: string; + input: Record; +} +interface ToolResultBlock { + type: 'tool_result'; + tool_use_id: string; + content: string | Array<{ + type: string; + [key: string]: any; + }>; + is_error?: boolean; +} +interface ThinkingBlock { + type: 'thinking'; + thinking: string; +} +interface SdkMcpToolDefinition { + name: string; + description: string; + inputSchema: Schema; + handler: (args: any, extra?: any) => Promise; +} +interface CallToolResult { + content: Array<{ + type: 'text' | 'image' | 'resource'; + text?: string; + data?: string; + mimeType?: string; + [key: string]: any; + }>; + isError?: boolean; +} +interface McpSdkServerConfigWithInstance { + name: string; + version?: string; + tools?: Array>; +} +type ProcessedEvents = TextMessageStartEvent | TextMessageContentEvent | TextMessageEndEvent | ToolCallStartEvent | ToolCallArgsEvent | ToolCallEndEvent | ToolCallResultEvent | RunStartedEvent | RunFinishedEvent | RunErrorEvent | StepStartedEvent | StepFinishedEvent; +interface Session { + id: string; + userId?: string; + client?: ClaudeSDKClient; + processedMessageIds: Set; + state: Record; + createdAt: number; + lastAccessedAt: number; +} +interface ClaudeAgentConfig extends AgentConfig { + apiKey?: string; + baseUrl?: string; + sessionTimeout?: number; + enablePersistentSessions?: boolean; + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + mcpServers?: Record; + stderr?: (data: string) => void; + verbose?: boolean; +} +interface ExecutionState$1 { + id: string; + sessionId: string; + isRunning: boolean; + startTime: number; + events: ProcessedEvents[]; + error?: Error; +} +declare function isAssistantMessage(message: SDKMessage): message is SDKAssistantMessage; +declare function isResultMessage(message: SDKMessage): message is SDKResultMessage; +declare function isTextBlock(block: ContentBlock): block is TextBlock; +declare function isToolUseBlock(block: ContentBlock): block is ToolUseBlock; +declare function isToolResultBlock(block: ContentBlock): block is ToolResultBlock; +declare function isThinkingBlock(block: ContentBlock): block is ThinkingBlock; +declare function hasContentProperty(message: SDKMessage): message is SDKAssistantMessage | SDKPartialAssistantMessage; +interface ToolExecutionContext { + toolName: string; + toolCallId: string; + isClientTool: boolean; + isLongRunning: boolean; +} +interface ConvertedMessage { + role: 'user' | 'assistant' | 'system'; + content: string | Array<{ + type: string; + [key: string]: any; + }>; +} + +/** + * Session manager: Manages agent sessions and state + */ + +/** + * SessionManager handles session lifecycle, message tracking, and state management + * Implements singleton pattern for centralized session control + */ +declare class SessionManager { + private static instance; + private sessions; + private cleanupInterval; + private sessionTimeout; + private constructor(); + /** + * Get the singleton instance + */ + static getInstance(sessionTimeout?: number): SessionManager; + /** + * Reset the singleton instance (useful for testing) + */ + static resetInstance(): void; + /** + * Get or create a session + */ + getSession(sessionId: string, userId?: string): Session; + /** + * Check if a session exists + */ + hasSession(sessionId: string): boolean; + /** + * Delete a session + */ + deleteSession(sessionId: string): boolean; + /** + * Track a processed message + */ + trackMessage(sessionId: string, messageId: string): void; + /** + * Check if a message has been processed + */ + isMessageProcessed(sessionId: string, messageId: string): boolean; + /** + * Get unseen messages (messages not yet processed) + */ + getUnseenMessages(sessionId: string, messages: Message[]): Message[]; + /** + * Mark messages as processed + */ + markMessagesAsProcessed(sessionId: string, messages: Message[]): void; + /** + * Get state value from session + */ + getStateValue(sessionId: string, key: string): any; + /** + * Set state value in session + */ + setStateValue(sessionId: string, key: string, value: any): void; + /** + * Remove state keys from session + */ + removeStateKeys(sessionId: string, keys: string[]): void; + /** + * Clear all state for a session + */ + clearSessionState(sessionId: string): void; + /** + * Set Claude SDK client for a session + */ + setClient(sessionId: string, client: ClaudeSDKClient): void; + /** + * Get Claude SDK client for a session + */ + getClient(sessionId: string): ClaudeSDKClient | undefined; + /** + * Get total number of sessions + */ + getSessionCount(): number; + /** + * Get number of sessions for a specific user + */ + getUserSessionCount(userId: string): number; + /** + * Get all session IDs + */ + getAllSessionIds(): string[]; + /** + * Get all sessions for a specific user + */ + getUserSessions(userId: string): Session[]; + /** + * Clean up stale sessions + */ + private cleanupStaleSessions; + /** + * Start the cleanup interval + */ + private startCleanupInterval; + /** + * Stop the cleanup interval + */ + private stopCleanupInterval; + /** + * Clear all sessions (useful for testing) + */ + clearAllSessions(): void; +} + +/** + * Execution state: Tracks background Claude executions + */ + +/** + * ExecutionState manages the state of a Claude SDK execution + */ +declare class ExecutionState { + readonly id: string; + readonly sessionId: string; + private _isRunning; + private _startTime; + private _endTime?; + private _events; + private _error?; + private _abortController; + constructor(id: string, sessionId: string); + /** + * Check if execution is running + */ + get isRunning(): boolean; + /** + * Get start time + */ + get startTime(): number; + /** + * Get end time + */ + get endTime(): number | undefined; + /** + * Get duration in milliseconds + */ + get duration(): number; + /** + * Get all collected events + */ + get events(): ProcessedEvents[]; + /** + * Get error if any + */ + get error(): Error | undefined; + /** + * Get abort signal + */ + get signal(): AbortSignal; + /** + * Add an event to the execution state + */ + addEvent(event: ProcessedEvents): void; + /** + * Add multiple events + */ + addEvents(events: ProcessedEvents[]): void; + /** + * Mark execution as completed + */ + complete(): void; + /** + * Mark execution as failed + */ + fail(error: Error): void; + /** + * Abort the execution + */ + abort(): void; + /** + * Get execution statistics + */ + getStats(): { + duration: number; + eventCount: number; + isRunning: boolean; + hasError: boolean; + }; + /** + * Clear events (useful for memory management) + */ + clearEvents(): void; + /** + * Get the last N events + */ + getLastEvents(count: number): ProcessedEvents[]; + /** + * Check if execution has been aborted + */ + isAborted(): boolean; +} +/** + * ExecutionStateManager manages multiple execution states + */ +declare class ExecutionStateManager { + private executions; + private readonly maxExecutions; + constructor(maxExecutions?: number); + /** + * Create a new execution state + */ + createExecution(id: string, sessionId: string): ExecutionState; + /** + * Get an execution state by ID + */ + getExecution(id: string): ExecutionState | undefined; + /** + * Check if an execution exists + */ + hasExecution(id: string): boolean; + /** + * Delete an execution state + */ + deleteExecution(id: string): boolean; + /** + * Get all executions for a session + */ + getSessionExecutions(sessionId: string): ExecutionState[]; + /** + * Get running executions + */ + getRunningExecutions(): ExecutionState[]; + /** + * Get completed executions + */ + getCompletedExecutions(): ExecutionState[]; + /** + * Abort all running executions for a session + */ + abortSessionExecutions(sessionId: string): void; + /** + * Clean up old completed executions + */ + private cleanupOldExecutions; + /** + * Clear all executions + */ + clearAll(): void; + /** + * Get total execution count + */ + getExecutionCount(): number; + /** + * Get execution statistics + */ + getStats(): { + total: number; + running: number; + completed: number; + failed: number; + }; +} + +/** + * Claude Agent: Main agent class that integrates Claude SDK with AG-UI Protocol + */ + +/** + * ClaudeAgent integrates Claude Agent SDK with AG-UI Protocol + */ +declare class ClaudeAgent extends AbstractAgent { + private sessionManager; + private executionStateManager; + private apiKey?; + private baseUrl?; + private sessionTimeout; + private enablePersistentSessions; + private permissionMode; + private stderr?; + private verbose?; + constructor(config: ClaudeAgentConfig); + /** + * Map legacy permission modes to new SDK values for backward compatibility + */ + private mapPermissionMode; + /** + * Run the agent with the given input + */ + run(input: RunAgentInput): Observable; + /** + * Execute the agent asynchronously + */ + private executeAgent; + /** + * Prepare Claude SDK options + * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + * But baseUrl needs to be explicitly passed for third-party APIs + */ + private prepareClaudeOptions; + /** + * Call Claude SDK + * Note: Currently only stateless mode is supported via query() function + */ + private callClaudeSDK; + /** + * Call Claude SDK in persistent session mode + * Note: The current SDK only supports stateless mode via query() function + * This method falls back to stateless mode + */ + private callClaudeSDKPersistent; + /** + * Call Claude SDK in stateless mode + */ + private callClaudeSDKStateless; + /** + * Dynamically import Claude SDK + */ + private importClaudeSDK; + /** + * Abort a running execution + */ + abortExecution(runId: string): void; + /** + * Get execution state + */ + getExecutionState(runId: string): ExecutionState | undefined; + /** + * Get session manager (for testing) + */ + getSessionManager(): SessionManager; + /** + * Get execution state manager (for testing) + */ + getExecutionStateManager(): ExecutionStateManager; + /** + * Cleanup resources + */ + cleanup(): Promise; +} + +/** + * Event translator: Converts Claude SDK messages to AG-UI events + */ + +/** + * EventTranslator converts Claude SDK messages to AG-UI protocol events + * + * NOTE: This translator only handles SDK message translation. + * Run lifecycle events (RUN_STARTED, RUN_FINISHED, etc.) and step events + * are handled by ClaudeAgent. + */ +declare class EventTranslator { + private messageIdCounter; + private currentMessageId; + private runId; + private threadId; + constructor(runId: string, threadId: string); + /** + * Translate a Claude SDK message to AG-UI events + * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent + */ + translateMessage(message: SDKMessage): ProcessedEvents[]; + /** + * Translate an AssistantMessage with content blocks + */ + private translateAssistantMessage; + /** + * Translate a TextBlock to text message events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateTextBlock; + /** + * Translate a ToolUseBlock to tool call events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateToolUseBlock; + /** + * Translate a ToolResultBlock to tool call result event + */ + private translateToolResultBlock; + /** + * Generate a unique message ID + */ + private generateMessageId; + /** + * Reset the translator state for a new execution + */ + reset(): void; + /** + * Get current message ID + */ + getCurrentMessageId(): string | null; + /** + * Set current message ID + */ + setCurrentMessageId(messageId: string | null): void; +} + +/** + * Tool adapter: Converts AG-UI tools to Claude SDK format + */ + +/** + * ToolAdapter handles conversion of AG-UI tools to Claude SDK format + */ +declare class ToolAdapter { + /** + * Convert AG-UI tools to Claude SDK MCP tool definitions + */ + static convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[]; + /** + * Convert a single AG-UI tool to Claude SDK format + */ + private static convertSingleTool; + /** + * Convert JSON Schema to Zod schema + */ + private static convertJsonSchemaToZod; + /** + * Convert a single JSON Schema type to Zod type + */ + private static convertJsonSchemaTypeToZod; + /** + * Create an MCP server configuration for AG-UI tools + */ + static createMcpServerForTools(tools: Tool[]): Promise; + /** + * Extract tool calls from Claude SDK response + */ + static extractToolCalls(message: any): Array<{ + id: string; + name: string; + input: Record; + }>; + /** + * Check if a tool is a long-running client tool + */ + static isClientTool(toolName: string, tools: Tool[]): boolean; + /** + * Check if a tool is marked as long-running + */ + static isLongRunningTool(toolName: string, tools: Tool[]): boolean; + /** + * Format tool names for Claude SDK (with MCP server prefix) + */ + static formatToolNameForSdk(toolName: string, serverName?: string): string; + /** + * Parse tool name from SDK format (remove MCP server prefix) + */ + static parseToolNameFromSdk(sdkToolName: string): string; + /** + * Get allowed tools list for SDK options + */ + static getAllowedToolsList(tools: Tool[], serverName?: string): string[]; +} + +/** + * Message format converters + */ + +/** + * Convert AG-UI messages to a format suitable for Claude SDK + */ +declare function convertAgUiMessagesToPrompt(messages: Message[]): string; +/** + * Extract text content from a message + */ +declare function extractMessageContent(message: Message): string; +/** + * Convert AG-UI message to Claude message format + */ +declare function convertAgUiMessageToClaude(message: Message): ConvertedMessage; +/** + * Convert multiple AG-UI messages to Claude format + */ +declare function convertAgUiMessagesToClaude(messages: Message[]): ConvertedMessage[]; +/** + * Check if messages contain tool results + */ +declare function hasToolResults(messages: Message[]): boolean; +/** + * Extract tool results from messages + */ +declare function extractToolResults(messages: Message[]): Array<{ + toolCallId: string; + result: string; +}>; +/** + * Generate a unique run ID + */ +declare function generateRunId(): string; +/** + * Generate a unique message ID + */ +declare function generateMessageId(prefix?: string): string; +/** + * Safely parse JSON string + */ +declare function safeJsonParse(json: string, defaultValue?: any): any; +/** + * Safely stringify JSON + */ +declare function safeJsonStringify(obj: any, defaultValue?: string): string; +/** + * Check if a message is a tool result submission + */ +declare function isToolResultSubmission(messages: Message[]): boolean; +/** + * Format error message for display + */ +declare function formatErrorMessage(error: any): string; +/** + * Truncate text to a maximum length + */ +declare function truncateText(text: string, maxLength?: number): string; +/** + * Merge consecutive text blocks + */ +declare function mergeTextBlocks(blocks: Array<{ + type: string; + text?: string; +}>): string; + +export { type CallToolResult, ClaudeAgent, type ClaudeAgentConfig, type ClaudeSDKClient, type ContentBlock, type ConvertedMessage, EventTranslator, ExecutionState, ExecutionStateManager, type ExecutionState$1 as ExecutionStateType, type McpSdkServerConfigWithInstance, type Options, type ProcessedEvents, type Query, type SDKAssistantMessage, type SDKCompactBoundaryMessage, type SDKMessage, type SDKPartialAssistantMessage, type SDKPermissionDenial, type SDKResultMessage, type SDKSystemMessage, type SDKUserMessage, type SdkMcpToolDefinition, type Session, SessionManager, type TextBlock, type ThinkingBlock, ToolAdapter, type ToolExecutionContext, type ToolResultBlock, type ToolUseBlock, convertAgUiMessageToClaude, convertAgUiMessagesToClaude, convertAgUiMessagesToPrompt, extractMessageContent, extractToolResults, formatErrorMessage, generateMessageId, generateRunId, hasContentProperty, hasToolResults, isAssistantMessage, isResultMessage, isTextBlock, isThinkingBlock, isToolResultBlock, isToolResultSubmission, isToolUseBlock, mergeTextBlocks, safeJsonParse, safeJsonStringify, truncateText }; diff --git a/integrations/claude-agent-sdk/typescript/dist/index.js b/integrations/claude-agent-sdk/typescript/dist/index.js new file mode 100644 index 000000000..aa142749c --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.js @@ -0,0 +1,1395 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __defProps = Object.defineProperties; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropDescs = Object.getOwnPropertyDescriptors; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getOwnPropSymbols = Object.getOwnPropertySymbols; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __propIsEnum = Object.prototype.propertyIsEnumerable; +var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name); +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; +}; +var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); +var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + ClaudeAgent: () => ClaudeAgent, + EventTranslator: () => EventTranslator, + ExecutionState: () => ExecutionState, + ExecutionStateManager: () => ExecutionStateManager, + SessionManager: () => SessionManager, + ToolAdapter: () => ToolAdapter, + convertAgUiMessageToClaude: () => convertAgUiMessageToClaude, + convertAgUiMessagesToClaude: () => convertAgUiMessagesToClaude, + convertAgUiMessagesToPrompt: () => convertAgUiMessagesToPrompt, + extractMessageContent: () => extractMessageContent, + extractToolResults: () => extractToolResults, + formatErrorMessage: () => formatErrorMessage, + generateMessageId: () => generateMessageId, + generateRunId: () => generateRunId, + hasContentProperty: () => hasContentProperty, + hasToolResults: () => hasToolResults, + isAssistantMessage: () => isAssistantMessage, + isResultMessage: () => isResultMessage, + isTextBlock: () => isTextBlock, + isThinkingBlock: () => isThinkingBlock, + isToolResultBlock: () => isToolResultBlock, + isToolResultSubmission: () => isToolResultSubmission, + isToolUseBlock: () => isToolUseBlock, + mergeTextBlocks: () => mergeTextBlocks, + safeJsonParse: () => safeJsonParse, + safeJsonStringify: () => safeJsonStringify, + truncateText: () => truncateText +}); +module.exports = __toCommonJS(src_exports); + +// src/agent.ts +var import_rxjs = require("rxjs"); +var import_client2 = require("@ag-ui/client"); + +// src/session-manager.ts +var DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1e3; +var CLEANUP_INTERVAL = 5 * 60 * 1e3; +var _SessionManager = class _SessionManager { + constructor(sessionTimeout = DEFAULT_SESSION_TIMEOUT) { + this.sessions = /* @__PURE__ */ new Map(); + this.cleanupInterval = null; + this.sessionTimeout = sessionTimeout; + this.startCleanupInterval(); + } + /** + * Get the singleton instance + */ + static getInstance(sessionTimeout) { + if (!_SessionManager.instance) { + _SessionManager.instance = new _SessionManager(sessionTimeout); + } + return _SessionManager.instance; + } + /** + * Reset the singleton instance (useful for testing) + */ + static resetInstance() { + if (_SessionManager.instance) { + _SessionManager.instance.stopCleanupInterval(); + _SessionManager.instance = null; + } + } + /** + * Get or create a session + */ + getSession(sessionId, userId) { + let session = this.sessions.get(sessionId); + if (!session) { + session = { + id: sessionId, + userId, + processedMessageIds: /* @__PURE__ */ new Set(), + state: {}, + createdAt: Date.now(), + lastAccessedAt: Date.now() + }; + this.sessions.set(sessionId, session); + } else { + session.lastAccessedAt = Date.now(); + } + return session; + } + /** + * Check if a session exists + */ + hasSession(sessionId) { + return this.sessions.has(sessionId); + } + /** + * Delete a session + */ + deleteSession(sessionId) { + const session = this.sessions.get(sessionId); + if (session == null ? void 0 : session.client) { + session.client.close().catch((error) => { + console.error(`Error closing Claude SDK client for session ${sessionId}:`, error); + }); + } + return this.sessions.delete(sessionId); + } + /** + * Track a processed message + */ + trackMessage(sessionId, messageId) { + const session = this.sessions.get(sessionId); + if (session) { + session.processedMessageIds.add(messageId); + session.lastAccessedAt = Date.now(); + } + } + /** + * Check if a message has been processed + */ + isMessageProcessed(sessionId, messageId) { + const session = this.sessions.get(sessionId); + return session ? session.processedMessageIds.has(messageId) : false; + } + /** + * Get unseen messages (messages not yet processed) + */ + getUnseenMessages(sessionId, messages) { + const session = this.sessions.get(sessionId); + if (!session) { + return messages; + } + return messages.filter((msg) => { + const msgId = msg.id || `${msg.role}_${msg.content}`; + return !session.processedMessageIds.has(msgId); + }); + } + /** + * Mark messages as processed + */ + markMessagesAsProcessed(sessionId, messages) { + const session = this.sessions.get(sessionId); + if (session) { + for (const msg of messages) { + const msgId = msg.id || `${msg.role}_${msg.content}`; + session.processedMessageIds.add(msgId); + } + session.lastAccessedAt = Date.now(); + } + } + /** + * Get state value from session + */ + getStateValue(sessionId, key) { + const session = this.sessions.get(sessionId); + return session == null ? void 0 : session.state[key]; + } + /** + * Set state value in session + */ + setStateValue(sessionId, key, value) { + const session = this.sessions.get(sessionId); + if (session) { + session.state[key] = value; + session.lastAccessedAt = Date.now(); + } + } + /** + * Remove state keys from session + */ + removeStateKeys(sessionId, keys) { + const session = this.sessions.get(sessionId); + if (session) { + for (const key of keys) { + delete session.state[key]; + } + session.lastAccessedAt = Date.now(); + } + } + /** + * Clear all state for a session + */ + clearSessionState(sessionId) { + const session = this.sessions.get(sessionId); + if (session) { + session.state = {}; + session.lastAccessedAt = Date.now(); + } + } + /** + * Set Claude SDK client for a session + */ + setClient(sessionId, client) { + const session = this.sessions.get(sessionId); + if (session) { + session.client = client; + session.lastAccessedAt = Date.now(); + } + } + /** + * Get Claude SDK client for a session + */ + getClient(sessionId) { + const session = this.sessions.get(sessionId); + return session == null ? void 0 : session.client; + } + /** + * Get total number of sessions + */ + getSessionCount() { + return this.sessions.size; + } + /** + * Get number of sessions for a specific user + */ + getUserSessionCount(userId) { + let count = 0; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + count++; + } + } + return count; + } + /** + * Get all session IDs + */ + getAllSessionIds() { + return Array.from(this.sessions.keys()); + } + /** + * Get all sessions for a specific user + */ + getUserSessions(userId) { + const userSessions = []; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + userSessions.push(session); + } + } + return userSessions; + } + /** + * Clean up stale sessions + */ + cleanupStaleSessions() { + const now = Date.now(); + const sessionsToDelete = []; + for (const [sessionId, session] of this.sessions.entries()) { + if (now - session.lastAccessedAt > this.sessionTimeout) { + sessionsToDelete.push(sessionId); + } + } + for (const sessionId of sessionsToDelete) { + this.deleteSession(sessionId); + } + if (sessionsToDelete.length > 0) { + console.log(`Cleaned up ${sessionsToDelete.length} stale sessions`); + } + } + /** + * Start the cleanup interval + */ + startCleanupInterval() { + if (!this.cleanupInterval) { + this.cleanupInterval = setInterval(() => { + this.cleanupStaleSessions(); + }, CLEANUP_INTERVAL); + if (typeof this.cleanupInterval.unref === "function") { + this.cleanupInterval.unref(); + } + } + } + /** + * Stop the cleanup interval + */ + stopCleanupInterval() { + if (this.cleanupInterval) { + clearInterval(this.cleanupInterval); + this.cleanupInterval = null; + } + } + /** + * Clear all sessions (useful for testing) + */ + clearAllSessions() { + for (const sessionId of this.sessions.keys()) { + this.deleteSession(sessionId); + } + this.sessions.clear(); + } +}; +_SessionManager.instance = null; +var SessionManager = _SessionManager; + +// src/event-translator.ts +var import_client = require("@ag-ui/client"); + +// src/types.ts +function isAssistantMessage(message) { + return message.type === "assistant"; +} +function isResultMessage(message) { + return message.type === "result"; +} +function isTextBlock(block) { + return block.type === "text"; +} +function isToolUseBlock(block) { + return block.type === "tool_use"; +} +function isToolResultBlock(block) { + return block.type === "tool_result"; +} +function isThinkingBlock(block) { + return block.type === "thinking"; +} +function hasContentProperty(message) { + if (message.type === "assistant") { + return "message" in message && message.message !== null && typeof message.message === "object" && "content" in message.message && Array.isArray(message.message.content); + } + return "content" in message && Array.isArray(message.content); +} + +// src/event-translator.ts +var EventTranslator = class { + constructor(runId, threadId) { + this.messageIdCounter = 0; + this.currentMessageId = null; + this.runId = runId; + this.threadId = threadId; + } + /** + * Translate a Claude SDK message to AG-UI events + * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent + */ + translateMessage(message) { + const events = []; + if (hasContentProperty(message)) { + events.push(...this.translateAssistantMessage(message)); + } + return events; + } + /** + * Translate an AssistantMessage with content blocks + */ + translateAssistantMessage(message) { + var _a; + const events = []; + const content = ((_a = message.message) == null ? void 0 : _a.content) || []; + for (const block of content) { + if (isTextBlock(block)) { + events.push(...this.translateTextBlock(block)); + } else if (isToolUseBlock(block)) { + events.push(...this.translateToolUseBlock(block)); + } else if (isToolResultBlock(block)) { + events.push(...this.translateToolResultBlock(block)); + } + } + return events; + } + /** + * Translate a TextBlock to text message events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + translateTextBlock(block) { + const events = []; + const messageId = this.generateMessageId(); + events.push({ + type: import_client.EventType.TEXT_MESSAGE_START, + messageId, + role: "assistant" + }); + const text = block.text; + if (text.length > 0) { + events.push({ + type: import_client.EventType.TEXT_MESSAGE_CONTENT, + messageId, + delta: text + }); + } + events.push({ + type: import_client.EventType.TEXT_MESSAGE_END, + messageId + }); + return events; + } + /** + * Translate a ToolUseBlock to tool call events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + translateToolUseBlock(block) { + const events = []; + const toolCallId = block.id; + events.push({ + type: import_client.EventType.TOOL_CALL_START, + toolCallId, + toolCallName: block.name + }); + const argsJson = JSON.stringify(block.input); + if (argsJson.length > 0) { + events.push({ + type: import_client.EventType.TOOL_CALL_ARGS, + toolCallId, + delta: argsJson + }); + } + events.push({ + type: import_client.EventType.TOOL_CALL_END, + toolCallId + }); + return events; + } + /** + * Translate a ToolResultBlock to tool call result event + */ + translateToolResultBlock(block) { + const events = []; + let resultContent; + if (typeof block.content === "string") { + resultContent = block.content; + } else if (Array.isArray(block.content)) { + resultContent = block.content.map((item) => { + if (item.type === "text") { + return item.text || ""; + } + return JSON.stringify(item); + }).join("\n"); + } else { + resultContent = JSON.stringify(block.content); + } + const messageId = this.generateMessageId(); + events.push(__spreadValues({ + type: import_client.EventType.TOOL_CALL_RESULT, + toolCallId: block.tool_use_id, + messageId, + content: resultContent + }, block.is_error && { role: "tool" })); + return events; + } + /** + * Generate a unique message ID + */ + generateMessageId() { + this.messageIdCounter++; + return `msg_${this.runId}_${this.messageIdCounter}`; + } + /** + * Reset the translator state for a new execution + */ + reset() { + this.messageIdCounter = 0; + this.currentMessageId = null; + } + /** + * Get current message ID + */ + getCurrentMessageId() { + return this.currentMessageId; + } + /** + * Set current message ID + */ + setCurrentMessageId(messageId) { + this.currentMessageId = messageId; + } +}; + +// src/tool-adapter.ts +var import_zod = require("zod"); +var ToolAdapter = class { + /** + * Convert AG-UI tools to Claude SDK MCP tool definitions + */ + static convertAgUiToolsToSdk(tools) { + return tools.map((tool) => this.convertSingleTool(tool)); + } + /** + * Convert a single AG-UI tool to Claude SDK format + */ + static convertSingleTool(tool) { + const zodSchema = this.convertJsonSchemaToZod(tool.parameters || {}); + return { + name: tool.name, + description: tool.description || "", + inputSchema: zodSchema, + handler: async (args) => { + if (tool.client) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + toolName: tool.name, + args, + isClientTool: true, + isLongRunning: true + }) + } + ] + }; + } + if (tool.handler) { + try { + const result = await tool.handler(args); + return { + content: [ + { + type: "text", + text: typeof result === "string" ? result : JSON.stringify(result) + } + ] + }; + } catch (error) { + return { + content: [ + { + type: "text", + text: error.message || "Tool execution failed" + } + ], + isError: true + }; + } + } + return { + content: [ + { + type: "text", + text: "Tool executed (no handler)" + } + ] + }; + } + }; + } + /** + * Convert JSON Schema to Zod schema + */ + static convertJsonSchemaToZod(jsonSchema) { + if (!jsonSchema || typeof jsonSchema !== "object") { + return import_zod.z.object({}); + } + const properties = jsonSchema.properties || {}; + const required = jsonSchema.required || []; + const zodShape = {}; + for (const [key, prop] of Object.entries(properties)) { + const propSchema = prop; + let zodType = this.convertJsonSchemaTypeToZod(propSchema); + if (!required.includes(key)) { + zodType = zodType.optional(); + } + zodShape[key] = zodType; + } + return import_zod.z.object(zodShape); + } + /** + * Convert a single JSON Schema type to Zod type + */ + static convertJsonSchemaTypeToZod(schema) { + const type = schema.type; + switch (type) { + case "string": + if (schema.enum) { + return import_zod.z.enum(schema.enum); + } + return import_zod.z.string(); + case "number": + case "integer": + let numType = type === "integer" ? import_zod.z.number().int() : import_zod.z.number(); + if (schema.minimum !== void 0) { + numType = numType.min(schema.minimum); + } + if (schema.maximum !== void 0) { + numType = numType.max(schema.maximum); + } + return numType; + case "boolean": + return import_zod.z.boolean(); + case "array": + if (schema.items) { + const itemType = this.convertJsonSchemaTypeToZod(schema.items); + return import_zod.z.array(itemType); + } + return import_zod.z.array(import_zod.z.any()); + case "object": + if (schema.properties) { + return this.convertJsonSchemaToZod(schema); + } + return import_zod.z.record(import_zod.z.any()); + case "null": + return import_zod.z.null(); + default: + return import_zod.z.any(); + } + } + /** + * Create an MCP server configuration for AG-UI tools + */ + static async createMcpServerForTools(tools) { + const sdkTools = this.convertAgUiToolsToSdk(tools); + const { createSdkMcpServer } = await import("@anthropic-ai/claude-agent-sdk"); + return createSdkMcpServer({ + name: "ag_ui_tools", + version: "1.0.0", + tools: sdkTools + // Cast to any to avoid type incompatibility + }); + } + /** + * Extract tool calls from Claude SDK response + */ + static extractToolCalls(message) { + if (!message.content || !Array.isArray(message.content)) { + return []; + } + return message.content.filter((block) => block.type === "tool_use").map((block) => ({ + id: block.id, + name: block.name, + input: block.input + })); + } + /** + * Check if a tool is a long-running client tool + */ + static isClientTool(toolName, tools) { + const tool = tools.find((t) => t.name === toolName); + return (tool == null ? void 0 : tool.client) === true; + } + /** + * Check if a tool is marked as long-running + */ + static isLongRunningTool(toolName, tools) { + const tool = tools.find((t) => t.name === toolName); + return (tool == null ? void 0 : tool.client) === true || (tool == null ? void 0 : tool.longRunning) === true; + } + /** + * Format tool names for Claude SDK (with MCP server prefix) + */ + static formatToolNameForSdk(toolName, serverName = "ag_ui_tools") { + return `mcp__${serverName}__${toolName}`; + } + /** + * Parse tool name from SDK format (remove MCP server prefix) + */ + static parseToolNameFromSdk(sdkToolName) { + const parts = sdkToolName.split("__"); + if (parts.length >= 3 && parts[0] === "mcp") { + return parts.slice(2).join("__"); + } + return sdkToolName; + } + /** + * Get allowed tools list for SDK options + */ + static getAllowedToolsList(tools, serverName = "ag_ui_tools") { + return tools.map((tool) => this.formatToolNameForSdk(tool.name, serverName)); + } +}; + +// src/execution-state.ts +var ExecutionState = class { + constructor(id, sessionId) { + this.id = id; + this.sessionId = sessionId; + this._isRunning = true; + this._startTime = Date.now(); + this._events = []; + this._abortController = new AbortController(); + } + /** + * Check if execution is running + */ + get isRunning() { + return this._isRunning; + } + /** + * Get start time + */ + get startTime() { + return this._startTime; + } + /** + * Get end time + */ + get endTime() { + return this._endTime; + } + /** + * Get duration in milliseconds + */ + get duration() { + const end = this._endTime || Date.now(); + return end - this._startTime; + } + /** + * Get all collected events + */ + get events() { + return [...this._events]; + } + /** + * Get error if any + */ + get error() { + return this._error; + } + /** + * Get abort signal + */ + get signal() { + return this._abortController.signal; + } + /** + * Add an event to the execution state + */ + addEvent(event) { + this._events.push(event); + } + /** + * Add multiple events + */ + addEvents(events) { + this._events.push(...events); + } + /** + * Mark execution as completed + */ + complete() { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + } + } + /** + * Mark execution as failed + */ + fail(error) { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + this._error = error; + } + } + /** + * Abort the execution + */ + abort() { + if (this._isRunning) { + this._abortController.abort(); + this._isRunning = false; + this._endTime = Date.now(); + } + } + /** + * Get execution statistics + */ + getStats() { + return { + duration: this.duration, + eventCount: this._events.length, + isRunning: this._isRunning, + hasError: !!this._error + }; + } + /** + * Clear events (useful for memory management) + */ + clearEvents() { + this._events = []; + } + /** + * Get the last N events + */ + getLastEvents(count) { + return this._events.slice(-count); + } + /** + * Check if execution has been aborted + */ + isAborted() { + return this._abortController.signal.aborted; + } +}; +var ExecutionStateManager = class { + constructor(maxExecutions = 100) { + this.executions = /* @__PURE__ */ new Map(); + this.maxExecutions = maxExecutions; + } + /** + * Create a new execution state + */ + createExecution(id, sessionId) { + const execution = new ExecutionState(id, sessionId); + this.executions.set(id, execution); + if (this.executions.size > this.maxExecutions) { + this.cleanupOldExecutions(); + } + return execution; + } + /** + * Get an execution state by ID + */ + getExecution(id) { + return this.executions.get(id); + } + /** + * Check if an execution exists + */ + hasExecution(id) { + return this.executions.has(id); + } + /** + * Delete an execution state + */ + deleteExecution(id) { + return this.executions.delete(id); + } + /** + * Get all executions for a session + */ + getSessionExecutions(sessionId) { + const executions = []; + for (const execution of this.executions.values()) { + if (execution.sessionId === sessionId) { + executions.push(execution); + } + } + return executions; + } + /** + * Get running executions + */ + getRunningExecutions() { + const running = []; + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running.push(execution); + } + } + return running; + } + /** + * Get completed executions + */ + getCompletedExecutions() { + const completed = []; + for (const execution of this.executions.values()) { + if (!execution.isRunning) { + completed.push(execution); + } + } + return completed; + } + /** + * Abort all running executions for a session + */ + abortSessionExecutions(sessionId) { + const sessionExecutions = this.getSessionExecutions(sessionId); + for (const execution of sessionExecutions) { + if (execution.isRunning) { + execution.abort(); + } + } + } + /** + * Clean up old completed executions + */ + cleanupOldExecutions() { + const completed = this.getCompletedExecutions(); + completed.sort((a, b) => { + const aTime = a.endTime || a.startTime; + const bTime = b.endTime || b.startTime; + return aTime - bTime; + }); + const toRemove = Math.max(0, this.executions.size - this.maxExecutions); + for (let i = 0; i < toRemove && i < completed.length; i++) { + this.executions.delete(completed[i].id); + } + } + /** + * Clear all executions + */ + clearAll() { + this.executions.clear(); + } + /** + * Get total execution count + */ + getExecutionCount() { + return this.executions.size; + } + /** + * Get execution statistics + */ + getStats() { + let running = 0; + let completed = 0; + let failed = 0; + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running++; + } else if (execution.error) { + failed++; + } else { + completed++; + } + } + return { + total: this.executions.size, + running, + completed, + failed + }; + } +}; + +// src/utils/converters.ts +function convertAgUiMessagesToPrompt(messages) { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + if (msg.role === "user") { + return extractMessageContent(msg); + } + } + return "Hello"; +} +function extractMessageContent(message) { + if (typeof message.content === "string") { + return message.content; + } + if (Array.isArray(message.content)) { + return message.content.map((block) => { + if (typeof block === "string") { + return block; + } + if (block.type === "text") { + return block.text || ""; + } + return ""; + }).filter(Boolean).join("\n"); + } + return String(message.content); +} +function convertAgUiMessageToClaude(message) { + const role = message.role; + const content = extractMessageContent(message); + return { + role, + content + }; +} +function convertAgUiMessagesToClaude(messages) { + return messages.map(convertAgUiMessageToClaude); +} +function hasToolResults(messages) { + return messages.some((msg) => { + if (typeof msg.content === "string") { + return false; + } + if (Array.isArray(msg.content)) { + return msg.content.some((block) => { + return typeof block === "object" && block.type === "tool_result"; + }); + } + return false; + }); +} +function extractToolResults(messages) { + const results = []; + for (const msg of messages) { + if (typeof msg.content === "string") { + continue; + } + if (Array.isArray(msg.content)) { + for (const block of msg.content) { + if (typeof block === "object" && block.type === "tool_result") { + results.push({ + toolCallId: block.toolCallId || block.tool_use_id || "", + result: block.result || block.content || "" + }); + } + } + } + } + return results; +} +function generateRunId() { + return `run_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} +function generateMessageId(prefix = "msg") { + return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} +function safeJsonParse(json, defaultValue = null) { + try { + return JSON.parse(json); + } catch (e) { + return defaultValue; + } +} +function safeJsonStringify(obj, defaultValue = "{}") { + try { + return JSON.stringify(obj); + } catch (e) { + return defaultValue; + } +} +function isToolResultSubmission(messages) { + if (messages.length === 0) { + return false; + } + const lastMessage = messages[messages.length - 1]; + return hasToolResults([lastMessage]); +} +function formatErrorMessage(error) { + if (error instanceof Error) { + return error.message; + } + if (typeof error === "string") { + return error; + } + return "An unknown error occurred"; +} +function truncateText(text, maxLength = 1e3) { + if (text.length <= maxLength) { + return text; + } + return text.slice(0, maxLength) + "..."; +} +function mergeTextBlocks(blocks) { + return blocks.filter((block) => block.type === "text" && block.text).map((block) => block.text).join(""); +} + +// src/agent.ts +var ClaudeAgent = class extends import_client2.AbstractAgent { + constructor(config) { + super(config); + this.apiKey = config.apiKey; + this.baseUrl = config.baseUrl; + this.sessionTimeout = config.sessionTimeout || 30 * 60 * 1e3; + this.enablePersistentSessions = config.enablePersistentSessions !== false; + this.permissionMode = this.mapPermissionMode(config.permissionMode || "bypassPermissions"); + this.stderr = config.stderr; + this.verbose = config.verbose; + this.sessionManager = SessionManager.getInstance(this.sessionTimeout); + this.executionStateManager = new ExecutionStateManager(); + } + /** + * Map legacy permission modes to new SDK values for backward compatibility + */ + mapPermissionMode(mode) { + const modeMap = { + "ask": "default", + "auto": "bypassPermissions", + "none": "bypassPermissions", + "default": "default", + "acceptEdits": "acceptEdits", + "bypassPermissions": "bypassPermissions", + "plan": "plan" + }; + return modeMap[mode || "bypassPermissions"] || "bypassPermissions"; + } + /** + * Run the agent with the given input + */ + run(input) { + return new import_rxjs.Observable((subscriber) => { + this.executeAgent(input, subscriber).catch((error) => { + subscriber.error(error); + }); + }); + } + /** + * Execute the agent asynchronously + */ + async executeAgent(input, subscriber) { + const runId = generateRunId(); + const sessionId = input.threadId || `session_${Date.now()}`; + const execution = this.executionStateManager.createExecution(runId, sessionId); + try { + const runStartedEvent = { + type: import_client2.EventType.RUN_STARTED, + threadId: sessionId, + runId + }; + subscriber.next(runStartedEvent); + execution.addEvent(runStartedEvent); + const session = this.sessionManager.getSession(sessionId, "default"); + const unseenMessages = this.sessionManager.getUnseenMessages( + sessionId, + input.messages || [] + ); + const isToolResult = isToolResultSubmission(input.messages || []); + const tools = input.tools || []; + const options = await this.prepareClaudeOptions(tools); + const prompt = convertAgUiMessagesToPrompt(unseenMessages); + const stepStartedEvent = { + type: import_client2.EventType.STEP_STARTED, + stepName: `step_${runId}_1` + }; + subscriber.next(stepStartedEvent); + execution.addEvent(stepStartedEvent); + await this.callClaudeSDK( + prompt, + options, + session, + runId, + sessionId, + subscriber, + execution + ); + this.sessionManager.markMessagesAsProcessed(sessionId, unseenMessages); + const stepFinishedEvent = { + type: import_client2.EventType.STEP_FINISHED, + stepName: `step_${runId}_1` + }; + subscriber.next(stepFinishedEvent); + execution.addEvent(stepFinishedEvent); + const runFinishedEvent = { + type: import_client2.EventType.RUN_FINISHED, + threadId: sessionId, + runId + }; + subscriber.next(runFinishedEvent); + execution.addEvent(runFinishedEvent); + execution.complete(); + subscriber.complete(); + } catch (error) { + const runErrorEvent = { + type: import_client2.EventType.RUN_ERROR, + message: formatErrorMessage(error) + }; + subscriber.next(runErrorEvent); + execution.addEvent(runErrorEvent); + execution.fail(error); + subscriber.complete(); + } + } + /** + * Prepare Claude SDK options + * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + * But baseUrl needs to be explicitly passed for third-party APIs + */ + async prepareClaudeOptions(tools) { + const baseUrl = this.baseUrl || process.env.ANTHROPIC_BASE_URL; + const apiKey = this.apiKey || process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY; + console.log("[Claude Agent] Preparing SDK options:", { + hasApiKey: !!apiKey, + hasBaseUrl: !!baseUrl, + baseUrl: baseUrl || "not set", + permissionMode: this.permissionMode, + hasStderr: !!this.stderr, + verbose: this.verbose + }); + const options = __spreadProps(__spreadValues(__spreadValues({ + permissionMode: this.permissionMode + }, this.stderr && { stderr: this.stderr }), this.verbose !== void 0 && { verbose: this.verbose }), { + env: process.env + }); + if (this.stderr) { + console.log("[Claude Agent] \u2713 stderr callback is configured for error logging"); + } else { + console.warn("[Claude Agent] \u26A0\uFE0F stderr callback not configured - CLI errors may not be visible"); + } + if (tools && tools.length > 0) { + const mcpServer = await ToolAdapter.createMcpServerForTools(tools); + options.mcpServers = { + ag_ui_tools: mcpServer + }; + options.allowedTools = ToolAdapter.getAllowedToolsList(tools); + } + return options; + } + /** + * Call Claude SDK + * Note: Currently only stateless mode is supported via query() function + */ + async callClaudeSDK(prompt, options, session, runId, sessionId, subscriber, execution) { + const eventTranslator = new EventTranslator(runId, sessionId); + await this.callClaudeSDKStateless( + prompt, + options, + eventTranslator, + subscriber, + execution + ); + } + /** + * Call Claude SDK in persistent session mode + * Note: The current SDK only supports stateless mode via query() function + * This method falls back to stateless mode + */ + async callClaudeSDKPersistent(prompt, options, session, eventTranslator, subscriber, execution) { + await this.callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution); + } + /** + * Call Claude SDK in stateless mode + */ + async callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution) { + try { + console.log("[Claude Agent] Environment check:"); + console.log(" ANTHROPIC_API_KEY:", process.env.ANTHROPIC_API_KEY ? "SET" : "NOT SET"); + console.log(" ANTHROPIC_AUTH_TOKEN:", process.env.ANTHROPIC_AUTH_TOKEN ? "SET" : "NOT SET"); + console.log(" ANTHROPIC_BASE_URL:", process.env.ANTHROPIC_BASE_URL || "NOT SET (using default)"); + console.log("[Claude Agent] Options passed to SDK:", { + hasApiKey: !!options.apiKey, + hasBaseUrl: !!options.baseUrl, + permissionMode: options.permissionMode, + hasMcpServers: !!options.mcpServers + }); + const { query } = await this.importClaudeSDK(); + console.log("[Claude Agent] Calling SDK query()..."); + const queryResult = query({ prompt, options }); + try { + for (var iter = __forAwait(queryResult), more, temp, error; more = !(temp = await iter.next()).done; more = false) { + const message = temp.value; + console.log("[Claude Agent] \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"); + console.log("[Claude Agent] Received message type:", (message == null ? void 0 : message.type) || "unknown"); + console.log("[Claude Agent] Full message:", JSON.stringify(message, null, 2)); + if (execution.isAborted()) { + console.log("[Claude Agent] Execution aborted by user"); + break; + } + const events = eventTranslator.translateMessage(message); + console.log("[Claude Agent] Translated events count:", events.length); + for (const event of events) { + console.log("[Claude Agent] Sending event:", JSON.stringify(event, null, 2)); + subscriber.next(event); + execution.addEvent(event); + } + console.log("[Claude Agent] \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"); + } + } catch (temp) { + error = [temp]; + } finally { + try { + more && (temp = iter.return) && await temp.call(iter); + } finally { + if (error) + throw error[0]; + } + } + console.log("[Claude Agent] Query completed successfully"); + } catch (error2) { + console.error("[Claude Agent] ERROR Details:"); + console.error(" Message:", error2.message); + console.error(" Stack:", error2.stack); + console.error(" Error object:", JSON.stringify(error2, Object.getOwnPropertyNames(error2), 2)); + if (error2.message && error2.message.includes("exited with code")) { + throw new Error( + `Claude Code process failed. Please ensure: +1. Claude CLI is installed and accessible (run: claude --version) +2. ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set correctly in environment variables +3. You have proper permissions to run Claude Code +4. If using ANTHROPIC_BASE_URL, ensure it supports Claude Code protocol + +Original error: ${error2.message} +Error stack: ${error2.stack || "No stack trace"}` + ); + } + if (error2.message && (error2.message.includes("API key") || error2.message.includes("auth"))) { + throw new Error( + `API key error: ${error2.message} +Please ensure ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set in environment variables.` + ); + } + throw error2; + } + } + /** + * Dynamically import Claude SDK + */ + async importClaudeSDK() { + try { + return await import("@anthropic-ai/claude-agent-sdk"); + } catch (error) { + throw new Error( + "Claude Agent SDK not found. Please install it: npm install @anthropic-ai/claude-agent-sdk" + ); + } + } + /** + * Abort a running execution + */ + abortExecution(runId) { + const execution = this.executionStateManager.getExecution(runId); + if (execution) { + execution.abort(); + } + } + /** + * Get execution state + */ + getExecutionState(runId) { + return this.executionStateManager.getExecution(runId); + } + /** + * Get session manager (for testing) + */ + getSessionManager() { + return this.sessionManager; + } + /** + * Get execution state manager (for testing) + */ + getExecutionStateManager() { + return this.executionStateManager; + } + /** + * Cleanup resources + */ + async cleanup() { + const runningExecutions = this.executionStateManager.getRunningExecutions(); + for (const execution of runningExecutions) { + execution.abort(); + } + this.sessionManager.clearAllSessions(); + this.executionStateManager.clearAll(); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + ClaudeAgent, + EventTranslator, + ExecutionState, + ExecutionStateManager, + SessionManager, + ToolAdapter, + convertAgUiMessageToClaude, + convertAgUiMessagesToClaude, + convertAgUiMessagesToPrompt, + extractMessageContent, + extractToolResults, + formatErrorMessage, + generateMessageId, + generateRunId, + hasContentProperty, + hasToolResults, + isAssistantMessage, + isResultMessage, + isTextBlock, + isThinkingBlock, + isToolResultBlock, + isToolResultSubmission, + isToolUseBlock, + mergeTextBlocks, + safeJsonParse, + safeJsonStringify, + truncateText +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/integrations/claude-agent-sdk/typescript/dist/index.js.map b/integrations/claude-agent-sdk/typescript/dist/index.js.map new file mode 100644 index 000000000..2523a4b13 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/session-manager.ts","../src/event-translator.ts","../src/types.ts","../src/tool-adapter.ts","../src/execution-state.ts","../src/utils/converters.ts"],"sourcesContent":["/**\n * Claude Agent SDK integration with AG-UI Protocol\n * \n * This package provides a bridge between Claude Agent SDK and the AG-UI Protocol,\n * enabling Claude agents to work seamlessly with AG-UI applications.\n * \n * @example\n * ```typescript\n * import { ClaudeAgent } from '@ag-ui/claude';\n * \n * const agent = new ClaudeAgent({\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * enablePersistentSessions: true\n * });\n * \n * agent.run(input).subscribe({\n * next: (event) => console.log(event),\n * error: (error) => console.error(error),\n * complete: () => console.log('Done')\n * });\n * ```\n */\n\n// Main agent class\nexport { ClaudeAgent } from './agent';\n\n// Session management\nexport { SessionManager } from './session-manager';\n\n// Event translation\nexport { EventTranslator } from './event-translator';\n\n// Tool adaptation\nexport { ToolAdapter } from './tool-adapter';\n\n// Execution state management\nexport { ExecutionState, ExecutionStateManager } from './execution-state';\n\n// Utility functions\nexport {\n convertAgUiMessagesToPrompt,\n convertAgUiMessageToClaude,\n convertAgUiMessagesToClaude,\n extractMessageContent,\n hasToolResults,\n extractToolResults,\n generateRunId,\n generateMessageId,\n safeJsonParse,\n safeJsonStringify,\n isToolResultSubmission,\n formatErrorMessage,\n truncateText,\n mergeTextBlocks,\n} from './utils/converters';\n\n// Type exports\nexport type {\n ClaudeAgentConfig,\n ProcessedEvents,\n Session,\n ClaudeSDKClient,\n Options,\n Query,\n SDKMessage,\n SDKAssistantMessage,\n SDKUserMessage,\n SDKSystemMessage,\n SDKResultMessage,\n SDKPartialAssistantMessage,\n SDKCompactBoundaryMessage,\n SDKPermissionDenial,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n ThinkingBlock,\n SdkMcpToolDefinition,\n CallToolResult,\n McpSdkServerConfigWithInstance,\n ExecutionState as ExecutionStateType,\n ToolExecutionContext,\n ConvertedMessage,\n} from './types';\n\n// Re-export type guards\nexport {\n isAssistantMessage,\n isResultMessage,\n isTextBlock,\n isToolUseBlock,\n isToolResultBlock,\n isThinkingBlock,\n hasContentProperty,\n} from './types';\n\n","/**\n * Claude Agent: Main agent class that integrates Claude SDK with AG-UI Protocol\n */\n\nimport { Observable, Subscriber } from 'rxjs';\nimport {\n AbstractAgent,\n RunAgentInput,\n EventType,\n RunStartedEvent,\n RunFinishedEvent,\n RunErrorEvent,\n StepStartedEvent,\n StepFinishedEvent,\n} from '@ag-ui/client';\nimport type {\n ClaudeAgentConfig,\n ProcessedEvents,\n ClaudeSDKClient,\n Options,\n SDKMessage,\n} from './types';\nimport { SessionManager } from './session-manager';\nimport { EventTranslator } from './event-translator';\nimport { ToolAdapter } from './tool-adapter';\nimport { ExecutionState, ExecutionStateManager } from './execution-state';\nimport {\n generateRunId,\n convertAgUiMessagesToPrompt,\n isToolResultSubmission,\n formatErrorMessage,\n} from './utils/converters';\n\n/**\n * ClaudeAgent integrates Claude Agent SDK with AG-UI Protocol\n */\nexport class ClaudeAgent extends AbstractAgent {\n private sessionManager: SessionManager;\n private executionStateManager: ExecutionStateManager;\n private apiKey?: string;\n private baseUrl?: string;\n private sessionTimeout: number;\n private enablePersistentSessions: boolean;\n private permissionMode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n private stderr?: (data: string) => void;\n private verbose?: boolean;\n\n constructor(config: ClaudeAgentConfig) {\n super(config);\n // SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment\n // Only set these if explicitly provided in config (optional)\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl;\n this.sessionTimeout = config.sessionTimeout || 30 * 60 * 1000; // 30 minutes\n this.enablePersistentSessions = config.enablePersistentSessions !== false;\n // Map legacy permission modes to new SDK values for backward compatibility\n this.permissionMode = this.mapPermissionMode(config.permissionMode || 'bypassPermissions');\n this.stderr = config.stderr;\n this.verbose = config.verbose;\n this.sessionManager = SessionManager.getInstance(this.sessionTimeout);\n this.executionStateManager = new ExecutionStateManager();\n }\n\n /**\n * Map legacy permission modes to new SDK values for backward compatibility\n */\n private mapPermissionMode(mode?: string): 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' {\n const modeMap: Record = {\n 'ask': 'default',\n 'auto': 'bypassPermissions',\n 'none': 'bypassPermissions',\n 'default': 'default',\n 'acceptEdits': 'acceptEdits',\n 'bypassPermissions': 'bypassPermissions',\n 'plan': 'plan',\n };\n return modeMap[mode || 'bypassPermissions'] || 'bypassPermissions';\n }\n\n /**\n * Run the agent with the given input\n */\n run(input: RunAgentInput): Observable {\n return new Observable((subscriber) => {\n this.executeAgent(input, subscriber).catch((error) => {\n subscriber.error(error);\n });\n });\n }\n\n /**\n * Execute the agent asynchronously\n */\n private async executeAgent(\n input: RunAgentInput,\n subscriber: Subscriber\n ): Promise {\n const runId = generateRunId();\n const sessionId = input.threadId || `session_${Date.now()}`;\n\n // Create execution state\n const execution = this.executionStateManager.createExecution(runId, sessionId);\n\n try {\n // Emit run started event\n const runStartedEvent: RunStartedEvent = {\n type: EventType.RUN_STARTED,\n threadId: sessionId,\n runId,\n };\n subscriber.next(runStartedEvent);\n execution.addEvent(runStartedEvent);\n\n // Get or create session\n const session = this.sessionManager.getSession(sessionId, 'default');\n\n // Get unseen messages\n const unseenMessages = this.sessionManager.getUnseenMessages(\n sessionId,\n input.messages || []\n );\n\n // Check if this is a tool result submission\n const isToolResult = isToolResultSubmission(input.messages || []);\n\n // Prepare tools\n const tools = input.tools || [];\n \n // Prepare options for Claude SDK\n const options = await this.prepareClaudeOptions(tools);\n\n // Extract prompt from messages\n const prompt = convertAgUiMessagesToPrompt(unseenMessages);\n\n // Emit step started event\n const stepStartedEvent: StepStartedEvent = {\n type: EventType.STEP_STARTED,\n stepName: `step_${runId}_1`,\n };\n subscriber.next(stepStartedEvent);\n execution.addEvent(stepStartedEvent);\n\n // Call Claude SDK\n await this.callClaudeSDK(\n prompt,\n options,\n session,\n runId,\n sessionId,\n subscriber,\n execution\n );\n\n // Mark messages as processed\n this.sessionManager.markMessagesAsProcessed(sessionId, unseenMessages);\n\n // Emit step finished event\n const stepFinishedEvent: StepFinishedEvent = {\n type: EventType.STEP_FINISHED,\n stepName: `step_${runId}_1`,\n };\n subscriber.next(stepFinishedEvent);\n execution.addEvent(stepFinishedEvent);\n\n // Emit run finished event\n const runFinishedEvent: RunFinishedEvent = {\n type: EventType.RUN_FINISHED,\n threadId: sessionId,\n runId,\n };\n subscriber.next(runFinishedEvent);\n execution.addEvent(runFinishedEvent);\n\n // Complete execution\n execution.complete();\n subscriber.complete();\n } catch (error: any) {\n // Emit run error event\n const runErrorEvent: RunErrorEvent = {\n type: EventType.RUN_ERROR,\n message: formatErrorMessage(error),\n };\n subscriber.next(runErrorEvent);\n execution.addEvent(runErrorEvent);\n\n // Mark execution as failed\n execution.fail(error);\n\n // Complete the observable\n subscriber.complete();\n }\n }\n\n /**\n * Prepare Claude SDK options\n * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment\n * But baseUrl needs to be explicitly passed for third-party APIs\n */\n private async prepareClaudeOptions(tools: any[]): Promise {\n // Get baseUrl from config or environment\n const baseUrl = this.baseUrl || process.env.ANTHROPIC_BASE_URL;\n const apiKey = this.apiKey || process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n \n // Debug logging\n console.log('[Claude Agent] Preparing SDK options:', {\n hasApiKey: !!apiKey,\n hasBaseUrl: !!baseUrl,\n baseUrl: baseUrl || 'not set',\n permissionMode: this.permissionMode,\n hasStderr: !!this.stderr,\n verbose: this.verbose,\n });\n \n const options: Options = {\n permissionMode: this.permissionMode,\n // Add stderr callback for debugging - CRITICAL for error logging\n ...(this.stderr && { stderr: this.stderr }),\n // Add verbose flag for detailed logging\n ...(this.verbose !== undefined && { verbose: this.verbose }),\n env: process.env\n };\n \n // Verify stderr callback is set\n if (this.stderr) {\n console.log('[Claude Agent] ✓ stderr callback is configured for error logging');\n } else {\n console.warn('[Claude Agent] ⚠️ stderr callback not configured - CLI errors may not be visible');\n }\n\n // Add tools if provided\n if (tools && tools.length > 0) {\n const mcpServer = await ToolAdapter.createMcpServerForTools(tools);\n options.mcpServers = {\n ag_ui_tools: mcpServer,\n };\n\n // Set allowed tools\n options.allowedTools = ToolAdapter.getAllowedToolsList(tools);\n }\n\n return options;\n }\n\n /**\n * Call Claude SDK\n * Note: Currently only stateless mode is supported via query() function\n */\n private async callClaudeSDK(\n prompt: string,\n options: Options,\n session: any,\n runId: string,\n sessionId: string,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n const eventTranslator = new EventTranslator(runId, sessionId);\n\n // The current @anthropic-ai/claude-agent-sdk only supports stateless mode\n // via the query() function. We use stateless mode for both cases.\n await this.callClaudeSDKStateless(\n prompt,\n options,\n eventTranslator,\n subscriber,\n execution\n );\n }\n\n /**\n * Call Claude SDK in persistent session mode\n * Note: The current SDK only supports stateless mode via query() function\n * This method falls back to stateless mode\n */\n private async callClaudeSDKPersistent(\n prompt: string,\n options: Options,\n session: any,\n eventTranslator: EventTranslator,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n // The current @anthropic-ai/claude-agent-sdk only supports stateless mode\n // via the query() function. For persistent sessions, we use query() \n // but maintain session state in our SessionManager\n await this.callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution);\n }\n\n /**\n * Call Claude SDK in stateless mode\n */\n private async callClaudeSDKStateless(\n prompt: string,\n options: Options,\n eventTranslator: EventTranslator,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n try {\n // Log environment variables for debugging\n console.log('[Claude Agent] Environment check:');\n console.log(' ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY ? 'SET' : 'NOT SET');\n console.log(' ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'SET' : 'NOT SET');\n console.log(' ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'NOT SET (using default)');\n console.log('[Claude Agent] Options passed to SDK:', {\n hasApiKey: !!options.apiKey,\n hasBaseUrl: !!options.baseUrl,\n permissionMode: options.permissionMode,\n hasMcpServers: !!options.mcpServers,\n });\n\n // Import Claude SDK dynamically\n const { query } = await this.importClaudeSDK();\n\n console.log('[Claude Agent] Calling SDK query()...');\n\n // Call query function\n // SDK will automatically read API key from environment variables (ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN)\n // if not provided in options.apiKey\n const queryResult = query({ prompt, options });\n\n // Process responses\n for await (const message of queryResult) {\n console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('[Claude Agent] Received message type:', message?.type || 'unknown');\n console.log('[Claude Agent] Full message:', JSON.stringify(message, null, 2));\n \n if (execution.isAborted()) {\n console.log('[Claude Agent] Execution aborted by user');\n break;\n }\n\n const events = eventTranslator.translateMessage(message);\n console.log('[Claude Agent] Translated events count:', events.length);\n for (const event of events) {\n console.log('[Claude Agent] Sending event:', JSON.stringify(event, null, 2));\n subscriber.next(event);\n execution.addEvent(event);\n }\n console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n }\n \n console.log('[Claude Agent] Query completed successfully');\n } catch (error: any) {\n // Log detailed error information\n console.error('[Claude Agent] ERROR Details:');\n console.error(' Message:', error.message);\n console.error(' Stack:', error.stack);\n console.error(' Error object:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2));\n \n // Handle Claude Code process errors\n if (error.message && error.message.includes('exited with code')) {\n throw new Error(\n `Claude Code process failed. Please ensure:\\n` +\n `1. Claude CLI is installed and accessible (run: claude --version)\\n` +\n `2. ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set correctly in environment variables\\n` +\n `3. You have proper permissions to run Claude Code\\n` +\n `4. If using ANTHROPIC_BASE_URL, ensure it supports Claude Code protocol\\n` +\n `\\nOriginal error: ${error.message}\\n` +\n `Error stack: ${error.stack || 'No stack trace'}`\n );\n }\n // Handle API key errors from SDK\n if (error.message && (error.message.includes('API key') || error.message.includes('auth'))) {\n throw new Error(\n `API key error: ${error.message}\\n` +\n `Please ensure ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set in environment variables.`\n );\n }\n throw error;\n }\n }\n\n /**\n * Dynamically import Claude SDK\n */\n private async importClaudeSDK(): Promise {\n try {\n return await import('@anthropic-ai/claude-agent-sdk');\n } catch (error) {\n throw new Error(\n 'Claude Agent SDK not found. Please install it: npm install @anthropic-ai/claude-agent-sdk'\n );\n }\n }\n\n /**\n * Abort a running execution\n */\n abortExecution(runId: string): void {\n const execution = this.executionStateManager.getExecution(runId);\n if (execution) {\n execution.abort();\n }\n }\n\n /**\n * Get execution state\n */\n getExecutionState(runId: string): ExecutionState | undefined {\n return this.executionStateManager.getExecution(runId);\n }\n\n /**\n * Get session manager (for testing)\n */\n getSessionManager(): SessionManager {\n return this.sessionManager;\n }\n\n /**\n * Get execution state manager (for testing)\n */\n getExecutionStateManager(): ExecutionStateManager {\n return this.executionStateManager;\n }\n\n /**\n * Cleanup resources\n */\n async cleanup(): Promise {\n // Abort all running executions\n const runningExecutions = this.executionStateManager.getRunningExecutions();\n for (const execution of runningExecutions) {\n execution.abort();\n }\n\n // Clear all sessions\n this.sessionManager.clearAllSessions();\n\n // Clear all executions\n this.executionStateManager.clearAll();\n }\n}\n\n","/**\n * Session manager: Manages agent sessions and state\n */\n\nimport type { Message } from '@ag-ui/client';\nimport type { Session, ClaudeSDKClient } from './types';\n\nconst DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000; // 30 minutes\nconst CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\n/**\n * SessionManager handles session lifecycle, message tracking, and state management\n * Implements singleton pattern for centralized session control\n */\nexport class SessionManager {\n private static instance: SessionManager | null = null;\n private sessions: Map = new Map();\n private cleanupInterval: ReturnType | null = null;\n private sessionTimeout: number;\n\n private constructor(sessionTimeout: number = DEFAULT_SESSION_TIMEOUT) {\n this.sessionTimeout = sessionTimeout;\n this.startCleanupInterval();\n }\n\n /**\n * Get the singleton instance\n */\n static getInstance(sessionTimeout?: number): SessionManager {\n if (!SessionManager.instance) {\n SessionManager.instance = new SessionManager(sessionTimeout);\n }\n return SessionManager.instance;\n }\n\n /**\n * Reset the singleton instance (useful for testing)\n */\n static resetInstance(): void {\n if (SessionManager.instance) {\n SessionManager.instance.stopCleanupInterval();\n SessionManager.instance = null;\n }\n }\n\n /**\n * Get or create a session\n */\n getSession(sessionId: string, userId?: string): Session {\n let session = this.sessions.get(sessionId);\n\n if (!session) {\n session = {\n id: sessionId,\n userId,\n processedMessageIds: new Set(),\n state: {},\n createdAt: Date.now(),\n lastAccessedAt: Date.now(),\n };\n this.sessions.set(sessionId, session);\n } else {\n // Update last accessed time\n session.lastAccessedAt = Date.now();\n }\n\n return session;\n }\n\n /**\n * Check if a session exists\n */\n hasSession(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n /**\n * Delete a session\n */\n deleteSession(sessionId: string): boolean {\n const session = this.sessions.get(sessionId);\n if (session?.client) {\n // Close the Claude SDK client if it exists\n session.client.close().catch((error) => {\n console.error(`Error closing Claude SDK client for session ${sessionId}:`, error);\n });\n }\n return this.sessions.delete(sessionId);\n }\n\n /**\n * Track a processed message\n */\n trackMessage(sessionId: string, messageId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.processedMessageIds.add(messageId);\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Check if a message has been processed\n */\n isMessageProcessed(sessionId: string, messageId: string): boolean {\n const session = this.sessions.get(sessionId);\n return session ? session.processedMessageIds.has(messageId) : false;\n }\n\n /**\n * Get unseen messages (messages not yet processed)\n */\n getUnseenMessages(sessionId: string, messages: Message[]): Message[] {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return messages;\n }\n\n return messages.filter((msg) => {\n const msgId = msg.id || `${msg.role}_${msg.content}`;\n return !session.processedMessageIds.has(msgId);\n });\n }\n\n /**\n * Mark messages as processed\n */\n markMessagesAsProcessed(sessionId: string, messages: Message[]): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n for (const msg of messages) {\n const msgId = msg.id || `${msg.role}_${msg.content}`;\n session.processedMessageIds.add(msgId);\n }\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Get state value from session\n */\n getStateValue(sessionId: string, key: string): any {\n const session = this.sessions.get(sessionId);\n return session?.state[key];\n }\n\n /**\n * Set state value in session\n */\n setStateValue(sessionId: string, key: string, value: any): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.state[key] = value;\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Remove state keys from session\n */\n removeStateKeys(sessionId: string, keys: string[]): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n for (const key of keys) {\n delete session.state[key];\n }\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Clear all state for a session\n */\n clearSessionState(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.state = {};\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Set Claude SDK client for a session\n */\n setClient(sessionId: string, client: ClaudeSDKClient): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.client = client;\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Get Claude SDK client for a session\n */\n getClient(sessionId: string): ClaudeSDKClient | undefined {\n const session = this.sessions.get(sessionId);\n return session?.client;\n }\n\n /**\n * Get total number of sessions\n */\n getSessionCount(): number {\n return this.sessions.size;\n }\n\n /**\n * Get number of sessions for a specific user\n */\n getUserSessionCount(userId: string): number {\n let count = 0;\n for (const session of this.sessions.values()) {\n if (session.userId === userId) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * Get all session IDs\n */\n getAllSessionIds(): string[] {\n return Array.from(this.sessions.keys());\n }\n\n /**\n * Get all sessions for a specific user\n */\n getUserSessions(userId: string): Session[] {\n const userSessions: Session[] = [];\n for (const session of this.sessions.values()) {\n if (session.userId === userId) {\n userSessions.push(session);\n }\n }\n return userSessions;\n }\n\n /**\n * Clean up stale sessions\n */\n private cleanupStaleSessions(): void {\n const now = Date.now();\n const sessionsToDelete: string[] = [];\n\n for (const [sessionId, session] of this.sessions.entries()) {\n if (now - session.lastAccessedAt > this.sessionTimeout) {\n sessionsToDelete.push(sessionId);\n }\n }\n\n for (const sessionId of sessionsToDelete) {\n this.deleteSession(sessionId);\n }\n\n if (sessionsToDelete.length > 0) {\n console.log(`Cleaned up ${sessionsToDelete.length} stale sessions`);\n }\n }\n\n /**\n * Start the cleanup interval\n */\n private startCleanupInterval(): void {\n if (!this.cleanupInterval) {\n this.cleanupInterval = setInterval(() => {\n this.cleanupStaleSessions();\n }, CLEANUP_INTERVAL);\n\n // Don't keep the process alive just for this interval\n if (typeof (this.cleanupInterval as any).unref === 'function') {\n (this.cleanupInterval as any).unref();\n }\n }\n }\n\n /**\n * Stop the cleanup interval\n */\n private stopCleanupInterval(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n\n /**\n * Clear all sessions (useful for testing)\n */\n clearAllSessions(): void {\n for (const sessionId of this.sessions.keys()) {\n this.deleteSession(sessionId);\n }\n this.sessions.clear();\n }\n}\n\n","/**\n * Event translator: Converts Claude SDK messages to AG-UI events\n */\n\nimport {\n TextMessageStartEvent,\n TextMessageContentEvent,\n TextMessageEndEvent,\n ToolCallStartEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallResultEvent,\n EventType,\n} from '@ag-ui/client';\nimport type {\n SDKMessage,\n SDKAssistantMessage,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n ProcessedEvents,\n} from './types';\nimport {\n hasContentProperty,\n isTextBlock,\n isToolUseBlock,\n isToolResultBlock,\n} from './types';\n\n/**\n * EventTranslator converts Claude SDK messages to AG-UI protocol events\n * \n * NOTE: This translator only handles SDK message translation.\n * Run lifecycle events (RUN_STARTED, RUN_FINISHED, etc.) and step events\n * are handled by ClaudeAgent.\n */\nexport class EventTranslator {\n private messageIdCounter = 0;\n private currentMessageId: string | null = null;\n private runId: string;\n private threadId: string;\n\n constructor(runId: string, threadId: string) {\n this.runId = runId;\n this.threadId = threadId;\n }\n\n /**\n * Translate a Claude SDK message to AG-UI events\n * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent\n */\n translateMessage(message: SDKMessage): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n if (hasContentProperty(message)) {\n events.push(...this.translateAssistantMessage(message as SDKAssistantMessage));\n }\n // Note: ResultMessage (success/error) is ignored here\n // Run completion is handled by ClaudeAgent, not EventTranslator\n\n return events;\n }\n\n /**\n * Translate an AssistantMessage with content blocks\n */\n private translateAssistantMessage(message: SDKAssistantMessage): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n // Content is in message.message.content for SDKAssistantMessage\n const content = message.message?.content || [];\n \n for (const block of content) {\n if (isTextBlock(block)) {\n events.push(...this.translateTextBlock(block));\n } else if (isToolUseBlock(block)) {\n events.push(...this.translateToolUseBlock(block));\n } else if (isToolResultBlock(block)) {\n events.push(...this.translateToolResultBlock(block));\n }\n }\n\n return events;\n }\n\n /**\n * Translate a TextBlock to text message events\n * NOTE: Step events are handled by ClaudeAgent, not here\n */\n private translateTextBlock(block: TextBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n const messageId = this.generateMessageId();\n\n // Start event\n events.push({\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: 'assistant',\n });\n\n // Content event - split text into delta chunks\n const text = block.text;\n if (text.length > 0) {\n events.push({\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: text,\n });\n }\n\n // End event\n events.push({\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n });\n\n return events;\n }\n\n /**\n * Translate a ToolUseBlock to tool call events\n * NOTE: Step events are handled by ClaudeAgent, not here\n */\n private translateToolUseBlock(block: ToolUseBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n const toolCallId = block.id;\n\n // Start event\n events.push({\n type: EventType.TOOL_CALL_START,\n toolCallId,\n toolCallName: block.name,\n });\n\n // Args event - send args as JSON string\n const argsJson = JSON.stringify(block.input);\n if (argsJson.length > 0) {\n events.push({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId,\n delta: argsJson,\n });\n }\n\n // End event\n events.push({\n type: EventType.TOOL_CALL_END,\n toolCallId,\n });\n\n return events;\n }\n\n /**\n * Translate a ToolResultBlock to tool call result event\n */\n private translateToolResultBlock(block: ToolResultBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n // Extract content as string\n let resultContent: string;\n if (typeof block.content === 'string') {\n resultContent = block.content;\n } else if (Array.isArray(block.content)) {\n // Handle array of content blocks\n resultContent = block.content\n .map((item) => {\n if (item.type === 'text') {\n return item.text || '';\n }\n return JSON.stringify(item);\n })\n .join('\\n');\n } else {\n resultContent = JSON.stringify(block.content);\n }\n\n const messageId = this.generateMessageId();\n events.push({\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: block.tool_use_id,\n messageId,\n content: resultContent,\n ...(block.is_error && { role: 'tool' as const }),\n });\n\n return events;\n }\n\n /**\n * Generate a unique message ID\n */\n private generateMessageId(): string {\n this.messageIdCounter++;\n return `msg_${this.runId}_${this.messageIdCounter}`;\n }\n\n /**\n * Reset the translator state for a new execution\n */\n reset(): void {\n this.messageIdCounter = 0;\n this.currentMessageId = null;\n }\n\n /**\n * Get current message ID\n */\n getCurrentMessageId(): string | null {\n return this.currentMessageId;\n }\n\n /**\n * Set current message ID\n */\n setCurrentMessageId(messageId: string | null): void {\n this.currentMessageId = messageId;\n }\n}\n\n","/**\n * Type definitions for Claude Agent SDK integration with AG-UI Protocol\n */\n\nimport type {\n TextMessageStartEvent,\n TextMessageContentEvent,\n TextMessageEndEvent,\n ToolCallStartEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallResultEvent,\n RunStartedEvent,\n RunFinishedEvent,\n RunErrorEvent,\n StepStartedEvent,\n StepFinishedEvent,\n AgentConfig,\n Tool,\n Message,\n} from '@ag-ui/client';\n\n// Re-export Claude SDK types (will be imported from the actual SDK)\n// These are placeholder interfaces based on the SDK documentation\nexport interface ClaudeSDKClient {\n query(prompt: string): Promise;\n receiveResponse(): AsyncIterableIterator;\n close(): Promise;\n}\n\nexport interface Options {\n apiKey?: string;\n baseUrl?: string;\n mcpServers?: Record;\n allowedTools?: string[];\n // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan'\n // Legacy values 'ask', 'auto', 'none' are also supported for backward compatibility\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none';\n stderr?: (data: string) => void;\n verbose?: boolean;\n [key: string]: any;\n}\n\nexport interface Query {\n next(): Promise>;\n [Symbol.asyncIterator](): AsyncIterableIterator;\n}\n\n// SDK Message types based on documentation\nexport type SDKMessage =\n | SDKAssistantMessage\n | SDKUserMessage\n | SDKSystemMessage\n | SDKResultMessage\n | SDKPartialAssistantMessage\n | SDKCompactBoundaryMessage\n | SDKPermissionDenial;\n\nexport interface SDKAssistantMessage {\n type: 'assistant';\n message: {\n id?: string;\n content: ContentBlock[];\n [key: string]: any;\n };\n parent_tool_use_id?: string | null;\n uuid?: string;\n session_id?: string;\n}\n\nexport interface SDKUserMessage {\n type: 'user';\n content: string;\n id?: string;\n}\n\nexport interface SDKSystemMessage {\n type: 'system';\n content: string;\n}\n\nexport interface SDKResultMessage {\n type: 'result';\n subtype: 'success' | 'error';\n error?: {\n type: string;\n message: string;\n };\n}\n\nexport interface SDKPartialAssistantMessage {\n type: 'partial_assistant';\n content: ContentBlock[];\n}\n\nexport interface SDKCompactBoundaryMessage {\n type: 'compact_boundary';\n}\n\nexport interface SDKPermissionDenial {\n type: 'permission_denial';\n tool: string;\n reason: string;\n}\n\n// Content block types\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock;\n\nexport interface TextBlock {\n type: 'text';\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string | Array<{ type: string; [key: string]: any }>;\n is_error?: boolean;\n}\n\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n}\n\n// Tool definition types\nexport interface SdkMcpToolDefinition {\n name: string;\n description: string;\n inputSchema: Schema;\n handler: (args: any, extra?: any) => Promise;\n}\n\nexport interface CallToolResult {\n content: Array<{\n type: 'text' | 'image' | 'resource';\n text?: string;\n data?: string;\n mimeType?: string;\n [key: string]: any;\n }>;\n isError?: boolean;\n}\n\nexport interface McpSdkServerConfigWithInstance {\n name: string;\n version?: string;\n tools?: Array>;\n}\n\n// AG-UI Integration types\nexport type ProcessedEvents =\n | TextMessageStartEvent\n | TextMessageContentEvent\n | TextMessageEndEvent\n | ToolCallStartEvent\n | ToolCallArgsEvent\n | ToolCallEndEvent\n | ToolCallResultEvent\n | RunStartedEvent\n | RunFinishedEvent\n | RunErrorEvent\n | StepStartedEvent\n | StepFinishedEvent;\n\n// Session management types\nexport interface Session {\n id: string;\n userId?: string;\n client?: ClaudeSDKClient;\n processedMessageIds: Set;\n state: Record;\n createdAt: number;\n lastAccessedAt: number;\n}\n\n// Agent configuration\nexport interface ClaudeAgentConfig extends AgentConfig {\n apiKey?: string;\n baseUrl?: string;\n sessionTimeout?: number;\n enablePersistentSessions?: boolean;\n // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan'\n // Legacy values 'ask', 'auto', 'none' are mapped internally for backward compatibility\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none';\n mcpServers?: Record;\n stderr?: (data: string) => void;\n verbose?: boolean;\n}\n\n// Execution state types\nexport interface ExecutionState {\n id: string;\n sessionId: string;\n isRunning: boolean;\n startTime: number;\n events: ProcessedEvents[];\n error?: Error;\n}\n\n// Helper type guards\nexport function isAssistantMessage(message: SDKMessage): message is SDKAssistantMessage {\n return message.type === 'assistant';\n}\n\nexport function isResultMessage(message: SDKMessage): message is SDKResultMessage {\n return message.type === 'result';\n}\n\nexport function isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === 'text';\n}\n\nexport function isToolUseBlock(block: ContentBlock): block is ToolUseBlock {\n return block.type === 'tool_use';\n}\n\nexport function isToolResultBlock(block: ContentBlock): block is ToolResultBlock {\n return block.type === 'tool_result';\n}\n\nexport function isThinkingBlock(block: ContentBlock): block is ThinkingBlock {\n return block.type === 'thinking';\n}\n\nexport function hasContentProperty(message: SDKMessage): message is SDKAssistantMessage | SDKPartialAssistantMessage {\n // For SDKAssistantMessage, content is in message.content\n if (message.type === 'assistant') {\n return 'message' in message && \n message.message !== null &&\n typeof message.message === 'object' &&\n 'content' in message.message && \n Array.isArray((message.message as any).content);\n }\n // For SDKPartialAssistantMessage, content might be at top level\n return 'content' in message && Array.isArray((message as any).content);\n}\n\n// Tool execution types\nexport interface ToolExecutionContext {\n toolName: string;\n toolCallId: string;\n isClientTool: boolean;\n isLongRunning: boolean;\n}\n\n// Message conversion types\nexport interface ConvertedMessage {\n role: 'user' | 'assistant' | 'system';\n content: string | Array<{ type: string; [key: string]: any }>;\n}\n\n","/**\n * Tool adapter: Converts AG-UI tools to Claude SDK format\n */\n\nimport { z } from 'zod';\nimport type { Tool } from '@ag-ui/client';\nimport type {\n SdkMcpToolDefinition,\n McpSdkServerConfigWithInstance,\n CallToolResult,\n} from './types';\n\n// Extended Tool type that includes runtime properties\ntype ExtendedTool = Tool & {\n client?: boolean;\n handler?: (args: any) => any | Promise;\n longRunning?: boolean;\n};\n\n/**\n * ToolAdapter handles conversion of AG-UI tools to Claude SDK format\n */\nexport class ToolAdapter {\n /**\n * Convert AG-UI tools to Claude SDK MCP tool definitions\n */\n static convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[] {\n return tools.map((tool) => this.convertSingleTool(tool as ExtendedTool));\n }\n\n /**\n * Convert a single AG-UI tool to Claude SDK format\n */\n private static convertSingleTool(tool: ExtendedTool): SdkMcpToolDefinition {\n const zodSchema = this.convertJsonSchemaToZod(tool.parameters || {});\n\n return {\n name: tool.name,\n description: tool.description || '',\n inputSchema: zodSchema,\n handler: async (args: any) => {\n // For client tools, we mark them as long-running\n // The actual execution will be handled by the client\n if (tool.client) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n toolName: tool.name,\n args,\n isClientTool: true,\n isLongRunning: true,\n }),\n },\n ],\n };\n }\n\n // For backend tools, if there's a handler, execute it\n if (tool.handler) {\n try {\n const result = await tool.handler(args);\n return {\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n };\n } catch (error: any) {\n return {\n content: [\n {\n type: 'text',\n text: error.message || 'Tool execution failed',\n },\n ],\n isError: true,\n };\n }\n }\n\n // Default response for tools without handlers\n return {\n content: [\n {\n type: 'text',\n text: 'Tool executed (no handler)',\n },\n ],\n };\n },\n };\n }\n\n /**\n * Convert JSON Schema to Zod schema\n */\n private static convertJsonSchemaToZod(jsonSchema: any): z.ZodTypeAny {\n if (!jsonSchema || typeof jsonSchema !== 'object') {\n return z.object({});\n }\n\n const properties = jsonSchema.properties || {};\n const required = jsonSchema.required || [];\n\n const zodShape: Record = {};\n\n for (const [key, prop] of Object.entries(properties)) {\n const propSchema = prop as any;\n let zodType = this.convertJsonSchemaTypeToZod(propSchema);\n\n // Make optional if not in required array\n if (!required.includes(key)) {\n zodType = zodType.optional();\n }\n\n zodShape[key] = zodType;\n }\n\n return z.object(zodShape);\n }\n\n /**\n * Convert a single JSON Schema type to Zod type\n */\n private static convertJsonSchemaTypeToZod(schema: any): z.ZodTypeAny {\n const type = schema.type;\n\n switch (type) {\n case 'string':\n if (schema.enum) {\n return z.enum(schema.enum as [string, ...string[]]);\n }\n return z.string();\n\n case 'number':\n case 'integer':\n let numType = type === 'integer' ? z.number().int() : z.number();\n if (schema.minimum !== undefined) {\n numType = numType.min(schema.minimum);\n }\n if (schema.maximum !== undefined) {\n numType = numType.max(schema.maximum);\n }\n return numType;\n\n case 'boolean':\n return z.boolean();\n\n case 'array':\n if (schema.items) {\n const itemType = this.convertJsonSchemaTypeToZod(schema.items);\n return z.array(itemType);\n }\n return z.array(z.any());\n\n case 'object':\n if (schema.properties) {\n return this.convertJsonSchemaToZod(schema);\n }\n return z.record(z.any());\n\n case 'null':\n return z.null();\n\n default:\n // For any other type or if type is not specified\n return z.any();\n }\n }\n\n /**\n * Create an MCP server configuration for AG-UI tools\n */\n static async createMcpServerForTools(tools: Tool[]): Promise {\n const sdkTools = this.convertAgUiToolsToSdk(tools as ExtendedTool[]);\n\n // Import createSdkMcpServer from Claude Agent SDK\n const { createSdkMcpServer } = await import('@anthropic-ai/claude-agent-sdk');\n \n // Use the official SDK function to create a properly formatted MCP server\n return createSdkMcpServer({\n name: 'ag_ui_tools',\n version: '1.0.0',\n tools: sdkTools as any, // Cast to any to avoid type incompatibility\n });\n }\n\n /**\n * Extract tool calls from Claude SDK response\n */\n static extractToolCalls(message: any): Array<{\n id: string;\n name: string;\n input: Record;\n }> {\n if (!message.content || !Array.isArray(message.content)) {\n return [];\n }\n\n return message.content\n .filter((block: any) => block.type === 'tool_use')\n .map((block: any) => ({\n id: block.id,\n name: block.name,\n input: block.input,\n }));\n }\n\n /**\n * Check if a tool is a long-running client tool\n */\n static isClientTool(toolName: string, tools: Tool[]): boolean {\n const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined;\n return tool?.client === true;\n }\n\n /**\n * Check if a tool is marked as long-running\n */\n static isLongRunningTool(toolName: string, tools: Tool[]): boolean {\n const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined;\n return tool?.client === true || tool?.longRunning === true;\n }\n\n /**\n * Format tool names for Claude SDK (with MCP server prefix)\n */\n static formatToolNameForSdk(toolName: string, serverName: string = 'ag_ui_tools'): string {\n return `mcp__${serverName}__${toolName}`;\n }\n\n /**\n * Parse tool name from SDK format (remove MCP server prefix)\n */\n static parseToolNameFromSdk(sdkToolName: string): string {\n const parts = sdkToolName.split('__');\n if (parts.length >= 3 && parts[0] === 'mcp') {\n return parts.slice(2).join('__');\n }\n return sdkToolName;\n }\n\n /**\n * Get allowed tools list for SDK options\n */\n static getAllowedToolsList(tools: Tool[], serverName: string = 'ag_ui_tools'): string[] {\n return tools.map((tool) => this.formatToolNameForSdk(tool.name, serverName));\n }\n}\n\n","/**\n * Execution state: Tracks background Claude executions\n */\n\nimport type { ProcessedEvents } from './types';\n\n/**\n * ExecutionState manages the state of a Claude SDK execution\n */\nexport class ExecutionState {\n readonly id: string;\n readonly sessionId: string;\n private _isRunning: boolean;\n private _startTime: number;\n private _endTime?: number;\n private _events: ProcessedEvents[];\n private _error?: Error;\n private _abortController: AbortController;\n\n constructor(id: string, sessionId: string) {\n this.id = id;\n this.sessionId = sessionId;\n this._isRunning = true;\n this._startTime = Date.now();\n this._events = [];\n this._abortController = new AbortController();\n }\n\n /**\n * Check if execution is running\n */\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n /**\n * Get start time\n */\n get startTime(): number {\n return this._startTime;\n }\n\n /**\n * Get end time\n */\n get endTime(): number | undefined {\n return this._endTime;\n }\n\n /**\n * Get duration in milliseconds\n */\n get duration(): number {\n const end = this._endTime || Date.now();\n return end - this._startTime;\n }\n\n /**\n * Get all collected events\n */\n get events(): ProcessedEvents[] {\n return [...this._events];\n }\n\n /**\n * Get error if any\n */\n get error(): Error | undefined {\n return this._error;\n }\n\n /**\n * Get abort signal\n */\n get signal(): AbortSignal {\n return this._abortController.signal;\n }\n\n /**\n * Add an event to the execution state\n */\n addEvent(event: ProcessedEvents): void {\n this._events.push(event);\n }\n\n /**\n * Add multiple events\n */\n addEvents(events: ProcessedEvents[]): void {\n this._events.push(...events);\n }\n\n /**\n * Mark execution as completed\n */\n complete(): void {\n if (this._isRunning) {\n this._isRunning = false;\n this._endTime = Date.now();\n }\n }\n\n /**\n * Mark execution as failed\n */\n fail(error: Error): void {\n if (this._isRunning) {\n this._isRunning = false;\n this._endTime = Date.now();\n this._error = error;\n }\n }\n\n /**\n * Abort the execution\n */\n abort(): void {\n if (this._isRunning) {\n this._abortController.abort();\n this._isRunning = false;\n this._endTime = Date.now();\n }\n }\n\n /**\n * Get execution statistics\n */\n getStats(): {\n duration: number;\n eventCount: number;\n isRunning: boolean;\n hasError: boolean;\n } {\n return {\n duration: this.duration,\n eventCount: this._events.length,\n isRunning: this._isRunning,\n hasError: !!this._error,\n };\n }\n\n /**\n * Clear events (useful for memory management)\n */\n clearEvents(): void {\n this._events = [];\n }\n\n /**\n * Get the last N events\n */\n getLastEvents(count: number): ProcessedEvents[] {\n return this._events.slice(-count);\n }\n\n /**\n * Check if execution has been aborted\n */\n isAborted(): boolean {\n return this._abortController.signal.aborted;\n }\n}\n\n/**\n * ExecutionStateManager manages multiple execution states\n */\nexport class ExecutionStateManager {\n private executions: Map = new Map();\n private readonly maxExecutions: number;\n\n constructor(maxExecutions: number = 100) {\n this.maxExecutions = maxExecutions;\n }\n\n /**\n * Create a new execution state\n */\n createExecution(id: string, sessionId: string): ExecutionState {\n const execution = new ExecutionState(id, sessionId);\n this.executions.set(id, execution);\n\n // Clean up old executions if we exceed the limit\n if (this.executions.size > this.maxExecutions) {\n this.cleanupOldExecutions();\n }\n\n return execution;\n }\n\n /**\n * Get an execution state by ID\n */\n getExecution(id: string): ExecutionState | undefined {\n return this.executions.get(id);\n }\n\n /**\n * Check if an execution exists\n */\n hasExecution(id: string): boolean {\n return this.executions.has(id);\n }\n\n /**\n * Delete an execution state\n */\n deleteExecution(id: string): boolean {\n return this.executions.delete(id);\n }\n\n /**\n * Get all executions for a session\n */\n getSessionExecutions(sessionId: string): ExecutionState[] {\n const executions: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (execution.sessionId === sessionId) {\n executions.push(execution);\n }\n }\n return executions;\n }\n\n /**\n * Get running executions\n */\n getRunningExecutions(): ExecutionState[] {\n const running: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (execution.isRunning) {\n running.push(execution);\n }\n }\n return running;\n }\n\n /**\n * Get completed executions\n */\n getCompletedExecutions(): ExecutionState[] {\n const completed: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (!execution.isRunning) {\n completed.push(execution);\n }\n }\n return completed;\n }\n\n /**\n * Abort all running executions for a session\n */\n abortSessionExecutions(sessionId: string): void {\n const sessionExecutions = this.getSessionExecutions(sessionId);\n for (const execution of sessionExecutions) {\n if (execution.isRunning) {\n execution.abort();\n }\n }\n }\n\n /**\n * Clean up old completed executions\n */\n private cleanupOldExecutions(): void {\n const completed = this.getCompletedExecutions();\n \n // Sort by end time (oldest first)\n completed.sort((a, b) => {\n const aTime = a.endTime || a.startTime;\n const bTime = b.endTime || b.startTime;\n return aTime - bTime;\n });\n\n // Remove the oldest executions\n const toRemove = Math.max(0, this.executions.size - this.maxExecutions);\n for (let i = 0; i < toRemove && i < completed.length; i++) {\n this.executions.delete(completed[i].id);\n }\n }\n\n /**\n * Clear all executions\n */\n clearAll(): void {\n this.executions.clear();\n }\n\n /**\n * Get total execution count\n */\n getExecutionCount(): number {\n return this.executions.size;\n }\n\n /**\n * Get execution statistics\n */\n getStats(): {\n total: number;\n running: number;\n completed: number;\n failed: number;\n } {\n let running = 0;\n let completed = 0;\n let failed = 0;\n\n for (const execution of this.executions.values()) {\n if (execution.isRunning) {\n running++;\n } else if (execution.error) {\n failed++;\n } else {\n completed++;\n }\n }\n\n return {\n total: this.executions.size,\n running,\n completed,\n failed,\n };\n }\n}\n\n","/**\n * Message format converters\n */\n\nimport type { Message } from '@ag-ui/client';\nimport type { ConvertedMessage } from '../types';\n\n/**\n * Convert AG-UI messages to a format suitable for Claude SDK\n */\nexport function convertAgUiMessagesToPrompt(messages: Message[]): string {\n // For Claude SDK, we typically extract the last user message as the prompt\n // The SDK maintains conversation history internally (in persistent mode)\n \n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'user') {\n return extractMessageContent(msg);\n }\n }\n\n // If no user message found, return a default prompt\n return 'Hello';\n}\n\n/**\n * Extract text content from a message\n */\nexport function extractMessageContent(message: Message): string {\n if (typeof message.content === 'string') {\n return message.content;\n }\n\n if (Array.isArray(message.content)) {\n return message.content\n .map((block: any) => {\n if (typeof block === 'string') {\n return block;\n }\n if (block.type === 'text') {\n return block.text || '';\n }\n // For other types (image, file, etc.), we might need special handling\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n }\n\n return String(message.content);\n}\n\n/**\n * Convert AG-UI message to Claude message format\n */\nexport function convertAgUiMessageToClaude(message: Message): ConvertedMessage {\n const role = message.role as 'user' | 'assistant' | 'system';\n const content = extractMessageContent(message);\n\n return {\n role,\n content,\n };\n}\n\n/**\n * Convert multiple AG-UI messages to Claude format\n */\nexport function convertAgUiMessagesToClaude(messages: Message[]): ConvertedMessage[] {\n return messages.map(convertAgUiMessageToClaude);\n}\n\n/**\n * Check if messages contain tool results\n */\nexport function hasToolResults(messages: Message[]): boolean {\n return messages.some((msg) => {\n if (typeof msg.content === 'string') {\n return false;\n }\n if (Array.isArray(msg.content)) {\n return msg.content.some((block: any) => {\n return typeof block === 'object' && block.type === 'tool_result';\n });\n }\n return false;\n });\n}\n\n/**\n * Extract tool results from messages\n */\nexport function extractToolResults(messages: Message[]): Array<{\n toolCallId: string;\n result: string;\n}> {\n const results: Array<{ toolCallId: string; result: string }> = [];\n\n for (const msg of messages) {\n if (typeof msg.content === 'string') {\n continue;\n }\n\n if (Array.isArray(msg.content)) {\n for (const block of msg.content as any[]) {\n if (typeof block === 'object' && block.type === 'tool_result') {\n results.push({\n toolCallId: (block as any).toolCallId || (block as any).tool_use_id || '',\n result: (block as any).result || (block as any).content || '',\n });\n }\n }\n }\n }\n\n return results;\n}\n\n/**\n * Generate a unique run ID\n */\nexport function generateRunId(): string {\n return `run_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(prefix: string = 'msg'): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Safely parse JSON string\n */\nexport function safeJsonParse(json: string, defaultValue: any = null): any {\n try {\n return JSON.parse(json);\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Safely stringify JSON\n */\nexport function safeJsonStringify(obj: any, defaultValue: string = '{}'): string {\n try {\n return JSON.stringify(obj);\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Check if a message is a tool result submission\n */\nexport function isToolResultSubmission(messages: Message[]): boolean {\n // Check if the last message contains tool results\n if (messages.length === 0) {\n return false;\n }\n\n const lastMessage = messages[messages.length - 1];\n return hasToolResults([lastMessage]);\n}\n\n/**\n * Format error message for display\n */\nexport function formatErrorMessage(error: any): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'string') {\n return error;\n }\n return 'An unknown error occurred';\n}\n\n/**\n * Truncate text to a maximum length\n */\nexport function truncateText(text: string, maxLength: number = 1000): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength) + '...';\n}\n\n/**\n * Merge consecutive text blocks\n */\nexport function mergeTextBlocks(blocks: Array<{ type: string; text?: string }>): string {\n return blocks\n .filter((block: any) => block.type === 'text' && block.text)\n .map((block: any) => block.text)\n .join('');\n}\n\n"],"mappings":"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","names":["import_client","error"]} \ No newline at end of file diff --git a/integrations/claude-agent-sdk/typescript/dist/index.mjs b/integrations/claude-agent-sdk/typescript/dist/index.mjs new file mode 100644 index 000000000..80fd5f74f --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.mjs @@ -0,0 +1,1340 @@ +var __defProp = Object.defineProperty; +var __defProps = Object.defineProperties; +var __getOwnPropDescs = Object.getOwnPropertyDescriptors; +var __getOwnPropSymbols = Object.getOwnPropertySymbols; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __propIsEnum = Object.prototype.propertyIsEnumerable; +var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name); +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; +}; +var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); +var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it); + +// src/agent.ts +import { Observable } from "rxjs"; +import { + AbstractAgent, + EventType as EventType2 +} from "@ag-ui/client"; + +// src/session-manager.ts +var DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1e3; +var CLEANUP_INTERVAL = 5 * 60 * 1e3; +var _SessionManager = class _SessionManager { + constructor(sessionTimeout = DEFAULT_SESSION_TIMEOUT) { + this.sessions = /* @__PURE__ */ new Map(); + this.cleanupInterval = null; + this.sessionTimeout = sessionTimeout; + this.startCleanupInterval(); + } + /** + * Get the singleton instance + */ + static getInstance(sessionTimeout) { + if (!_SessionManager.instance) { + _SessionManager.instance = new _SessionManager(sessionTimeout); + } + return _SessionManager.instance; + } + /** + * Reset the singleton instance (useful for testing) + */ + static resetInstance() { + if (_SessionManager.instance) { + _SessionManager.instance.stopCleanupInterval(); + _SessionManager.instance = null; + } + } + /** + * Get or create a session + */ + getSession(sessionId, userId) { + let session = this.sessions.get(sessionId); + if (!session) { + session = { + id: sessionId, + userId, + processedMessageIds: /* @__PURE__ */ new Set(), + state: {}, + createdAt: Date.now(), + lastAccessedAt: Date.now() + }; + this.sessions.set(sessionId, session); + } else { + session.lastAccessedAt = Date.now(); + } + return session; + } + /** + * Check if a session exists + */ + hasSession(sessionId) { + return this.sessions.has(sessionId); + } + /** + * Delete a session + */ + deleteSession(sessionId) { + const session = this.sessions.get(sessionId); + if (session == null ? void 0 : session.client) { + session.client.close().catch((error) => { + console.error(`Error closing Claude SDK client for session ${sessionId}:`, error); + }); + } + return this.sessions.delete(sessionId); + } + /** + * Track a processed message + */ + trackMessage(sessionId, messageId) { + const session = this.sessions.get(sessionId); + if (session) { + session.processedMessageIds.add(messageId); + session.lastAccessedAt = Date.now(); + } + } + /** + * Check if a message has been processed + */ + isMessageProcessed(sessionId, messageId) { + const session = this.sessions.get(sessionId); + return session ? session.processedMessageIds.has(messageId) : false; + } + /** + * Get unseen messages (messages not yet processed) + */ + getUnseenMessages(sessionId, messages) { + const session = this.sessions.get(sessionId); + if (!session) { + return messages; + } + return messages.filter((msg) => { + const msgId = msg.id || `${msg.role}_${msg.content}`; + return !session.processedMessageIds.has(msgId); + }); + } + /** + * Mark messages as processed + */ + markMessagesAsProcessed(sessionId, messages) { + const session = this.sessions.get(sessionId); + if (session) { + for (const msg of messages) { + const msgId = msg.id || `${msg.role}_${msg.content}`; + session.processedMessageIds.add(msgId); + } + session.lastAccessedAt = Date.now(); + } + } + /** + * Get state value from session + */ + getStateValue(sessionId, key) { + const session = this.sessions.get(sessionId); + return session == null ? void 0 : session.state[key]; + } + /** + * Set state value in session + */ + setStateValue(sessionId, key, value) { + const session = this.sessions.get(sessionId); + if (session) { + session.state[key] = value; + session.lastAccessedAt = Date.now(); + } + } + /** + * Remove state keys from session + */ + removeStateKeys(sessionId, keys) { + const session = this.sessions.get(sessionId); + if (session) { + for (const key of keys) { + delete session.state[key]; + } + session.lastAccessedAt = Date.now(); + } + } + /** + * Clear all state for a session + */ + clearSessionState(sessionId) { + const session = this.sessions.get(sessionId); + if (session) { + session.state = {}; + session.lastAccessedAt = Date.now(); + } + } + /** + * Set Claude SDK client for a session + */ + setClient(sessionId, client) { + const session = this.sessions.get(sessionId); + if (session) { + session.client = client; + session.lastAccessedAt = Date.now(); + } + } + /** + * Get Claude SDK client for a session + */ + getClient(sessionId) { + const session = this.sessions.get(sessionId); + return session == null ? void 0 : session.client; + } + /** + * Get total number of sessions + */ + getSessionCount() { + return this.sessions.size; + } + /** + * Get number of sessions for a specific user + */ + getUserSessionCount(userId) { + let count = 0; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + count++; + } + } + return count; + } + /** + * Get all session IDs + */ + getAllSessionIds() { + return Array.from(this.sessions.keys()); + } + /** + * Get all sessions for a specific user + */ + getUserSessions(userId) { + const userSessions = []; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + userSessions.push(session); + } + } + return userSessions; + } + /** + * Clean up stale sessions + */ + cleanupStaleSessions() { + const now = Date.now(); + const sessionsToDelete = []; + for (const [sessionId, session] of this.sessions.entries()) { + if (now - session.lastAccessedAt > this.sessionTimeout) { + sessionsToDelete.push(sessionId); + } + } + for (const sessionId of sessionsToDelete) { + this.deleteSession(sessionId); + } + if (sessionsToDelete.length > 0) { + console.log(`Cleaned up ${sessionsToDelete.length} stale sessions`); + } + } + /** + * Start the cleanup interval + */ + startCleanupInterval() { + if (!this.cleanupInterval) { + this.cleanupInterval = setInterval(() => { + this.cleanupStaleSessions(); + }, CLEANUP_INTERVAL); + if (typeof this.cleanupInterval.unref === "function") { + this.cleanupInterval.unref(); + } + } + } + /** + * Stop the cleanup interval + */ + stopCleanupInterval() { + if (this.cleanupInterval) { + clearInterval(this.cleanupInterval); + this.cleanupInterval = null; + } + } + /** + * Clear all sessions (useful for testing) + */ + clearAllSessions() { + for (const sessionId of this.sessions.keys()) { + this.deleteSession(sessionId); + } + this.sessions.clear(); + } +}; +_SessionManager.instance = null; +var SessionManager = _SessionManager; + +// src/event-translator.ts +import { + EventType +} from "@ag-ui/client"; + +// src/types.ts +function isAssistantMessage(message) { + return message.type === "assistant"; +} +function isResultMessage(message) { + return message.type === "result"; +} +function isTextBlock(block) { + return block.type === "text"; +} +function isToolUseBlock(block) { + return block.type === "tool_use"; +} +function isToolResultBlock(block) { + return block.type === "tool_result"; +} +function isThinkingBlock(block) { + return block.type === "thinking"; +} +function hasContentProperty(message) { + if (message.type === "assistant") { + return "message" in message && message.message !== null && typeof message.message === "object" && "content" in message.message && Array.isArray(message.message.content); + } + return "content" in message && Array.isArray(message.content); +} + +// src/event-translator.ts +var EventTranslator = class { + constructor(runId, threadId) { + this.messageIdCounter = 0; + this.currentMessageId = null; + this.runId = runId; + this.threadId = threadId; + } + /** + * Translate a Claude SDK message to AG-UI events + * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent + */ + translateMessage(message) { + const events = []; + if (hasContentProperty(message)) { + events.push(...this.translateAssistantMessage(message)); + } + return events; + } + /** + * Translate an AssistantMessage with content blocks + */ + translateAssistantMessage(message) { + var _a; + const events = []; + const content = ((_a = message.message) == null ? void 0 : _a.content) || []; + for (const block of content) { + if (isTextBlock(block)) { + events.push(...this.translateTextBlock(block)); + } else if (isToolUseBlock(block)) { + events.push(...this.translateToolUseBlock(block)); + } else if (isToolResultBlock(block)) { + events.push(...this.translateToolResultBlock(block)); + } + } + return events; + } + /** + * Translate a TextBlock to text message events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + translateTextBlock(block) { + const events = []; + const messageId = this.generateMessageId(); + events.push({ + type: EventType.TEXT_MESSAGE_START, + messageId, + role: "assistant" + }); + const text = block.text; + if (text.length > 0) { + events.push({ + type: EventType.TEXT_MESSAGE_CONTENT, + messageId, + delta: text + }); + } + events.push({ + type: EventType.TEXT_MESSAGE_END, + messageId + }); + return events; + } + /** + * Translate a ToolUseBlock to tool call events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + translateToolUseBlock(block) { + const events = []; + const toolCallId = block.id; + events.push({ + type: EventType.TOOL_CALL_START, + toolCallId, + toolCallName: block.name + }); + const argsJson = JSON.stringify(block.input); + if (argsJson.length > 0) { + events.push({ + type: EventType.TOOL_CALL_ARGS, + toolCallId, + delta: argsJson + }); + } + events.push({ + type: EventType.TOOL_CALL_END, + toolCallId + }); + return events; + } + /** + * Translate a ToolResultBlock to tool call result event + */ + translateToolResultBlock(block) { + const events = []; + let resultContent; + if (typeof block.content === "string") { + resultContent = block.content; + } else if (Array.isArray(block.content)) { + resultContent = block.content.map((item) => { + if (item.type === "text") { + return item.text || ""; + } + return JSON.stringify(item); + }).join("\n"); + } else { + resultContent = JSON.stringify(block.content); + } + const messageId = this.generateMessageId(); + events.push(__spreadValues({ + type: EventType.TOOL_CALL_RESULT, + toolCallId: block.tool_use_id, + messageId, + content: resultContent + }, block.is_error && { role: "tool" })); + return events; + } + /** + * Generate a unique message ID + */ + generateMessageId() { + this.messageIdCounter++; + return `msg_${this.runId}_${this.messageIdCounter}`; + } + /** + * Reset the translator state for a new execution + */ + reset() { + this.messageIdCounter = 0; + this.currentMessageId = null; + } + /** + * Get current message ID + */ + getCurrentMessageId() { + return this.currentMessageId; + } + /** + * Set current message ID + */ + setCurrentMessageId(messageId) { + this.currentMessageId = messageId; + } +}; + +// src/tool-adapter.ts +import { z } from "zod"; +var ToolAdapter = class { + /** + * Convert AG-UI tools to Claude SDK MCP tool definitions + */ + static convertAgUiToolsToSdk(tools) { + return tools.map((tool) => this.convertSingleTool(tool)); + } + /** + * Convert a single AG-UI tool to Claude SDK format + */ + static convertSingleTool(tool) { + const zodSchema = this.convertJsonSchemaToZod(tool.parameters || {}); + return { + name: tool.name, + description: tool.description || "", + inputSchema: zodSchema, + handler: async (args) => { + if (tool.client) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + toolName: tool.name, + args, + isClientTool: true, + isLongRunning: true + }) + } + ] + }; + } + if (tool.handler) { + try { + const result = await tool.handler(args); + return { + content: [ + { + type: "text", + text: typeof result === "string" ? result : JSON.stringify(result) + } + ] + }; + } catch (error) { + return { + content: [ + { + type: "text", + text: error.message || "Tool execution failed" + } + ], + isError: true + }; + } + } + return { + content: [ + { + type: "text", + text: "Tool executed (no handler)" + } + ] + }; + } + }; + } + /** + * Convert JSON Schema to Zod schema + */ + static convertJsonSchemaToZod(jsonSchema) { + if (!jsonSchema || typeof jsonSchema !== "object") { + return z.object({}); + } + const properties = jsonSchema.properties || {}; + const required = jsonSchema.required || []; + const zodShape = {}; + for (const [key, prop] of Object.entries(properties)) { + const propSchema = prop; + let zodType = this.convertJsonSchemaTypeToZod(propSchema); + if (!required.includes(key)) { + zodType = zodType.optional(); + } + zodShape[key] = zodType; + } + return z.object(zodShape); + } + /** + * Convert a single JSON Schema type to Zod type + */ + static convertJsonSchemaTypeToZod(schema) { + const type = schema.type; + switch (type) { + case "string": + if (schema.enum) { + return z.enum(schema.enum); + } + return z.string(); + case "number": + case "integer": + let numType = type === "integer" ? z.number().int() : z.number(); + if (schema.minimum !== void 0) { + numType = numType.min(schema.minimum); + } + if (schema.maximum !== void 0) { + numType = numType.max(schema.maximum); + } + return numType; + case "boolean": + return z.boolean(); + case "array": + if (schema.items) { + const itemType = this.convertJsonSchemaTypeToZod(schema.items); + return z.array(itemType); + } + return z.array(z.any()); + case "object": + if (schema.properties) { + return this.convertJsonSchemaToZod(schema); + } + return z.record(z.any()); + case "null": + return z.null(); + default: + return z.any(); + } + } + /** + * Create an MCP server configuration for AG-UI tools + */ + static async createMcpServerForTools(tools) { + const sdkTools = this.convertAgUiToolsToSdk(tools); + const { createSdkMcpServer } = await import("@anthropic-ai/claude-agent-sdk"); + return createSdkMcpServer({ + name: "ag_ui_tools", + version: "1.0.0", + tools: sdkTools + // Cast to any to avoid type incompatibility + }); + } + /** + * Extract tool calls from Claude SDK response + */ + static extractToolCalls(message) { + if (!message.content || !Array.isArray(message.content)) { + return []; + } + return message.content.filter((block) => block.type === "tool_use").map((block) => ({ + id: block.id, + name: block.name, + input: block.input + })); + } + /** + * Check if a tool is a long-running client tool + */ + static isClientTool(toolName, tools) { + const tool = tools.find((t) => t.name === toolName); + return (tool == null ? void 0 : tool.client) === true; + } + /** + * Check if a tool is marked as long-running + */ + static isLongRunningTool(toolName, tools) { + const tool = tools.find((t) => t.name === toolName); + return (tool == null ? void 0 : tool.client) === true || (tool == null ? void 0 : tool.longRunning) === true; + } + /** + * Format tool names for Claude SDK (with MCP server prefix) + */ + static formatToolNameForSdk(toolName, serverName = "ag_ui_tools") { + return `mcp__${serverName}__${toolName}`; + } + /** + * Parse tool name from SDK format (remove MCP server prefix) + */ + static parseToolNameFromSdk(sdkToolName) { + const parts = sdkToolName.split("__"); + if (parts.length >= 3 && parts[0] === "mcp") { + return parts.slice(2).join("__"); + } + return sdkToolName; + } + /** + * Get allowed tools list for SDK options + */ + static getAllowedToolsList(tools, serverName = "ag_ui_tools") { + return tools.map((tool) => this.formatToolNameForSdk(tool.name, serverName)); + } +}; + +// src/execution-state.ts +var ExecutionState = class { + constructor(id, sessionId) { + this.id = id; + this.sessionId = sessionId; + this._isRunning = true; + this._startTime = Date.now(); + this._events = []; + this._abortController = new AbortController(); + } + /** + * Check if execution is running + */ + get isRunning() { + return this._isRunning; + } + /** + * Get start time + */ + get startTime() { + return this._startTime; + } + /** + * Get end time + */ + get endTime() { + return this._endTime; + } + /** + * Get duration in milliseconds + */ + get duration() { + const end = this._endTime || Date.now(); + return end - this._startTime; + } + /** + * Get all collected events + */ + get events() { + return [...this._events]; + } + /** + * Get error if any + */ + get error() { + return this._error; + } + /** + * Get abort signal + */ + get signal() { + return this._abortController.signal; + } + /** + * Add an event to the execution state + */ + addEvent(event) { + this._events.push(event); + } + /** + * Add multiple events + */ + addEvents(events) { + this._events.push(...events); + } + /** + * Mark execution as completed + */ + complete() { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + } + } + /** + * Mark execution as failed + */ + fail(error) { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + this._error = error; + } + } + /** + * Abort the execution + */ + abort() { + if (this._isRunning) { + this._abortController.abort(); + this._isRunning = false; + this._endTime = Date.now(); + } + } + /** + * Get execution statistics + */ + getStats() { + return { + duration: this.duration, + eventCount: this._events.length, + isRunning: this._isRunning, + hasError: !!this._error + }; + } + /** + * Clear events (useful for memory management) + */ + clearEvents() { + this._events = []; + } + /** + * Get the last N events + */ + getLastEvents(count) { + return this._events.slice(-count); + } + /** + * Check if execution has been aborted + */ + isAborted() { + return this._abortController.signal.aborted; + } +}; +var ExecutionStateManager = class { + constructor(maxExecutions = 100) { + this.executions = /* @__PURE__ */ new Map(); + this.maxExecutions = maxExecutions; + } + /** + * Create a new execution state + */ + createExecution(id, sessionId) { + const execution = new ExecutionState(id, sessionId); + this.executions.set(id, execution); + if (this.executions.size > this.maxExecutions) { + this.cleanupOldExecutions(); + } + return execution; + } + /** + * Get an execution state by ID + */ + getExecution(id) { + return this.executions.get(id); + } + /** + * Check if an execution exists + */ + hasExecution(id) { + return this.executions.has(id); + } + /** + * Delete an execution state + */ + deleteExecution(id) { + return this.executions.delete(id); + } + /** + * Get all executions for a session + */ + getSessionExecutions(sessionId) { + const executions = []; + for (const execution of this.executions.values()) { + if (execution.sessionId === sessionId) { + executions.push(execution); + } + } + return executions; + } + /** + * Get running executions + */ + getRunningExecutions() { + const running = []; + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running.push(execution); + } + } + return running; + } + /** + * Get completed executions + */ + getCompletedExecutions() { + const completed = []; + for (const execution of this.executions.values()) { + if (!execution.isRunning) { + completed.push(execution); + } + } + return completed; + } + /** + * Abort all running executions for a session + */ + abortSessionExecutions(sessionId) { + const sessionExecutions = this.getSessionExecutions(sessionId); + for (const execution of sessionExecutions) { + if (execution.isRunning) { + execution.abort(); + } + } + } + /** + * Clean up old completed executions + */ + cleanupOldExecutions() { + const completed = this.getCompletedExecutions(); + completed.sort((a, b) => { + const aTime = a.endTime || a.startTime; + const bTime = b.endTime || b.startTime; + return aTime - bTime; + }); + const toRemove = Math.max(0, this.executions.size - this.maxExecutions); + for (let i = 0; i < toRemove && i < completed.length; i++) { + this.executions.delete(completed[i].id); + } + } + /** + * Clear all executions + */ + clearAll() { + this.executions.clear(); + } + /** + * Get total execution count + */ + getExecutionCount() { + return this.executions.size; + } + /** + * Get execution statistics + */ + getStats() { + let running = 0; + let completed = 0; + let failed = 0; + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running++; + } else if (execution.error) { + failed++; + } else { + completed++; + } + } + return { + total: this.executions.size, + running, + completed, + failed + }; + } +}; + +// src/utils/converters.ts +function convertAgUiMessagesToPrompt(messages) { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + if (msg.role === "user") { + return extractMessageContent(msg); + } + } + return "Hello"; +} +function extractMessageContent(message) { + if (typeof message.content === "string") { + return message.content; + } + if (Array.isArray(message.content)) { + return message.content.map((block) => { + if (typeof block === "string") { + return block; + } + if (block.type === "text") { + return block.text || ""; + } + return ""; + }).filter(Boolean).join("\n"); + } + return String(message.content); +} +function convertAgUiMessageToClaude(message) { + const role = message.role; + const content = extractMessageContent(message); + return { + role, + content + }; +} +function convertAgUiMessagesToClaude(messages) { + return messages.map(convertAgUiMessageToClaude); +} +function hasToolResults(messages) { + return messages.some((msg) => { + if (typeof msg.content === "string") { + return false; + } + if (Array.isArray(msg.content)) { + return msg.content.some((block) => { + return typeof block === "object" && block.type === "tool_result"; + }); + } + return false; + }); +} +function extractToolResults(messages) { + const results = []; + for (const msg of messages) { + if (typeof msg.content === "string") { + continue; + } + if (Array.isArray(msg.content)) { + for (const block of msg.content) { + if (typeof block === "object" && block.type === "tool_result") { + results.push({ + toolCallId: block.toolCallId || block.tool_use_id || "", + result: block.result || block.content || "" + }); + } + } + } + } + return results; +} +function generateRunId() { + return `run_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} +function generateMessageId(prefix = "msg") { + return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} +function safeJsonParse(json, defaultValue = null) { + try { + return JSON.parse(json); + } catch (e) { + return defaultValue; + } +} +function safeJsonStringify(obj, defaultValue = "{}") { + try { + return JSON.stringify(obj); + } catch (e) { + return defaultValue; + } +} +function isToolResultSubmission(messages) { + if (messages.length === 0) { + return false; + } + const lastMessage = messages[messages.length - 1]; + return hasToolResults([lastMessage]); +} +function formatErrorMessage(error) { + if (error instanceof Error) { + return error.message; + } + if (typeof error === "string") { + return error; + } + return "An unknown error occurred"; +} +function truncateText(text, maxLength = 1e3) { + if (text.length <= maxLength) { + return text; + } + return text.slice(0, maxLength) + "..."; +} +function mergeTextBlocks(blocks) { + return blocks.filter((block) => block.type === "text" && block.text).map((block) => block.text).join(""); +} + +// src/agent.ts +var ClaudeAgent = class extends AbstractAgent { + constructor(config) { + super(config); + this.apiKey = config.apiKey; + this.baseUrl = config.baseUrl; + this.sessionTimeout = config.sessionTimeout || 30 * 60 * 1e3; + this.enablePersistentSessions = config.enablePersistentSessions !== false; + this.permissionMode = this.mapPermissionMode(config.permissionMode || "bypassPermissions"); + this.stderr = config.stderr; + this.verbose = config.verbose; + this.sessionManager = SessionManager.getInstance(this.sessionTimeout); + this.executionStateManager = new ExecutionStateManager(); + } + /** + * Map legacy permission modes to new SDK values for backward compatibility + */ + mapPermissionMode(mode) { + const modeMap = { + "ask": "default", + "auto": "bypassPermissions", + "none": "bypassPermissions", + "default": "default", + "acceptEdits": "acceptEdits", + "bypassPermissions": "bypassPermissions", + "plan": "plan" + }; + return modeMap[mode || "bypassPermissions"] || "bypassPermissions"; + } + /** + * Run the agent with the given input + */ + run(input) { + return new Observable((subscriber) => { + this.executeAgent(input, subscriber).catch((error) => { + subscriber.error(error); + }); + }); + } + /** + * Execute the agent asynchronously + */ + async executeAgent(input, subscriber) { + const runId = generateRunId(); + const sessionId = input.threadId || `session_${Date.now()}`; + const execution = this.executionStateManager.createExecution(runId, sessionId); + try { + const runStartedEvent = { + type: EventType2.RUN_STARTED, + threadId: sessionId, + runId + }; + subscriber.next(runStartedEvent); + execution.addEvent(runStartedEvent); + const session = this.sessionManager.getSession(sessionId, "default"); + const unseenMessages = this.sessionManager.getUnseenMessages( + sessionId, + input.messages || [] + ); + const isToolResult = isToolResultSubmission(input.messages || []); + const tools = input.tools || []; + const options = await this.prepareClaudeOptions(tools); + const prompt = convertAgUiMessagesToPrompt(unseenMessages); + const stepStartedEvent = { + type: EventType2.STEP_STARTED, + stepName: `step_${runId}_1` + }; + subscriber.next(stepStartedEvent); + execution.addEvent(stepStartedEvent); + await this.callClaudeSDK( + prompt, + options, + session, + runId, + sessionId, + subscriber, + execution + ); + this.sessionManager.markMessagesAsProcessed(sessionId, unseenMessages); + const stepFinishedEvent = { + type: EventType2.STEP_FINISHED, + stepName: `step_${runId}_1` + }; + subscriber.next(stepFinishedEvent); + execution.addEvent(stepFinishedEvent); + const runFinishedEvent = { + type: EventType2.RUN_FINISHED, + threadId: sessionId, + runId + }; + subscriber.next(runFinishedEvent); + execution.addEvent(runFinishedEvent); + execution.complete(); + subscriber.complete(); + } catch (error) { + const runErrorEvent = { + type: EventType2.RUN_ERROR, + message: formatErrorMessage(error) + }; + subscriber.next(runErrorEvent); + execution.addEvent(runErrorEvent); + execution.fail(error); + subscriber.complete(); + } + } + /** + * Prepare Claude SDK options + * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + * But baseUrl needs to be explicitly passed for third-party APIs + */ + async prepareClaudeOptions(tools) { + const baseUrl = this.baseUrl || process.env.ANTHROPIC_BASE_URL; + const apiKey = this.apiKey || process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY; + console.log("[Claude Agent] Preparing SDK options:", { + hasApiKey: !!apiKey, + hasBaseUrl: !!baseUrl, + baseUrl: baseUrl || "not set", + permissionMode: this.permissionMode, + hasStderr: !!this.stderr, + verbose: this.verbose + }); + const options = __spreadProps(__spreadValues(__spreadValues({ + permissionMode: this.permissionMode + }, this.stderr && { stderr: this.stderr }), this.verbose !== void 0 && { verbose: this.verbose }), { + env: process.env + }); + if (this.stderr) { + console.log("[Claude Agent] \u2713 stderr callback is configured for error logging"); + } else { + console.warn("[Claude Agent] \u26A0\uFE0F stderr callback not configured - CLI errors may not be visible"); + } + if (tools && tools.length > 0) { + const mcpServer = await ToolAdapter.createMcpServerForTools(tools); + options.mcpServers = { + ag_ui_tools: mcpServer + }; + options.allowedTools = ToolAdapter.getAllowedToolsList(tools); + } + return options; + } + /** + * Call Claude SDK + * Note: Currently only stateless mode is supported via query() function + */ + async callClaudeSDK(prompt, options, session, runId, sessionId, subscriber, execution) { + const eventTranslator = new EventTranslator(runId, sessionId); + await this.callClaudeSDKStateless( + prompt, + options, + eventTranslator, + subscriber, + execution + ); + } + /** + * Call Claude SDK in persistent session mode + * Note: The current SDK only supports stateless mode via query() function + * This method falls back to stateless mode + */ + async callClaudeSDKPersistent(prompt, options, session, eventTranslator, subscriber, execution) { + await this.callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution); + } + /** + * Call Claude SDK in stateless mode + */ + async callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution) { + try { + console.log("[Claude Agent] Environment check:"); + console.log(" ANTHROPIC_API_KEY:", process.env.ANTHROPIC_API_KEY ? "SET" : "NOT SET"); + console.log(" ANTHROPIC_AUTH_TOKEN:", process.env.ANTHROPIC_AUTH_TOKEN ? "SET" : "NOT SET"); + console.log(" ANTHROPIC_BASE_URL:", process.env.ANTHROPIC_BASE_URL || "NOT SET (using default)"); + console.log("[Claude Agent] Options passed to SDK:", { + hasApiKey: !!options.apiKey, + hasBaseUrl: !!options.baseUrl, + permissionMode: options.permissionMode, + hasMcpServers: !!options.mcpServers + }); + const { query } = await this.importClaudeSDK(); + console.log("[Claude Agent] Calling SDK query()..."); + const queryResult = query({ prompt, options }); + try { + for (var iter = __forAwait(queryResult), more, temp, error; more = !(temp = await iter.next()).done; more = false) { + const message = temp.value; + console.log("[Claude Agent] \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"); + console.log("[Claude Agent] Received message type:", (message == null ? void 0 : message.type) || "unknown"); + console.log("[Claude Agent] Full message:", JSON.stringify(message, null, 2)); + if (execution.isAborted()) { + console.log("[Claude Agent] Execution aborted by user"); + break; + } + const events = eventTranslator.translateMessage(message); + console.log("[Claude Agent] Translated events count:", events.length); + for (const event of events) { + console.log("[Claude Agent] Sending event:", JSON.stringify(event, null, 2)); + subscriber.next(event); + execution.addEvent(event); + } + console.log("[Claude Agent] \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"); + } + } catch (temp) { + error = [temp]; + } finally { + try { + more && (temp = iter.return) && await temp.call(iter); + } finally { + if (error) + throw error[0]; + } + } + console.log("[Claude Agent] Query completed successfully"); + } catch (error2) { + console.error("[Claude Agent] ERROR Details:"); + console.error(" Message:", error2.message); + console.error(" Stack:", error2.stack); + console.error(" Error object:", JSON.stringify(error2, Object.getOwnPropertyNames(error2), 2)); + if (error2.message && error2.message.includes("exited with code")) { + throw new Error( + `Claude Code process failed. Please ensure: +1. Claude CLI is installed and accessible (run: claude --version) +2. ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set correctly in environment variables +3. You have proper permissions to run Claude Code +4. If using ANTHROPIC_BASE_URL, ensure it supports Claude Code protocol + +Original error: ${error2.message} +Error stack: ${error2.stack || "No stack trace"}` + ); + } + if (error2.message && (error2.message.includes("API key") || error2.message.includes("auth"))) { + throw new Error( + `API key error: ${error2.message} +Please ensure ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set in environment variables.` + ); + } + throw error2; + } + } + /** + * Dynamically import Claude SDK + */ + async importClaudeSDK() { + try { + return await import("@anthropic-ai/claude-agent-sdk"); + } catch (error) { + throw new Error( + "Claude Agent SDK not found. Please install it: npm install @anthropic-ai/claude-agent-sdk" + ); + } + } + /** + * Abort a running execution + */ + abortExecution(runId) { + const execution = this.executionStateManager.getExecution(runId); + if (execution) { + execution.abort(); + } + } + /** + * Get execution state + */ + getExecutionState(runId) { + return this.executionStateManager.getExecution(runId); + } + /** + * Get session manager (for testing) + */ + getSessionManager() { + return this.sessionManager; + } + /** + * Get execution state manager (for testing) + */ + getExecutionStateManager() { + return this.executionStateManager; + } + /** + * Cleanup resources + */ + async cleanup() { + const runningExecutions = this.executionStateManager.getRunningExecutions(); + for (const execution of runningExecutions) { + execution.abort(); + } + this.sessionManager.clearAllSessions(); + this.executionStateManager.clearAll(); + } +}; +export { + ClaudeAgent, + EventTranslator, + ExecutionState, + ExecutionStateManager, + SessionManager, + ToolAdapter, + convertAgUiMessageToClaude, + convertAgUiMessagesToClaude, + convertAgUiMessagesToPrompt, + extractMessageContent, + extractToolResults, + formatErrorMessage, + generateMessageId, + generateRunId, + hasContentProperty, + hasToolResults, + isAssistantMessage, + isResultMessage, + isTextBlock, + isThinkingBlock, + isToolResultBlock, + isToolResultSubmission, + isToolUseBlock, + mergeTextBlocks, + safeJsonParse, + safeJsonStringify, + truncateText +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/integrations/claude-agent-sdk/typescript/dist/index.mjs.map b/integrations/claude-agent-sdk/typescript/dist/index.mjs.map new file mode 100644 index 000000000..6e3a243e3 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/dist/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/agent.ts","../src/session-manager.ts","../src/event-translator.ts","../src/types.ts","../src/tool-adapter.ts","../src/execution-state.ts","../src/utils/converters.ts"],"sourcesContent":["/**\n * Claude Agent: Main agent class that integrates Claude SDK with AG-UI Protocol\n */\n\nimport { Observable, Subscriber } from 'rxjs';\nimport {\n AbstractAgent,\n RunAgentInput,\n EventType,\n RunStartedEvent,\n RunFinishedEvent,\n RunErrorEvent,\n StepStartedEvent,\n StepFinishedEvent,\n} from '@ag-ui/client';\nimport type {\n ClaudeAgentConfig,\n ProcessedEvents,\n ClaudeSDKClient,\n Options,\n SDKMessage,\n} from './types';\nimport { SessionManager } from './session-manager';\nimport { EventTranslator } from './event-translator';\nimport { ToolAdapter } from './tool-adapter';\nimport { ExecutionState, ExecutionStateManager } from './execution-state';\nimport {\n generateRunId,\n convertAgUiMessagesToPrompt,\n isToolResultSubmission,\n formatErrorMessage,\n} from './utils/converters';\n\n/**\n * ClaudeAgent integrates Claude Agent SDK with AG-UI Protocol\n */\nexport class ClaudeAgent extends AbstractAgent {\n private sessionManager: SessionManager;\n private executionStateManager: ExecutionStateManager;\n private apiKey?: string;\n private baseUrl?: string;\n private sessionTimeout: number;\n private enablePersistentSessions: boolean;\n private permissionMode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n private stderr?: (data: string) => void;\n private verbose?: boolean;\n\n constructor(config: ClaudeAgentConfig) {\n super(config);\n // SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment\n // Only set these if explicitly provided in config (optional)\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl;\n this.sessionTimeout = config.sessionTimeout || 30 * 60 * 1000; // 30 minutes\n this.enablePersistentSessions = config.enablePersistentSessions !== false;\n // Map legacy permission modes to new SDK values for backward compatibility\n this.permissionMode = this.mapPermissionMode(config.permissionMode || 'bypassPermissions');\n this.stderr = config.stderr;\n this.verbose = config.verbose;\n this.sessionManager = SessionManager.getInstance(this.sessionTimeout);\n this.executionStateManager = new ExecutionStateManager();\n }\n\n /**\n * Map legacy permission modes to new SDK values for backward compatibility\n */\n private mapPermissionMode(mode?: string): 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' {\n const modeMap: Record = {\n 'ask': 'default',\n 'auto': 'bypassPermissions',\n 'none': 'bypassPermissions',\n 'default': 'default',\n 'acceptEdits': 'acceptEdits',\n 'bypassPermissions': 'bypassPermissions',\n 'plan': 'plan',\n };\n return modeMap[mode || 'bypassPermissions'] || 'bypassPermissions';\n }\n\n /**\n * Run the agent with the given input\n */\n run(input: RunAgentInput): Observable {\n return new Observable((subscriber) => {\n this.executeAgent(input, subscriber).catch((error) => {\n subscriber.error(error);\n });\n });\n }\n\n /**\n * Execute the agent asynchronously\n */\n private async executeAgent(\n input: RunAgentInput,\n subscriber: Subscriber\n ): Promise {\n const runId = generateRunId();\n const sessionId = input.threadId || `session_${Date.now()}`;\n\n // Create execution state\n const execution = this.executionStateManager.createExecution(runId, sessionId);\n\n try {\n // Emit run started event\n const runStartedEvent: RunStartedEvent = {\n type: EventType.RUN_STARTED,\n threadId: sessionId,\n runId,\n };\n subscriber.next(runStartedEvent);\n execution.addEvent(runStartedEvent);\n\n // Get or create session\n const session = this.sessionManager.getSession(sessionId, 'default');\n\n // Get unseen messages\n const unseenMessages = this.sessionManager.getUnseenMessages(\n sessionId,\n input.messages || []\n );\n\n // Check if this is a tool result submission\n const isToolResult = isToolResultSubmission(input.messages || []);\n\n // Prepare tools\n const tools = input.tools || [];\n \n // Prepare options for Claude SDK\n const options = await this.prepareClaudeOptions(tools);\n\n // Extract prompt from messages\n const prompt = convertAgUiMessagesToPrompt(unseenMessages);\n\n // Emit step started event\n const stepStartedEvent: StepStartedEvent = {\n type: EventType.STEP_STARTED,\n stepName: `step_${runId}_1`,\n };\n subscriber.next(stepStartedEvent);\n execution.addEvent(stepStartedEvent);\n\n // Call Claude SDK\n await this.callClaudeSDK(\n prompt,\n options,\n session,\n runId,\n sessionId,\n subscriber,\n execution\n );\n\n // Mark messages as processed\n this.sessionManager.markMessagesAsProcessed(sessionId, unseenMessages);\n\n // Emit step finished event\n const stepFinishedEvent: StepFinishedEvent = {\n type: EventType.STEP_FINISHED,\n stepName: `step_${runId}_1`,\n };\n subscriber.next(stepFinishedEvent);\n execution.addEvent(stepFinishedEvent);\n\n // Emit run finished event\n const runFinishedEvent: RunFinishedEvent = {\n type: EventType.RUN_FINISHED,\n threadId: sessionId,\n runId,\n };\n subscriber.next(runFinishedEvent);\n execution.addEvent(runFinishedEvent);\n\n // Complete execution\n execution.complete();\n subscriber.complete();\n } catch (error: any) {\n // Emit run error event\n const runErrorEvent: RunErrorEvent = {\n type: EventType.RUN_ERROR,\n message: formatErrorMessage(error),\n };\n subscriber.next(runErrorEvent);\n execution.addEvent(runErrorEvent);\n\n // Mark execution as failed\n execution.fail(error);\n\n // Complete the observable\n subscriber.complete();\n }\n }\n\n /**\n * Prepare Claude SDK options\n * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment\n * But baseUrl needs to be explicitly passed for third-party APIs\n */\n private async prepareClaudeOptions(tools: any[]): Promise {\n // Get baseUrl from config or environment\n const baseUrl = this.baseUrl || process.env.ANTHROPIC_BASE_URL;\n const apiKey = this.apiKey || process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n \n // Debug logging\n console.log('[Claude Agent] Preparing SDK options:', {\n hasApiKey: !!apiKey,\n hasBaseUrl: !!baseUrl,\n baseUrl: baseUrl || 'not set',\n permissionMode: this.permissionMode,\n hasStderr: !!this.stderr,\n verbose: this.verbose,\n });\n \n const options: Options = {\n permissionMode: this.permissionMode,\n // Add stderr callback for debugging - CRITICAL for error logging\n ...(this.stderr && { stderr: this.stderr }),\n // Add verbose flag for detailed logging\n ...(this.verbose !== undefined && { verbose: this.verbose }),\n env: process.env\n };\n \n // Verify stderr callback is set\n if (this.stderr) {\n console.log('[Claude Agent] ✓ stderr callback is configured for error logging');\n } else {\n console.warn('[Claude Agent] ⚠️ stderr callback not configured - CLI errors may not be visible');\n }\n\n // Add tools if provided\n if (tools && tools.length > 0) {\n const mcpServer = await ToolAdapter.createMcpServerForTools(tools);\n options.mcpServers = {\n ag_ui_tools: mcpServer,\n };\n\n // Set allowed tools\n options.allowedTools = ToolAdapter.getAllowedToolsList(tools);\n }\n\n return options;\n }\n\n /**\n * Call Claude SDK\n * Note: Currently only stateless mode is supported via query() function\n */\n private async callClaudeSDK(\n prompt: string,\n options: Options,\n session: any,\n runId: string,\n sessionId: string,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n const eventTranslator = new EventTranslator(runId, sessionId);\n\n // The current @anthropic-ai/claude-agent-sdk only supports stateless mode\n // via the query() function. We use stateless mode for both cases.\n await this.callClaudeSDKStateless(\n prompt,\n options,\n eventTranslator,\n subscriber,\n execution\n );\n }\n\n /**\n * Call Claude SDK in persistent session mode\n * Note: The current SDK only supports stateless mode via query() function\n * This method falls back to stateless mode\n */\n private async callClaudeSDKPersistent(\n prompt: string,\n options: Options,\n session: any,\n eventTranslator: EventTranslator,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n // The current @anthropic-ai/claude-agent-sdk only supports stateless mode\n // via the query() function. For persistent sessions, we use query() \n // but maintain session state in our SessionManager\n await this.callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution);\n }\n\n /**\n * Call Claude SDK in stateless mode\n */\n private async callClaudeSDKStateless(\n prompt: string,\n options: Options,\n eventTranslator: EventTranslator,\n subscriber: Subscriber,\n execution: ExecutionState\n ): Promise {\n try {\n // Log environment variables for debugging\n console.log('[Claude Agent] Environment check:');\n console.log(' ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY ? 'SET' : 'NOT SET');\n console.log(' ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'SET' : 'NOT SET');\n console.log(' ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'NOT SET (using default)');\n console.log('[Claude Agent] Options passed to SDK:', {\n hasApiKey: !!options.apiKey,\n hasBaseUrl: !!options.baseUrl,\n permissionMode: options.permissionMode,\n hasMcpServers: !!options.mcpServers,\n });\n\n // Import Claude SDK dynamically\n const { query } = await this.importClaudeSDK();\n\n console.log('[Claude Agent] Calling SDK query()...');\n\n // Call query function\n // SDK will automatically read API key from environment variables (ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN)\n // if not provided in options.apiKey\n const queryResult = query({ prompt, options });\n\n // Process responses\n for await (const message of queryResult) {\n console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('[Claude Agent] Received message type:', message?.type || 'unknown');\n console.log('[Claude Agent] Full message:', JSON.stringify(message, null, 2));\n \n if (execution.isAborted()) {\n console.log('[Claude Agent] Execution aborted by user');\n break;\n }\n\n const events = eventTranslator.translateMessage(message);\n console.log('[Claude Agent] Translated events count:', events.length);\n for (const event of events) {\n console.log('[Claude Agent] Sending event:', JSON.stringify(event, null, 2));\n subscriber.next(event);\n execution.addEvent(event);\n }\n console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n }\n \n console.log('[Claude Agent] Query completed successfully');\n } catch (error: any) {\n // Log detailed error information\n console.error('[Claude Agent] ERROR Details:');\n console.error(' Message:', error.message);\n console.error(' Stack:', error.stack);\n console.error(' Error object:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2));\n \n // Handle Claude Code process errors\n if (error.message && error.message.includes('exited with code')) {\n throw new Error(\n `Claude Code process failed. Please ensure:\\n` +\n `1. Claude CLI is installed and accessible (run: claude --version)\\n` +\n `2. ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set correctly in environment variables\\n` +\n `3. You have proper permissions to run Claude Code\\n` +\n `4. If using ANTHROPIC_BASE_URL, ensure it supports Claude Code protocol\\n` +\n `\\nOriginal error: ${error.message}\\n` +\n `Error stack: ${error.stack || 'No stack trace'}`\n );\n }\n // Handle API key errors from SDK\n if (error.message && (error.message.includes('API key') || error.message.includes('auth'))) {\n throw new Error(\n `API key error: ${error.message}\\n` +\n `Please ensure ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set in environment variables.`\n );\n }\n throw error;\n }\n }\n\n /**\n * Dynamically import Claude SDK\n */\n private async importClaudeSDK(): Promise {\n try {\n return await import('@anthropic-ai/claude-agent-sdk');\n } catch (error) {\n throw new Error(\n 'Claude Agent SDK not found. Please install it: npm install @anthropic-ai/claude-agent-sdk'\n );\n }\n }\n\n /**\n * Abort a running execution\n */\n abortExecution(runId: string): void {\n const execution = this.executionStateManager.getExecution(runId);\n if (execution) {\n execution.abort();\n }\n }\n\n /**\n * Get execution state\n */\n getExecutionState(runId: string): ExecutionState | undefined {\n return this.executionStateManager.getExecution(runId);\n }\n\n /**\n * Get session manager (for testing)\n */\n getSessionManager(): SessionManager {\n return this.sessionManager;\n }\n\n /**\n * Get execution state manager (for testing)\n */\n getExecutionStateManager(): ExecutionStateManager {\n return this.executionStateManager;\n }\n\n /**\n * Cleanup resources\n */\n async cleanup(): Promise {\n // Abort all running executions\n const runningExecutions = this.executionStateManager.getRunningExecutions();\n for (const execution of runningExecutions) {\n execution.abort();\n }\n\n // Clear all sessions\n this.sessionManager.clearAllSessions();\n\n // Clear all executions\n this.executionStateManager.clearAll();\n }\n}\n\n","/**\n * Session manager: Manages agent sessions and state\n */\n\nimport type { Message } from '@ag-ui/client';\nimport type { Session, ClaudeSDKClient } from './types';\n\nconst DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000; // 30 minutes\nconst CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\n/**\n * SessionManager handles session lifecycle, message tracking, and state management\n * Implements singleton pattern for centralized session control\n */\nexport class SessionManager {\n private static instance: SessionManager | null = null;\n private sessions: Map = new Map();\n private cleanupInterval: ReturnType | null = null;\n private sessionTimeout: number;\n\n private constructor(sessionTimeout: number = DEFAULT_SESSION_TIMEOUT) {\n this.sessionTimeout = sessionTimeout;\n this.startCleanupInterval();\n }\n\n /**\n * Get the singleton instance\n */\n static getInstance(sessionTimeout?: number): SessionManager {\n if (!SessionManager.instance) {\n SessionManager.instance = new SessionManager(sessionTimeout);\n }\n return SessionManager.instance;\n }\n\n /**\n * Reset the singleton instance (useful for testing)\n */\n static resetInstance(): void {\n if (SessionManager.instance) {\n SessionManager.instance.stopCleanupInterval();\n SessionManager.instance = null;\n }\n }\n\n /**\n * Get or create a session\n */\n getSession(sessionId: string, userId?: string): Session {\n let session = this.sessions.get(sessionId);\n\n if (!session) {\n session = {\n id: sessionId,\n userId,\n processedMessageIds: new Set(),\n state: {},\n createdAt: Date.now(),\n lastAccessedAt: Date.now(),\n };\n this.sessions.set(sessionId, session);\n } else {\n // Update last accessed time\n session.lastAccessedAt = Date.now();\n }\n\n return session;\n }\n\n /**\n * Check if a session exists\n */\n hasSession(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n /**\n * Delete a session\n */\n deleteSession(sessionId: string): boolean {\n const session = this.sessions.get(sessionId);\n if (session?.client) {\n // Close the Claude SDK client if it exists\n session.client.close().catch((error) => {\n console.error(`Error closing Claude SDK client for session ${sessionId}:`, error);\n });\n }\n return this.sessions.delete(sessionId);\n }\n\n /**\n * Track a processed message\n */\n trackMessage(sessionId: string, messageId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.processedMessageIds.add(messageId);\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Check if a message has been processed\n */\n isMessageProcessed(sessionId: string, messageId: string): boolean {\n const session = this.sessions.get(sessionId);\n return session ? session.processedMessageIds.has(messageId) : false;\n }\n\n /**\n * Get unseen messages (messages not yet processed)\n */\n getUnseenMessages(sessionId: string, messages: Message[]): Message[] {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return messages;\n }\n\n return messages.filter((msg) => {\n const msgId = msg.id || `${msg.role}_${msg.content}`;\n return !session.processedMessageIds.has(msgId);\n });\n }\n\n /**\n * Mark messages as processed\n */\n markMessagesAsProcessed(sessionId: string, messages: Message[]): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n for (const msg of messages) {\n const msgId = msg.id || `${msg.role}_${msg.content}`;\n session.processedMessageIds.add(msgId);\n }\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Get state value from session\n */\n getStateValue(sessionId: string, key: string): any {\n const session = this.sessions.get(sessionId);\n return session?.state[key];\n }\n\n /**\n * Set state value in session\n */\n setStateValue(sessionId: string, key: string, value: any): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.state[key] = value;\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Remove state keys from session\n */\n removeStateKeys(sessionId: string, keys: string[]): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n for (const key of keys) {\n delete session.state[key];\n }\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Clear all state for a session\n */\n clearSessionState(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.state = {};\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Set Claude SDK client for a session\n */\n setClient(sessionId: string, client: ClaudeSDKClient): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.client = client;\n session.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Get Claude SDK client for a session\n */\n getClient(sessionId: string): ClaudeSDKClient | undefined {\n const session = this.sessions.get(sessionId);\n return session?.client;\n }\n\n /**\n * Get total number of sessions\n */\n getSessionCount(): number {\n return this.sessions.size;\n }\n\n /**\n * Get number of sessions for a specific user\n */\n getUserSessionCount(userId: string): number {\n let count = 0;\n for (const session of this.sessions.values()) {\n if (session.userId === userId) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * Get all session IDs\n */\n getAllSessionIds(): string[] {\n return Array.from(this.sessions.keys());\n }\n\n /**\n * Get all sessions for a specific user\n */\n getUserSessions(userId: string): Session[] {\n const userSessions: Session[] = [];\n for (const session of this.sessions.values()) {\n if (session.userId === userId) {\n userSessions.push(session);\n }\n }\n return userSessions;\n }\n\n /**\n * Clean up stale sessions\n */\n private cleanupStaleSessions(): void {\n const now = Date.now();\n const sessionsToDelete: string[] = [];\n\n for (const [sessionId, session] of this.sessions.entries()) {\n if (now - session.lastAccessedAt > this.sessionTimeout) {\n sessionsToDelete.push(sessionId);\n }\n }\n\n for (const sessionId of sessionsToDelete) {\n this.deleteSession(sessionId);\n }\n\n if (sessionsToDelete.length > 0) {\n console.log(`Cleaned up ${sessionsToDelete.length} stale sessions`);\n }\n }\n\n /**\n * Start the cleanup interval\n */\n private startCleanupInterval(): void {\n if (!this.cleanupInterval) {\n this.cleanupInterval = setInterval(() => {\n this.cleanupStaleSessions();\n }, CLEANUP_INTERVAL);\n\n // Don't keep the process alive just for this interval\n if (typeof (this.cleanupInterval as any).unref === 'function') {\n (this.cleanupInterval as any).unref();\n }\n }\n }\n\n /**\n * Stop the cleanup interval\n */\n private stopCleanupInterval(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n\n /**\n * Clear all sessions (useful for testing)\n */\n clearAllSessions(): void {\n for (const sessionId of this.sessions.keys()) {\n this.deleteSession(sessionId);\n }\n this.sessions.clear();\n }\n}\n\n","/**\n * Event translator: Converts Claude SDK messages to AG-UI events\n */\n\nimport {\n TextMessageStartEvent,\n TextMessageContentEvent,\n TextMessageEndEvent,\n ToolCallStartEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallResultEvent,\n EventType,\n} from '@ag-ui/client';\nimport type {\n SDKMessage,\n SDKAssistantMessage,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n ProcessedEvents,\n} from './types';\nimport {\n hasContentProperty,\n isTextBlock,\n isToolUseBlock,\n isToolResultBlock,\n} from './types';\n\n/**\n * EventTranslator converts Claude SDK messages to AG-UI protocol events\n * \n * NOTE: This translator only handles SDK message translation.\n * Run lifecycle events (RUN_STARTED, RUN_FINISHED, etc.) and step events\n * are handled by ClaudeAgent.\n */\nexport class EventTranslator {\n private messageIdCounter = 0;\n private currentMessageId: string | null = null;\n private runId: string;\n private threadId: string;\n\n constructor(runId: string, threadId: string) {\n this.runId = runId;\n this.threadId = threadId;\n }\n\n /**\n * Translate a Claude SDK message to AG-UI events\n * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent\n */\n translateMessage(message: SDKMessage): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n if (hasContentProperty(message)) {\n events.push(...this.translateAssistantMessage(message as SDKAssistantMessage));\n }\n // Note: ResultMessage (success/error) is ignored here\n // Run completion is handled by ClaudeAgent, not EventTranslator\n\n return events;\n }\n\n /**\n * Translate an AssistantMessage with content blocks\n */\n private translateAssistantMessage(message: SDKAssistantMessage): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n // Content is in message.message.content for SDKAssistantMessage\n const content = message.message?.content || [];\n \n for (const block of content) {\n if (isTextBlock(block)) {\n events.push(...this.translateTextBlock(block));\n } else if (isToolUseBlock(block)) {\n events.push(...this.translateToolUseBlock(block));\n } else if (isToolResultBlock(block)) {\n events.push(...this.translateToolResultBlock(block));\n }\n }\n\n return events;\n }\n\n /**\n * Translate a TextBlock to text message events\n * NOTE: Step events are handled by ClaudeAgent, not here\n */\n private translateTextBlock(block: TextBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n const messageId = this.generateMessageId();\n\n // Start event\n events.push({\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: 'assistant',\n });\n\n // Content event - split text into delta chunks\n const text = block.text;\n if (text.length > 0) {\n events.push({\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: text,\n });\n }\n\n // End event\n events.push({\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n });\n\n return events;\n }\n\n /**\n * Translate a ToolUseBlock to tool call events\n * NOTE: Step events are handled by ClaudeAgent, not here\n */\n private translateToolUseBlock(block: ToolUseBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n const toolCallId = block.id;\n\n // Start event\n events.push({\n type: EventType.TOOL_CALL_START,\n toolCallId,\n toolCallName: block.name,\n });\n\n // Args event - send args as JSON string\n const argsJson = JSON.stringify(block.input);\n if (argsJson.length > 0) {\n events.push({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId,\n delta: argsJson,\n });\n }\n\n // End event\n events.push({\n type: EventType.TOOL_CALL_END,\n toolCallId,\n });\n\n return events;\n }\n\n /**\n * Translate a ToolResultBlock to tool call result event\n */\n private translateToolResultBlock(block: ToolResultBlock): ProcessedEvents[] {\n const events: ProcessedEvents[] = [];\n\n // Extract content as string\n let resultContent: string;\n if (typeof block.content === 'string') {\n resultContent = block.content;\n } else if (Array.isArray(block.content)) {\n // Handle array of content blocks\n resultContent = block.content\n .map((item) => {\n if (item.type === 'text') {\n return item.text || '';\n }\n return JSON.stringify(item);\n })\n .join('\\n');\n } else {\n resultContent = JSON.stringify(block.content);\n }\n\n const messageId = this.generateMessageId();\n events.push({\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: block.tool_use_id,\n messageId,\n content: resultContent,\n ...(block.is_error && { role: 'tool' as const }),\n });\n\n return events;\n }\n\n /**\n * Generate a unique message ID\n */\n private generateMessageId(): string {\n this.messageIdCounter++;\n return `msg_${this.runId}_${this.messageIdCounter}`;\n }\n\n /**\n * Reset the translator state for a new execution\n */\n reset(): void {\n this.messageIdCounter = 0;\n this.currentMessageId = null;\n }\n\n /**\n * Get current message ID\n */\n getCurrentMessageId(): string | null {\n return this.currentMessageId;\n }\n\n /**\n * Set current message ID\n */\n setCurrentMessageId(messageId: string | null): void {\n this.currentMessageId = messageId;\n }\n}\n\n","/**\n * Type definitions for Claude Agent SDK integration with AG-UI Protocol\n */\n\nimport type {\n TextMessageStartEvent,\n TextMessageContentEvent,\n TextMessageEndEvent,\n ToolCallStartEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallResultEvent,\n RunStartedEvent,\n RunFinishedEvent,\n RunErrorEvent,\n StepStartedEvent,\n StepFinishedEvent,\n AgentConfig,\n Tool,\n Message,\n} from '@ag-ui/client';\n\n// Re-export Claude SDK types (will be imported from the actual SDK)\n// These are placeholder interfaces based on the SDK documentation\nexport interface ClaudeSDKClient {\n query(prompt: string): Promise;\n receiveResponse(): AsyncIterableIterator;\n close(): Promise;\n}\n\nexport interface Options {\n apiKey?: string;\n baseUrl?: string;\n mcpServers?: Record;\n allowedTools?: string[];\n // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan'\n // Legacy values 'ask', 'auto', 'none' are also supported for backward compatibility\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none';\n stderr?: (data: string) => void;\n verbose?: boolean;\n [key: string]: any;\n}\n\nexport interface Query {\n next(): Promise>;\n [Symbol.asyncIterator](): AsyncIterableIterator;\n}\n\n// SDK Message types based on documentation\nexport type SDKMessage =\n | SDKAssistantMessage\n | SDKUserMessage\n | SDKSystemMessage\n | SDKResultMessage\n | SDKPartialAssistantMessage\n | SDKCompactBoundaryMessage\n | SDKPermissionDenial;\n\nexport interface SDKAssistantMessage {\n type: 'assistant';\n message: {\n id?: string;\n content: ContentBlock[];\n [key: string]: any;\n };\n parent_tool_use_id?: string | null;\n uuid?: string;\n session_id?: string;\n}\n\nexport interface SDKUserMessage {\n type: 'user';\n content: string;\n id?: string;\n}\n\nexport interface SDKSystemMessage {\n type: 'system';\n content: string;\n}\n\nexport interface SDKResultMessage {\n type: 'result';\n subtype: 'success' | 'error';\n error?: {\n type: string;\n message: string;\n };\n}\n\nexport interface SDKPartialAssistantMessage {\n type: 'partial_assistant';\n content: ContentBlock[];\n}\n\nexport interface SDKCompactBoundaryMessage {\n type: 'compact_boundary';\n}\n\nexport interface SDKPermissionDenial {\n type: 'permission_denial';\n tool: string;\n reason: string;\n}\n\n// Content block types\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock;\n\nexport interface TextBlock {\n type: 'text';\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string | Array<{ type: string; [key: string]: any }>;\n is_error?: boolean;\n}\n\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n}\n\n// Tool definition types\nexport interface SdkMcpToolDefinition {\n name: string;\n description: string;\n inputSchema: Schema;\n handler: (args: any, extra?: any) => Promise;\n}\n\nexport interface CallToolResult {\n content: Array<{\n type: 'text' | 'image' | 'resource';\n text?: string;\n data?: string;\n mimeType?: string;\n [key: string]: any;\n }>;\n isError?: boolean;\n}\n\nexport interface McpSdkServerConfigWithInstance {\n name: string;\n version?: string;\n tools?: Array>;\n}\n\n// AG-UI Integration types\nexport type ProcessedEvents =\n | TextMessageStartEvent\n | TextMessageContentEvent\n | TextMessageEndEvent\n | ToolCallStartEvent\n | ToolCallArgsEvent\n | ToolCallEndEvent\n | ToolCallResultEvent\n | RunStartedEvent\n | RunFinishedEvent\n | RunErrorEvent\n | StepStartedEvent\n | StepFinishedEvent;\n\n// Session management types\nexport interface Session {\n id: string;\n userId?: string;\n client?: ClaudeSDKClient;\n processedMessageIds: Set;\n state: Record;\n createdAt: number;\n lastAccessedAt: number;\n}\n\n// Agent configuration\nexport interface ClaudeAgentConfig extends AgentConfig {\n apiKey?: string;\n baseUrl?: string;\n sessionTimeout?: number;\n enablePersistentSessions?: boolean;\n // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan'\n // Legacy values 'ask', 'auto', 'none' are mapped internally for backward compatibility\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none';\n mcpServers?: Record;\n stderr?: (data: string) => void;\n verbose?: boolean;\n}\n\n// Execution state types\nexport interface ExecutionState {\n id: string;\n sessionId: string;\n isRunning: boolean;\n startTime: number;\n events: ProcessedEvents[];\n error?: Error;\n}\n\n// Helper type guards\nexport function isAssistantMessage(message: SDKMessage): message is SDKAssistantMessage {\n return message.type === 'assistant';\n}\n\nexport function isResultMessage(message: SDKMessage): message is SDKResultMessage {\n return message.type === 'result';\n}\n\nexport function isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === 'text';\n}\n\nexport function isToolUseBlock(block: ContentBlock): block is ToolUseBlock {\n return block.type === 'tool_use';\n}\n\nexport function isToolResultBlock(block: ContentBlock): block is ToolResultBlock {\n return block.type === 'tool_result';\n}\n\nexport function isThinkingBlock(block: ContentBlock): block is ThinkingBlock {\n return block.type === 'thinking';\n}\n\nexport function hasContentProperty(message: SDKMessage): message is SDKAssistantMessage | SDKPartialAssistantMessage {\n // For SDKAssistantMessage, content is in message.content\n if (message.type === 'assistant') {\n return 'message' in message && \n message.message !== null &&\n typeof message.message === 'object' &&\n 'content' in message.message && \n Array.isArray((message.message as any).content);\n }\n // For SDKPartialAssistantMessage, content might be at top level\n return 'content' in message && Array.isArray((message as any).content);\n}\n\n// Tool execution types\nexport interface ToolExecutionContext {\n toolName: string;\n toolCallId: string;\n isClientTool: boolean;\n isLongRunning: boolean;\n}\n\n// Message conversion types\nexport interface ConvertedMessage {\n role: 'user' | 'assistant' | 'system';\n content: string | Array<{ type: string; [key: string]: any }>;\n}\n\n","/**\n * Tool adapter: Converts AG-UI tools to Claude SDK format\n */\n\nimport { z } from 'zod';\nimport type { Tool } from '@ag-ui/client';\nimport type {\n SdkMcpToolDefinition,\n McpSdkServerConfigWithInstance,\n CallToolResult,\n} from './types';\n\n// Extended Tool type that includes runtime properties\ntype ExtendedTool = Tool & {\n client?: boolean;\n handler?: (args: any) => any | Promise;\n longRunning?: boolean;\n};\n\n/**\n * ToolAdapter handles conversion of AG-UI tools to Claude SDK format\n */\nexport class ToolAdapter {\n /**\n * Convert AG-UI tools to Claude SDK MCP tool definitions\n */\n static convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[] {\n return tools.map((tool) => this.convertSingleTool(tool as ExtendedTool));\n }\n\n /**\n * Convert a single AG-UI tool to Claude SDK format\n */\n private static convertSingleTool(tool: ExtendedTool): SdkMcpToolDefinition {\n const zodSchema = this.convertJsonSchemaToZod(tool.parameters || {});\n\n return {\n name: tool.name,\n description: tool.description || '',\n inputSchema: zodSchema,\n handler: async (args: any) => {\n // For client tools, we mark them as long-running\n // The actual execution will be handled by the client\n if (tool.client) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n toolName: tool.name,\n args,\n isClientTool: true,\n isLongRunning: true,\n }),\n },\n ],\n };\n }\n\n // For backend tools, if there's a handler, execute it\n if (tool.handler) {\n try {\n const result = await tool.handler(args);\n return {\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n };\n } catch (error: any) {\n return {\n content: [\n {\n type: 'text',\n text: error.message || 'Tool execution failed',\n },\n ],\n isError: true,\n };\n }\n }\n\n // Default response for tools without handlers\n return {\n content: [\n {\n type: 'text',\n text: 'Tool executed (no handler)',\n },\n ],\n };\n },\n };\n }\n\n /**\n * Convert JSON Schema to Zod schema\n */\n private static convertJsonSchemaToZod(jsonSchema: any): z.ZodTypeAny {\n if (!jsonSchema || typeof jsonSchema !== 'object') {\n return z.object({});\n }\n\n const properties = jsonSchema.properties || {};\n const required = jsonSchema.required || [];\n\n const zodShape: Record = {};\n\n for (const [key, prop] of Object.entries(properties)) {\n const propSchema = prop as any;\n let zodType = this.convertJsonSchemaTypeToZod(propSchema);\n\n // Make optional if not in required array\n if (!required.includes(key)) {\n zodType = zodType.optional();\n }\n\n zodShape[key] = zodType;\n }\n\n return z.object(zodShape);\n }\n\n /**\n * Convert a single JSON Schema type to Zod type\n */\n private static convertJsonSchemaTypeToZod(schema: any): z.ZodTypeAny {\n const type = schema.type;\n\n switch (type) {\n case 'string':\n if (schema.enum) {\n return z.enum(schema.enum as [string, ...string[]]);\n }\n return z.string();\n\n case 'number':\n case 'integer':\n let numType = type === 'integer' ? z.number().int() : z.number();\n if (schema.minimum !== undefined) {\n numType = numType.min(schema.minimum);\n }\n if (schema.maximum !== undefined) {\n numType = numType.max(schema.maximum);\n }\n return numType;\n\n case 'boolean':\n return z.boolean();\n\n case 'array':\n if (schema.items) {\n const itemType = this.convertJsonSchemaTypeToZod(schema.items);\n return z.array(itemType);\n }\n return z.array(z.any());\n\n case 'object':\n if (schema.properties) {\n return this.convertJsonSchemaToZod(schema);\n }\n return z.record(z.any());\n\n case 'null':\n return z.null();\n\n default:\n // For any other type or if type is not specified\n return z.any();\n }\n }\n\n /**\n * Create an MCP server configuration for AG-UI tools\n */\n static async createMcpServerForTools(tools: Tool[]): Promise {\n const sdkTools = this.convertAgUiToolsToSdk(tools as ExtendedTool[]);\n\n // Import createSdkMcpServer from Claude Agent SDK\n const { createSdkMcpServer } = await import('@anthropic-ai/claude-agent-sdk');\n \n // Use the official SDK function to create a properly formatted MCP server\n return createSdkMcpServer({\n name: 'ag_ui_tools',\n version: '1.0.0',\n tools: sdkTools as any, // Cast to any to avoid type incompatibility\n });\n }\n\n /**\n * Extract tool calls from Claude SDK response\n */\n static extractToolCalls(message: any): Array<{\n id: string;\n name: string;\n input: Record;\n }> {\n if (!message.content || !Array.isArray(message.content)) {\n return [];\n }\n\n return message.content\n .filter((block: any) => block.type === 'tool_use')\n .map((block: any) => ({\n id: block.id,\n name: block.name,\n input: block.input,\n }));\n }\n\n /**\n * Check if a tool is a long-running client tool\n */\n static isClientTool(toolName: string, tools: Tool[]): boolean {\n const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined;\n return tool?.client === true;\n }\n\n /**\n * Check if a tool is marked as long-running\n */\n static isLongRunningTool(toolName: string, tools: Tool[]): boolean {\n const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined;\n return tool?.client === true || tool?.longRunning === true;\n }\n\n /**\n * Format tool names for Claude SDK (with MCP server prefix)\n */\n static formatToolNameForSdk(toolName: string, serverName: string = 'ag_ui_tools'): string {\n return `mcp__${serverName}__${toolName}`;\n }\n\n /**\n * Parse tool name from SDK format (remove MCP server prefix)\n */\n static parseToolNameFromSdk(sdkToolName: string): string {\n const parts = sdkToolName.split('__');\n if (parts.length >= 3 && parts[0] === 'mcp') {\n return parts.slice(2).join('__');\n }\n return sdkToolName;\n }\n\n /**\n * Get allowed tools list for SDK options\n */\n static getAllowedToolsList(tools: Tool[], serverName: string = 'ag_ui_tools'): string[] {\n return tools.map((tool) => this.formatToolNameForSdk(tool.name, serverName));\n }\n}\n\n","/**\n * Execution state: Tracks background Claude executions\n */\n\nimport type { ProcessedEvents } from './types';\n\n/**\n * ExecutionState manages the state of a Claude SDK execution\n */\nexport class ExecutionState {\n readonly id: string;\n readonly sessionId: string;\n private _isRunning: boolean;\n private _startTime: number;\n private _endTime?: number;\n private _events: ProcessedEvents[];\n private _error?: Error;\n private _abortController: AbortController;\n\n constructor(id: string, sessionId: string) {\n this.id = id;\n this.sessionId = sessionId;\n this._isRunning = true;\n this._startTime = Date.now();\n this._events = [];\n this._abortController = new AbortController();\n }\n\n /**\n * Check if execution is running\n */\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n /**\n * Get start time\n */\n get startTime(): number {\n return this._startTime;\n }\n\n /**\n * Get end time\n */\n get endTime(): number | undefined {\n return this._endTime;\n }\n\n /**\n * Get duration in milliseconds\n */\n get duration(): number {\n const end = this._endTime || Date.now();\n return end - this._startTime;\n }\n\n /**\n * Get all collected events\n */\n get events(): ProcessedEvents[] {\n return [...this._events];\n }\n\n /**\n * Get error if any\n */\n get error(): Error | undefined {\n return this._error;\n }\n\n /**\n * Get abort signal\n */\n get signal(): AbortSignal {\n return this._abortController.signal;\n }\n\n /**\n * Add an event to the execution state\n */\n addEvent(event: ProcessedEvents): void {\n this._events.push(event);\n }\n\n /**\n * Add multiple events\n */\n addEvents(events: ProcessedEvents[]): void {\n this._events.push(...events);\n }\n\n /**\n * Mark execution as completed\n */\n complete(): void {\n if (this._isRunning) {\n this._isRunning = false;\n this._endTime = Date.now();\n }\n }\n\n /**\n * Mark execution as failed\n */\n fail(error: Error): void {\n if (this._isRunning) {\n this._isRunning = false;\n this._endTime = Date.now();\n this._error = error;\n }\n }\n\n /**\n * Abort the execution\n */\n abort(): void {\n if (this._isRunning) {\n this._abortController.abort();\n this._isRunning = false;\n this._endTime = Date.now();\n }\n }\n\n /**\n * Get execution statistics\n */\n getStats(): {\n duration: number;\n eventCount: number;\n isRunning: boolean;\n hasError: boolean;\n } {\n return {\n duration: this.duration,\n eventCount: this._events.length,\n isRunning: this._isRunning,\n hasError: !!this._error,\n };\n }\n\n /**\n * Clear events (useful for memory management)\n */\n clearEvents(): void {\n this._events = [];\n }\n\n /**\n * Get the last N events\n */\n getLastEvents(count: number): ProcessedEvents[] {\n return this._events.slice(-count);\n }\n\n /**\n * Check if execution has been aborted\n */\n isAborted(): boolean {\n return this._abortController.signal.aborted;\n }\n}\n\n/**\n * ExecutionStateManager manages multiple execution states\n */\nexport class ExecutionStateManager {\n private executions: Map = new Map();\n private readonly maxExecutions: number;\n\n constructor(maxExecutions: number = 100) {\n this.maxExecutions = maxExecutions;\n }\n\n /**\n * Create a new execution state\n */\n createExecution(id: string, sessionId: string): ExecutionState {\n const execution = new ExecutionState(id, sessionId);\n this.executions.set(id, execution);\n\n // Clean up old executions if we exceed the limit\n if (this.executions.size > this.maxExecutions) {\n this.cleanupOldExecutions();\n }\n\n return execution;\n }\n\n /**\n * Get an execution state by ID\n */\n getExecution(id: string): ExecutionState | undefined {\n return this.executions.get(id);\n }\n\n /**\n * Check if an execution exists\n */\n hasExecution(id: string): boolean {\n return this.executions.has(id);\n }\n\n /**\n * Delete an execution state\n */\n deleteExecution(id: string): boolean {\n return this.executions.delete(id);\n }\n\n /**\n * Get all executions for a session\n */\n getSessionExecutions(sessionId: string): ExecutionState[] {\n const executions: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (execution.sessionId === sessionId) {\n executions.push(execution);\n }\n }\n return executions;\n }\n\n /**\n * Get running executions\n */\n getRunningExecutions(): ExecutionState[] {\n const running: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (execution.isRunning) {\n running.push(execution);\n }\n }\n return running;\n }\n\n /**\n * Get completed executions\n */\n getCompletedExecutions(): ExecutionState[] {\n const completed: ExecutionState[] = [];\n for (const execution of this.executions.values()) {\n if (!execution.isRunning) {\n completed.push(execution);\n }\n }\n return completed;\n }\n\n /**\n * Abort all running executions for a session\n */\n abortSessionExecutions(sessionId: string): void {\n const sessionExecutions = this.getSessionExecutions(sessionId);\n for (const execution of sessionExecutions) {\n if (execution.isRunning) {\n execution.abort();\n }\n }\n }\n\n /**\n * Clean up old completed executions\n */\n private cleanupOldExecutions(): void {\n const completed = this.getCompletedExecutions();\n \n // Sort by end time (oldest first)\n completed.sort((a, b) => {\n const aTime = a.endTime || a.startTime;\n const bTime = b.endTime || b.startTime;\n return aTime - bTime;\n });\n\n // Remove the oldest executions\n const toRemove = Math.max(0, this.executions.size - this.maxExecutions);\n for (let i = 0; i < toRemove && i < completed.length; i++) {\n this.executions.delete(completed[i].id);\n }\n }\n\n /**\n * Clear all executions\n */\n clearAll(): void {\n this.executions.clear();\n }\n\n /**\n * Get total execution count\n */\n getExecutionCount(): number {\n return this.executions.size;\n }\n\n /**\n * Get execution statistics\n */\n getStats(): {\n total: number;\n running: number;\n completed: number;\n failed: number;\n } {\n let running = 0;\n let completed = 0;\n let failed = 0;\n\n for (const execution of this.executions.values()) {\n if (execution.isRunning) {\n running++;\n } else if (execution.error) {\n failed++;\n } else {\n completed++;\n }\n }\n\n return {\n total: this.executions.size,\n running,\n completed,\n failed,\n };\n }\n}\n\n","/**\n * Message format converters\n */\n\nimport type { Message } from '@ag-ui/client';\nimport type { ConvertedMessage } from '../types';\n\n/**\n * Convert AG-UI messages to a format suitable for Claude SDK\n */\nexport function convertAgUiMessagesToPrompt(messages: Message[]): string {\n // For Claude SDK, we typically extract the last user message as the prompt\n // The SDK maintains conversation history internally (in persistent mode)\n \n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'user') {\n return extractMessageContent(msg);\n }\n }\n\n // If no user message found, return a default prompt\n return 'Hello';\n}\n\n/**\n * Extract text content from a message\n */\nexport function extractMessageContent(message: Message): string {\n if (typeof message.content === 'string') {\n return message.content;\n }\n\n if (Array.isArray(message.content)) {\n return message.content\n .map((block: any) => {\n if (typeof block === 'string') {\n return block;\n }\n if (block.type === 'text') {\n return block.text || '';\n }\n // For other types (image, file, etc.), we might need special handling\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n }\n\n return String(message.content);\n}\n\n/**\n * Convert AG-UI message to Claude message format\n */\nexport function convertAgUiMessageToClaude(message: Message): ConvertedMessage {\n const role = message.role as 'user' | 'assistant' | 'system';\n const content = extractMessageContent(message);\n\n return {\n role,\n content,\n };\n}\n\n/**\n * Convert multiple AG-UI messages to Claude format\n */\nexport function convertAgUiMessagesToClaude(messages: Message[]): ConvertedMessage[] {\n return messages.map(convertAgUiMessageToClaude);\n}\n\n/**\n * Check if messages contain tool results\n */\nexport function hasToolResults(messages: Message[]): boolean {\n return messages.some((msg) => {\n if (typeof msg.content === 'string') {\n return false;\n }\n if (Array.isArray(msg.content)) {\n return msg.content.some((block: any) => {\n return typeof block === 'object' && block.type === 'tool_result';\n });\n }\n return false;\n });\n}\n\n/**\n * Extract tool results from messages\n */\nexport function extractToolResults(messages: Message[]): Array<{\n toolCallId: string;\n result: string;\n}> {\n const results: Array<{ toolCallId: string; result: string }> = [];\n\n for (const msg of messages) {\n if (typeof msg.content === 'string') {\n continue;\n }\n\n if (Array.isArray(msg.content)) {\n for (const block of msg.content as any[]) {\n if (typeof block === 'object' && block.type === 'tool_result') {\n results.push({\n toolCallId: (block as any).toolCallId || (block as any).tool_use_id || '',\n result: (block as any).result || (block as any).content || '',\n });\n }\n }\n }\n }\n\n return results;\n}\n\n/**\n * Generate a unique run ID\n */\nexport function generateRunId(): string {\n return `run_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(prefix: string = 'msg'): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n}\n\n/**\n * Safely parse JSON string\n */\nexport function safeJsonParse(json: string, defaultValue: any = null): any {\n try {\n return JSON.parse(json);\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Safely stringify JSON\n */\nexport function safeJsonStringify(obj: any, defaultValue: string = '{}'): string {\n try {\n return JSON.stringify(obj);\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Check if a message is a tool result submission\n */\nexport function isToolResultSubmission(messages: Message[]): boolean {\n // Check if the last message contains tool results\n if (messages.length === 0) {\n return false;\n }\n\n const lastMessage = messages[messages.length - 1];\n return hasToolResults([lastMessage]);\n}\n\n/**\n * Format error message for display\n */\nexport function formatErrorMessage(error: any): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'string') {\n return error;\n }\n return 'An unknown error occurred';\n}\n\n/**\n * Truncate text to a maximum length\n */\nexport function truncateText(text: string, maxLength: number = 1000): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength) + '...';\n}\n\n/**\n * Merge consecutive text blocks\n */\nexport function mergeTextBlocks(blocks: Array<{ type: string; text?: string }>): string {\n return blocks\n .filter((block: any) => block.type === 'text' && block.text)\n .map((block: any) => block.text)\n .join('');\n}\n\n"],"mappings":"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","names":["EventType","EventType","error"]} \ No newline at end of file diff --git a/integrations/claude-agent-sdk/typescript/examples/.env.local.example b/integrations/claude-agent-sdk/typescript/examples/.env.local.example new file mode 100644 index 000000000..e925bb858 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/.env.local.example @@ -0,0 +1,10 @@ +# Claude Agent SDK Integration - Environment Variables +# Copy this file to .env.local and fill in your actual values + +# Anthropic API Key (required for real API tests) +# Get your API key from: https://console.anthropic.com/ +# ANTHROPIC_API_KEY=your-anthropic-api-key-here + +# Optional for third party service +# ANTHROPIC_AUTH_TOKEN=third-party-auth-token +# ANTHROPIC_BASE_URL=third-party-base-url diff --git a/integrations/claude-agent-sdk/typescript/examples/.gitignore b/integrations/claude-agent-sdk/typescript/examples/.gitignore new file mode 100644 index 000000000..32319dd4a --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/.gitignore @@ -0,0 +1,31 @@ +# Environment files +.env +.env.local +.env*.local + +# Dependencies +node_modules/ + +# Build output +dist/ +build/ + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* + +# OS +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + diff --git a/integrations/claude-agent-sdk/typescript/examples/README.md b/integrations/claude-agent-sdk/typescript/examples/README.md new file mode 100644 index 000000000..9a6b3b01f --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/README.md @@ -0,0 +1,142 @@ +# Claude Agent SDK Example + +This example demonstrates how to use the Claude Agent SDK with Express.js to create an AI agent server that follows the AG-UI Protocol. + +## Setup + +### 1. Configure Environment Variables + +Copy the environment variable template file and configure it: + +```bash +cd examples +cp env.example .env.local +``` + +Edit the `.env.local` file and set the required environment variables: + +```bash +# Required: Claude API key +ANTHROPIC_API_KEY=your_api_key_here + +# Optional configuration +PORT=3000 # Server port +APP_NAME=claude-example # Application name +SYSTEM_PROMPT=You are a helpful assistant # System prompt +ENABLE_PERSISTENT_SESSIONS=true # Enable persistent sessions +SESSION_TIMEOUT=1800000 # Session timeout (milliseconds) +PERMISSION_MODE=ask # Permission mode: ask, auto, none +``` + +### 2. Install Dependencies + +```bash +pnpm install +``` + +### 3. Run the Server + +```bash +pnpm dev +``` + +The server will start at `http://localhost:3000`. + +## API Endpoints + +### POST /api/run-agent + +Run the agent with a simple conversation. + +**Request:** + +```json +{ + "agentId": "my_agent", + "threadId": "thread_123", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "Hello, how are you?" + } + ], + "context": {} +} +``` + +**Response:** Server-Sent Events (SSE) stream with AG-UI protocol events. + +### POST /api/run-agent-with-tools + +Run the agent with predefined tools (calculator and weather). + +**Request:** + +```json +{ + "agentId": "my_agent", + "threadId": "thread_123", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "What is 42 + 58?" + } + ], + "context": {} +} +``` + +### POST /api/cleanup + +Cleanup all sessions and resources. + +## Example Usage with curl + +```bash +# Simple conversation +curl -X POST http://localhost:3000/api/run-agent \ + -H "Content-Type: application/json" \ + -d '{ + "agentId": "test_agent", + "messages": [ + {"id": "msg_1", "role": "user", "content": "Hello!"} + ], + "context": {} + }' + +# With tools +curl -X POST http://localhost:3000/api/run-agent-with-tools \ + -H "Content-Type: application/json" \ + -d '{ + "agentId": "test_agent", + "messages": [ + {"id": "msg_1", "role": "user", "content": "Calculate 15 + 27"} + ], + "context": {} + }' +``` + +## Features Demonstrated + +- **Server-Sent Events (SSE)**: Real-time streaming of agent responses +- **Persistent Sessions**: Maintains conversation context across requests +- **Tool Integration**: Example tools (calculator, weather) +- **Error Handling**: Graceful error handling and reporting +- **Graceful Shutdown**: Clean resource cleanup on server stop + +## Event Types + +The agent emits the following AG-UI protocol events: + +- `run_started`: Execution started +- `text_message_start`: Text message begins +- `text_message_content`: Streaming text content +- `text_message_end`: Text message complete +- `tool_call_start`: Tool call begins +- `tool_call_args`: Tool arguments +- `tool_call_end`: Tool call complete +- `tool_call_result`: Tool execution result +- `run_finished`: Execution complete +- `run_error`: Error occurred diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/.gitignore b/integrations/claude-agent-sdk/typescript/examples/copilotkit/.gitignore new file mode 100644 index 000000000..1403e903b --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/README.md b/integrations/claude-agent-sdk/typescript/examples/copilotkit/README.md new file mode 100644 index 000000000..b196ab54a --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/README.md @@ -0,0 +1,131 @@ +# CopilotKit + Claude Agent SDK Integration Demo + +This example demonstrates how to integrate Claude Agent SDK into CopilotKit using AG-UI Protocol. + +## Architecture Diagram + +``` +┌─────────────────────────────────────┐ +│ CopilotKit Frontend (React/Next.js) │ +│ - CopilotChat UI │ +│ - Frontend Tools │ +└──────────────┬──────────────────────┘ + │ HTTP/SSE + ↓ +┌─────────────────────────────────────┐ +│ CopilotKit Runtime (Next.js API) │ +│ - HttpAgent (@ag-ui/client) │ +│ - CopilotRuntime │ +└──────────────┬──────────────────────┘ + │ AG-UI Protocol + ↓ +┌─────────────────────────────────────┐ +│ Claude Agent SDK Server (FastAPI) │ +│ - AG-UI Protocol Endpoint │ +│ - ClaudeAgent │ +└──────────────┬──────────────────────┘ + │ + ↓ +┌─────────────────────────────────────┐ +│ Claude Agent SDK (Python) │ +│ - ClaudeSDKClient │ +│ - Multi-turn Conversations │ +└─────────────────────────────────────┘ +``` + +## Quick Start + +### 1. Start Claude Agent SDK Server + +In one terminal: + +```bash +cd ../../python/examples/server +python fastapi_server.py +``` + +The server will run at `http://localhost:8000/chat`. + +### 2. Install and Start CopilotKit Frontend + +In another terminal: + +```bash +cd integrations/claude-agent-sdk/typescript/examples/copilotkit +npm install +npm run dev +``` + +The frontend will run at `http://localhost:3000`. + +### 3. Open Browser + +Visit `http://localhost:3000` to see the CopilotKit chat interface. + +## Features + +- ✅ **Persistent Conversations**: Uses `ClaudeSDKClient` to maintain conversation history +- ✅ **Tool Support**: Claude can call frontend tools +- ✅ **Streaming Responses**: Real-time streaming via Server-Sent Events +- ✅ **Session Management**: Persistent sessions across multiple requests +- ✅ **Full Features**: Supports interrupts, hooks, custom tools (when using `ClaudeSDKClient`) + +## Directory Structure + +``` +copilotkit/ +├── src/ +│ └── app/ +│ ├── api/ +│ │ └── copilotkit/ +│ │ └── route.ts # CopilotKit runtime endpoint +│ ├── layout.tsx # Next.js layout +│ ├── page.tsx # Frontend chat interface +│ └── globals.css # Global styles +├── package.json # Dependencies configuration +├── tsconfig.json # TypeScript configuration +├── next.config.js # Next.js configuration +├── tailwind.config.js # Tailwind CSS configuration +├── postcss.config.js # PostCSS configuration +└── README.md # Detailed documentation +``` + +## How It Works + +### 1. Frontend (React + CopilotKit) + +`src/app/page.tsx` uses CopilotKit React components: +- `CopilotKit`: Wraps the app and connects to runtime +- `CopilotChat`: Provides chat UI +- `useFrontendTool`: Defines frontend tools that Claude can call + +### 2. API Route (Next.js) + +`src/app/api/copilotkit/route.ts`: +- Creates `HttpAgent` (from `@ag-ui/client`) pointing to Claude Agent SDK server +- Wraps it in `CopilotRuntime` +- Exposes POST endpoint that CopilotKit calls + +### 3. Backend (Claude Agent SDK) + +Claude Agent SDK server (`../../python/examples/server/fastapi_server.py`): +- Handles AG-UI Protocol requests +- Converts them to Claude Agent SDK calls +- Returns AG-UI Protocol events +- Supports CORS for frontend integration + +## Environment Variables + +- `CLAUDE_AGENT_URL`: URL of Claude Agent SDK server (default: `http://localhost:8000/chat`) + +## Troubleshooting + +1. **Connection Error**: Ensure Claude Agent SDK server is running on the correct port +2. **CORS Issues**: FastAPI server includes CORS middleware. Edit `fastapi_server.py` if you need to add more origins +3. **Agent Not Found**: Check if the agent ID (`agentic_chat`) in the frontend matches the one in the API route + +## References + +- [CopilotKit Documentation](https://docs.copilotkit.ai/adk/quickstart?path=exiting-agent) +- [AG-UI Protocol Documentation](https://ag-ui-protocol.github.io/ag-ui/) +- [Claude Agent SDK Documentation](https://docs.claude.com/api/agent-sdk/python) diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/next.config.js b/integrations/claude-agent-sdk/typescript/examples/copilotkit/next.config.js new file mode 100644 index 000000000..3776bb093 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/next.config.js @@ -0,0 +1,7 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, +}; + +module.exports = nextConfig; + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/package-lock.json b/integrations/claude-agent-sdk/typescript/examples/copilotkit/package-lock.json new file mode 100644 index 000000000..9b6f59ca3 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/package-lock.json @@ -0,0 +1,12917 @@ +{ + "name": "claude-agent-sdk-copilotkit-demo", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "claude-agent-sdk-copilotkit-demo", + "version": "0.1.0", + "dependencies": { + "@ag-ui/client": "^0.0.40", + "@copilotkit/react-core": "^1.10.6", + "@copilotkit/react-ui": "^1.10.6", + "@copilotkit/runtime": "^1.10.6", + "next": "^14.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32", + "tailwindcss": "^3.4.0", + "typescript": "^5.0.0" + } + }, + "node_modules/@0no-co/graphql.web": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz", + "integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==", + "license": "MIT", + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "graphql": { + "optional": true + } + } + }, + "node_modules/@ag-ui/client": { + "version": "0.0.40", + "resolved": "https://registry.npmmirror.com/@ag-ui/client/-/client-0.0.40.tgz", + "integrity": "sha512-4ftyZgMN7DIAX64k7Mdex/KGq7lfz8yxEKzniqosD6TE/xk65k4Z0v3bxTzPk2iS2+Cj2uVBgFkb5lC7k5Loqg==", + "dependencies": { + "@ag-ui/core": "0.0.39", + "@ag-ui/encoder": "0.0.39", + "@ag-ui/proto": "0.0.39", + "@types/uuid": "^10.0.0", + "fast-json-patch": "^3.1.1", + "rxjs": "7.8.1", + "untruncate-json": "^0.0.1", + "uuid": "^11.1.0", + "zod": "^3.22.4" + } + }, + "node_modules/@ag-ui/core": { + "version": "0.0.39", + "resolved": "https://registry.npmmirror.com/@ag-ui/core/-/core-0.0.39.tgz", + "integrity": "sha512-T5Hp4oFkQ+H5MynWAvSwrX/rNYJOD+PJ4qPQ0o771oSZQAxoIvDDft47Cx5wRyBNNLXAe1RWqJjfWUUwJFNKqA==", + "dependencies": { + "rxjs": "7.8.1", + "zod": "^3.22.4" + } + }, + "node_modules/@ag-ui/encoder": { + "version": "0.0.39", + "resolved": "https://registry.npmmirror.com/@ag-ui/encoder/-/encoder-0.0.39.tgz", + "integrity": "sha512-6fsoFwPWkStK7Uyj3pwBn7+aQjUWf7pbDTSI43cD53sBLvTr5oEFNnoKOzRfC5UqvHc4JjUIuLKPQyjHRwWg4g==", + "dependencies": { + "@ag-ui/core": "0.0.39", + "@ag-ui/proto": "0.0.39" + } + }, + "node_modules/@ag-ui/langgraph": { + "version": "0.0.18", + "resolved": "https://registry.npmmirror.com/@ag-ui/langgraph/-/langgraph-0.0.18.tgz", + "integrity": "sha512-soWSV8+xR91jMArZUJoRv85UCgTi3Zt3u3gTMZhvs1t6fGFpAi6+hEQ4AqP13Rgvg90IlmIU8MTWo2k0OZDnoA==", + "peer": true, + "dependencies": { + "@langchain/core": "^0.3.66", + "@langchain/langgraph-sdk": "^0.1.2", + "partial-json": "^0.1.7", + "rxjs": "7.8.1" + }, + "peerDependencies": { + "@ag-ui/client": ">=0.0.38", + "@ag-ui/core": ">=0.0.38" + } + }, + "node_modules/@ag-ui/proto": { + "version": "0.0.39", + "resolved": "https://registry.npmmirror.com/@ag-ui/proto/-/proto-0.0.39.tgz", + "integrity": "sha512-xlj/PzZHkJ3CgoQC5QP9g7DEl/78wUK1+A2rdkoLKoNAMOkM2g6jKw0N88iFIh5GZhtiCNN2wb8XwRWPYx9XQQ==", + "dependencies": { + "@ag-ui/core": "0.0.39", + "@bufbuild/protobuf": "^2.2.5", + "@protobuf-ts/protoc": "^2.11.1" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.57.0", + "resolved": "https://registry.npmmirror.com/@anthropic-ai/sdk/-/sdk-0.57.0.tgz", + "integrity": "sha512-z5LMy0MWu0+w2hflUgj4RlJr1R+0BxKXL7ldXTO8FasU8fu599STghO+QKwId2dAD0d464aHtU+ChWuRHw4FNw==", + "license": "MIT", + "bin": { + "anthropic-ai-sdk": "bin/cli" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD", + "optional": true, + "peer": true + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-bedrock-agent-runtime/-/client-bedrock-agent-runtime-3.921.0.tgz", + "integrity": "sha512-nK97vLzXZoLZLfJKq19F0Y35a5YMHNst3AlAo3KMfsRDbe3uctsgjv0Xtib/PuED4x8mcy2RpmqvzmHTFry5TA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/credential-provider-node": "3.921.0", + "@aws-sdk/middleware-host-header": "3.921.0", + "@aws-sdk/middleware-logger": "3.921.0", + "@aws-sdk/middleware-recursion-detection": "3.921.0", + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/region-config-resolver": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@aws-sdk/util-user-agent-browser": "3.921.0", + "@aws-sdk/util-user-agent-node": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/core": "^3.17.2", + "@smithy/eventstream-serde-browser": "^4.2.4", + "@smithy/eventstream-serde-config-resolver": "^4.3.4", + "@smithy/eventstream-serde-node": "^4.2.4", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/hash-node": "^4.2.4", + "@smithy/invalid-dependency": "^4.2.4", + "@smithy/middleware-content-length": "^4.2.4", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-retry": "^4.4.6", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.5", + "@smithy/util-defaults-mode-node": "^4.2.7", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.921.0.tgz", + "integrity": "sha512-FWOcHJj2li0TvGYYFLxJBVrz/dpInWHk+d1gonEG+YAiG1TPS5bxOQVQPj6o4IclwwaFM3MTzzHw4BMlwTc5NQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/credential-provider-node": "3.921.0", + "@aws-sdk/eventstream-handler-node": "3.921.0", + "@aws-sdk/middleware-eventstream": "3.921.0", + "@aws-sdk/middleware-host-header": "3.921.0", + "@aws-sdk/middleware-logger": "3.921.0", + "@aws-sdk/middleware-recursion-detection": "3.921.0", + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/middleware-websocket": "3.921.0", + "@aws-sdk/region-config-resolver": "3.921.0", + "@aws-sdk/token-providers": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@aws-sdk/util-user-agent-browser": "3.921.0", + "@aws-sdk/util-user-agent-node": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/core": "^3.17.2", + "@smithy/eventstream-serde-browser": "^4.2.4", + "@smithy/eventstream-serde-config-resolver": "^4.3.4", + "@smithy/eventstream-serde-node": "^4.2.4", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/hash-node": "^4.2.4", + "@smithy/invalid-dependency": "^4.2.4", + "@smithy/middleware-content-length": "^4.2.4", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-retry": "^4.4.6", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.5", + "@smithy/util-defaults-mode-node": "^4.2.7", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/util-stream": "^4.5.5", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kendra": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-kendra/-/client-kendra-3.921.0.tgz", + "integrity": "sha512-/8D1OneFcZy6Dtylyg2vT9u6vd2lSH/cxZl3+Fq646I3xnGoHzKWrGEb5FWxafpSNYlYuuavFGZQHhWnhJW5cw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/credential-provider-node": "3.921.0", + "@aws-sdk/middleware-host-header": "3.921.0", + "@aws-sdk/middleware-logger": "3.921.0", + "@aws-sdk/middleware-recursion-detection": "3.921.0", + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/region-config-resolver": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@aws-sdk/util-user-agent-browser": "3.921.0", + "@aws-sdk/util-user-agent-node": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/core": "^3.17.2", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/hash-node": "^4.2.4", + "@smithy/invalid-dependency": "^4.2.4", + "@smithy/middleware-content-length": "^4.2.4", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-retry": "^4.4.6", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.5", + "@smithy/util-defaults-mode-node": "^4.2.7", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-kendra/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/client-sso/-/client-sso-3.921.0.tgz", + "integrity": "sha512-qWyT7WikdkPRAMuWidZ2l8jcQAPwNjvLcFZ/8K+oCAaMLt0LKLd7qeTwZ5tZFNqRNPXKfE8MkvAjyqSpE3i2yg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/middleware-host-header": "3.921.0", + "@aws-sdk/middleware-logger": "3.921.0", + "@aws-sdk/middleware-recursion-detection": "3.921.0", + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/region-config-resolver": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@aws-sdk/util-user-agent-browser": "3.921.0", + "@aws-sdk/util-user-agent-node": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/core": "^3.17.2", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/hash-node": "^4.2.4", + "@smithy/invalid-dependency": "^4.2.4", + "@smithy/middleware-content-length": "^4.2.4", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-retry": "^4.4.6", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.5", + "@smithy/util-defaults-mode-node": "^4.2.7", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/core/-/core-3.921.0.tgz", + "integrity": "sha512-1eiD9ZO9cvEHdQUn/pwJVGN9LXg6D0O7knGVA0TA/v7nFSYy0n8RYG8vdnlcoYYnV1BcHgaf4KmRVMOszafNZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@aws-sdk/xml-builder": "3.921.0", + "@smithy/core": "^3.17.2", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/signature-v4": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/signature-v4": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/signature-v4/-/signature-v4-5.3.4.tgz", + "integrity": "sha512-ScDCpasxH7w1HXHYbtk3jcivjvdA1VICyAdgvVqKhKKwxi+MTwZEqFw0minE+oZ7F07oF25xh4FGJxgqgShz0A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.921.0.tgz", + "integrity": "sha512-RGG+zZdOYGJBQ8+L7BI6v41opoF8knErMtBZAUGcD3gvWEhjatc7lSbIpBeYWbTaWPPLHQU+ZVbmQ/jRLBgefw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/property-provider": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.921.0.tgz", + "integrity": "sha512-TAv08Ow0oF/olV4DTLoPDj46KMk35bL1IUCfToESDrWk1TOSur7d4sCL0p/7dUsAxS244cEgeyIIijKNtxj2AA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/util-stream": "^4.5.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.921.0.tgz", + "integrity": "sha512-MUSRYGiMRq5NRGPRgJ7Nuh7GqXzE9iteAwdbzMJ4pnImgr7CjeWDihCIGk+gKLSG+NoRVVJM0V9PA4rxFir0Pg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/credential-provider-env": "3.921.0", + "@aws-sdk/credential-provider-http": "3.921.0", + "@aws-sdk/credential-provider-process": "3.921.0", + "@aws-sdk/credential-provider-sso": "3.921.0", + "@aws-sdk/credential-provider-web-identity": "3.921.0", + "@aws-sdk/nested-clients": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/credential-provider-imds": "^4.2.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.921.0.tgz", + "integrity": "sha512-bxUAqRyo49WzKWn/XS0d8QXT9GydY/ew5m58PYfSMwYfmwBZXx1GLSWe3tZnefm6santFiqmIWfMmeRWdygKmQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.921.0", + "@aws-sdk/credential-provider-http": "3.921.0", + "@aws-sdk/credential-provider-ini": "3.921.0", + "@aws-sdk/credential-provider-process": "3.921.0", + "@aws-sdk/credential-provider-sso": "3.921.0", + "@aws-sdk/credential-provider-web-identity": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/credential-provider-imds": "^4.2.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.921.0.tgz", + "integrity": "sha512-DM62ooWI/aZ+ENBcLszuKmOkiICf6p4vYO2HgA3Cy2OEsTsjb67NEcntksxpZkD3mSIrCy/Qi4Z7tc77gle2Nw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.921.0.tgz", + "integrity": "sha512-Nh5jPJ6Y6nu3cHzZnq394lGXE5YO8Szke5zlATbNI7Tl0QJR65GE0IZsBcjzRMGpYX6ENCqPDK8FmklkmCYyVQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.921.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/token-providers": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.921.0.tgz", + "integrity": "sha512-VWcbgB2/shPPK674roHV4s8biCtvn0P/05EbTqy9WeyM5Oblx291gRGccyDhQbJbOL/6diRPBM08tlKPlBKNfw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/nested-clients": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.921.0.tgz", + "integrity": "sha512-wgvhLaUpJv0h9WJFTvIJVmxtCWAeHZhk6VU3HCGwWSOAcBiiGbsFt8bMZ7SE6aAMoLYQQLblxS3yqLSiiw8ZXw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/eventstream-codec": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node/node_modules/@smithy/eventstream-codec": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-codec/-/eventstream-codec-4.2.4.tgz", + "integrity": "sha512-aV8blR9RBDKrOlZVgjOdmOibTC2sBXNiT7WA558b4MPdsLTV6sbyc1WIE9QiIuYMJjYtnPLciefoqSW8Gi+MZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-eventstream": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.921.0.tgz", + "integrity": "sha512-5i+YdW5L4UA/jOhrprtkgJvQTBsI3ltJsua5NMpTcFYQhOXmt//1UizhspruSSH/xF9K/b4TU83fljOX7R4vzw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-eventstream/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.921.0.tgz", + "integrity": "sha512-eX1Ka29XzuEcXG4YABTwyLtPLchjmcjSjaq4irKJTFkxSYzX7gjoKt18rh/ZzOWOSqi23+cpjvBacL4VBKvE2Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-logger/-/middleware-logger-3.921.0.tgz", + "integrity": "sha512-14Qqp8wisKGj/2Y22OfO5jTBG5Xez+p3Zr2piAtz7AcbY8vBEoZbd6f+9lwwVFC73Aobkau223wzKbGT8HYQMw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.921.0.tgz", + "integrity": "sha512-MYU5oI2b97M7u1dC1nt7SiGEvvLrQDlzV6hq9CB5TYX2glgbyvkaS//1Tjm87VF6qVSf5jYfwFDPeFGd8O1NrQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@aws/lambda-invoke-store": "^0.1.1", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.921.0.tgz", + "integrity": "sha512-gXgokMBTPZAbQMm1+JOxItqA81aSFK6n7V2mAwxdmHjzCUZacX5RzkVPNbSaPPgDkroYnIzK09EusIpM6dLaqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@smithy/core": "^3.17.2", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/middleware-websocket/-/middleware-websocket-3.921.0.tgz", + "integrity": "sha512-MjA5JhLSm7umZqy9BiStmDSqxp/9dyleVo2H62y0kYypUZwyIEC0+NbyUzrxTX9QmAM8ZC44fUBvKmikGKyRHA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-format-url": "3.921.0", + "@smithy/eventstream-codec": "^4.2.4", + "@smithy/eventstream-serde-browser": "^4.2.4", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/protocol-http": "^5.3.4", + "@smithy/signature-v4": "^5.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/eventstream-codec": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-codec/-/eventstream-codec-4.2.4.tgz", + "integrity": "sha512-aV8blR9RBDKrOlZVgjOdmOibTC2sBXNiT7WA558b4MPdsLTV6sbyc1WIE9QiIuYMJjYtnPLciefoqSW8Gi+MZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/signature-v4": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/signature-v4/-/signature-v4-5.3.4.tgz", + "integrity": "sha512-ScDCpasxH7w1HXHYbtk3jcivjvdA1VICyAdgvVqKhKKwxi+MTwZEqFw0minE+oZ7F07oF25xh4FGJxgqgShz0A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/nested-clients/-/nested-clients-3.921.0.tgz", + "integrity": "sha512-GV9aV8WqH/EWo4x3T5BrYb2ph1yfYuzUXZc0hhvxbFbDKD8m2fX9menao3Mgm7E5C68Su392u+MD9SGmGCmfKQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.921.0", + "@aws-sdk/middleware-host-header": "3.921.0", + "@aws-sdk/middleware-logger": "3.921.0", + "@aws-sdk/middleware-recursion-detection": "3.921.0", + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/region-config-resolver": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@aws-sdk/util-endpoints": "3.921.0", + "@aws-sdk/util-user-agent-browser": "3.921.0", + "@aws-sdk/util-user-agent-node": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/core": "^3.17.2", + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/hash-node": "^4.2.4", + "@smithy/invalid-dependency": "^4.2.4", + "@smithy/middleware-content-length": "^4.2.4", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-retry": "^4.4.6", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.5", + "@smithy/util-defaults-mode-node": "^4.2.7", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.921.0.tgz", + "integrity": "sha512-cSycw4wXcvsrssUdcEaeYQhQcZYVsBwHtgATh9HcIm01PrMV0lV71vcoyZ+9vUhwHwchRT6dItAyTHSQxwjvjg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/config-resolver": "^4.4.1", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/token-providers/-/token-providers-3.921.0.tgz", + "integrity": "sha512-d+w6X7ykqXirFBF+dYyK5Ntw0KmO2sgMj+JLR/vAe1vaR8/Fuqs3yOAFU7yNEzpcnbLJmMznxKpht03CSEMh4Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.921.0", + "@aws-sdk/nested-clients": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/types/-/types-3.921.0.tgz", + "integrity": "sha512-mqEG8+vFh5w0ZZC+R8VCOdSk998Hy93pIDuwYpfMAWgYwVhFaIMOLn1fZw0w2DhTs5+ONHHwMJ6uVXtuuqOLQQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-endpoints/-/util-endpoints-3.921.0.tgz", + "integrity": "sha512-kuJYRqug6V8gOg401BuK4w4IAVO3575VDR8iYiFw0gPwNIfOXvdlChfsJQoREqwJfif45J4eSmUsFtMfx87BQg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-endpoints": "^3.2.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-format-url/-/util-format-url-3.921.0.tgz", + "integrity": "sha512-ubU5/w/LERnELxgUKGQcVBlbcZaKGnCM9yuNqRuOuQeOKn+O6TLtFLxafrAcO0Ss1vwhoG5LEELFIykjE0soWQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/querystring-builder": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.921.0.tgz", + "integrity": "sha512-buhv/ICWr4Nt8bquHOejCiVikBsfEYw4/HSc9U050QebRXIakt50zKYaWDQw4iCMeeqCiwE9mElEaXJAysythg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.921.0", + "@smithy/types": "^4.8.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.921.0.tgz", + "integrity": "sha512-Ilftai6AMAU1cEaUqIiTxkyj1NupLhP9Eq8HRfVuIH8489J2wLCcOyiLklAgSzBNmrxW+fagxkY+Dg0lFwmcVA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.921.0", + "@aws-sdk/types": "3.921.0", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.921.0", + "resolved": "https://registry.npmmirror.com/@aws-sdk/xml-builder/-/xml-builder-3.921.0.tgz", + "integrity": "sha512-LVHg0jgjyicKKvpNIEMXIMr1EBViESxcPkqfOlT+X1FkmUMTNZEEVF18tOJg4m4hV5vxtkWcqtr4IEeWa1C41Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.1.1.tgz", + "integrity": "sha512-RcLam17LdlbSOSp9VxmUu1eI6Mwxp+OwhD2QhiSNmNCzoDb0EeUXTD2n/WbcnrAYMGlmf05th6QYq23VqvJqpA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@browserbasehq/sdk": { + "version": "2.6.0", + "resolved": "https://registry.npmmirror.com/@browserbasehq/sdk/-/sdk-2.6.0.tgz", + "integrity": "sha512-83iXP5D7xMm8Wyn66TUaUrgoByCmAJuoMoZQI3sGg3JAiMlTfnCIMqyVBoNSaItaPIkaCnrsj6LiusmXV2X9YA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@browserbasehq/sdk/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@browserbasehq/sdk/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT", + "peer": true + }, + "node_modules/@browserbasehq/stagehand": { + "version": "1.14.0", + "resolved": "https://registry.npmmirror.com/@browserbasehq/stagehand/-/stagehand-1.14.0.tgz", + "integrity": "sha512-Hi/EzgMFWz+FKyepxHTrqfTPjpsuBS4zRy3e9sbMpBgLPv+9c0R+YZEvS7Bw4mTS66QtvvURRT6zgDGFotthVQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@anthropic-ai/sdk": "^0.27.3", + "@browserbasehq/sdk": "^2.0.0", + "ws": "^8.18.0", + "zod-to-json-schema": "^3.23.5" + }, + "peerDependencies": { + "@playwright/test": "^1.42.1", + "deepmerge": "^4.3.1", + "dotenv": "^16.4.5", + "openai": "^4.62.1", + "zod": "^3.23.8" + } + }, + "node_modules/@browserbasehq/stagehand/node_modules/@anthropic-ai/sdk": { + "version": "0.27.3", + "resolved": "https://registry.npmmirror.com/@anthropic-ai/sdk/-/sdk-0.27.3.tgz", + "integrity": "sha512-IjLt0gd3L4jlOfilxVXTifn42FnVffMgDC04RJK1KDZpmkBWLv0XC92MVVmkxrFZNS/7l3xWgP/I3nqtX1sQHw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@browserbasehq/stagehand/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@browserbasehq/stagehand/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT", + "peer": true + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.10.0", + "resolved": "https://registry.npmmirror.com/@bufbuild/protobuf/-/protobuf-2.10.0.tgz", + "integrity": "sha512-fdRs9PSrBF7QUntpZpq6BTw58fhgGJojgg39m9oFOJGZT+nip9b0so5cYY1oWl5pvemDLr0cPPsH46vwThEbpQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@cfworker/json-schema": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz", + "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", + "license": "MIT" + }, + "node_modules/@copilotkit/react-core": { + "version": "1.10.6", + "resolved": "https://registry.npmmirror.com/@copilotkit/react-core/-/react-core-1.10.6.tgz", + "integrity": "sha512-sdojpntwgOxP8lWRzaFEiWr0g2wDefjQHtve5GPPie+otseFonV88FZjSqIq5LN+q5BIwDOEhCmDjALsGjXvuQ==", + "license": "MIT", + "dependencies": { + "@copilotkit/runtime-client-gql": "1.10.6", + "@copilotkit/shared": "1.10.6", + "@scarf/scarf": "^1.3.0", + "react-markdown": "^8.0.7", + "untruncate-json": "^0.0.1" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@copilotkit/react-ui": { + "version": "1.10.6", + "resolved": "https://registry.npmmirror.com/@copilotkit/react-ui/-/react-ui-1.10.6.tgz", + "integrity": "sha512-eNIbZKMvBVZqlAR4fqkmZRIYIt8WhwZOxfVJVwMD9nfmWdtatmxrOLecyDiPk/hkq2o/8s2/rubaZSMK6m+GHQ==", + "license": "MIT", + "dependencies": { + "@copilotkit/react-core": "1.10.6", + "@copilotkit/runtime-client-gql": "1.10.6", + "@copilotkit/shared": "1.10.6", + "@headlessui/react": "^2.1.3", + "react-markdown": "^10.1.0", + "react-syntax-highlighter": "^15.6.1", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-math": "^6.0.0" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react": { + "version": "2.2.9", + "resolved": "https://registry.npmmirror.com/@headlessui/react/-/react-2.2.9.tgz", + "integrity": "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmmirror.com/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@floating-ui/react/node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmmirror.com/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@react-aria/focus": { + "version": "3.21.2", + "resolved": "https://registry.npmmirror.com/@react-aria/focus/-/focus-3.21.2.tgz", + "integrity": "sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.25.6", + "@react-aria/utils": "^3.31.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@react-aria/focus/node_modules/@react-aria/utils": { + "version": "3.31.0", + "resolved": "https://registry.npmmirror.com/@react-aria/utils/-/utils-3.31.0.tgz", + "integrity": "sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@react-aria/interactions": { + "version": "3.25.6", + "resolved": "https://registry.npmmirror.com/@react-aria/interactions/-/interactions-3.25.6.tgz", + "integrity": "sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.31.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@react-aria/interactions/node_modules/@react-aria/utils": { + "version": "3.31.0", + "resolved": "https://registry.npmmirror.com/@react-aria/utils/-/utils-3.31.0.tgz", + "integrity": "sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@headlessui/react/node_modules/@tanstack/react-virtual": { + "version": "3.13.12", + "resolved": "https://registry.npmmirror.com/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", + "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.13.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@copilotkit/react-ui/node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmmirror.com/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/react-ui/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@copilotkit/runtime": { + "version": "1.10.6", + "resolved": "https://registry.npmmirror.com/@copilotkit/runtime/-/runtime-1.10.6.tgz", + "integrity": "sha512-35MdJ6nutC+spgHRJURbanLxBoQCNvVBYD0CBIk4Rv3/Ck8XgZA4lcc+5aGteuERXOPBsYEQjGD4xEPy3QXmGg==", + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "^0.57.0", + "@copilotkit/shared": "1.10.6", + "@graphql-yoga/plugin-defer-stream": "^3.3.1", + "@langchain/aws": "^0.1.9", + "@langchain/community": "^0.3.29", + "@langchain/core": "^0.3.38", + "@langchain/google-gauth": "^0.1.0", + "@langchain/langgraph-sdk": "^0.0.70", + "@langchain/openai": "^0.4.2", + "@scarf/scarf": "^1.3.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", + "express": "^4.19.2", + "graphql": "^16.8.1", + "graphql-scalars": "^1.23.0", + "graphql-yoga": "^5.3.1", + "groq-sdk": "^0.5.0", + "langchain": "^0.3.3", + "openai": "^4.85.1", + "partial-json": "^0.1.7", + "pino": "^9.2.0", + "pino-pretty": "^11.2.1", + "reflect-metadata": "^0.2.2", + "rxjs": "7.8.1", + "type-graphql": "2.0.0-rc.1", + "zod": "^3.23.3" + }, + "peerDependencies": { + "@ag-ui/client": ">=0.0.39", + "@ag-ui/core": ">=0.0.39", + "@ag-ui/encoder": ">=0.0.39", + "@ag-ui/langgraph": ">=0.0.18", + "@ag-ui/proto": ">=0.0.39" + } + }, + "node_modules/@copilotkit/runtime-client-gql": { + "version": "1.10.6", + "resolved": "https://registry.npmmirror.com/@copilotkit/runtime-client-gql/-/runtime-client-gql-1.10.6.tgz", + "integrity": "sha512-oLX8mjppVvQCWfquW9A0500hYVNxM4X/mtt76SEvfGUb2KsNQ4j2HOCzpmtm85MeLproC+f9738wLwRueLliZg==", + "license": "MIT", + "dependencies": { + "@copilotkit/shared": "1.10.6", + "@urql/core": "^5.0.3", + "untruncate-json": "^0.0.1", + "urql": "^4.1.0" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@copilotkit/runtime/node_modules/@langchain/langgraph-sdk": { + "version": "0.0.70", + "resolved": "https://registry.npmmirror.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.70.tgz", + "integrity": "sha512-O8I12bfeMVz5fOrXnIcK4IdRf50IqyJTO458V56wAIHLNoi4H8/JHM+2M+Y4H2PtslXIGnvomWqlBd0eY5z/Og==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "p-queue": "^6.6.2", + "p-retry": "4", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.31 <0.4.0", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@langchain/core": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@copilotkit/runtime/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@copilotkit/shared": { + "version": "1.10.6", + "resolved": "https://registry.npmmirror.com/@copilotkit/shared/-/shared-1.10.6.tgz", + "integrity": "sha512-56Rltf4fDBqCpl1ZXARypt5NdE4LTg3tGPPLurZpgPmm31Lv5EAHpfjC7I55vt9A0mXWlTCHtCrpiaAlTyzGJw==", + "license": "MIT", + "dependencies": { + "@ag-ui/core": "^0.0.37", + "@segment/analytics-node": "^2.1.2", + "chalk": "4.1.2", + "graphql": "^16.8.1", + "uuid": "^10.0.0", + "zod": "^3.23.3", + "zod-to-json-schema": "^3.23.5" + } + }, + "node_modules/@copilotkit/shared/node_modules/@ag-ui/core": { + "version": "0.0.37", + "resolved": "https://registry.npmmirror.com/@ag-ui/core/-/core-0.0.37.tgz", + "integrity": "sha512-7bmjPn1Ol0Zo00F+MrPr0eOwH4AFZbhmq/ZMhCsrMILtVYBiBLcLU9QFBpBL3Zm9MCHha8b79N7JE2FzwcMaVA==", + "dependencies": { + "rxjs": "7.8.1", + "zod": "^3.22.4" + } + }, + "node_modules/@copilotkit/shared/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@envelop/core": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/@envelop/core/-/core-5.3.2.tgz", + "integrity": "sha512-06Mu7fmyKzk09P2i2kHpGfItqLLgCq7uO5/nX4fc/iHMplWPNuAx4iYR+WXUQoFHDnP6EUbceQNQ5iyeMz9f3g==", + "license": "MIT", + "dependencies": { + "@envelop/instrumentation": "^1.0.0", + "@envelop/types": "^5.2.1", + "@whatwg-node/promise-helpers": "^1.2.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@envelop/instrumentation": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/@envelop/instrumentation/-/instrumentation-1.0.0.tgz", + "integrity": "sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==", + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@envelop/types": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/@envelop/types/-/types-5.2.1.tgz", + "integrity": "sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==", + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/@fastify/busboy/-/busboy-3.2.0.tgz", + "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", + "license": "MIT" + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@graphql-tools/executor": { + "version": "1.4.10", + "resolved": "https://registry.npmmirror.com/@graphql-tools/executor/-/executor-1.4.10.tgz", + "integrity": "sha512-/o7QScMdJpx/qIJlQcYs9ohB2qU2jSpuMyPStQy30kKTLHKyMETWpbljvRsuQxHJ2MJmEF3bYZgBHzdNAQHhug==", + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.10.0", + "@graphql-typed-document-node/core": "^3.2.0", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/merge": { + "version": "9.1.2", + "resolved": "https://registry.npmmirror.com/@graphql-tools/merge/-/merge-9.1.2.tgz", + "integrity": "sha512-Ny9YhWKv+KxZFdXYt+wlyEW55GzhFiq4daV4wYgpP0aRbwQaczNJd1L3VjjBsPKjmW8lctZXUoqYTqU5QPcBGw==", + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/schema": { + "version": "10.0.26", + "resolved": "https://registry.npmmirror.com/@graphql-tools/schema/-/schema-10.0.26.tgz", + "integrity": "sha512-KOmjuiWa9poP/Lza4HV0ZBPYGJI3VE3QzXA/8e0+wjcsRuEmxMLP82re1PUg0QRzp2UzifAB/gd7DoXmVGG9Fg==", + "license": "MIT", + "dependencies": { + "@graphql-tools/merge": "^9.1.2", + "@graphql-tools/utils": "^10.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/utils": { + "version": "10.10.0", + "resolved": "https://registry.npmmirror.com/@graphql-tools/utils/-/utils-10.10.0.tgz", + "integrity": "sha512-OOeab5Y9qeKq0zfoJCSScMcDfGcIxp05+LW2xYVCS2l3su+K3lYcg5+cAAx9n0SFxpJl8zF5denq2QDsfM7NnQ==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@whatwg-node/promise-helpers": "^1.0.0", + "cross-inspect": "1.0.1", + "dset": "^3.1.4", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-yoga/logger": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/@graphql-yoga/logger/-/logger-2.0.1.tgz", + "integrity": "sha512-Nv0BoDGLMg9QBKy9cIswQ3/6aKaKjlTh87x3GiBg2Z4RrjyrM48DvOOK0pJh1C1At+b0mUIM67cwZcFTDLN4sA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@graphql-yoga/plugin-defer-stream": { + "version": "3.16.0", + "resolved": "https://registry.npmmirror.com/@graphql-yoga/plugin-defer-stream/-/plugin-defer-stream-3.16.0.tgz", + "integrity": "sha512-LGn8DSSIB4iWT/EgeXR+rIvl80LOlZqIZrnK4slNJLgnXyMyvXMSlIcE/NnzH4zQq1YRixZtshXNOtekrVH9+g==", + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.6.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^15.2.0 || ^16.0.0", + "graphql-yoga": "^5.16.0" + } + }, + "node_modules/@graphql-yoga/subscription": { + "version": "5.0.5", + "resolved": "https://registry.npmmirror.com/@graphql-yoga/subscription/-/subscription-5.0.5.tgz", + "integrity": "sha512-oCMWOqFs6QV96/NZRt/ZhTQvzjkGB4YohBOpKM4jH/lDT4qb7Lex/aGCxpi/JD9njw3zBBtMqxbaC22+tFHVvw==", + "license": "MIT", + "dependencies": { + "@graphql-yoga/typed-event-target": "^3.0.2", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/events": "^0.1.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@graphql-yoga/typed-event-target": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@graphql-yoga/typed-event-target/-/typed-event-target-3.0.2.tgz", + "integrity": "sha512-ZpJxMqB+Qfe3rp6uszCQoag4nSw42icURnBRfFYSOmTgEeOe4rD0vYlbA8spvCu2TlCesNTlEN9BLWtQqLxabA==", + "license": "MIT", + "dependencies": { + "@repeaterjs/repeater": "^3.0.4", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.0", + "resolved": "https://registry.npmmirror.com/@grpc/grpc-js/-/grpc-js-1.14.0.tgz", + "integrity": "sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", + "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.3", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@ibm-cloud/watsonx-ai": { + "version": "1.7.2", + "resolved": "https://registry.npmmirror.com/@ibm-cloud/watsonx-ai/-/watsonx-ai-1.7.2.tgz", + "integrity": "sha512-8NhBvyWoHM/UjOF2AZPqO1otu82lTA0su1VTsCIafC0G1+KW4uFGUIDjI2b/gJrIAtQy7c9so/fTERe/lCv3iw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/node": "^18.0.0", + "extend": "3.0.2", + "form-data": "^4.0.4", + "ibm-cloud-sdk-core": "^5.4.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@ibm-cloud/watsonx-ai/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@ibm-cloud/watsonx-ai/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT", + "peer": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmmirror.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@langchain/aws": { + "version": "0.1.15", + "resolved": "https://registry.npmmirror.com/@langchain/aws/-/aws-0.1.15.tgz", + "integrity": "sha512-oyOMhTHP0rxdSCVI/g5KXYCOs9Kq/FpXMZbOk1JSIUoaIzUg4p6d98lsHu7erW//8NSaT+SX09QRbVDAgt7pNA==", + "license": "MIT", + "dependencies": { + "@aws-sdk/client-bedrock-agent-runtime": "^3.755.0", + "@aws-sdk/client-bedrock-runtime": "^3.840.0", + "@aws-sdk/client-kendra": "^3.750.0", + "@aws-sdk/credential-provider-node": "^3.750.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.58 <0.4.0" + } + }, + "node_modules/@langchain/community": { + "version": "0.3.57", + "resolved": "https://registry.npmmirror.com/@langchain/community/-/community-0.3.57.tgz", + "integrity": "sha512-xUe5UIlh1yZjt/cMtdSVlCoC5xm/RMN/rp+KZGLbquvjQeONmQ2rvpCqWjAOgQ6SPLqKiXvoXaKSm20r+LHISw==", + "license": "MIT", + "dependencies": { + "@langchain/openai": ">=0.2.0 <0.7.0", + "@langchain/weaviate": "^0.2.0", + "binary-extensions": "^2.2.0", + "expr-eval": "^2.0.2", + "flat": "^5.0.2", + "js-yaml": "^4.1.0", + "langchain": ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0", + "langsmith": "^0.3.67", + "uuid": "^10.0.0", + "zod": "^3.25.32" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@arcjet/redact": "^v1.0.0-alpha.23", + "@aws-crypto/sha256-js": "^5.0.0", + "@aws-sdk/client-bedrock-agent-runtime": "^3.749.0", + "@aws-sdk/client-bedrock-runtime": "^3.749.0", + "@aws-sdk/client-dynamodb": "^3.749.0", + "@aws-sdk/client-kendra": "^3.749.0", + "@aws-sdk/client-lambda": "^3.749.0", + "@aws-sdk/client-s3": "^3.749.0", + "@aws-sdk/client-sagemaker-runtime": "^3.749.0", + "@aws-sdk/client-sfn": "^3.749.0", + "@aws-sdk/credential-provider-node": "^3.388.0", + "@azure/search-documents": "^12.0.0", + "@azure/storage-blob": "^12.15.0", + "@browserbasehq/sdk": "*", + "@browserbasehq/stagehand": "^1.0.0", + "@clickhouse/client": "^0.2.5", + "@cloudflare/ai": "*", + "@datastax/astra-db-ts": "^1.0.0", + "@elastic/elasticsearch": "^8.4.0", + "@getmetal/metal-sdk": "*", + "@getzep/zep-cloud": "^1.0.6", + "@getzep/zep-js": "^0.9.0", + "@gomomento/sdk": "^1.51.1", + "@gomomento/sdk-core": "^1.51.1", + "@google-ai/generativelanguage": "*", + "@google-cloud/storage": "^6.10.1 || ^7.7.0", + "@gradientai/nodejs-sdk": "^1.2.0", + "@huggingface/inference": "^4.0.5", + "@huggingface/transformers": "^3.5.2", + "@ibm-cloud/watsonx-ai": "*", + "@lancedb/lancedb": "^0.19.1", + "@langchain/core": ">=0.3.58 <0.4.0", + "@layerup/layerup-security": "^1.5.12", + "@libsql/client": "^0.14.0", + "@mendable/firecrawl-js": "^1.4.3", + "@mlc-ai/web-llm": "*", + "@mozilla/readability": "*", + "@neondatabase/serverless": "*", + "@notionhq/client": "^2.2.10", + "@opensearch-project/opensearch": "*", + "@pinecone-database/pinecone": "*", + "@planetscale/database": "^1.8.0", + "@premai/prem-sdk": "^0.3.25", + "@qdrant/js-client-rest": "^1.15.0", + "@raycast/api": "^1.55.2", + "@rockset/client": "^0.9.1", + "@smithy/eventstream-codec": "^2.0.5", + "@smithy/protocol-http": "^3.0.6", + "@smithy/signature-v4": "^2.0.10", + "@smithy/util-utf8": "^2.0.0", + "@spider-cloud/spider-client": "^0.0.21", + "@supabase/supabase-js": "^2.45.0", + "@tensorflow-models/universal-sentence-encoder": "*", + "@tensorflow/tfjs-converter": "*", + "@tensorflow/tfjs-core": "*", + "@upstash/ratelimit": "^1.1.3 || ^2.0.3", + "@upstash/redis": "^1.20.6", + "@upstash/vector": "^1.1.1", + "@vercel/kv": "*", + "@vercel/postgres": "*", + "@writerai/writer-sdk": "^0.40.2", + "@xata.io/client": "^0.28.0", + "@zilliz/milvus2-sdk-node": ">=2.3.5", + "apify-client": "^2.7.1", + "assemblyai": "^4.6.0", + "azion": "^1.11.1", + "better-sqlite3": ">=9.4.0 <12.0.0", + "cassandra-driver": "^4.7.2", + "cborg": "^4.1.1", + "cheerio": "^1.0.0-rc.12", + "chromadb": "*", + "closevector-common": "0.1.3", + "closevector-node": "0.1.6", + "closevector-web": "0.1.6", + "cohere-ai": "*", + "convex": "^1.3.1", + "crypto-js": "^4.2.0", + "d3-dsv": "^2.0.0", + "discord.js": "^14.14.1", + "duck-duck-scrape": "^2.2.5", + "epub2": "^3.0.1", + "fast-xml-parser": "*", + "firebase-admin": "^11.9.0 || ^12.0.0 || ^13.0.0", + "google-auth-library": "*", + "googleapis": "*", + "hnswlib-node": "^3.0.0", + "html-to-text": "^9.0.5", + "ibm-cloud-sdk-core": "*", + "ignore": "^5.2.0", + "interface-datastore": "^8.2.11", + "ioredis": "^5.3.2", + "it-all": "^3.0.4", + "jsdom": "*", + "jsonwebtoken": "^9.0.2", + "llmonitor": "^0.5.9", + "lodash": "^4.17.21", + "lunary": "^0.7.10", + "mammoth": "^1.6.0", + "mariadb": "^3.4.0", + "mem0ai": "^2.1.8", + "mongodb": "^6.17.0", + "mysql2": "^3.9.8", + "neo4j-driver": "*", + "notion-to-md": "^3.1.0", + "officeparser": "^4.0.4", + "openai": "*", + "pdf-parse": "1.1.1", + "pg": "^8.11.0", + "pg-copy-streams": "^6.0.5", + "pickleparser": "^0.2.1", + "playwright": "^1.32.1", + "portkey-ai": "^0.1.11", + "puppeteer": "*", + "pyodide": ">=0.24.1 <0.27.0", + "redis": "*", + "replicate": "*", + "sonix-speech-recognition": "^2.1.1", + "srt-parser-2": "^1.2.3", + "typeorm": "^0.3.20", + "typesense": "^1.5.3", + "usearch": "^1.1.1", + "voy-search": "0.6.2", + "weaviate-client": "^3.5.2", + "web-auth-library": "^1.0.3", + "word-extractor": "*", + "ws": "^8.14.2", + "youtubei.js": "*" + }, + "peerDependenciesMeta": { + "@arcjet/redact": { + "optional": true + }, + "@aws-crypto/sha256-js": { + "optional": true + }, + "@aws-sdk/client-bedrock-agent-runtime": { + "optional": true + }, + "@aws-sdk/client-bedrock-runtime": { + "optional": true + }, + "@aws-sdk/client-dynamodb": { + "optional": true + }, + "@aws-sdk/client-kendra": { + "optional": true + }, + "@aws-sdk/client-lambda": { + "optional": true + }, + "@aws-sdk/client-s3": { + "optional": true + }, + "@aws-sdk/client-sagemaker-runtime": { + "optional": true + }, + "@aws-sdk/client-sfn": { + "optional": true + }, + "@aws-sdk/credential-provider-node": { + "optional": true + }, + "@aws-sdk/dsql-signer": { + "optional": true + }, + "@azure/search-documents": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@browserbasehq/sdk": { + "optional": true + }, + "@clickhouse/client": { + "optional": true + }, + "@cloudflare/ai": { + "optional": true + }, + "@datastax/astra-db-ts": { + "optional": true + }, + "@elastic/elasticsearch": { + "optional": true + }, + "@getmetal/metal-sdk": { + "optional": true + }, + "@getzep/zep-cloud": { + "optional": true + }, + "@getzep/zep-js": { + "optional": true + }, + "@gomomento/sdk": { + "optional": true + }, + "@gomomento/sdk-core": { + "optional": true + }, + "@google-ai/generativelanguage": { + "optional": true + }, + "@google-cloud/storage": { + "optional": true + }, + "@gradientai/nodejs-sdk": { + "optional": true + }, + "@huggingface/inference": { + "optional": true + }, + "@huggingface/transformers": { + "optional": true + }, + "@lancedb/lancedb": { + "optional": true + }, + "@layerup/layerup-security": { + "optional": true + }, + "@libsql/client": { + "optional": true + }, + "@mendable/firecrawl-js": { + "optional": true + }, + "@mlc-ai/web-llm": { + "optional": true + }, + "@mozilla/readability": { + "optional": true + }, + "@neondatabase/serverless": { + "optional": true + }, + "@notionhq/client": { + "optional": true + }, + "@opensearch-project/opensearch": { + "optional": true + }, + "@pinecone-database/pinecone": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@premai/prem-sdk": { + "optional": true + }, + "@qdrant/js-client-rest": { + "optional": true + }, + "@raycast/api": { + "optional": true + }, + "@rockset/client": { + "optional": true + }, + "@smithy/eventstream-codec": { + "optional": true + }, + "@smithy/protocol-http": { + "optional": true + }, + "@smithy/signature-v4": { + "optional": true + }, + "@smithy/util-utf8": { + "optional": true + }, + "@spider-cloud/spider-client": { + "optional": true + }, + "@supabase/supabase-js": { + "optional": true + }, + "@tensorflow-models/universal-sentence-encoder": { + "optional": true + }, + "@tensorflow/tfjs-converter": { + "optional": true + }, + "@tensorflow/tfjs-core": { + "optional": true + }, + "@upstash/ratelimit": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@upstash/vector": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "@vercel/postgres": { + "optional": true + }, + "@writerai/writer-sdk": { + "optional": true + }, + "@xata.io/client": { + "optional": true + }, + "@zilliz/milvus2-sdk-node": { + "optional": true + }, + "apify-client": { + "optional": true + }, + "assemblyai": { + "optional": true + }, + "azion": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "cassandra-driver": { + "optional": true + }, + "cborg": { + "optional": true + }, + "cheerio": { + "optional": true + }, + "chromadb": { + "optional": true + }, + "closevector-common": { + "optional": true + }, + "closevector-node": { + "optional": true + }, + "closevector-web": { + "optional": true + }, + "cohere-ai": { + "optional": true + }, + "convex": { + "optional": true + }, + "crypto-js": { + "optional": true + }, + "d3-dsv": { + "optional": true + }, + "discord.js": { + "optional": true + }, + "duck-duck-scrape": { + "optional": true + }, + "epub2": { + "optional": true + }, + "fast-xml-parser": { + "optional": true + }, + "firebase-admin": { + "optional": true + }, + "google-auth-library": { + "optional": true + }, + "googleapis": { + "optional": true + }, + "hnswlib-node": { + "optional": true + }, + "html-to-text": { + "optional": true + }, + "ignore": { + "optional": true + }, + "interface-datastore": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "it-all": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "jsonwebtoken": { + "optional": true + }, + "llmonitor": { + "optional": true + }, + "lodash": { + "optional": true + }, + "lunary": { + "optional": true + }, + "mammoth": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mem0ai": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "neo4j-driver": { + "optional": true + }, + "notion-to-md": { + "optional": true + }, + "officeparser": { + "optional": true + }, + "pdf-parse": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-copy-streams": { + "optional": true + }, + "pickleparser": { + "optional": true + }, + "playwright": { + "optional": true + }, + "portkey-ai": { + "optional": true + }, + "puppeteer": { + "optional": true + }, + "pyodide": { + "optional": true + }, + "redis": { + "optional": true + }, + "replicate": { + "optional": true + }, + "sonix-speech-recognition": { + "optional": true + }, + "srt-parser-2": { + "optional": true + }, + "typeorm": { + "optional": true + }, + "typesense": { + "optional": true + }, + "usearch": { + "optional": true + }, + "voy-search": { + "optional": true + }, + "weaviate-client": { + "optional": true + }, + "web-auth-library": { + "optional": true + }, + "word-extractor": { + "optional": true + }, + "ws": { + "optional": true + }, + "youtubei.js": { + "optional": true + } + } + }, + "node_modules/@langchain/community/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@langchain/core": { + "version": "0.3.79", + "resolved": "https://registry.npmmirror.com/@langchain/core/-/core-0.3.79.tgz", + "integrity": "sha512-ZLAs5YMM5N2UXN3kExMglltJrKKoW7hs3KMZFlXUnD7a5DFKBYxPFMeXA4rT+uvTxuJRZPCYX0JKI5BhyAWx4A==", + "license": "MIT", + "dependencies": { + "@cfworker/json-schema": "^4.0.2", + "ansi-styles": "^5.0.0", + "camelcase": "6", + "decamelize": "1.2.0", + "js-tiktoken": "^1.0.12", + "langsmith": "^0.3.67", + "mustache": "^4.2.0", + "p-queue": "^6.6.2", + "p-retry": "4", + "uuid": "^10.0.0", + "zod": "^3.25.32", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@langchain/core/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@langchain/google-common": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/@langchain/google-common/-/google-common-0.1.8.tgz", + "integrity": "sha512-8auqWw2PMPhcHQHS+nMN3tVZrUPgSLckUaFeOHDOeSBiDvBd4KCybPwyl2oCwMDGvmyIxvOOckkMdeGaJ92vpQ==", + "license": "MIT", + "dependencies": { + "uuid": "^10.0.0", + "zod-to-json-schema": "^3.22.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@langchain/google-common/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@langchain/google-gauth": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/@langchain/google-gauth/-/google-gauth-0.1.8.tgz", + "integrity": "sha512-2QK7d5SQMrnSv7X4j05BGfO74hiA8FJuNwSsQKZvzlGoVnNXil3x2aqD5V+zsYOPpxhkDCpNlmh2Pue2Wzy1rQ==", + "license": "MIT", + "dependencies": { + "@langchain/google-common": "~0.1.8", + "google-auth-library": "^8.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@langchain/langgraph-sdk": { + "version": "0.1.10", + "resolved": "https://registry.npmmirror.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.1.10.tgz", + "integrity": "sha512-9srSCb2bSvcvehMgjA2sMMwX0o1VUgPN6ghwm5Fwc9JGAKsQa6n1S4eCwy1h4abuYxwajH5n3spBw+4I2WYbgw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15", + "p-queue": "^6.6.2", + "p-retry": "4", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.31 <0.4.0 || ^1.0.0-alpha", + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@langchain/core": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@langchain/langgraph-sdk/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@langchain/openai": { + "version": "0.4.9", + "resolved": "https://registry.npmmirror.com/@langchain/openai/-/openai-0.4.9.tgz", + "integrity": "sha512-NAsaionRHNdqaMjVLPkFCyjUDze+OqRHghA1Cn4fPoAafz+FXcl9c7LlEl9Xo0FH6/8yiCl7Rw2t780C/SBVxQ==", + "license": "MIT", + "dependencies": { + "js-tiktoken": "^1.0.12", + "openai": "^4.87.3", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.39 <0.4.0" + } + }, + "node_modules/@langchain/textsplitters": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/@langchain/textsplitters/-/textsplitters-0.1.0.tgz", + "integrity": "sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==", + "license": "MIT", + "dependencies": { + "js-tiktoken": "^1.0.12" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@langchain/weaviate": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@langchain/weaviate/-/weaviate-0.2.3.tgz", + "integrity": "sha512-WqNGn1eSrI+ZigJd7kZjCj3fvHBYicKr054qts2nNJ+IyO5dWmY3oFTaVHFq1OLFVZJJxrFeDnxSEOC3JnfP0w==", + "license": "MIT", + "dependencies": { + "uuid": "^10.0.0", + "weaviate-client": "^3.5.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@langchain/weaviate/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@lukeed/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/@lukeed/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==", + "license": "MIT", + "dependencies": { + "@lukeed/csprng": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@next/env": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/env/-/env-14.2.33.tgz", + "integrity": "sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/test": { + "version": "1.56.1", + "resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@protobuf-ts/protoc": { + "version": "2.11.1", + "resolved": "https://registry.npmmirror.com/@protobuf-ts/protoc/-/protoc-2.11.1.tgz", + "integrity": "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==", + "license": "Apache-2.0", + "bin": { + "protoc": "protoc.js" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmmirror.com/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.8", + "resolved": "https://registry.npmmirror.com/@react-stately/utils/-/utils-3.10.8.tgz", + "integrity": "sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmmirror.com/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@repeaterjs/repeater": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/@repeaterjs/repeater/-/repeater-3.0.6.tgz", + "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", + "license": "MIT" + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@segment/analytics-core": { + "version": "1.8.2", + "resolved": "https://registry.npmmirror.com/@segment/analytics-core/-/analytics-core-1.8.2.tgz", + "integrity": "sha512-5FDy6l8chpzUfJcNlIcyqYQq4+JTUynlVoCeCUuVz+l+6W0PXg+ljKp34R4yLVCcY5VVZohuW+HH0VLWdwYVAg==", + "license": "MIT", + "dependencies": { + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-generic-utils": "1.2.0", + "dset": "^3.1.4", + "tslib": "^2.4.1" + } + }, + "node_modules/@segment/analytics-generic-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@segment/analytics-generic-utils/-/analytics-generic-utils-1.2.0.tgz", + "integrity": "sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.1" + } + }, + "node_modules/@segment/analytics-node": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@segment/analytics-node/-/analytics-node-2.3.0.tgz", + "integrity": "sha512-fOXLL8uY0uAWw/sTLmezze80hj8YGgXXlAfvSS6TUmivk4D/SP0C0sxnbpFdkUzWg2zT64qWIZj26afEtSnxUA==", + "license": "MIT", + "dependencies": { + "@lukeed/uuid": "^2.0.0", + "@segment/analytics-core": "1.8.2", + "@segment/analytics-generic-utils": "1.2.0", + "buffer": "^6.0.3", + "jose": "^5.1.0", + "node-fetch": "^2.6.7", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/abort-controller/-/abort-controller-4.2.4.tgz", + "integrity": "sha512-Z4DUr/AkgyFf1bOThW2HwzREagee0sB5ycl+hDiSZOfRLW8ZgrOjDi6g8mHH19yyU5E2A/64W3z6SMIf5XiUSQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/@smithy/config-resolver/-/config-resolver-4.4.1.tgz", + "integrity": "sha512-BciDJ5hkyYEGBBKMbjGB1A/Zq8bYZ41Zo9BMnGdKF6QD1fY4zIkYx6zui/0CHaVGnv6h0iy8y4rnPX9CPCAPyQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.4", + "@smithy/util-middleware": "^4.2.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.17.2", + "resolved": "https://registry.npmmirror.com/@smithy/core/-/core-3.17.2.tgz", + "integrity": "sha512-n3g4Nl1Te+qGPDbNFAYf+smkRVB+JhFsGy9uJXXZQEufoP4u0r+WLh6KvTDolCswaagysDc/afS1yvb2jnj1gQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-stream": "^4.5.5", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.4.tgz", + "integrity": "sha512-YVNMjhdz2pVto5bRdux7GMs0x1m0Afz3OcQy/4Yf9DH4fWOtroGH7uLvs7ZmDyoBJzLdegtIPpXrpJOZWvUXdw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-codec/-/eventstream-codec-2.2.0.tgz", + "integrity": "sha512-8janZoJw85nJmQZc4L8TuePp2pk1nxLgkxIR0TUjKJ5Dkj5oelB9WtiSSGXCQvNsJl0VSTvK/2ueMXxvpa9GVw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.12.0", + "@smithy/util-hex-encoding": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-codec/node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmmirror.com/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec/node_modules/@smithy/util-hex-encoding": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz", + "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.4.tgz", + "integrity": "sha512-d5T7ZS3J/r8P/PDjgmCcutmNxnSRvPH1U6iHeXjzI50sMr78GLmFcrczLw33Ap92oEKqa4CLrkAPeSSOqvGdUA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.4.tgz", + "integrity": "sha512-lxfDT0UuSc1HqltOGsTEAlZ6H29gpfDSdEPTapD5G63RbnYToZ+ezjzdonCCH90j5tRRCw3aLXVbiZaBW3VRVg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.4.tgz", + "integrity": "sha512-TPhiGByWnYyzcpU/K3pO5V7QgtXYpE0NaJPEZBCa1Y5jlw5SjqzMSbFiLb+ZkJhqoQc0ImGyVINqnq1ze0ZRcQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.4.tgz", + "integrity": "sha512-GNI/IXaY/XBB1SkGBFmbW033uWA0tj085eCxYih0eccUe/PFR7+UBQv9HNDk2fD9TJu7UVsCWsH99TkpEPSOzQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/eventstream-codec": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/eventstream-codec/-/eventstream-codec-4.2.4.tgz", + "integrity": "sha512-aV8blR9RBDKrOlZVgjOdmOibTC2sBXNiT7WA558b4MPdsLTV6sbyc1WIE9QiIuYMJjYtnPLciefoqSW8Gi+MZQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.8.1", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.5", + "resolved": "https://registry.npmmirror.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.5.tgz", + "integrity": "sha512-mg83SM3FLI8Sa2ooTJbsh5MFfyMTyNRwxqpKHmE0ICRIa66Aodv80DMsTQI02xBLVJ0hckwqTRr5IGAbbWuFLQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.4", + "@smithy/querystring-builder": "^4.2.4", + "@smithy/types": "^4.8.1", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/hash-node/-/hash-node-4.2.4.tgz", + "integrity": "sha512-kKU0gVhx/ppVMntvUOZE7WRMFW86HuaxLwvqileBEjL7PoILI8/djoILw3gPQloGVE6O0oOzqafxeNi2KbnUJw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/invalid-dependency/-/invalid-dependency-4.2.4.tgz", + "integrity": "sha512-z6aDLGiHzsMhbS2MjetlIWopWz//K+mCoPXjW6aLr0mypF+Y7qdEh5TyJ20Onf9FbWHiWl4eC+rITdizpnXqOw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-content-length/-/middleware-content-length-4.2.4.tgz", + "integrity": "sha512-hJRZuFS9UsElX4DJSJfoX4M1qXRH+VFiLMUnhsWvtOOUWRNvvOfDaUSdlNbjwv1IkpVjj/Rd/O59Jl3nhAcxow==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.6", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.6.tgz", + "integrity": "sha512-PXehXofGMFpDqr933rxD8RGOcZ0QBAWtuzTgYRAHAL2BnKawHDEdf/TnGpcmfPJGwonhginaaeJIKluEojiF/w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.17.2", + "@smithy/middleware-serde": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "@smithy/url-parser": "^4.2.4", + "@smithy/util-middleware": "^4.2.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.6", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-retry/-/middleware-retry-4.4.6.tgz", + "integrity": "sha512-OhLx131znrEDxZPAvH/OYufR9d1nB2CQADyYFN4C3V/NQS7Mg4V6uvxHC/Dr96ZQW8IlHJTJ+vAhKt6oxWRndA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/service-error-classification": "^4.2.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "@smithy/util-middleware": "^4.2.4", + "@smithy/util-retry": "^4.2.4", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-serde/-/middleware-serde-4.2.4.tgz", + "integrity": "sha512-jUr3x2CDhV15TOX2/Uoz4gfgeqLrRoTQbYAuhLS7lcVKNev7FeYSJ1ebEfjk+l9kbb7k7LfzIR/irgxys5ZTOg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/middleware-stack/-/middleware-stack-4.2.4.tgz", + "integrity": "sha512-Gy3TKCOnm9JwpFooldwAboazw+EFYlC+Bb+1QBsSi5xI0W5lX81j/P5+CXvD/9ZjtYKRgxq+kkqd/KOHflzvgA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/node-config-provider/-/node-config-provider-4.3.4.tgz", + "integrity": "sha512-3X3w7qzmo4XNNdPKNS4nbJcGSwiEMsNsRSunMA92S4DJLLIrH5g1AyuOA2XKM9PAPi8mIWfqC+fnfKNsI4KvHw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.4", + "@smithy/shared-ini-file-loader": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.4", + "resolved": "https://registry.npmmirror.com/@smithy/node-http-handler/-/node-http-handler-4.4.4.tgz", + "integrity": "sha512-VXHGfzCXLZeKnFp6QXjAdy+U8JF9etfpUXD1FAbzY1GzsFJiDQRQIt2CnMUvUdz3/YaHNqT3RphVWMUpXTIODA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/querystring-builder": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/property-provider/-/property-provider-4.2.4.tgz", + "integrity": "sha512-g2DHo08IhxV5GdY3Cpt/jr0mkTlAD39EJKN27Jb5N8Fb5qt8KG39wVKTXiTRCmHHou7lbXR8nKVU14/aRUf86w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-3.3.0.tgz", + "integrity": "sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http/node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmmirror.com/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/querystring-builder/-/querystring-builder-4.2.4.tgz", + "integrity": "sha512-KQ1gFXXC+WsbPFnk7pzskzOpn4s+KheWgO3dzkIEmnb6NskAIGp/dGdbKisTPJdtov28qNDohQrgDUKzXZBLig==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "@smithy/util-uri-escape": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/querystring-parser/-/querystring-parser-4.2.4.tgz", + "integrity": "sha512-aHb5cqXZocdzEkZ/CvhVjdw5l4r1aU/9iMEyoKzH4eXMowT6M0YjBpp7W/+XjkBnY8Xh0kVd55GKjnPKlCwinQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/service-error-classification/-/service-error-classification-4.2.4.tgz", + "integrity": "sha512-fdWuhEx4+jHLGeew9/IvqVU/fxT/ot70tpRGuOLxE3HzZOyKeTQfYeV1oaBXpzi93WOk668hjMuuagJ2/Qs7ng==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.3.4.tgz", + "integrity": "sha512-y5ozxeQ9omVjbnJo9dtTsdXj9BEvGx2X8xvRgKnV+/7wLBuYJQL6dOa/qMY6omyHi7yjt1OA97jZLoVRYi8lxA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/signature-v4/-/signature-v4-2.3.0.tgz", + "integrity": "sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "@smithy/types": "^2.12.0", + "@smithy/util-hex-encoding": "^2.2.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-uri-escape": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmmirror.com/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/util-hex-encoding": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz", + "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/util-middleware": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-middleware/-/util-middleware-2.2.0.tgz", + "integrity": "sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/@smithy/util-uri-escape": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-uri-escape/-/util-uri-escape-2.2.0.tgz", + "integrity": "sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.9.2", + "resolved": "https://registry.npmmirror.com/@smithy/smithy-client/-/smithy-client-4.9.2.tgz", + "integrity": "sha512-gZU4uAFcdrSi3io8U99Qs/FvVdRxPvIMToi+MFfsy/DN9UqtknJ1ais+2M9yR8e0ASQpNmFYEKeIKVcMjQg3rg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.17.2", + "@smithy/middleware-endpoint": "^4.3.6", + "@smithy/middleware-stack": "^4.2.4", + "@smithy/protocol-http": "^5.3.4", + "@smithy/types": "^4.8.1", + "@smithy/util-stream": "^4.5.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client/node_modules/@smithy/protocol-http": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/@smithy/protocol-http/-/protocol-http-5.3.4.tgz", + "integrity": "sha512-3sfFd2MAzVt0Q/klOmjFi3oIkxczHs0avbwrfn1aBqtc23WqQSmjvk77MBw9WkEQcwbOYIX5/2z4ULj8DuxSsw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.8.1", + "resolved": "https://registry.npmmirror.com/@smithy/types/-/types-4.8.1.tgz", + "integrity": "sha512-N0Zn0OT1zc+NA+UVfkYqQzviRh5ucWwO7mBV3TmHHprMnfcJNfhlPicDkBHi0ewbh+y3evR6cNAW0Raxvb01NA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/url-parser/-/url-parser-4.2.4.tgz", + "integrity": "sha512-w/N/Iw0/PTwJ36PDqU9PzAwVElo4qXxCC0eCTlUtIz/Z5V/2j/cViMHi0hPukSBHp4DVwvUlUhLgCzqSJ6plrg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from/node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.5", + "resolved": "https://registry.npmmirror.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.5.tgz", + "integrity": "sha512-GwaGjv/QLuL/QHQaqhf/maM7+MnRFQQs7Bsl6FlaeK6lm6U7mV5AAnVabw68cIoMl5FQFyKK62u7RWRzWL25OQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.7", + "resolved": "https://registry.npmmirror.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.7.tgz", + "integrity": "sha512-6hinjVqec0WYGsqN7h9hL/ywfULmJJNXGXnNZW7jrIn/cFuC/aVlVaiDfBIJEvKcOrmN8/EgsW69eY0gXABeHw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.1", + "@smithy/credential-provider-imds": "^4.2.4", + "@smithy/node-config-provider": "^4.3.4", + "@smithy/property-provider": "^4.2.4", + "@smithy/smithy-client": "^4.9.2", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/util-endpoints/-/util-endpoints-3.2.4.tgz", + "integrity": "sha512-f+nBDhgYRCmUEDKEQb6q0aCcOTXRDqH5wWaFHJxt4anB4pKHlgGoYP3xtioKXH64e37ANUkzWf6p4Mnv1M5/Vg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/util-middleware/-/util-middleware-4.2.4.tgz", + "integrity": "sha512-fKGQAPAn8sgV0plRikRVo6g6aR0KyKvgzNrPuM74RZKy/wWVzx3BMk+ZWEueyN3L5v5EDg+P582mKU+sH5OAsg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@smithy/util-retry/-/util-retry-4.2.4.tgz", + "integrity": "sha512-yQncJmj4dtv/isTXxRb4AamZHy4QFr4ew8GxS6XLWt7sCIxkPxPzINWd7WLISEFPsIan14zrKgvyAF+/yzfwoA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.4", + "@smithy/types": "^4.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.5", + "resolved": "https://registry.npmmirror.com/@smithy/util-stream/-/util-stream-4.5.5.tgz", + "integrity": "sha512-7M5aVFjT+HPilPOKbOmQfCIPchZe4DSBc1wf1+NvHvSoFTiFtauZzT+onZvCj70xhXd0AEmYnZYmdJIuwxOo4w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.5", + "@smithy/node-http-handler": "^4.4.4", + "@smithy/types": "^4.8.1", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.13.12", + "resolved": "https://registry.npmmirror.com/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", + "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmmirror.com/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.24", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.19.24.tgz", + "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmmirror.com/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.26", + "resolved": "https://registry.npmmirror.com/@types/react/-/react-18.3.26.tgz", + "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, + "node_modules/@types/validator": { + "version": "13.15.4", + "resolved": "https://registry.npmmirror.com/@types/validator/-/validator-13.15.4.tgz", + "integrity": "sha512-LSFfpSnJJY9wbC0LQxgvfb+ynbHftFo0tMsFOl/J4wexLnYMmDSPaj2ZyDv3TkfL1UePxPrxOWJfbiRS8mQv7A==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@urql/core": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@urql/core/-/core-5.2.0.tgz", + "integrity": "sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.0.13", + "wonka": "^6.3.2" + } + }, + "node_modules/@whatwg-node/disposablestack": { + "version": "0.0.6", + "resolved": "https://registry.npmmirror.com/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz", + "integrity": "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==", + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/events": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/@whatwg-node/events/-/events-0.1.2.tgz", + "integrity": "sha512-ApcWxkrs1WmEMS2CaLLFUEem/49erT3sxIVjpzU5f6zmVcnijtDSrhoK2zVobOIikZJdH63jdAXOrvjf6eOUNQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/fetch": { + "version": "0.10.11", + "resolved": "https://registry.npmmirror.com/@whatwg-node/fetch/-/fetch-0.10.11.tgz", + "integrity": "sha512-eR8SYtf9Nem1Tnl0IWrY33qJ5wCtIWlt3Fs3c6V4aAaTFLtkEQErXu3SSZg/XCHrj9hXSJ8/8t+CdMk5Qec/ZA==", + "license": "MIT", + "dependencies": { + "@whatwg-node/node-fetch": "^0.8.0", + "urlpattern-polyfill": "^10.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/node-fetch": { + "version": "0.8.1", + "resolved": "https://registry.npmmirror.com/@whatwg-node/node-fetch/-/node-fetch-0.8.1.tgz", + "integrity": "sha512-cQmQEo7IsI0EPX9VrwygXVzrVlX43Jb7/DBZSmpnC7xH4xkyOnn/HykHpTaQk7TUs7zh59A5uTGqx3p2Ouzffw==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^3.1.1", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/promise-helpers": "^1.3.2", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/promise-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz", + "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@whatwg-node/server": { + "version": "0.10.13", + "resolved": "https://registry.npmmirror.com/@whatwg-node/server/-/server-0.10.13.tgz", + "integrity": "sha512-Otmxo+0mp8az3B48pLI1I4msNOXPIoP7TLm6h5wOEQmynqHt8oP9nR6NJUeJk6iI5OtFpQtkbJFwfGkmplvc3Q==", + "license": "MIT", + "dependencies": { + "@envelop/instrumentation": "^1.0.0", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/fetch": "^0.10.10", + "@whatwg-node/promise-helpers": "^1.3.2", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abort-controller-x": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/abort-controller-x/-/abort-controller-x-0.4.3.tgz", + "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.13.1", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", + "license": "MIT", + "peer": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.21", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.21.tgz", + "integrity": "sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmmirror.com/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT" + }, + "node_modules/class-validator": { + "version": "0.14.2", + "resolved": "https://registry.npmmirror.com/class-validator/-/class-validator-0.14.2.tgz", + "integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==", + "license": "MIT", + "dependencies": { + "@types/validator": "^13.11.8", + "libphonenumber-js": "^1.11.1", + "validator": "^13.9.0" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/console-table-printer": { + "version": "2.15.0", + "resolved": "https://registry.npmmirror.com/console-table-printer/-/console-table-printer-2.15.0.tgz", + "integrity": "sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==", + "license": "MIT", + "dependencies": { + "simple-wcswidth": "^1.1.2" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-inspect": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/cross-inspect/-/cross-inspect-1.0.1.tgz", + "integrity": "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmmirror.com/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-named-character-reference/node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.244", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expr-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/expr-eval/-/expr-eval-2.0.2.tgz", + "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==", + "license": "MIT" + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmmirror.com/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "license": "Apache-2.0" + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmmirror.com/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmmirror.com/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "license": "MIT", + "peer": true, + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmmirror.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "license": "MIT" + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmmirror.com/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/google-auth-library": { + "version": "8.9.0", + "resolved": "https://registry.npmmirror.com/google-auth-library/-/google-auth-library-8.9.0.tgz", + "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.3.0", + "gtoken": "^6.1.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/google-p12-pem": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", + "deprecated": "Package is no longer maintained", + "license": "MIT", + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmmirror.com/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-query-complexity": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/graphql-query-complexity/-/graphql-query-complexity-0.12.0.tgz", + "integrity": "sha512-fWEyuSL6g/+nSiIRgIipfI6UXTI7bAxrpPlCY1c0+V3pAEUo1ybaKmSBgNr1ed2r+agm1plJww8Loig9y6s2dw==", + "license": "MIT", + "dependencies": { + "lodash.get": "^4.4.2" + }, + "peerDependencies": { + "graphql": "^14.6.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-scalars": { + "version": "1.25.0", + "resolved": "https://registry.npmmirror.com/graphql-scalars/-/graphql-scalars-1.25.0.tgz", + "integrity": "sha512-b0xyXZeRFkne4Eq7NAnL400gStGqG/Sx9VqX0A05nHyEbv57UJnWKsjNnrpVqv5e/8N1MUxkt0wwcRXbiyKcFg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-yoga": { + "version": "5.16.0", + "resolved": "https://registry.npmmirror.com/graphql-yoga/-/graphql-yoga-5.16.0.tgz", + "integrity": "sha512-/R2dJea7WgvNlXRU4F8iFwWd95Qn1mN+R+yC8XBs1wKjUzr0Pvv8cGYtt6UUcVHw5CiDEtu7iQY5oOe3sDAWCQ==", + "license": "MIT", + "dependencies": { + "@envelop/core": "^5.3.0", + "@envelop/instrumentation": "^1.0.0", + "@graphql-tools/executor": "^1.4.0", + "@graphql-tools/schema": "^10.0.11", + "@graphql-tools/utils": "^10.6.2", + "@graphql-yoga/logger": "^2.0.1", + "@graphql-yoga/subscription": "^5.0.5", + "@whatwg-node/fetch": "^0.10.6", + "@whatwg-node/promise-helpers": "^1.2.4", + "@whatwg-node/server": "^0.10.5", + "dset": "^3.1.4", + "lru-cache": "^10.0.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^15.2.0 || ^16.0.0" + } + }, + "node_modules/graphql-yoga/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/groq-sdk": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/groq-sdk/-/groq-sdk-0.5.0.tgz", + "integrity": "sha512-RVmhW7qZ+XZoy5fIuSdx/LGQJONpL8MHgZEW7dFwTdgkzStub2XQx6OKv28CHogijdwH41J+Npj/z2jBPu3vmw==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + } + }, + "node_modules/groq-sdk/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/groq-sdk/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, + "node_modules/groq-sdk/node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/gtoken": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", + "license": "MIT", + "dependencies": { + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmmirror.com/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/hast-util-from-parse5/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-from-parse5/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmmirror.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmmirror.com/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/hast-util-raw/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-raw/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmmirror.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/highlightjs-vue": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", + "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", + "license": "CC0-1.0" + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/ibm-cloud-sdk-core": { + "version": "5.4.3", + "resolved": "https://registry.npmmirror.com/ibm-cloud-sdk-core/-/ibm-cloud-sdk-core-5.4.3.tgz", + "integrity": "sha512-D0lvClcoCp/HXyaFlCbOT4aTYgGyeIb4ncxZpxRuiuw7Eo79C6c49W53+8WJRD9nxzT5vrIdaky3NBcTdBtaEg==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/debug": "^4.1.12", + "@types/node": "^18.19.80", + "@types/tough-cookie": "^4.0.0", + "axios": "^1.12.2", + "camelcase": "^6.3.0", + "debug": "^4.3.4", + "dotenv": "^16.4.5", + "extend": "3.0.2", + "file-type": "16.5.4", + "form-data": "^4.0.4", + "isstream": "0.1.2", + "jsonwebtoken": "^9.0.2", + "mime-types": "2.1.35", + "retry-axios": "^2.6.0", + "tough-cookie": "^4.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ibm-cloud-sdk-core/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/ibm-cloud-sdk-core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ibm-cloud-sdk-core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/ibm-cloud-sdk-core/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT", + "peer": true + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "license": "MIT" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "license": "MIT", + "peer": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmmirror.com/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tiktoken": { + "version": "1.0.21", + "resolved": "https://registry.npmmirror.com/js-tiktoken/-/js-tiktoken-1.0.21.tgz", + "integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.5.1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "peer": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/katex": { + "version": "0.16.25", + "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.25.tgz", + "integrity": "sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/langchain": { + "version": "0.3.36", + "resolved": "https://registry.npmmirror.com/langchain/-/langchain-0.3.36.tgz", + "integrity": "sha512-PqC19KChFF0QlTtYDFgfEbIg+SCnCXox29G8tY62QWfj9bOW7ew2kgWmPw5qoHLOTKOdQPvXET20/1Pdq8vAtQ==", + "license": "MIT", + "dependencies": { + "@langchain/openai": ">=0.1.0 <0.7.0", + "@langchain/textsplitters": ">=0.0.0 <0.2.0", + "js-tiktoken": "^1.0.12", + "js-yaml": "^4.1.0", + "jsonpointer": "^5.0.1", + "langsmith": "^0.3.67", + "openapi-types": "^12.1.3", + "p-retry": "4", + "uuid": "^10.0.0", + "yaml": "^2.2.1", + "zod": "^3.25.32" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/anthropic": "*", + "@langchain/aws": "*", + "@langchain/cerebras": "*", + "@langchain/cohere": "*", + "@langchain/core": ">=0.3.58 <0.4.0", + "@langchain/deepseek": "*", + "@langchain/google-genai": "*", + "@langchain/google-vertexai": "*", + "@langchain/google-vertexai-web": "*", + "@langchain/groq": "*", + "@langchain/mistralai": "*", + "@langchain/ollama": "*", + "@langchain/xai": "*", + "axios": "*", + "cheerio": "*", + "handlebars": "^4.7.8", + "peggy": "^3.0.2", + "typeorm": "*" + }, + "peerDependenciesMeta": { + "@langchain/anthropic": { + "optional": true + }, + "@langchain/aws": { + "optional": true + }, + "@langchain/cerebras": { + "optional": true + }, + "@langchain/cohere": { + "optional": true + }, + "@langchain/deepseek": { + "optional": true + }, + "@langchain/google-genai": { + "optional": true + }, + "@langchain/google-vertexai": { + "optional": true + }, + "@langchain/google-vertexai-web": { + "optional": true + }, + "@langchain/groq": { + "optional": true + }, + "@langchain/mistralai": { + "optional": true + }, + "@langchain/ollama": { + "optional": true + }, + "@langchain/xai": { + "optional": true + }, + "axios": { + "optional": true + }, + "cheerio": { + "optional": true + }, + "handlebars": { + "optional": true + }, + "peggy": { + "optional": true + }, + "typeorm": { + "optional": true + } + } + }, + "node_modules/langchain/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/langsmith": { + "version": "0.3.76", + "resolved": "https://registry.npmmirror.com/langsmith/-/langsmith-0.3.76.tgz", + "integrity": "sha512-JIRyT+InuaaMxq3dhXVOAkedAsugY5TOEAJrI87UuIfJVgV2i7K/lPI4+jNtakaYL9gIKbIwpXHBMpb8rrRgOg==", + "license": "MIT", + "dependencies": { + "@types/uuid": "^10.0.0", + "chalk": "^4.1.2", + "console-table-printer": "^2.12.1", + "p-queue": "^6.6.2", + "p-retry": "4", + "semver": "^7.6.3", + "uuid": "^10.0.0" + }, + "peerDependencies": { + "@opentelemetry/api": "*", + "@opentelemetry/exporter-trace-otlp-proto": "*", + "@opentelemetry/sdk-trace-base": "*", + "openai": "*" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@opentelemetry/exporter-trace-otlp-proto": { + "optional": true + }, + "@opentelemetry/sdk-trace-base": { + "optional": true + }, + "openai": { + "optional": true + } + } + }, + "node_modules/langsmith/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.12.25", + "resolved": "https://registry.npmmirror.com/libphonenumber-js/-/libphonenumber-js-1.12.25.tgz", + "integrity": "sha512-u90tUu/SEF8b+RaDKCoW7ZNFDakyBtFlX1ex3J+VH+ElWes/UaitJLt/w4jGu8uAE41lltV/s+kMVtywcMEg7g==", + "license": "MIT" + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmmirror.com/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT", + "peer": true + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmmirror.com/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "license": "MIT", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-mdx-jsx/node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/mdast-util-mdx-jsx/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-to-hast/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-to-hast/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-to-markdown/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/micromark/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next": { + "version": "14.2.33", + "resolved": "https://registry.npmmirror.com/next/-/next-14.2.33.tgz", + "integrity": "sha512-GiKHLsD00t4ACm1p00VgrI0rUFAC9cRDGReKyERlM57aeEZkOQGcZTpIbsGn0b562FTPJWmYfKwplfO9EaT6ng==", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.33", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/nice-grpc": { + "version": "2.1.13", + "resolved": "https://registry.npmmirror.com/nice-grpc/-/nice-grpc-2.1.13.tgz", + "integrity": "sha512-IkXNok2NFyYh0WKp1aJFwFV3Ue2frBkJ16ojrmgX3Tc9n0g7r0VU+ur3H/leDHPPGsEeVozdMynGxYT30k3D/Q==", + "license": "MIT", + "dependencies": { + "@grpc/grpc-js": "^1.14.0", + "abort-controller-x": "^0.4.0", + "nice-grpc-common": "^2.0.2" + } + }, + "node_modules/nice-grpc-client-middleware-retry": { + "version": "3.1.12", + "resolved": "https://registry.npmmirror.com/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-3.1.12.tgz", + "integrity": "sha512-CHKIeHznAePOsT2dLeGwoOFaybQz6LvkIsFfN8SLcyGyTR7AB6vZMaECJjx+QPL8O2qVgaVE167PdeOmQrPuag==", + "license": "MIT", + "dependencies": { + "abort-controller-x": "^0.4.0", + "nice-grpc-common": "^2.0.2" + } + }, + "node_modules/nice-grpc-common": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/nice-grpc-common/-/nice-grpc-common-2.0.2.tgz", + "integrity": "sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==", + "license": "MIT", + "dependencies": { + "ts-error": "^1.0.6" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openai": { + "version": "4.104.0", + "resolved": "https://registry.npmmirror.com/openai/-/openai-4.104.0.tgz", + "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + }, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/openai/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmmirror.com/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT" + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/partial-json": { + "version": "0.1.7", + "resolved": "https://registry.npmmirror.com/partial-json/-/partial-json-0.1.7.tgz", + "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", + "license": "MIT" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmmirror.com/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.3.0", + "resolved": "https://registry.npmmirror.com/pino-pretty/-/pino-pretty-11.3.0.tgz", + "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/playwright": { + "version": "1.56.1", + "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright-core": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.56.1", + "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmmirror.com/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmmirror.com/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmmirror.com/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT", + "peer": true + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "peer": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT", + "peer": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-markdown": { + "version": "8.0.7", + "resolved": "https://registry.npmmirror.com/react-markdown/-/react-markdown-8.0.7.tgz", + "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/prop-types": "^15.0.0", + "@types/unist": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^2.0.0", + "prop-types": "^15.0.0", + "property-information": "^6.0.0", + "react-is": "^18.0.0", + "remark-parse": "^10.0.0", + "remark-rehype": "^10.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unified": "^10.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/react-syntax-highlighter": { + "version": "15.6.6", + "resolved": "https://registry.npmmirror.com/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", + "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.4.1", + "highlightjs-vue": "^1.0.0", + "lowlight": "^1.17.0", + "prismjs": "^1.30.0", + "refractor": "^3.6.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", + "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "^4.7.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "license": "MIT", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/rehype-raw/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/rehype-raw/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/remark-gfm/node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm/node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/remark-math/node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "10.0.2", + "resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse/node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/remark-parse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/remark-parse/node_modules/mdast-util-from-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse/node_modules/mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse/node_modules/micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-factory-whitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-combine-extensions": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-decode-string": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-parse/node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-parse/node_modules/micromark-util-normalize-identifier": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-subtokenize": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/remark-parse/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-parse/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-parse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/remark-parse/node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/remark-rehype/-/remark-rehype-10.1.0.tgz", + "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-to-hast": "^12.1.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype/node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/remark-rehype/node_modules/mdast-util-to-hast": { + "version": "12.3.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-definitions": "^5.0.0", + "micromark-util-sanitize-uri": "^1.1.0", + "trim-lines": "^3.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/remark-rehype/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-rehype/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/remark-rehype/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-rehype/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/remark-rehype/node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/remark-stringify/node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT", + "peer": true + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-axios": { + "version": "2.6.0", + "resolved": "https://registry.npmmirror.com/retry-axios/-/retry-axios-2.6.0.tgz", + "integrity": "sha512-pOLi+Gdll3JekwuFjXO3fTq+L9lzMQGcSq7M5gIjExcl3Gu1hd4XXuf5o3+LuSBsaULQH7DiNbsqPd1chVpQGQ==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=10.7.0" + }, + "peerDependencies": { + "axios": "*" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-wcswidth": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz", + "integrity": "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==", + "license": "MIT" + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities/node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/style-to-js": { + "version": "1.1.18", + "resolved": "https://registry.npmmirror.com/style-to-js/-/style-to-js-1.1.18.tgz", + "integrity": "sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.11" + } + }, + "node_modules/style-to-js/node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmmirror.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/style-to-js/node_modules/style-to-object": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/style-to-object/-/style-to-object-1.0.11.tgz", + "integrity": "sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmmirror.com/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmmirror.com/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tabbable": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.3.0.tgz", + "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==", + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "3.4.18", + "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-3.4.18.tgz", + "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-error": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/ts-error/-/ts-error-1.0.6.tgz", + "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==", + "license": "MIT" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-graphql": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmmirror.com/type-graphql/-/type-graphql-2.0.0-rc.1.tgz", + "integrity": "sha512-HCu4j3jR0tZvAAoO7DMBT3MRmah0DFRe5APymm9lXUghXA0sbhiMf6SLRafRYfk0R0KiUQYRduuGP3ap1RnF1Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/TypeGraphQL" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/typegraphql" + } + ], + "license": "MIT", + "dependencies": { + "@graphql-yoga/subscription": "^5.0.0", + "@types/node": "*", + "@types/semver": "^7.5.6", + "graphql-query-complexity": "^0.12.0", + "semver": "^7.5.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "class-validator": ">=0.14.0", + "graphql": "^16.8.1", + "graphql-scalars": "^1.22.4" + }, + "peerDependenciesMeta": { + "class-validator": { + "optional": true + } + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmmirror.com/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-remove-position/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-visit/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit/node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/untruncate-json": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/untruncate-json/-/untruncate-json-0.0.1.tgz", + "integrity": "sha512-4W9enDK4X1y1s2S/Rz7ysw6kDuMS3VmRjMFg7GZrNO+98OSe+x5Lh7PKYoVjy3lW/1wmhs6HW0lusnQRHgMarA==", + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "license": "MIT" + }, + "node_modules/urql": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/urql/-/urql-4.2.2.tgz", + "integrity": "sha512-3GgqNa6iF7bC4hY/ImJKN4REQILcSU9VKcKL8gfELZM8mM5BnLH1BsCc8kBdnVGD1LIFOs4W3O2idNHhON1r0w==", + "license": "MIT", + "dependencies": { + "@urql/core": "^5.1.1", + "wonka": "^6.3.2" + }, + "peerDependencies": { + "@urql/core": "^5.0.0", + "react": ">= 16.8.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/validator": { + "version": "13.15.20", + "resolved": "https://registry.npmmirror.com/validator/-/validator-13.15.20.tgz", + "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/vfile-location/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message/node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile/node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/weaviate-client": { + "version": "3.9.0", + "resolved": "https://registry.npmmirror.com/weaviate-client/-/weaviate-client-3.9.0.tgz", + "integrity": "sha512-7qwg7YONAaT4zWnohLrFdzky+rZegVe76J+Tky/+7tuyvjFpdKgSrdqI/wPDh8aji0ZGZrL4DdGwGfFnZ+uV4w==", + "license": "BSD-3-Clause", + "dependencies": { + "abort-controller-x": "^0.4.3", + "graphql": "^16.11.0", + "graphql-request": "^6.1.0", + "long": "^5.3.2", + "nice-grpc": "^2.1.12", + "nice-grpc-client-middleware-retry": "^3.1.11", + "nice-grpc-common": "^2.0.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/weaviate-client/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wonka": { + "version": "6.3.5", + "resolved": "https://registry.npmmirror.com/wonka/-/wonka-6.3.5.tgz", + "integrity": "sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmmirror.com/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/package.json b/integrations/claude-agent-sdk/typescript/examples/copilotkit/package.json new file mode 100644 index 000000000..186c1213a --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/package.json @@ -0,0 +1,30 @@ +{ + "name": "claude-agent-sdk-copilotkit-demo", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@ag-ui/client": "^0.0.40", + "@copilotkit/runtime": "^1.10.6", + "@copilotkit/react-core": "^1.10.6", + "@copilotkit/react-ui": "^1.10.6", + "next": "^14.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32", + "tailwindcss": "^3.4.0", + "typescript": "^5.0.0" + } +} + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/postcss.config.js b/integrations/claude-agent-sdk/typescript/examples/copilotkit/postcss.config.js new file mode 100644 index 000000000..c21c07635 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/api/copilotkit/route.ts b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/api/copilotkit/route.ts new file mode 100644 index 000000000..b9ebcea62 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/api/copilotkit/route.ts @@ -0,0 +1,54 @@ +import { + CopilotRuntime, + ExperimentalEmptyAdapter, + copilotRuntimeNextJSAppRouterEndpoint, +} from "@copilotkit/runtime"; + +import { HttpAgent } from "@ag-ui/client"; +import { NextRequest } from "next/server"; + +// Base URL for the Claude Agent SDK server +// This should point to your FastAPI server running Claude Agent SDK integration +const CLAUDE_AGENT_URL = process.env.CLAUDE_AGENT_URL || "http://localhost:8000/chat"; + +// You can use any service adapter here for multi-agent support. We use +// the empty adapter since we're only using one agent. +const serviceAdapter = new ExperimentalEmptyAdapter(); + +// Create HttpAgent that connects to Claude Agent SDK server +// This agent implements the AbstractAgent interface required by CopilotKit +const claudeAgent = new HttpAgent({ + url: CLAUDE_AGENT_URL, + // Optional: Set initial state if needed + // initialState: { + // 'language': 'en' + // }, + // Optional: Set initial messages for context + // initialMessages: [ + // { + // id: '1', + // role: 'user', + // content: 'Initial message' + // } + // ] +}); + +// Create CopilotRuntime with the Claude Agent +const runtime = new CopilotRuntime({ + agents: { + // Agent ID that will be used in the frontend + 'agentic_chat': claudeAgent + } +}); + +// Next.js API route handler for CopilotKit runtime requests +export const POST = async (req: NextRequest) => { + const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ + runtime, + serviceAdapter, + endpoint: "/api/copilotkit", + }); + + return handleRequest(req); +}; + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/globals.css b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/globals.css new file mode 100644 index 000000000..447d786d6 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/globals.css @@ -0,0 +1,19 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/layout.tsx b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/layout.tsx new file mode 100644 index 000000000..9bdd6111f --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/layout.tsx @@ -0,0 +1,20 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "Claude Agent SDK + CopilotKit Demo", + description: "Integration of Claude Agent SDK with CopilotKit using AG-UI Protocol", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/page.tsx b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/page.tsx new file mode 100644 index 000000000..dab6265eb --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/src/app/page.tsx @@ -0,0 +1,79 @@ +"use client"; +import React, { useState } from "react"; +import "@copilotkit/react-ui/styles.css"; +import { + CopilotKit, + useFrontendTool, +} from "@copilotkit/react-core"; +import { CopilotChat } from "@copilotkit/react-ui"; +import "./globals.css"; + +const AgenticChat = () => { + return ( + + + + ); +}; + +const Chat = () => { + const [background, setBackground] = useState("--copilot-kit-background-color"); + + // Example frontend tool that can be called by Claude Agent + // NOTE: useFrontendTool must be called inside a component that's wrapped by CopilotKit + useFrontendTool({ + name: "change_background", + description: + "Change the background color of the chat. Can be anything that the CSS background attribute accepts. Regular colors, linear or radial gradients etc.", + parameters: [ + { + name: "background", + type: "string", + description: "The background. Prefer gradients. Only use when asked.", + }, + ], + handler: ({ background }) => { + setBackground(background); + return { + status: "success", + message: `Background changed to ${background}`, + }; + }, + }); + + return ( +
+
+ +
+
+ ); +}; + +export default AgenticChat; + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/tailwind.config.js b/integrations/claude-agent-sdk/typescript/examples/copilotkit/tailwind.config.js new file mode 100644 index 000000000..dcccb4312 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/tailwind.config.js @@ -0,0 +1,12 @@ +module.exports = { + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}; + diff --git a/integrations/claude-agent-sdk/typescript/examples/copilotkit/tsconfig.json b/integrations/claude-agent-sdk/typescript/examples/copilotkit/tsconfig.json new file mode 100644 index 000000000..79cde9086 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/copilotkit/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} + diff --git a/integrations/claude-agent-sdk/typescript/examples/direct-api-example.ts b/integrations/claude-agent-sdk/typescript/examples/direct-api-example.ts new file mode 100644 index 000000000..c170cb13e --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/direct-api-example.ts @@ -0,0 +1,87 @@ +/** + * Direct Anthropic API Example + * + * Does not use Agent SDK, directly uses @anthropic-ai/sdk + * This method is compatible with third-party API proxies (e.g., Zhipu) + * + * Environment variables (in .env.local): + * - ANTHROPIC_AUTH_TOKEN: Claude API authentication token + * - ANTHROPIC_BASE_URL: API base URL (optional) + */ + +import dotenv from 'dotenv'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; +import Anthropic from '@anthropic-ai/sdk'; + +// Get current file directory in ESM mode +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Load .env.local environment variables +const envPath1 = resolve(__dirname, '.env.local'); +const envPath2 = resolve(process.cwd(), '.env.local'); + +dotenv.config({ path: envPath1 }); +dotenv.config({ path: envPath2 }); + +// Validate environment variables +if (!process.env.ANTHROPIC_AUTH_TOKEN && !process.env.ANTHROPIC_API_KEY) { + console.error('❌ Error: ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY not found'); + process.exit(1); +} + +console.log('✅ Environment variables loaded'); +console.log(' - ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'Set' : 'Not set'); +console.log(' - ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'Using default'); +console.log(''); + +async function main() { + try { + // Initialize Anthropic client + const client = new Anthropic({ + apiKey: process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY, + baseURL: process.env.ANTHROPIC_BASE_URL, + }); + + console.log('🚀 Starting Claude API call...\n'); + console.log('💬 AI Response:\n'); + + // Call API (streaming response) + const stream = await client.messages.stream({ + model: 'claude-3-5-sonnet-20241022', + max_tokens: 1024, + messages: [ + { + role: 'user', + content: 'Hello! Please introduce yourself in one sentence.', + }, + ], + }); + + // Listen to streaming events + for await (const event of stream) { + if (event.type === 'content_block_delta') { + if (event.delta.type === 'text_delta') { + process.stdout.write(event.delta.text); + } + } + } + + console.log('\n\n✅ Conversation completed'); + console.log('🎉 Done!\n'); + + } catch (error: any) { + console.error('\n❌ Error occurred:', error.message); + if (error.status) { + console.error('HTTP Status Code:', error.status); + } + if (error.error) { + console.error('Error details:', JSON.stringify(error.error, null, 2)); + } + process.exit(1); + } +} + +// Run main function +main(); diff --git a/integrations/claude-agent-sdk/typescript/examples/env.example b/integrations/claude-agent-sdk/typescript/examples/env.example new file mode 100644 index 000000000..04aab37c7 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/env.example @@ -0,0 +1,20 @@ +# Claude API Key (Required) +ANTHROPIC_API_KEY=your_api_key_here + +# Server Port (Optional, default is 3000) +# PORT=3000 + +# Application Name (Optional) +# APP_NAME=claude-example + +# System Prompt (Optional) +# SYSTEM_PROMPT=You are a helpful assistant + +# Enable Persistent Sessions (Optional, default is true) +# ENABLE_PERSISTENT_SESSIONS=true + +# Session Timeout (milliseconds) (Optional, default is 30 minutes) +# SESSION_TIMEOUT=1800000 + +# Permission Mode (Optional, allowed values: ask, auto, none, default is ask) +# PERMISSION_MODE=ask diff --git a/integrations/claude-agent-sdk/typescript/examples/package.json b/integrations/claude-agent-sdk/typescript/examples/package.json new file mode 100644 index 000000000..52f3608ab --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/package.json @@ -0,0 +1,30 @@ +{ + "name": "@ag-ui/claude-example", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "tsx src/server.ts", + "simple": "tsx simple-example.ts", + "pure": "tsx pure-sdk-example.ts", + "pure-tools": "tsx pure-sdk-with-tools.ts", + "direct": "tsx direct-api-example.ts", + "build": "tsc" + }, + "dependencies": { + "@ag-ui/claude": "workspace:*", + "@ag-ui/client": "workspace:*", + "@ag-ui/core": "workspace:*", + "@anthropic-ai/sdk": "^0.68.0", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "express": "^4.18.2" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/dotenv": "^8.2.0", + "@types/express": "^4.17.17", + "@types/node": "^20.11.19", + "tsx": "^4.7.0", + "typescript": "^5.3.3" + } +} diff --git a/integrations/claude-agent-sdk/typescript/examples/pure-sdk-example.ts b/integrations/claude-agent-sdk/typescript/examples/pure-sdk-example.ts new file mode 100644 index 000000000..1798a4de0 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/pure-sdk-example.ts @@ -0,0 +1,154 @@ +/** + * Pure Claude Agent SDK Example + * + * Directly calls @anthropic-ai/claude-agent-sdk without ag-ui + * + * Environment variables (in .env.local): + * - ANTHROPIC_AUTH_TOKEN: Claude API authentication token + * - ANTHROPIC_BASE_URL: API base URL (optional) + */ + +import dotenv from 'dotenv'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +// Get current file directory in ESM mode +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Load .env.local environment variables (try multiple paths) +const envPath1 = resolve(__dirname, '.env.local'); +const envPath2 = resolve(process.cwd(), '.env.local'); + +console.log('Attempting to load environment variables:'); +console.log(' Path 1:', envPath1); +console.log(' Path 2:', envPath2); +console.log(' Current directory:', process.cwd()); +console.log(''); + +dotenv.config({ path: envPath1 }); +dotenv.config({ path: envPath2 }); + +// Validate environment variables +if (!process.env.ANTHROPIC_AUTH_TOKEN && !process.env.ANTHROPIC_API_KEY) { + console.error('❌ Error: ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY not found'); + console.error('Please set ANTHROPIC_AUTH_TOKEN in .env.local file'); + console.error(''); + console.error('Current environment variables:'); + console.error(' ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN); + console.error(' ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY); + process.exit(1); +} + +console.log('✅ Environment variables loaded'); +console.log(' - ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'Set' : 'Not set'); +console.log(' - ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'Using default'); +console.log(''); + +async function main() { + try { + // Dynamically import Claude Agent SDK + const { query } = await import('@anthropic-ai/claude-agent-sdk'); + + console.log('🚀 Starting Claude Agent SDK call...\n'); + + // SDK configuration options + const options: any = { + // SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + // Also automatically reads ANTHROPIC_BASE_URL if set + permissionMode: 'bypassPermissions' as const, // Allowed values: acceptEdits, bypassPermissions, default, plan + verbose: true, // Enable verbose logging + + // Add stderr callback for debugging + stderr: (data: string) => { + console.error('[Claude CLI Debug]:', data); + }, + }; + + // If base URL is set, pass it explicitly (some third-party APIs may require this) + if (process.env.ANTHROPIC_BASE_URL) { + options.baseUrl = process.env.ANTHROPIC_BASE_URL; + console.log(' Using custom Base URL:', options.baseUrl); + } + + // If API Key is set, pass it explicitly + if (process.env.ANTHROPIC_AUTH_TOKEN) { + console.log(' Using AUTH_TOKEN'); + } else if (process.env.ANTHROPIC_API_KEY) { + options.apiKey = process.env.ANTHROPIC_API_KEY; + console.log(' Using API_KEY'); + } + + options.env = process.env; + + console.log(''); + + // Call SDK's query function + const result = query({ + prompt: 'Hello! Please introduce yourself in one sentence.', + options, + }); + + console.log('💬 AI Response:\n'); + + // Iterate through response stream + for await (const message of result) { + // Handle different message types + switch (message.type) { + case 'assistant': + // Assistant message - contains text content + if (message.content) { + for (const block of message.content) { + if (block.type === 'text') { + console.log(block.text); + } else if (block.type === 'thinking') { + console.log('🤔 [Thinking]:', block.thinking); + } + } + } + break; + + case 'partial_assistant': + // Streaming assistant message (partial content) + if (message.content) { + for (const block of message.content) { + if (block.type === 'text') { + process.stdout.write(block.text); + } + } + } + break; + + case 'result': + // Final result message + if (message.subtype === 'success') { + console.log('\n\n✅ Conversation completed'); + } else if (message.subtype === 'error') { + console.error('\n\n❌ Error:', message.error); + } + break; + + case 'compact_boundary': + // Compact boundary message (used to separate messages) + console.log('\n--- Message Boundary ---'); + break; + + default: + // Other message types + console.log('\n[Message Type]:', message.type); + } + } + + console.log('\n🎉 Done!\n'); + + } catch (error: any) { + console.error('\n❌ Error occurred:', error.message); + if (error.stack) { + console.error('Error stack:', error.stack); + } + process.exit(1); + } +} + +// Run main function +main(); diff --git a/integrations/claude-agent-sdk/typescript/examples/pure-sdk-with-tools.ts b/integrations/claude-agent-sdk/typescript/examples/pure-sdk-with-tools.ts new file mode 100644 index 000000000..a4b2d1c20 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/pure-sdk-with-tools.ts @@ -0,0 +1,164 @@ +/** + * Pure Claude Agent SDK Example - With Tools + * + * Demonstrates how to use tool() and createSdkMcpServer() to define and use tools + * Reference: https://docs.claude.com/docs/agent-sdk/typescript#tool + * + * Environment variables (in .env.local): + * - ANTHROPIC_AUTH_TOKEN: Claude API authentication token + */ + +import dotenv from 'dotenv'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { z } from 'zod'; + +// Get current file directory in ESM mode +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Load .env.local environment variables (try multiple paths) +dotenv.config({ path: resolve(__dirname, '.env.local') }); +dotenv.config({ path: resolve(process.cwd(), '.env.local') }); + +// Validate environment variables +if (!process.env.ANTHROPIC_AUTH_TOKEN && !process.env.ANTHROPIC_API_KEY) { + console.error('❌ Error: ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY not found'); + process.exit(1); +} + +console.log('✅ Environment variables loaded\n'); + +async function main() { + try { + // Dynamically import Claude Agent SDK + const { query, tool, createSdkMcpServer } = await import('@anthropic-ai/claude-agent-sdk'); + + console.log('🚀 Starting Claude Agent SDK call (with tools)...\n'); + + // Create addition tool using tool() + const addTool = tool( + 'add', + 'Adds two numbers', + { + a: z.number().describe('First number'), + b: z.number().describe('Second number'), + }, + async (args) => { + const result = args.a + args.b; + console.log(`\n🔧 [Tool Execution] add(${args.a}, ${args.b}) = ${result}`); + return { + content: [ + { + type: 'text', + text: `Calculation result: ${args.a} + ${args.b} = ${result}`, + }, + ], + }; + } + ); + + // Create multiplication tool using tool() + const multiplyTool = tool( + 'multiply', + 'Multiplies two numbers', + { + a: z.number().describe('First number'), + b: z.number().describe('Second number'), + }, + async (args) => { + const result = args.a * args.b; + console.log(`\n🔧 [Tool Execution] multiply(${args.a}, ${args.b}) = ${result}`); + return { + content: [ + { + type: 'text', + text: `Calculation result: ${args.a} × ${args.b} = ${result}`, + }, + ], + }; + } + ); + + // Create MCP server using createSdkMcpServer() + const calculatorServer = createSdkMcpServer({ + name: 'calculator', + version: '1.0.0', + tools: [addTool, multiplyTool], + }); + + // SDK configuration options + const options: any = { + permissionMode: 'bypassPermissions' as const, + mcpServers: { + calculator: calculatorServer, // Use the created MCP server + }, + verbose: true, + + // Add stderr callback for debugging + stderr: (data: string) => { + console.error('[Claude CLI Debug]:', data); + }, + }; + + // Call SDK + const result = query({ + prompt: 'Please help me calculate: (15 + 27) × 2', + options, + }); + + console.log('💬 AI Response:\n'); + + // Iterate through response stream + for await (const message of result) { + switch (message.type) { + case 'assistant': + // SDKAssistantMessage contains message.message.content + if (message.message?.content) { + for (const block of message.message.content) { + if (block.type === 'text') { + console.log(block.text); + } else if (block.type === 'tool_use') { + console.log(`\n🔧 [Tool Call] ${block.name}`, block.input); + } + } + } + break; + + case 'stream_event': + // Streaming events + if (message.event?.type === 'content_block_delta') { + const delta = (message.event as any).delta; + if (delta?.type === 'text_delta') { + process.stdout.write(delta.text); + } + } + break; + + case 'result': + if (message.subtype === 'success') { + console.log('\n\n✅ Conversation completed'); + } else { + // error_during_execution | error_max_turns | error_max_budget_usd + console.error('\n\n❌ Error:', message.subtype); + if ('errors' in message && message.errors) { + console.error('Detailed errors:', message.errors); + } + } + break; + } + } + + console.log('\n🎉 Done!\n'); + + } catch (error: any) { + console.error('\n❌ Error occurred:', error.message); + if (error.stack) { + console.error('Error stack:', error.stack); + } + process.exit(1); + } +} + +// Run main function +main(); diff --git a/integrations/claude-agent-sdk/typescript/examples/simple-test-server.js b/integrations/claude-agent-sdk/typescript/examples/simple-test-server.js new file mode 100644 index 000000000..2c17efdb0 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/simple-test-server.js @@ -0,0 +1,158 @@ +/** + * Simplified test server - for quick testing of Claude Agent SDK TypeScript integration + * Does not depend on complex workspace dependencies + */ + +const http = require('http'); +const { ClaudeAgent } = require('../dist/index.js'); + +// Get configuration from environment variables +require('dotenv').config({ path: '.env.local' }); +require('dotenv').config({ path: '.env' }); + +const PORT = process.env.PORT || 3000; +const API_KEY = process.env.ANTHROPIC_API_KEY; + +if (!API_KEY) { + console.error('❌ Error: ANTHROPIC_API_KEY environment variable not set'); + console.error('Please set ANTHROPIC_API_KEY in .env.local or .env file'); + process.exit(1); +} + +// Initialize Claude Agent +const agent = new ClaudeAgent({ + apiKey: API_KEY, + enablePersistentSessions: true, + sessionTimeout: 30 * 60 * 1000, // 30 minutes + permissionMode: 'ask', + claudeOptions: { + systemPrompt: process.env.SYSTEM_PROMPT || 'You are a helpful assistant', + appName: process.env.APP_NAME || 'simple-test-server', + }, +}); + +console.log('✓ Claude Agent initialized successfully'); + +// Create HTTP server +const server = http.createServer(async (req, res) => { + // CORS headers + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + + // Handle OPTIONS preflight request + if (req.method === 'OPTIONS') { + res.writeHead(200); + res.end(); + return; + } + + // Health check + if (req.url === '/health' && req.method === 'GET') { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ status: 'ok', timestamp: new Date().toISOString() })); + return; + } + + // Chat endpoint + if (req.url === '/api/chat' && req.method === 'POST') { + let body = ''; + + req.on('data', chunk => { + body += chunk.toString(); + }); + + req.on('end', async () => { + try { + const input = JSON.parse(body); + + console.log('📨 Received request:', { + agentId: input.agentId, + threadId: input.threadId, + messageCount: input.messages?.length || 0 + }); + + // Set SSE response headers + res.writeHead(200, { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + 'Connection': 'keep-alive', + }); + + // Run agent and stream results + const subscription = agent.run(input).subscribe({ + next: (event) => { + // Send SSE event + const eventData = JSON.stringify(event); + res.write(`data: ${eventData}\n\n`); + + // Logging + if (event.type === 'text_message_content') { + process.stdout.write(event.text || ''); + } else if (event.type === 'run_started') { + console.log('\n🚀 Execution started, runId:', event.runId); + } else if (event.type === 'run_finished') { + console.log('\n✓ Execution completed'); + } + }, + error: (error) => { + console.error('\n❌ Error:', error.message); + const errorEvent = JSON.stringify({ + type: 'error', + error: error.message + }); + res.write(`data: ${errorEvent}\n\n`); + res.end(); + }, + complete: () => { + res.end(); + }, + }); + + // Handle client disconnect + req.on('close', () => { + subscription.unsubscribe(); + console.log('🔌 Client disconnected'); + }); + + } catch (error) { + console.error('❌ Request processing error:', error.message); + res.writeHead(500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: error.message })); + } + }); + return; + } + + // 404 + res.writeHead(404, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Not Found' })); +}); + +// Start server +server.listen(PORT, () => { + console.log('\n🎉 Simplified test server started!'); + console.log(`📍 Address: http://localhost:${PORT}`); + console.log(`🏥 Health check: http://localhost:${PORT}/health`); + console.log(`💬 Chat endpoint: http://localhost:${PORT}/api/chat`); + console.log('\nPress Ctrl+C to stop the server\n'); +}); + +// Graceful shutdown +process.on('SIGINT', async () => { + console.log('\n\n👋 Shutting down server...'); + await agent.cleanup(); + server.close(() => { + console.log('✓ Server closed'); + process.exit(0); + }); +}); + +process.on('SIGTERM', async () => { + console.log('\n\n👋 Shutting down server...'); + await agent.cleanup(); + server.close(() => { + console.log('✓ Server closed'); + process.exit(0); + }); +}); diff --git a/integrations/claude-agent-sdk/typescript/examples/src/server.ts b/integrations/claude-agent-sdk/typescript/examples/src/server.ts new file mode 100644 index 000000000..2f0aa86ab --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/src/server.ts @@ -0,0 +1,297 @@ +/** + * Example Express server using Claude Agent SDK + */ + +import dotenv from 'dotenv'; +import { resolve } from 'path'; +import express, { Request, Response } from 'express'; +import cors from 'cors'; +import { ClaudeAgent } from '@ag-ui/claude'; +import type { RunAgentInput } from '@ag-ui/client'; + +// Load environment variables from .env.local or .env +// Try multiple locations in order of priority +dotenv.config({ path: resolve(__dirname, '../.env.local') }); // examples/.env.local (highest priority) +dotenv.config({ path: resolve(__dirname, '../../.env.local') }); // typescript/.env.local +dotenv.config({ path: resolve(__dirname, '../.env') }); // examples/.env +dotenv.config({ path: resolve(__dirname, '../../.env') }); // typescript/.env + +const app = express(); +const port = process.env.PORT || 8000; + +// Middleware +app.use(cors()); +app.use(express.json()); + +// Validate and log environment variables +console.log('=== Environment Variables ==='); +console.log('ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY ? 'SET (' + process.env.ANTHROPIC_API_KEY.substring(0, 10) + '...)' : 'NOT SET'); +console.log('ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'SET (' + process.env.ANTHROPIC_AUTH_TOKEN.substring(0, 10) + '...)' : 'NOT SET'); +console.log('ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'NOT SET (will use default)'); +console.log('PORT:', process.env.PORT || '8000 (default)'); +console.log('PERMISSION_MODE:', process.env.PERMISSION_MODE || 'bypassPermissions (default)'); +console.log('VERBOSE:', process.env.VERBOSE || 'false (default)'); +console.log('=============================\n'); + +// SDK will automatically read ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment +// Do NOT pass apiKey in config - let SDK handle it automatically +if (!process.env.ANTHROPIC_AUTH_TOKEN && !process.env.ANTHROPIC_API_KEY) { + console.error('❌ ERROR: Neither ANTHROPIC_API_KEY nor ANTHROPIC_AUTH_TOKEN found in environment variables.'); + console.error('SDK will not be able to authenticate. Please set one in .env.local or .env file.'); + process.exit(1); +} + +// Initialize Claude Agent +// Do NOT pass apiKey or baseUrl - SDK reads from environment variables automatically +const agent = new ClaudeAgent({ + enablePersistentSessions: process.env.ENABLE_PERSISTENT_SESSIONS !== 'false', + sessionTimeout: process.env.SESSION_TIMEOUT + ? parseInt(process.env.SESSION_TIMEOUT) + : 30 * 60 * 1000, // 30 minutes + // Valid permission modes: 'default', 'acceptEdits', 'bypassPermissions', 'plan' + permissionMode: (process.env.PERMISSION_MODE as any) || 'bypassPermissions', + // Add stderr callback for debugging - CRITICAL for capturing CLI errors + stderr: (data: string) => { + // Log all stderr output from Claude CLI + console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + console.error('[Claude CLI stderr]:', data); + console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + + // Also log to file if needed for debugging + if (process.env.LOG_TO_FILE === 'true') { + const fs = require('fs'); + const timestamp = new Date().toISOString(); + fs.appendFileSync('/tmp/claude-cli-stderr.log', `[${timestamp}] ${data}\n`); + } + }, + // Enable verbose logging + verbose: process.env.VERBOSE === 'true', +}); + +console.log('✓ Claude Agent initialized with stderr callback for error logging'); + +// Health check endpoint +app.get('/health', (req: Request, res: Response) => { + res.json({ status: 'ok' }); +}); + +// Chat endpoint for CopilotKit compatibility +app.post('/chat', async (req: Request, res: Response) => { + try { + const input: RunAgentInput = req.body; + + // Validate input + if (!input.messages || input.messages.length === 0) { + return res.status(400).json({ error: 'Messages are required' }); + } + + // Set headers for Server-Sent Events + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + // Run the agent and stream events + agent.run(input).subscribe({ + next: (event: any) => { + // Send event as SSE + res.write(`data: ${JSON.stringify(event)}\n\n`); + }, + error: (error: any) => { + console.error('Agent error:', error); + res.write(`data: ${JSON.stringify({ type: 'error', error: error.message })}\n\n`); + res.end(); + }, + complete: () => { + res.end(); + }, + }); + + // Handle client disconnect + req.on('close', () => { + console.log('Client disconnected'); + }); + } catch (error: any) { + console.error('Request error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Main agent endpoint +app.post('/api/run-agent', async (req: Request, res: Response) => { + try { + const input: RunAgentInput = req.body; + + // Validate input + if (!input.messages || input.messages.length === 0) { + return res.status(400).json({ error: 'Messages are required' }); + } + + // Set headers for Server-Sent Events + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + // Run the agent and stream events + agent.run(input).subscribe({ + next: (event: any) => { + // Send event as SSE + res.write(`data: ${JSON.stringify(event)}\n\n`); + }, + error: (error: any) => { + console.error('Agent error:', error); + res.write(`data: ${JSON.stringify({ type: 'error', error: error.message })}\n\n`); + res.end(); + }, + complete: () => { + res.end(); + }, + }); + + // Handle client disconnect + req.on('close', () => { + console.log('Client disconnected'); + }); + } catch (error: any) { + console.error('Request error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Example tools definition +const exampleTools = [ + { + name: 'calculator', + description: 'Performs basic arithmetic calculations', + parameters: { + type: 'object', + properties: { + operation: { + type: 'string', + enum: ['add', 'subtract', 'multiply', 'divide'], + description: 'The operation to perform', + }, + a: { + type: 'number', + description: 'First number', + }, + b: { + type: 'number', + description: 'Second number', + }, + }, + required: ['operation', 'a', 'b'], + }, + handler: async (args: { operation: string; a: number; b: number }) => { + const { operation, a, b } = args; + let result: number; + + switch (operation) { + case 'add': + result = a + b; + break; + case 'subtract': + result = a - b; + break; + case 'multiply': + result = a * b; + break; + case 'divide': + if (b === 0) { + throw new Error('Division by zero'); + } + result = a / b; + break; + default: + throw new Error(`Unknown operation: ${operation}`); + } + + return `The result of ${a} ${operation} ${b} is ${result}`; + }, + }, + { + name: 'get_weather', + description: 'Gets the current weather for a location', + client: true, // This tool runs on the client + parameters: { + type: 'object', + properties: { + location: { + type: 'string', + description: 'The city and country, e.g. "San Francisco, US"', + }, + }, + required: ['location'], + }, + }, +]; + +// Example endpoint with tools +app.post('/api/run-agent-with-tools', async (req: Request, res: Response) => { + try { + const input: RunAgentInput = { + ...req.body, + context: { + ...req.body.context, + tools: exampleTools, + }, + }; + + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + agent.run(input).subscribe({ + next: (event: any) => { + res.write(`data: ${JSON.stringify(event)}\n\n`); + }, + error: (error: any) => { + console.error('Agent error:', error); + res.write(`data: ${JSON.stringify({ type: 'error', error: error.message })}\n\n`); + res.end(); + }, + complete: () => { + res.end(); + }, + }); + + req.on('close', () => { + console.log('Client disconnected'); + }); + } catch (error: any) { + console.error('Request error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Cleanup endpoint +app.post('/api/cleanup', async (req: Request, res: Response) => { + try { + await agent.cleanup(); + res.json({ message: 'Cleanup successful' }); + } catch (error: any) { + console.error('Cleanup error:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Start server +app.listen(port, () => { + console.log(`Claude Agent server listening on port ${port}`); + console.log(`Chat endpoint: http://localhost:${port}/chat`); + console.log(`API endpoint: http://localhost:${port}/api/run-agent`); + console.log(`With tools: http://localhost:${port}/api/run-agent-with-tools`); +}); + +// Graceful shutdown +process.on('SIGINT', async () => { + console.log('Shutting down gracefully...'); + await agent.cleanup(); + process.exit(0); +}); + +process.on('SIGTERM', async () => { + console.log('Shutting down gracefully...'); + await agent.cleanup(); + process.exit(0); +}); + diff --git a/integrations/claude-agent-sdk/typescript/examples/test-client.sh b/integrations/claude-agent-sdk/typescript/examples/test-client.sh new file mode 100644 index 000000000..9c1fa247a --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/test-client.sh @@ -0,0 +1,160 @@ +#!/bin/bash + +# Simple test client script +# For testing Claude Agent SDK TypeScript server + +BASE_URL="http://localhost:3000" + +# Color definitions +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE} Claude Agent SDK TypeScript - Test Client${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" + +# Test 1: Health check +echo -e "${YELLOW}[Test 1]${NC} Health check..." +HEALTH_RESPONSE=$(curl -s "$BASE_URL/health") +if echo "$HEALTH_RESPONSE" | grep -q "ok"; then + echo -e "${GREEN}✓${NC} Server health status OK" + echo " Response: $HEALTH_RESPONSE" +else + echo -e "${RED}✗${NC} Health check failed" + echo " Response: $HEALTH_RESPONSE" + exit 1 +fi +echo "" + +# Test 2: Simple conversation +echo -e "${YELLOW}[Test 2]${NC} Simple conversation test..." +echo -e "${BLUE}Sending message:${NC} 'Hello, please introduce yourself'" +echo "" + +curl -N -X POST "$BASE_URL/api/chat" \ + -H "Content-Type: application/json" \ + -d '{ + "agentId": "test_agent", + "threadId": "test_thread_1", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "Hello, please introduce yourself in one sentence" + } + ], + "context": {} + }' 2>/dev/null | while IFS= read -r line; do + if [[ $line == data:* ]]; then + # Extract JSON after data: + json_data="${line#data: }" + # Try to parse and format output + event_type=$(echo "$json_data" | grep -o '"type":"[^"]*"' | cut -d'"' -f4) + + case $event_type in + "run_started") + echo -e "\n${GREEN}▶ Execution started${NC}" + ;; + "text_message_content") + text=$(echo "$json_data" | grep -o '"text":"[^"]*"' | cut -d'"' -f4 | sed 's/\\n/\n/g') + echo -n "$text" + ;; + "run_finished") + echo -e "\n${GREEN}✓ Execution completed${NC}" + ;; + "error") + error=$(echo "$json_data" | grep -o '"error":"[^"]*"' | cut -d'"' -f4) + echo -e "\n${RED}✗ Error: $error${NC}" + ;; + esac + fi +done + +echo "" +echo "" + +# Test 3: Multi-turn conversation +echo -e "${YELLOW}[Test 3]${NC} Multi-turn conversation test..." +echo -e "${BLUE}Round 1:${NC} 'My name is Zhang San'" +echo "" + +curl -N -X POST "$BASE_URL/api/chat" \ + -H "Content-Type: application/json" \ + -d '{ + "agentId": "test_agent", + "threadId": "test_thread_2", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "My name is Zhang San" + } + ], + "context": {} + }' 2>/dev/null | while IFS= read -r line; do + if [[ $line == data:* ]]; then + json_data="${line#data: }" + event_type=$(echo "$json_data" | grep -o '"type":"[^"]*"' | cut -d'"' -f4) + + if [[ $event_type == "text_message_content" ]]; then + text=$(echo "$json_data" | grep -o '"text":"[^"]*"' | cut -d'"' -f4) + echo -n "$text" + elif [[ $event_type == "run_finished" ]]; then + echo "" + fi + fi +done + +echo "" +echo "" +sleep 1 + +echo -e "${BLUE}Round 2:${NC} 'Do you remember my name?'" +echo "" + +curl -N -X POST "$BASE_URL/api/chat" \ + -H "Content-Type: application/json" \ + -d '{ + "agentId": "test_agent", + "threadId": "test_thread_2", + "messages": [ + { + "id": "msg_1", + "role": "user", + "content": "My name is Zhang San" + }, + { + "id": "msg_2", + "role": "assistant", + "content": "Hello Zhang San! Nice to meet you." + }, + { + "id": "msg_3", + "role": "user", + "content": "Do you remember my name?" + } + ], + "context": {} + }' 2>/dev/null | while IFS= read -r line; do + if [[ $line == data:* ]]; then + json_data="${line#data: }" + event_type=$(echo "$json_data" | grep -o '"type":"[^"]*"' | cut -d'"' -f4) + + if [[ $event_type == "text_message_content" ]]; then + text=$(echo "$json_data" | grep -o '"text":"[^"]*"' | cut -d'"' -f4) + echo -n "$text" + elif [[ $event_type == "run_finished" ]]; then + echo "" + fi + fi +done + +echo "" +echo "" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${GREEN}✓ All tests completed!${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" diff --git a/integrations/claude-agent-sdk/typescript/examples/tsconfig.json b/integrations/claude-agent-sdk/typescript/examples/tsconfig.json new file mode 100644 index 000000000..ab4b79f19 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/examples/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} + diff --git a/integrations/claude-agent-sdk/typescript/jest.config.js b/integrations/claude-agent-sdk/typescript/jest.config.js new file mode 100644 index 000000000..247c74502 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/jest.config.js @@ -0,0 +1,26 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + roots: ['/__tests__', '/__mocks__'], + testMatch: ['**/__tests__/**/*.test.ts'], + setupFilesAfterEnv: ['/__tests__/setup.ts'], + moduleNameMapper: { + '^@ag-ui/client$': '/__mocks__/@ag-ui/client.ts', + '^@ag-ui/core$': '/__mocks__/@ag-ui/core.ts', + '^@anthropic-ai/claude-agent-sdk$': '/__mocks__/@anthropic-ai/claude-agent-sdk.ts', + }, + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/**/*.d.ts', + '!src/index.ts', + ], + coverageThreshold: { + global: { + branches: 40, + functions: 40, + lines: 40, + statements: 40, + }, + }, +}; + diff --git a/integrations/claude-agent-sdk/typescript/package.json b/integrations/claude-agent-sdk/typescript/package.json new file mode 100644 index 000000000..53c54110c --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/package.json @@ -0,0 +1,47 @@ +{ + "name": "@ag-ui/claude", + "version": "0.0.1", + "license": "Apache-2.0", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "sideEffects": false, + "private": false, + "publishConfig": { + "access": "public" + }, + "files": [ + "dist/**", + "README.md" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "clean": "rm -rf dist .turbo node_modules", + "typecheck": "tsc --noEmit", + "test": "jest", + "test:watch": "jest --watch", + "link:global": "pnpm link --global", + "unlink:global": "pnpm unlink --global" + }, + "dependencies": { + "@anthropic-ai/claude-agent-sdk": "latest", + "rxjs": "7.8.1", + "zod": "^3.25.67" + }, + "peerDependencies": { + "@ag-ui/core": ">=0.0.40", + "@ag-ui/client": ">=0.0.40" + }, + "devDependencies": { + "@ag-ui/core": "workspace:*", + "@ag-ui/client": "workspace:*", + "@types/jest": "^29.5.14", + "@types/node": "^20.11.19", + "jest": "^29.7.0", + "ts-jest": "^29.1.2", + "tsup": "^8.0.2", + "typescript": "^5.3.3" + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/agent.ts b/integrations/claude-agent-sdk/typescript/src/agent.ts new file mode 100644 index 000000000..753e48c72 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/agent.ts @@ -0,0 +1,435 @@ +/** + * Claude Agent: Main agent class that integrates Claude SDK with AG-UI Protocol + */ + +import { Observable, Subscriber } from 'rxjs'; +import { + AbstractAgent, + RunAgentInput, + EventType, + RunStartedEvent, + RunFinishedEvent, + RunErrorEvent, + StepStartedEvent, + StepFinishedEvent, +} from '@ag-ui/client'; +import type { + ClaudeAgentConfig, + ProcessedEvents, + ClaudeSDKClient, + Options, + SDKMessage, +} from './types'; +import { SessionManager } from './session-manager'; +import { EventTranslator } from './event-translator'; +import { ToolAdapter } from './tool-adapter'; +import { ExecutionState, ExecutionStateManager } from './execution-state'; +import { + generateRunId, + convertAgUiMessagesToPrompt, + isToolResultSubmission, + formatErrorMessage, +} from './utils/converters'; + +/** + * ClaudeAgent integrates Claude Agent SDK with AG-UI Protocol + */ +export class ClaudeAgent extends AbstractAgent { + private sessionManager: SessionManager; + private executionStateManager: ExecutionStateManager; + private apiKey?: string; + private baseUrl?: string; + private sessionTimeout: number; + private enablePersistentSessions: boolean; + private permissionMode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'; + private stderr?: (data: string) => void; + private verbose?: boolean; + + constructor(config: ClaudeAgentConfig) { + super(config); + // SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + // Only set these if explicitly provided in config (optional) + this.apiKey = config.apiKey; + this.baseUrl = config.baseUrl; + this.sessionTimeout = config.sessionTimeout || 30 * 60 * 1000; // 30 minutes + this.enablePersistentSessions = config.enablePersistentSessions !== false; + // Map legacy permission modes to new SDK values for backward compatibility + this.permissionMode = this.mapPermissionMode(config.permissionMode || 'bypassPermissions'); + this.stderr = config.stderr; + this.verbose = config.verbose; + this.sessionManager = SessionManager.getInstance(this.sessionTimeout); + this.executionStateManager = new ExecutionStateManager(); + } + + /** + * Map legacy permission modes to new SDK values for backward compatibility + */ + private mapPermissionMode(mode?: string): 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' { + const modeMap: Record = { + 'ask': 'default', + 'auto': 'bypassPermissions', + 'none': 'bypassPermissions', + 'default': 'default', + 'acceptEdits': 'acceptEdits', + 'bypassPermissions': 'bypassPermissions', + 'plan': 'plan', + }; + return modeMap[mode || 'bypassPermissions'] || 'bypassPermissions'; + } + + /** + * Run the agent with the given input + */ + run(input: RunAgentInput): Observable { + return new Observable((subscriber) => { + this.executeAgent(input, subscriber).catch((error) => { + subscriber.error(error); + }); + }); + } + + /** + * Execute the agent asynchronously + */ + private async executeAgent( + input: RunAgentInput, + subscriber: Subscriber + ): Promise { + const runId = generateRunId(); + const sessionId = input.threadId || `session_${Date.now()}`; + + // Create execution state + const execution = this.executionStateManager.createExecution(runId, sessionId); + + try { + // Emit run started event + const runStartedEvent: RunStartedEvent = { + type: EventType.RUN_STARTED, + threadId: sessionId, + runId, + }; + subscriber.next(runStartedEvent); + execution.addEvent(runStartedEvent); + + // Get or create session + const session = this.sessionManager.getSession(sessionId, 'default'); + + // Get unseen messages + const unseenMessages = this.sessionManager.getUnseenMessages( + sessionId, + input.messages || [] + ); + + // Check if this is a tool result submission + const isToolResult = isToolResultSubmission(input.messages || []); + + // Prepare tools + const tools = input.tools || []; + + // Prepare options for Claude SDK + const options = await this.prepareClaudeOptions(tools); + + // Extract prompt from messages + const prompt = convertAgUiMessagesToPrompt(unseenMessages); + + // Emit step started event + const stepStartedEvent: StepStartedEvent = { + type: EventType.STEP_STARTED, + stepName: `step_${runId}_1`, + }; + subscriber.next(stepStartedEvent); + execution.addEvent(stepStartedEvent); + + // Call Claude SDK + await this.callClaudeSDK( + prompt, + options, + session, + runId, + sessionId, + subscriber, + execution + ); + + // Mark messages as processed + this.sessionManager.markMessagesAsProcessed(sessionId, unseenMessages); + + // Emit step finished event + const stepFinishedEvent: StepFinishedEvent = { + type: EventType.STEP_FINISHED, + stepName: `step_${runId}_1`, + }; + subscriber.next(stepFinishedEvent); + execution.addEvent(stepFinishedEvent); + + // Emit run finished event + const runFinishedEvent: RunFinishedEvent = { + type: EventType.RUN_FINISHED, + threadId: sessionId, + runId, + }; + subscriber.next(runFinishedEvent); + execution.addEvent(runFinishedEvent); + + // Complete execution + execution.complete(); + subscriber.complete(); + } catch (error: any) { + // Emit run error event + const runErrorEvent: RunErrorEvent = { + type: EventType.RUN_ERROR, + message: formatErrorMessage(error), + }; + subscriber.next(runErrorEvent); + execution.addEvent(runErrorEvent); + + // Mark execution as failed + execution.fail(error); + + // Complete the observable + subscriber.complete(); + } + } + + /** + * Prepare Claude SDK options + * SDK automatically reads ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY from environment + * But baseUrl needs to be explicitly passed for third-party APIs + */ + private async prepareClaudeOptions(tools: any[]): Promise { + // Get baseUrl from config or environment + const baseUrl = this.baseUrl || process.env.ANTHROPIC_BASE_URL; + const apiKey = this.apiKey || process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY; + + // Debug logging + console.log('[Claude Agent] Preparing SDK options:', { + hasApiKey: !!apiKey, + hasBaseUrl: !!baseUrl, + baseUrl: baseUrl || 'not set', + permissionMode: this.permissionMode, + hasStderr: !!this.stderr, + verbose: this.verbose, + }); + + const options: Options = { + permissionMode: this.permissionMode, + // Add stderr callback for debugging - CRITICAL for error logging + ...(this.stderr && { stderr: this.stderr }), + // Add verbose flag for detailed logging + ...(this.verbose !== undefined && { verbose: this.verbose }), + env: process.env + }; + + // Verify stderr callback is set + if (this.stderr) { + console.log('[Claude Agent] ✓ stderr callback is configured for error logging'); + } else { + console.warn('[Claude Agent] ⚠️ stderr callback not configured - CLI errors may not be visible'); + } + + // Add tools if provided + if (tools && tools.length > 0) { + const mcpServer = await ToolAdapter.createMcpServerForTools(tools); + options.mcpServers = { + ag_ui_tools: mcpServer, + }; + + // Set allowed tools + options.allowedTools = ToolAdapter.getAllowedToolsList(tools); + } + + return options; + } + + /** + * Call Claude SDK + * Note: Currently only stateless mode is supported via query() function + */ + private async callClaudeSDK( + prompt: string, + options: Options, + session: any, + runId: string, + sessionId: string, + subscriber: Subscriber, + execution: ExecutionState + ): Promise { + const eventTranslator = new EventTranslator(runId, sessionId); + + // The current @anthropic-ai/claude-agent-sdk only supports stateless mode + // via the query() function. We use stateless mode for both cases. + await this.callClaudeSDKStateless( + prompt, + options, + eventTranslator, + subscriber, + execution + ); + } + + /** + * Call Claude SDK in persistent session mode + * Note: The current SDK only supports stateless mode via query() function + * This method falls back to stateless mode + */ + private async callClaudeSDKPersistent( + prompt: string, + options: Options, + session: any, + eventTranslator: EventTranslator, + subscriber: Subscriber, + execution: ExecutionState + ): Promise { + // The current @anthropic-ai/claude-agent-sdk only supports stateless mode + // via the query() function. For persistent sessions, we use query() + // but maintain session state in our SessionManager + await this.callClaudeSDKStateless(prompt, options, eventTranslator, subscriber, execution); + } + + /** + * Call Claude SDK in stateless mode + */ + private async callClaudeSDKStateless( + prompt: string, + options: Options, + eventTranslator: EventTranslator, + subscriber: Subscriber, + execution: ExecutionState + ): Promise { + try { + // Log environment variables for debugging + console.log('[Claude Agent] Environment check:'); + console.log(' ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY ? 'SET' : 'NOT SET'); + console.log(' ANTHROPIC_AUTH_TOKEN:', process.env.ANTHROPIC_AUTH_TOKEN ? 'SET' : 'NOT SET'); + console.log(' ANTHROPIC_BASE_URL:', process.env.ANTHROPIC_BASE_URL || 'NOT SET (using default)'); + console.log('[Claude Agent] Options passed to SDK:', { + hasApiKey: !!options.apiKey, + hasBaseUrl: !!options.baseUrl, + permissionMode: options.permissionMode, + hasMcpServers: !!options.mcpServers, + }); + + // Import Claude SDK dynamically + const { query } = await this.importClaudeSDK(); + + console.log('[Claude Agent] Calling SDK query()...'); + + // Call query function + // SDK will automatically read API key from environment variables (ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN) + // if not provided in options.apiKey + const queryResult = query({ prompt, options }); + + // Process responses + for await (const message of queryResult) { + console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + console.log('[Claude Agent] Received message type:', message?.type || 'unknown'); + console.log('[Claude Agent] Full message:', JSON.stringify(message, null, 2)); + + if (execution.isAborted()) { + console.log('[Claude Agent] Execution aborted by user'); + break; + } + + const events = eventTranslator.translateMessage(message); + console.log('[Claude Agent] Translated events count:', events.length); + for (const event of events) { + console.log('[Claude Agent] Sending event:', JSON.stringify(event, null, 2)); + subscriber.next(event); + execution.addEvent(event); + } + console.log('[Claude Agent] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + } + + console.log('[Claude Agent] Query completed successfully'); + } catch (error: any) { + // Log detailed error information + console.error('[Claude Agent] ERROR Details:'); + console.error(' Message:', error.message); + console.error(' Stack:', error.stack); + console.error(' Error object:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2)); + + // Handle Claude Code process errors + if (error.message && error.message.includes('exited with code')) { + throw new Error( + `Claude Code process failed. Please ensure:\n` + + `1. Claude CLI is installed and accessible (run: claude --version)\n` + + `2. ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set correctly in environment variables\n` + + `3. You have proper permissions to run Claude Code\n` + + `4. If using ANTHROPIC_BASE_URL, ensure it supports Claude Code protocol\n` + + `\nOriginal error: ${error.message}\n` + + `Error stack: ${error.stack || 'No stack trace'}` + ); + } + // Handle API key errors from SDK + if (error.message && (error.message.includes('API key') || error.message.includes('auth'))) { + throw new Error( + `API key error: ${error.message}\n` + + `Please ensure ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set in environment variables.` + ); + } + throw error; + } + } + + /** + * Dynamically import Claude SDK + */ + private async importClaudeSDK(): Promise { + try { + return await import('@anthropic-ai/claude-agent-sdk'); + } catch (error) { + throw new Error( + 'Claude Agent SDK not found. Please install it: npm install @anthropic-ai/claude-agent-sdk' + ); + } + } + + /** + * Abort a running execution + */ + abortExecution(runId: string): void { + const execution = this.executionStateManager.getExecution(runId); + if (execution) { + execution.abort(); + } + } + + /** + * Get execution state + */ + getExecutionState(runId: string): ExecutionState | undefined { + return this.executionStateManager.getExecution(runId); + } + + /** + * Get session manager (for testing) + */ + getSessionManager(): SessionManager { + return this.sessionManager; + } + + /** + * Get execution state manager (for testing) + */ + getExecutionStateManager(): ExecutionStateManager { + return this.executionStateManager; + } + + /** + * Cleanup resources + */ + async cleanup(): Promise { + // Abort all running executions + const runningExecutions = this.executionStateManager.getRunningExecutions(); + for (const execution of runningExecutions) { + execution.abort(); + } + + // Clear all sessions + this.sessionManager.clearAllSessions(); + + // Clear all executions + this.executionStateManager.clearAll(); + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/event-translator.ts b/integrations/claude-agent-sdk/typescript/src/event-translator.ts new file mode 100644 index 000000000..368f02f22 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/event-translator.ts @@ -0,0 +1,221 @@ +/** + * Event translator: Converts Claude SDK messages to AG-UI events + */ + +import { + TextMessageStartEvent, + TextMessageContentEvent, + TextMessageEndEvent, + ToolCallStartEvent, + ToolCallArgsEvent, + ToolCallEndEvent, + ToolCallResultEvent, + EventType, +} from '@ag-ui/client'; +import type { + SDKMessage, + SDKAssistantMessage, + ContentBlock, + TextBlock, + ToolUseBlock, + ToolResultBlock, + ProcessedEvents, +} from './types'; +import { + hasContentProperty, + isTextBlock, + isToolUseBlock, + isToolResultBlock, +} from './types'; + +/** + * EventTranslator converts Claude SDK messages to AG-UI protocol events + * + * NOTE: This translator only handles SDK message translation. + * Run lifecycle events (RUN_STARTED, RUN_FINISHED, etc.) and step events + * are handled by ClaudeAgent. + */ +export class EventTranslator { + private messageIdCounter = 0; + private currentMessageId: string | null = null; + private runId: string; + private threadId: string; + + constructor(runId: string, threadId: string) { + this.runId = runId; + this.threadId = threadId; + } + + /** + * Translate a Claude SDK message to AG-UI events + * NOTE: Does not emit RUN_STARTED, RUN_FINISHED, or STEP events - those are handled by ClaudeAgent + */ + translateMessage(message: SDKMessage): ProcessedEvents[] { + const events: ProcessedEvents[] = []; + + if (hasContentProperty(message)) { + events.push(...this.translateAssistantMessage(message as SDKAssistantMessage)); + } + // Note: ResultMessage (success/error) is ignored here + // Run completion is handled by ClaudeAgent, not EventTranslator + + return events; + } + + /** + * Translate an AssistantMessage with content blocks + */ + private translateAssistantMessage(message: SDKAssistantMessage): ProcessedEvents[] { + const events: ProcessedEvents[] = []; + + // Content is in message.message.content for SDKAssistantMessage + const content = message.message?.content || []; + + for (const block of content) { + if (isTextBlock(block)) { + events.push(...this.translateTextBlock(block)); + } else if (isToolUseBlock(block)) { + events.push(...this.translateToolUseBlock(block)); + } else if (isToolResultBlock(block)) { + events.push(...this.translateToolResultBlock(block)); + } + } + + return events; + } + + /** + * Translate a TextBlock to text message events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateTextBlock(block: TextBlock): ProcessedEvents[] { + const events: ProcessedEvents[] = []; + const messageId = this.generateMessageId(); + + // Start event + events.push({ + type: EventType.TEXT_MESSAGE_START, + messageId, + role: 'assistant', + }); + + // Content event - split text into delta chunks + const text = block.text; + if (text.length > 0) { + events.push({ + type: EventType.TEXT_MESSAGE_CONTENT, + messageId, + delta: text, + }); + } + + // End event + events.push({ + type: EventType.TEXT_MESSAGE_END, + messageId, + }); + + return events; + } + + /** + * Translate a ToolUseBlock to tool call events + * NOTE: Step events are handled by ClaudeAgent, not here + */ + private translateToolUseBlock(block: ToolUseBlock): ProcessedEvents[] { + const events: ProcessedEvents[] = []; + const toolCallId = block.id; + + // Start event + events.push({ + type: EventType.TOOL_CALL_START, + toolCallId, + toolCallName: block.name, + }); + + // Args event - send args as JSON string + const argsJson = JSON.stringify(block.input); + if (argsJson.length > 0) { + events.push({ + type: EventType.TOOL_CALL_ARGS, + toolCallId, + delta: argsJson, + }); + } + + // End event + events.push({ + type: EventType.TOOL_CALL_END, + toolCallId, + }); + + return events; + } + + /** + * Translate a ToolResultBlock to tool call result event + */ + private translateToolResultBlock(block: ToolResultBlock): ProcessedEvents[] { + const events: ProcessedEvents[] = []; + + // Extract content as string + let resultContent: string; + if (typeof block.content === 'string') { + resultContent = block.content; + } else if (Array.isArray(block.content)) { + // Handle array of content blocks + resultContent = block.content + .map((item) => { + if (item.type === 'text') { + return item.text || ''; + } + return JSON.stringify(item); + }) + .join('\n'); + } else { + resultContent = JSON.stringify(block.content); + } + + const messageId = this.generateMessageId(); + events.push({ + type: EventType.TOOL_CALL_RESULT, + toolCallId: block.tool_use_id, + messageId, + content: resultContent, + ...(block.is_error && { role: 'tool' as const }), + }); + + return events; + } + + /** + * Generate a unique message ID + */ + private generateMessageId(): string { + this.messageIdCounter++; + return `msg_${this.runId}_${this.messageIdCounter}`; + } + + /** + * Reset the translator state for a new execution + */ + reset(): void { + this.messageIdCounter = 0; + this.currentMessageId = null; + } + + /** + * Get current message ID + */ + getCurrentMessageId(): string | null { + return this.currentMessageId; + } + + /** + * Set current message ID + */ + setCurrentMessageId(messageId: string | null): void { + this.currentMessageId = messageId; + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/execution-state.ts b/integrations/claude-agent-sdk/typescript/src/execution-state.ts new file mode 100644 index 000000000..e5c98dba1 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/execution-state.ts @@ -0,0 +1,327 @@ +/** + * Execution state: Tracks background Claude executions + */ + +import type { ProcessedEvents } from './types'; + +/** + * ExecutionState manages the state of a Claude SDK execution + */ +export class ExecutionState { + readonly id: string; + readonly sessionId: string; + private _isRunning: boolean; + private _startTime: number; + private _endTime?: number; + private _events: ProcessedEvents[]; + private _error?: Error; + private _abortController: AbortController; + + constructor(id: string, sessionId: string) { + this.id = id; + this.sessionId = sessionId; + this._isRunning = true; + this._startTime = Date.now(); + this._events = []; + this._abortController = new AbortController(); + } + + /** + * Check if execution is running + */ + get isRunning(): boolean { + return this._isRunning; + } + + /** + * Get start time + */ + get startTime(): number { + return this._startTime; + } + + /** + * Get end time + */ + get endTime(): number | undefined { + return this._endTime; + } + + /** + * Get duration in milliseconds + */ + get duration(): number { + const end = this._endTime || Date.now(); + return end - this._startTime; + } + + /** + * Get all collected events + */ + get events(): ProcessedEvents[] { + return [...this._events]; + } + + /** + * Get error if any + */ + get error(): Error | undefined { + return this._error; + } + + /** + * Get abort signal + */ + get signal(): AbortSignal { + return this._abortController.signal; + } + + /** + * Add an event to the execution state + */ + addEvent(event: ProcessedEvents): void { + this._events.push(event); + } + + /** + * Add multiple events + */ + addEvents(events: ProcessedEvents[]): void { + this._events.push(...events); + } + + /** + * Mark execution as completed + */ + complete(): void { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + } + } + + /** + * Mark execution as failed + */ + fail(error: Error): void { + if (this._isRunning) { + this._isRunning = false; + this._endTime = Date.now(); + this._error = error; + } + } + + /** + * Abort the execution + */ + abort(): void { + if (this._isRunning) { + this._abortController.abort(); + this._isRunning = false; + this._endTime = Date.now(); + } + } + + /** + * Get execution statistics + */ + getStats(): { + duration: number; + eventCount: number; + isRunning: boolean; + hasError: boolean; + } { + return { + duration: this.duration, + eventCount: this._events.length, + isRunning: this._isRunning, + hasError: !!this._error, + }; + } + + /** + * Clear events (useful for memory management) + */ + clearEvents(): void { + this._events = []; + } + + /** + * Get the last N events + */ + getLastEvents(count: number): ProcessedEvents[] { + return this._events.slice(-count); + } + + /** + * Check if execution has been aborted + */ + isAborted(): boolean { + return this._abortController.signal.aborted; + } +} + +/** + * ExecutionStateManager manages multiple execution states + */ +export class ExecutionStateManager { + private executions: Map = new Map(); + private readonly maxExecutions: number; + + constructor(maxExecutions: number = 100) { + this.maxExecutions = maxExecutions; + } + + /** + * Create a new execution state + */ + createExecution(id: string, sessionId: string): ExecutionState { + const execution = new ExecutionState(id, sessionId); + this.executions.set(id, execution); + + // Clean up old executions if we exceed the limit + if (this.executions.size > this.maxExecutions) { + this.cleanupOldExecutions(); + } + + return execution; + } + + /** + * Get an execution state by ID + */ + getExecution(id: string): ExecutionState | undefined { + return this.executions.get(id); + } + + /** + * Check if an execution exists + */ + hasExecution(id: string): boolean { + return this.executions.has(id); + } + + /** + * Delete an execution state + */ + deleteExecution(id: string): boolean { + return this.executions.delete(id); + } + + /** + * Get all executions for a session + */ + getSessionExecutions(sessionId: string): ExecutionState[] { + const executions: ExecutionState[] = []; + for (const execution of this.executions.values()) { + if (execution.sessionId === sessionId) { + executions.push(execution); + } + } + return executions; + } + + /** + * Get running executions + */ + getRunningExecutions(): ExecutionState[] { + const running: ExecutionState[] = []; + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running.push(execution); + } + } + return running; + } + + /** + * Get completed executions + */ + getCompletedExecutions(): ExecutionState[] { + const completed: ExecutionState[] = []; + for (const execution of this.executions.values()) { + if (!execution.isRunning) { + completed.push(execution); + } + } + return completed; + } + + /** + * Abort all running executions for a session + */ + abortSessionExecutions(sessionId: string): void { + const sessionExecutions = this.getSessionExecutions(sessionId); + for (const execution of sessionExecutions) { + if (execution.isRunning) { + execution.abort(); + } + } + } + + /** + * Clean up old completed executions + */ + private cleanupOldExecutions(): void { + const completed = this.getCompletedExecutions(); + + // Sort by end time (oldest first) + completed.sort((a, b) => { + const aTime = a.endTime || a.startTime; + const bTime = b.endTime || b.startTime; + return aTime - bTime; + }); + + // Remove the oldest executions + const toRemove = Math.max(0, this.executions.size - this.maxExecutions); + for (let i = 0; i < toRemove && i < completed.length; i++) { + this.executions.delete(completed[i].id); + } + } + + /** + * Clear all executions + */ + clearAll(): void { + this.executions.clear(); + } + + /** + * Get total execution count + */ + getExecutionCount(): number { + return this.executions.size; + } + + /** + * Get execution statistics + */ + getStats(): { + total: number; + running: number; + completed: number; + failed: number; + } { + let running = 0; + let completed = 0; + let failed = 0; + + for (const execution of this.executions.values()) { + if (execution.isRunning) { + running++; + } else if (execution.error) { + failed++; + } else { + completed++; + } + } + + return { + total: this.executions.size, + running, + completed, + failed, + }; + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/index.ts b/integrations/claude-agent-sdk/typescript/src/index.ts new file mode 100644 index 000000000..ab4080b9d --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/index.ts @@ -0,0 +1,96 @@ +/** + * Claude Agent SDK integration with AG-UI Protocol + * + * This package provides a bridge between Claude Agent SDK and the AG-UI Protocol, + * enabling Claude agents to work seamlessly with AG-UI applications. + * + * @example + * ```typescript + * import { ClaudeAgent } from '@ag-ui/claude'; + * + * const agent = new ClaudeAgent({ + * apiKey: process.env.ANTHROPIC_API_KEY, + * enablePersistentSessions: true + * }); + * + * agent.run(input).subscribe({ + * next: (event) => console.log(event), + * error: (error) => console.error(error), + * complete: () => console.log('Done') + * }); + * ``` + */ + +// Main agent class +export { ClaudeAgent } from './agent'; + +// Session management +export { SessionManager } from './session-manager'; + +// Event translation +export { EventTranslator } from './event-translator'; + +// Tool adaptation +export { ToolAdapter } from './tool-adapter'; + +// Execution state management +export { ExecutionState, ExecutionStateManager } from './execution-state'; + +// Utility functions +export { + convertAgUiMessagesToPrompt, + convertAgUiMessageToClaude, + convertAgUiMessagesToClaude, + extractMessageContent, + hasToolResults, + extractToolResults, + generateRunId, + generateMessageId, + safeJsonParse, + safeJsonStringify, + isToolResultSubmission, + formatErrorMessage, + truncateText, + mergeTextBlocks, +} from './utils/converters'; + +// Type exports +export type { + ClaudeAgentConfig, + ProcessedEvents, + Session, + ClaudeSDKClient, + Options, + Query, + SDKMessage, + SDKAssistantMessage, + SDKUserMessage, + SDKSystemMessage, + SDKResultMessage, + SDKPartialAssistantMessage, + SDKCompactBoundaryMessage, + SDKPermissionDenial, + ContentBlock, + TextBlock, + ToolUseBlock, + ToolResultBlock, + ThinkingBlock, + SdkMcpToolDefinition, + CallToolResult, + McpSdkServerConfigWithInstance, + ExecutionState as ExecutionStateType, + ToolExecutionContext, + ConvertedMessage, +} from './types'; + +// Re-export type guards +export { + isAssistantMessage, + isResultMessage, + isTextBlock, + isToolUseBlock, + isToolResultBlock, + isThinkingBlock, + hasContentProperty, +} from './types'; + diff --git a/integrations/claude-agent-sdk/typescript/src/session-manager.ts b/integrations/claude-agent-sdk/typescript/src/session-manager.ts new file mode 100644 index 000000000..339cd94cb --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/session-manager.ts @@ -0,0 +1,299 @@ +/** + * Session manager: Manages agent sessions and state + */ + +import type { Message } from '@ag-ui/client'; +import type { Session, ClaudeSDKClient } from './types'; + +const DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000; // 30 minutes +const CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes + +/** + * SessionManager handles session lifecycle, message tracking, and state management + * Implements singleton pattern for centralized session control + */ +export class SessionManager { + private static instance: SessionManager | null = null; + private sessions: Map = new Map(); + private cleanupInterval: ReturnType | null = null; + private sessionTimeout: number; + + private constructor(sessionTimeout: number = DEFAULT_SESSION_TIMEOUT) { + this.sessionTimeout = sessionTimeout; + this.startCleanupInterval(); + } + + /** + * Get the singleton instance + */ + static getInstance(sessionTimeout?: number): SessionManager { + if (!SessionManager.instance) { + SessionManager.instance = new SessionManager(sessionTimeout); + } + return SessionManager.instance; + } + + /** + * Reset the singleton instance (useful for testing) + */ + static resetInstance(): void { + if (SessionManager.instance) { + SessionManager.instance.stopCleanupInterval(); + SessionManager.instance = null; + } + } + + /** + * Get or create a session + */ + getSession(sessionId: string, userId?: string): Session { + let session = this.sessions.get(sessionId); + + if (!session) { + session = { + id: sessionId, + userId, + processedMessageIds: new Set(), + state: {}, + createdAt: Date.now(), + lastAccessedAt: Date.now(), + }; + this.sessions.set(sessionId, session); + } else { + // Update last accessed time + session.lastAccessedAt = Date.now(); + } + + return session; + } + + /** + * Check if a session exists + */ + hasSession(sessionId: string): boolean { + return this.sessions.has(sessionId); + } + + /** + * Delete a session + */ + deleteSession(sessionId: string): boolean { + const session = this.sessions.get(sessionId); + if (session?.client) { + // Close the Claude SDK client if it exists + session.client.close().catch((error) => { + console.error(`Error closing Claude SDK client for session ${sessionId}:`, error); + }); + } + return this.sessions.delete(sessionId); + } + + /** + * Track a processed message + */ + trackMessage(sessionId: string, messageId: string): void { + const session = this.sessions.get(sessionId); + if (session) { + session.processedMessageIds.add(messageId); + session.lastAccessedAt = Date.now(); + } + } + + /** + * Check if a message has been processed + */ + isMessageProcessed(sessionId: string, messageId: string): boolean { + const session = this.sessions.get(sessionId); + return session ? session.processedMessageIds.has(messageId) : false; + } + + /** + * Get unseen messages (messages not yet processed) + */ + getUnseenMessages(sessionId: string, messages: Message[]): Message[] { + const session = this.sessions.get(sessionId); + if (!session) { + return messages; + } + + return messages.filter((msg) => { + const msgId = msg.id || `${msg.role}_${msg.content}`; + return !session.processedMessageIds.has(msgId); + }); + } + + /** + * Mark messages as processed + */ + markMessagesAsProcessed(sessionId: string, messages: Message[]): void { + const session = this.sessions.get(sessionId); + if (session) { + for (const msg of messages) { + const msgId = msg.id || `${msg.role}_${msg.content}`; + session.processedMessageIds.add(msgId); + } + session.lastAccessedAt = Date.now(); + } + } + + /** + * Get state value from session + */ + getStateValue(sessionId: string, key: string): any { + const session = this.sessions.get(sessionId); + return session?.state[key]; + } + + /** + * Set state value in session + */ + setStateValue(sessionId: string, key: string, value: any): void { + const session = this.sessions.get(sessionId); + if (session) { + session.state[key] = value; + session.lastAccessedAt = Date.now(); + } + } + + /** + * Remove state keys from session + */ + removeStateKeys(sessionId: string, keys: string[]): void { + const session = this.sessions.get(sessionId); + if (session) { + for (const key of keys) { + delete session.state[key]; + } + session.lastAccessedAt = Date.now(); + } + } + + /** + * Clear all state for a session + */ + clearSessionState(sessionId: string): void { + const session = this.sessions.get(sessionId); + if (session) { + session.state = {}; + session.lastAccessedAt = Date.now(); + } + } + + /** + * Set Claude SDK client for a session + */ + setClient(sessionId: string, client: ClaudeSDKClient): void { + const session = this.sessions.get(sessionId); + if (session) { + session.client = client; + session.lastAccessedAt = Date.now(); + } + } + + /** + * Get Claude SDK client for a session + */ + getClient(sessionId: string): ClaudeSDKClient | undefined { + const session = this.sessions.get(sessionId); + return session?.client; + } + + /** + * Get total number of sessions + */ + getSessionCount(): number { + return this.sessions.size; + } + + /** + * Get number of sessions for a specific user + */ + getUserSessionCount(userId: string): number { + let count = 0; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + count++; + } + } + return count; + } + + /** + * Get all session IDs + */ + getAllSessionIds(): string[] { + return Array.from(this.sessions.keys()); + } + + /** + * Get all sessions for a specific user + */ + getUserSessions(userId: string): Session[] { + const userSessions: Session[] = []; + for (const session of this.sessions.values()) { + if (session.userId === userId) { + userSessions.push(session); + } + } + return userSessions; + } + + /** + * Clean up stale sessions + */ + private cleanupStaleSessions(): void { + const now = Date.now(); + const sessionsToDelete: string[] = []; + + for (const [sessionId, session] of this.sessions.entries()) { + if (now - session.lastAccessedAt > this.sessionTimeout) { + sessionsToDelete.push(sessionId); + } + } + + for (const sessionId of sessionsToDelete) { + this.deleteSession(sessionId); + } + + if (sessionsToDelete.length > 0) { + console.log(`Cleaned up ${sessionsToDelete.length} stale sessions`); + } + } + + /** + * Start the cleanup interval + */ + private startCleanupInterval(): void { + if (!this.cleanupInterval) { + this.cleanupInterval = setInterval(() => { + this.cleanupStaleSessions(); + }, CLEANUP_INTERVAL); + + // Don't keep the process alive just for this interval + if (typeof (this.cleanupInterval as any).unref === 'function') { + (this.cleanupInterval as any).unref(); + } + } + } + + /** + * Stop the cleanup interval + */ + private stopCleanupInterval(): void { + if (this.cleanupInterval) { + clearInterval(this.cleanupInterval); + this.cleanupInterval = null; + } + } + + /** + * Clear all sessions (useful for testing) + */ + clearAllSessions(): void { + for (const sessionId of this.sessions.keys()) { + this.deleteSession(sessionId); + } + this.sessions.clear(); + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/tool-adapter.ts b/integrations/claude-agent-sdk/typescript/src/tool-adapter.ts new file mode 100644 index 000000000..3f24f6cb1 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/tool-adapter.ts @@ -0,0 +1,254 @@ +/** + * Tool adapter: Converts AG-UI tools to Claude SDK format + */ + +import { z } from 'zod'; +import type { Tool } from '@ag-ui/client'; +import type { + SdkMcpToolDefinition, + McpSdkServerConfigWithInstance, + CallToolResult, +} from './types'; + +// Extended Tool type that includes runtime properties +type ExtendedTool = Tool & { + client?: boolean; + handler?: (args: any) => any | Promise; + longRunning?: boolean; +}; + +/** + * ToolAdapter handles conversion of AG-UI tools to Claude SDK format + */ +export class ToolAdapter { + /** + * Convert AG-UI tools to Claude SDK MCP tool definitions + */ + static convertAgUiToolsToSdk(tools: Tool[]): SdkMcpToolDefinition[] { + return tools.map((tool) => this.convertSingleTool(tool as ExtendedTool)); + } + + /** + * Convert a single AG-UI tool to Claude SDK format + */ + private static convertSingleTool(tool: ExtendedTool): SdkMcpToolDefinition { + const zodSchema = this.convertJsonSchemaToZod(tool.parameters || {}); + + return { + name: tool.name, + description: tool.description || '', + inputSchema: zodSchema, + handler: async (args: any) => { + // For client tools, we mark them as long-running + // The actual execution will be handled by the client + if (tool.client) { + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + toolName: tool.name, + args, + isClientTool: true, + isLongRunning: true, + }), + }, + ], + }; + } + + // For backend tools, if there's a handler, execute it + if (tool.handler) { + try { + const result = await tool.handler(args); + return { + content: [ + { + type: 'text', + text: typeof result === 'string' ? result : JSON.stringify(result), + }, + ], + }; + } catch (error: any) { + return { + content: [ + { + type: 'text', + text: error.message || 'Tool execution failed', + }, + ], + isError: true, + }; + } + } + + // Default response for tools without handlers + return { + content: [ + { + type: 'text', + text: 'Tool executed (no handler)', + }, + ], + }; + }, + }; + } + + /** + * Convert JSON Schema to Zod schema + */ + private static convertJsonSchemaToZod(jsonSchema: any): z.ZodTypeAny { + if (!jsonSchema || typeof jsonSchema !== 'object') { + return z.object({}); + } + + const properties = jsonSchema.properties || {}; + const required = jsonSchema.required || []; + + const zodShape: Record = {}; + + for (const [key, prop] of Object.entries(properties)) { + const propSchema = prop as any; + let zodType = this.convertJsonSchemaTypeToZod(propSchema); + + // Make optional if not in required array + if (!required.includes(key)) { + zodType = zodType.optional(); + } + + zodShape[key] = zodType; + } + + return z.object(zodShape); + } + + /** + * Convert a single JSON Schema type to Zod type + */ + private static convertJsonSchemaTypeToZod(schema: any): z.ZodTypeAny { + const type = schema.type; + + switch (type) { + case 'string': + if (schema.enum) { + return z.enum(schema.enum as [string, ...string[]]); + } + return z.string(); + + case 'number': + case 'integer': + let numType = type === 'integer' ? z.number().int() : z.number(); + if (schema.minimum !== undefined) { + numType = numType.min(schema.minimum); + } + if (schema.maximum !== undefined) { + numType = numType.max(schema.maximum); + } + return numType; + + case 'boolean': + return z.boolean(); + + case 'array': + if (schema.items) { + const itemType = this.convertJsonSchemaTypeToZod(schema.items); + return z.array(itemType); + } + return z.array(z.any()); + + case 'object': + if (schema.properties) { + return this.convertJsonSchemaToZod(schema); + } + return z.record(z.any()); + + case 'null': + return z.null(); + + default: + // For any other type or if type is not specified + return z.any(); + } + } + + /** + * Create an MCP server configuration for AG-UI tools + */ + static async createMcpServerForTools(tools: Tool[]): Promise { + const sdkTools = this.convertAgUiToolsToSdk(tools as ExtendedTool[]); + + // Import createSdkMcpServer from Claude Agent SDK + const { createSdkMcpServer } = await import('@anthropic-ai/claude-agent-sdk'); + + // Use the official SDK function to create a properly formatted MCP server + return createSdkMcpServer({ + name: 'ag_ui_tools', + version: '1.0.0', + tools: sdkTools as any, // Cast to any to avoid type incompatibility + }); + } + + /** + * Extract tool calls from Claude SDK response + */ + static extractToolCalls(message: any): Array<{ + id: string; + name: string; + input: Record; + }> { + if (!message.content || !Array.isArray(message.content)) { + return []; + } + + return message.content + .filter((block: any) => block.type === 'tool_use') + .map((block: any) => ({ + id: block.id, + name: block.name, + input: block.input, + })); + } + + /** + * Check if a tool is a long-running client tool + */ + static isClientTool(toolName: string, tools: Tool[]): boolean { + const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined; + return tool?.client === true; + } + + /** + * Check if a tool is marked as long-running + */ + static isLongRunningTool(toolName: string, tools: Tool[]): boolean { + const tool = tools.find((t) => t.name === toolName) as ExtendedTool | undefined; + return tool?.client === true || tool?.longRunning === true; + } + + /** + * Format tool names for Claude SDK (with MCP server prefix) + */ + static formatToolNameForSdk(toolName: string, serverName: string = 'ag_ui_tools'): string { + return `mcp__${serverName}__${toolName}`; + } + + /** + * Parse tool name from SDK format (remove MCP server prefix) + */ + static parseToolNameFromSdk(sdkToolName: string): string { + const parts = sdkToolName.split('__'); + if (parts.length >= 3 && parts[0] === 'mcp') { + return parts.slice(2).join('__'); + } + return sdkToolName; + } + + /** + * Get allowed tools list for SDK options + */ + static getAllowedToolsList(tools: Tool[], serverName: string = 'ag_ui_tools'): string[] { + return tools.map((tool) => this.formatToolNameForSdk(tool.name, serverName)); + } +} + diff --git a/integrations/claude-agent-sdk/typescript/src/types.ts b/integrations/claude-agent-sdk/typescript/src/types.ts new file mode 100644 index 000000000..744b743c8 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/types.ts @@ -0,0 +1,259 @@ +/** + * Type definitions for Claude Agent SDK integration with AG-UI Protocol + */ + +import type { + TextMessageStartEvent, + TextMessageContentEvent, + TextMessageEndEvent, + ToolCallStartEvent, + ToolCallArgsEvent, + ToolCallEndEvent, + ToolCallResultEvent, + RunStartedEvent, + RunFinishedEvent, + RunErrorEvent, + StepStartedEvent, + StepFinishedEvent, + AgentConfig, + Tool, + Message, +} from '@ag-ui/client'; + +// Re-export Claude SDK types (will be imported from the actual SDK) +// These are placeholder interfaces based on the SDK documentation +export interface ClaudeSDKClient { + query(prompt: string): Promise; + receiveResponse(): AsyncIterableIterator; + close(): Promise; +} + +export interface Options { + apiKey?: string; + baseUrl?: string; + mcpServers?: Record; + allowedTools?: string[]; + // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan' + // Legacy values 'ask', 'auto', 'none' are also supported for backward compatibility + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + stderr?: (data: string) => void; + verbose?: boolean; + [key: string]: any; +} + +export interface Query { + next(): Promise>; + [Symbol.asyncIterator](): AsyncIterableIterator; +} + +// SDK Message types based on documentation +export type SDKMessage = + | SDKAssistantMessage + | SDKUserMessage + | SDKSystemMessage + | SDKResultMessage + | SDKPartialAssistantMessage + | SDKCompactBoundaryMessage + | SDKPermissionDenial; + +export interface SDKAssistantMessage { + type: 'assistant'; + message: { + id?: string; + content: ContentBlock[]; + [key: string]: any; + }; + parent_tool_use_id?: string | null; + uuid?: string; + session_id?: string; +} + +export interface SDKUserMessage { + type: 'user'; + content: string; + id?: string; +} + +export interface SDKSystemMessage { + type: 'system'; + content: string; +} + +export interface SDKResultMessage { + type: 'result'; + subtype: 'success' | 'error'; + error?: { + type: string; + message: string; + }; +} + +export interface SDKPartialAssistantMessage { + type: 'partial_assistant'; + content: ContentBlock[]; +} + +export interface SDKCompactBoundaryMessage { + type: 'compact_boundary'; +} + +export interface SDKPermissionDenial { + type: 'permission_denial'; + tool: string; + reason: string; +} + +// Content block types +export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ThinkingBlock; + +export interface TextBlock { + type: 'text'; + text: string; +} + +export interface ToolUseBlock { + type: 'tool_use'; + id: string; + name: string; + input: Record; +} + +export interface ToolResultBlock { + type: 'tool_result'; + tool_use_id: string; + content: string | Array<{ type: string; [key: string]: any }>; + is_error?: boolean; +} + +export interface ThinkingBlock { + type: 'thinking'; + thinking: string; +} + +// Tool definition types +export interface SdkMcpToolDefinition { + name: string; + description: string; + inputSchema: Schema; + handler: (args: any, extra?: any) => Promise; +} + +export interface CallToolResult { + content: Array<{ + type: 'text' | 'image' | 'resource'; + text?: string; + data?: string; + mimeType?: string; + [key: string]: any; + }>; + isError?: boolean; +} + +export interface McpSdkServerConfigWithInstance { + name: string; + version?: string; + tools?: Array>; +} + +// AG-UI Integration types +export type ProcessedEvents = + | TextMessageStartEvent + | TextMessageContentEvent + | TextMessageEndEvent + | ToolCallStartEvent + | ToolCallArgsEvent + | ToolCallEndEvent + | ToolCallResultEvent + | RunStartedEvent + | RunFinishedEvent + | RunErrorEvent + | StepStartedEvent + | StepFinishedEvent; + +// Session management types +export interface Session { + id: string; + userId?: string; + client?: ClaudeSDKClient; + processedMessageIds: Set; + state: Record; + createdAt: number; + lastAccessedAt: number; +} + +// Agent configuration +export interface ClaudeAgentConfig extends AgentConfig { + apiKey?: string; + baseUrl?: string; + sessionTimeout?: number; + enablePersistentSessions?: boolean; + // Valid permission modes from Agent SDK: 'default', 'acceptEdits', 'bypassPermissions', 'plan' + // Legacy values 'ask', 'auto', 'none' are mapped internally for backward compatibility + permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'ask' | 'auto' | 'none'; + mcpServers?: Record; + stderr?: (data: string) => void; + verbose?: boolean; +} + +// Execution state types +export interface ExecutionState { + id: string; + sessionId: string; + isRunning: boolean; + startTime: number; + events: ProcessedEvents[]; + error?: Error; +} + +// Helper type guards +export function isAssistantMessage(message: SDKMessage): message is SDKAssistantMessage { + return message.type === 'assistant'; +} + +export function isResultMessage(message: SDKMessage): message is SDKResultMessage { + return message.type === 'result'; +} + +export function isTextBlock(block: ContentBlock): block is TextBlock { + return block.type === 'text'; +} + +export function isToolUseBlock(block: ContentBlock): block is ToolUseBlock { + return block.type === 'tool_use'; +} + +export function isToolResultBlock(block: ContentBlock): block is ToolResultBlock { + return block.type === 'tool_result'; +} + +export function isThinkingBlock(block: ContentBlock): block is ThinkingBlock { + return block.type === 'thinking'; +} + +export function hasContentProperty(message: SDKMessage): message is SDKAssistantMessage | SDKPartialAssistantMessage { + // For SDKAssistantMessage, content is in message.content + if (message.type === 'assistant') { + return 'message' in message && + message.message !== null && + typeof message.message === 'object' && + 'content' in message.message && + Array.isArray((message.message as any).content); + } + // For SDKPartialAssistantMessage, content might be at top level + return 'content' in message && Array.isArray((message as any).content); +} + +// Tool execution types +export interface ToolExecutionContext { + toolName: string; + toolCallId: string; + isClientTool: boolean; + isLongRunning: boolean; +} + +// Message conversion types +export interface ConvertedMessage { + role: 'user' | 'assistant' | 'system'; + content: string | Array<{ type: string; [key: string]: any }>; +} + diff --git a/integrations/claude-agent-sdk/typescript/src/utils/converters.ts b/integrations/claude-agent-sdk/typescript/src/utils/converters.ts new file mode 100644 index 000000000..ba66d7913 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/src/utils/converters.ts @@ -0,0 +1,201 @@ +/** + * Message format converters + */ + +import type { Message } from '@ag-ui/client'; +import type { ConvertedMessage } from '../types'; + +/** + * Convert AG-UI messages to a format suitable for Claude SDK + */ +export function convertAgUiMessagesToPrompt(messages: Message[]): string { + // For Claude SDK, we typically extract the last user message as the prompt + // The SDK maintains conversation history internally (in persistent mode) + + // Find the last user message + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + if (msg.role === 'user') { + return extractMessageContent(msg); + } + } + + // If no user message found, return a default prompt + return 'Hello'; +} + +/** + * Extract text content from a message + */ +export function extractMessageContent(message: Message): string { + if (typeof message.content === 'string') { + return message.content; + } + + if (Array.isArray(message.content)) { + return message.content + .map((block: any) => { + if (typeof block === 'string') { + return block; + } + if (block.type === 'text') { + return block.text || ''; + } + // For other types (image, file, etc.), we might need special handling + return ''; + }) + .filter(Boolean) + .join('\n'); + } + + return String(message.content); +} + +/** + * Convert AG-UI message to Claude message format + */ +export function convertAgUiMessageToClaude(message: Message): ConvertedMessage { + const role = message.role as 'user' | 'assistant' | 'system'; + const content = extractMessageContent(message); + + return { + role, + content, + }; +} + +/** + * Convert multiple AG-UI messages to Claude format + */ +export function convertAgUiMessagesToClaude(messages: Message[]): ConvertedMessage[] { + return messages.map(convertAgUiMessageToClaude); +} + +/** + * Check if messages contain tool results + */ +export function hasToolResults(messages: Message[]): boolean { + return messages.some((msg) => { + if (typeof msg.content === 'string') { + return false; + } + if (Array.isArray(msg.content)) { + return msg.content.some((block: any) => { + return typeof block === 'object' && block.type === 'tool_result'; + }); + } + return false; + }); +} + +/** + * Extract tool results from messages + */ +export function extractToolResults(messages: Message[]): Array<{ + toolCallId: string; + result: string; +}> { + const results: Array<{ toolCallId: string; result: string }> = []; + + for (const msg of messages) { + if (typeof msg.content === 'string') { + continue; + } + + if (Array.isArray(msg.content)) { + for (const block of msg.content as any[]) { + if (typeof block === 'object' && block.type === 'tool_result') { + results.push({ + toolCallId: (block as any).toolCallId || (block as any).tool_use_id || '', + result: (block as any).result || (block as any).content || '', + }); + } + } + } + } + + return results; +} + +/** + * Generate a unique run ID + */ +export function generateRunId(): string { + return `run_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} + +/** + * Generate a unique message ID + */ +export function generateMessageId(prefix: string = 'msg'): string { + return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; +} + +/** + * Safely parse JSON string + */ +export function safeJsonParse(json: string, defaultValue: any = null): any { + try { + return JSON.parse(json); + } catch { + return defaultValue; + } +} + +/** + * Safely stringify JSON + */ +export function safeJsonStringify(obj: any, defaultValue: string = '{}'): string { + try { + return JSON.stringify(obj); + } catch { + return defaultValue; + } +} + +/** + * Check if a message is a tool result submission + */ +export function isToolResultSubmission(messages: Message[]): boolean { + // Check if the last message contains tool results + if (messages.length === 0) { + return false; + } + + const lastMessage = messages[messages.length - 1]; + return hasToolResults([lastMessage]); +} + +/** + * Format error message for display + */ +export function formatErrorMessage(error: any): string { + if (error instanceof Error) { + return error.message; + } + if (typeof error === 'string') { + return error; + } + return 'An unknown error occurred'; +} + +/** + * Truncate text to a maximum length + */ +export function truncateText(text: string, maxLength: number = 1000): string { + if (text.length <= maxLength) { + return text; + } + return text.slice(0, maxLength) + '...'; +} + +/** + * Merge consecutive text blocks + */ +export function mergeTextBlocks(blocks: Array<{ type: string; text?: string }>): string { + return blocks + .filter((block: any) => block.type === 'text' && block.text) + .map((block: any) => block.text) + .join(''); +} + diff --git a/integrations/claude-agent-sdk/typescript/tsconfig.json b/integrations/claude-agent-sdk/typescript/tsconfig.json new file mode 100644 index 000000000..051745ce9 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "esnext", + "lib": ["dom", "dom.iterable", "esnext"], + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "moduleResolution": "node", + "skipLibCheck": true, + "strict": true, + "jsx": "react-jsx", + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "stripInternal": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "__tests__"] +} + diff --git a/integrations/claude-agent-sdk/typescript/tsup.config.ts b/integrations/claude-agent-sdk/typescript/tsup.config.ts new file mode 100644 index 000000000..a6809a760 --- /dev/null +++ b/integrations/claude-agent-sdk/typescript/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: { + index: 'src/index.ts', + }, + dts: true, + format: ['cjs', 'esm'], + splitting: false, + sourcemap: true, + clean: true, + external: ['@ag-ui/core', '@ag-ui/client', '@anthropic-ai/claude-agent-sdk'], +}); + diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 512b27006..d770b73f7 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,5 +3,6 @@ packages: - "middlewares/*" - "sdks/typescript/packages/*" - "integrations/*/typescript" + - "integrations/*/typescript/examples" - "integrations/community/*/typescript" - "integrations/mastra/typescript/examples"