diff --git a/apps/cli/src/commands.ts b/apps/cli/src/commands.ts index ed50527..118e28d 100644 --- a/apps/cli/src/commands.ts +++ b/apps/cli/src/commands.ts @@ -1,7 +1,12 @@ // CLI slash commands — pure functions over a session context. // Spec: docs/DEVELOPMENT_PLAN.md §3.6 (30+ commands; M2 ships a core subset) -import type { DeepCodeSettings, SessionManager, SessionMeta } from '@deepcode/core'; +import type { + DeepCodeSettings, + McpClientHandle, + SessionManager, + SessionMeta, +} from '@deepcode/core'; import { redact, type Credentials } from '@deepcode/core'; export interface SessionContext { @@ -18,6 +23,10 @@ export interface SessionContext { exitRequested?: boolean; /** Replace history entirely (used by /clear, /resume). */ clearHistory?: boolean; + /** Connected MCP server handles (M3c). */ + mcpServers?: McpClientHandle[]; + /** MCP servers that failed to connect on startup (M3c). */ + mcpErrors?: Array<{ serverName: string; error: string }>; } export interface SlashCommand { @@ -215,6 +224,37 @@ export const InitCommand: SlashCommand = { }, }; +export const McpCommand: SlashCommand = { + name: '/mcp', + description: 'List connected MCP servers and their tools.', + async run(_args, ctx) { + const servers = ctx.mcpServers ?? []; + if (servers.length === 0) { + return [ + 'No MCP servers connected.', + '', + 'Add servers in settings.json under "mcpServers". Example:', + ' { "mcpServers": { "filesystem": { "command": "npx",', + ' "args": ["@modelcontextprotocol/server-filesystem", "/tmp"] } } }', + ]; + } + const lines = [`Connected MCP servers (${servers.length}):`]; + for (const s of servers) { + lines.push(` ● ${s.serverName} · ${s.tools.length} tools`); + for (const t of s.tools.slice(0, 6)) { + lines.push(` - ${t.name}`); + } + if (s.tools.length > 6) lines.push(` … and ${s.tools.length - 6} more`); + } + if ((ctx.mcpErrors ?? []).length > 0) { + lines.push(''); + lines.push('Servers that failed to connect:'); + for (const e of ctx.mcpErrors!) lines.push(` ✕ ${e.serverName} ${e.error}`); + } + return lines; + }, +}; + export const TodosCommand: SlashCommand = { name: '/todos', description: 'Show active TODO list (M3 wires TodoWrite tool).', @@ -237,6 +277,7 @@ export const BUILTIN_COMMANDS: SlashCommand[] = [ AddDirCommand, ResumeCommand, InitCommand, + McpCommand, TodosCommand, ]; diff --git a/apps/cli/src/repl.ts b/apps/cli/src/repl.ts index 9aa6863..171a331 100644 --- a/apps/cli/src/repl.ts +++ b/apps/cli/src/repl.ts @@ -10,6 +10,8 @@ import { ToolRegistry, applyStyle, buildSkillsDescriptionBlock, + closeAllMcpServers, + connectAllMcpServers, findStyle, loadMemory, loadOutputStyles, @@ -20,6 +22,7 @@ import { runAgent, type DeepCodeSettings, type Effort, + type McpClientHandle, type Mode, type AgentEvent, type StoredMessage, @@ -98,6 +101,32 @@ export async function startRepl(opts: ReplOpts): Promise { tools.register(makeSkillTool(skills)); } + // M3c: connect MCP servers (best-effort; individual failures don't abort) + let mcpServers: McpClientHandle[] = []; + let mcpErrors: Array<{ serverName: string; error: string }> = []; + if (settings.mcpServers && Object.keys(settings.mcpServers).length > 0) { + const enabled = settings.enabledMcpjsonServers; + const disabled = settings.disabledMcpjsonServers ?? []; + const result = await connectAllMcpServers(settings.mcpServers, { + enabledOnly: enabled, + disabled, + }); + mcpServers = result.handles; + mcpErrors = result.errors; + // Register every MCP-tool handler into the live registry + for (const handle of mcpServers) { + for (const tool of handle.tools) tools.register(tool); + } + if (mcpServers.length > 0) { + output.write( + ` ⊞ MCP: ${mcpServers.length} server(s) connected (${mcpServers.reduce((n, h) => n + h.tools.length, 0)} tools)\n`, + ); + } + if (mcpErrors.length > 0) { + output.write(` ⊞ MCP: ${mcpErrors.length} server(s) failed (see /mcp)\n`); + } + } + // Build the composite system prompt let systemPrompt = DEFAULT_SYSTEM_PROMPT; if (memory.text) systemPrompt += '\n\n' + memory.text; @@ -122,6 +151,8 @@ export async function startRepl(opts: ReplOpts): Promise { sessionId: session.id, sessions, usage: { inputTokens: 0, outputTokens: 0, reasoningTokens: 0 }, + mcpServers, + mcpErrors, }; output.write(`\n ▎ DeepCode · ${ctx.model} · mode: ${ctx.mode} · effort: ${ctx.effort}\n`); @@ -202,6 +233,10 @@ export async function startRepl(opts: ReplOpts): Promise { } rl.close(); + // Clean up MCP server connections + if (mcpServers.length > 0) { + await closeAllMcpServers(mcpServers); + } return 0; } diff --git a/docs/m1-validation.md b/docs/m1-validation.md index 8dc38b9..88c1e35 100644 --- a/docs/m1-validation.md +++ b/docs/m1-validation.md @@ -14,11 +14,11 @@ ## End-to-end runs -| Scenario | Result | -|---|---| -| Agent reads a file via Read tool | ✓ 2 turns, 2523 in / 137 out tokens, ended `end_turn`, correct answer | +| Scenario | Result | +| ----------------------------------- | ------------------------------------------------------------------------------------- | +| Agent reads a file via Read tool | ✓ 2 turns, 2523 in / 137 out tokens, ended `end_turn`, correct answer | | Reasoner solves a math word problem | ✓ 1 turn, 1188 in / 500 out / 427 reasoning, both `thinking` + `text` blocks streamed | -| `/v1/models` + alias mapping | ✓ documented in §3.1 update | +| `/v1/models` + alias mapping | ✓ documented in §3.1 update | ## Changes in this PR diff --git a/docs/milestones/M3c-mcp.md b/docs/milestones/M3c-mcp.md new file mode 100644 index 0000000..0f4e0dd --- /dev/null +++ b/docs/milestones/M3c-mcp.md @@ -0,0 +1,44 @@ +# M3c · MCP Client (stdio) + +> **Status**: ✅ stdio transport shipped + wired into REPL +> **Branch**: `feat/m3c-mcp-client` + +## Shipped + +- `packages/core/src/mcp/client.ts` — `connectMcpServer(name, config)` + `connectAllMcpServers(servers)` + `closeAllMcpServers(handles)`. +- Uses official `@modelcontextprotocol/sdk@^1.29.0` for protocol details. +- Tools are exposed with **`mcp____` qualified name**, registered into the same `ToolRegistry` that powers the 6 P0 tools. The agent loop sees them identically. +- Tool results unwrap MCP's `content[].text` array into a single string for the `tool_result` block. +- Individual server failures are isolated — one bad config doesn't kill others. +- `/mcp` slash command lists connected servers + tool count + errors. +- CLI REPL now auto-connects MCP servers from `settings.mcpServers` on startup, honoring `enabledMcpjsonServers` / `disabledMcpjsonServers`. +- Graceful shutdown closes all connections. + +## Tests (6 new) + +`packages/core/src/mcp/client.test.ts` spawns tiny in-disk MCP server scripts that import the SDK via absolute path (so /tmp doesn't need node_modules): + +1. lists tools and qualifies names +2. calls a remote tool, returns its text output +3. `connectAllMcpServers` continues on individual failures +4. respects `disabled` list +5. respects `enabledOnly` list +6. rejects server config missing `command` + +## NOT in this PR (M3c-ext, next) + +- HTTP transport +- SSE transport +- OAuth (2.0 client credentials + dynamic flows) +- `headersHelper` (dynamic auth via shell) +- Elicitation hooks (server-requested user input) +- `deepcode mcp serve` (reverse-expose DeepCode as MCP server) +- `_meta["anthropic/maxResultSizeChars"]` per-tool output caps +- MCP resource references in composer (`@server:proto://path`) +- `mcp__server__prompt` slash commands + +## Verified + +- `pnpm typecheck` → green +- `pnpm test` → 264 passed / 0 failed / 7 skipped (was 258) +- CLI builds: `node apps/cli/dist/cli.js --help` still works diff --git a/packages/core/package.json b/packages/core/package.json index e0aeec0..18bc585 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -26,6 +26,7 @@ "clean": "rm -rf dist *.tsbuildinfo" }, "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0", "openai": "^6.0.0" }, "devDependencies": { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 12a8403..f7d0f97 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -136,6 +136,16 @@ export { type Frontmatter, } from './skills/index.js'; +// MCP client (M3c — stdio transport; http/sse/OAuth/serve → M3c-ext) +export { + connectMcpServer, + connectAllMcpServers, + closeAllMcpServers, + type McpClientHandle, + type McpToolMeta, + type ConnectAllResult, +} from './mcp/index.js'; + // Plugins (M5 — manifest + hash pinning + local install + discovery) export { installLocal, diff --git a/packages/core/src/mcp/client.test.ts b/packages/core/src/mcp/client.test.ts new file mode 100644 index 0000000..ac38e76 --- /dev/null +++ b/packages/core/src/mcp/client.test.ts @@ -0,0 +1,196 @@ +// MCP client tests — use a tiny in-process MCP server (via SDK) over a pipe +// pair to avoid spawning external `npx` (which is slow + network-dependent). + +import { Server } from '@modelcontextprotocol/sdk/server/index.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { createRequire } from 'node:module'; +import { promises as fs } from 'node:fs'; +import { mkdtemp, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { connectAllMcpServers, connectMcpServer } from './client.js'; + +const require_ = createRequire(import.meta.url); +// Resolve a known sub-export (CJS shim file) to find the package root, +// then point to the ESM build for the spawned script. +const sdkSubmodule = require_.resolve('@modelcontextprotocol/sdk/server/index.js'); +// .../sdk/dist/cjs/server/index.js → walk up to .../sdk/ +const SDK_PKG_PATH = sdkSubmodule.replace(/\/dist\/(?:cjs|esm)\/.*$/, ''); +const SERVER_INDEX = join(SDK_PKG_PATH, 'dist/esm/server/index.js'); +const SERVER_STDIO = join(SDK_PKG_PATH, 'dist/esm/server/stdio.js'); +const TYPES_INDEX = join(SDK_PKG_PATH, 'dist/esm/types.js'); + +/** + * Spawn-a-script approach: write a tiny MCP server to disk, run it via node. + * We import the SDK by absolute path so the spawned script doesn't have to + * resolve `@modelcontextprotocol/sdk` from /tmp (which lacks node_modules). + */ +async function writeFakeServer(dir: string, name: string, tools: object[]): Promise { + const serverPath = join(dir, `${name}.mjs`); + await fs.writeFile( + serverPath, + ` +import { Server } from '${SERVER_INDEX}'; +import { StdioServerTransport } from '${SERVER_STDIO}'; +import { CallToolRequestSchema, ListToolsRequestSchema } from '${TYPES_INDEX}'; + +const server = new Server( + { name: '${name}', version: '0.0.1' }, + { capabilities: { tools: {} } }, +); + +const TOOLS = ${JSON.stringify(tools)}; + +server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS })); +server.setRequestHandler(CallToolRequestSchema, async (req) => { + const argsStr = JSON.stringify(req.params.arguments); + return { + content: [{ type: 'text', text: 'called: ' + req.params.name + ' args: ' + argsStr }], + }; +}); + +await server.connect(new StdioServerTransport()); +`, + 'utf8', + ); + return serverPath; +} + +describe('MCP client', () => { + let tmp: string; + + beforeEach(async () => { + tmp = await mkdtemp(join(tmpdir(), 'dc-mcp-test-')); + }); + afterEach(async () => { + await rm(tmp, { recursive: true, force: true }); + }); + + it('connects to a stdio server, lists tools, qualifies names', async () => { + const serverScript = await writeFakeServer(tmp, 'tester', [ + { + name: 'ping', + description: 'returns pong', + inputSchema: { type: 'object', properties: { msg: { type: 'string' } } }, + }, + { + name: 'echo', + description: 'echoes input', + inputSchema: { type: 'object', properties: { text: { type: 'string' } } }, + }, + ]); + const handle = await connectMcpServer('tester', { + command: 'node', + args: [serverScript], + }); + try { + expect(handle.serverName).toBe('tester'); + expect(handle.tools).toHaveLength(2); + expect(handle.tools.map((t) => t.name).sort()).toEqual([ + 'mcp__tester__echo', + 'mcp__tester__ping', + ]); + expect(handle.tools[0]?.definition.description).toBeDefined(); + } finally { + await handle.close(); + } + }, 20_000); + + it('calls a remote tool and returns its text output', async () => { + const serverScript = await writeFakeServer(tmp, 'srv', [ + { + name: 'hello', + description: 'd', + inputSchema: { type: 'object', properties: { name: { type: 'string' } } }, + }, + ]); + const handle = await connectMcpServer('srv', { + command: 'node', + args: [serverScript], + }); + try { + const helloTool = handle.tools.find((t) => t.name === 'mcp__srv__hello')!; + const result = await helloTool.execute({ name: 'world' }, { cwd: tmp }); + expect(result.isError).toBeFalsy(); + expect(result.content).toContain('called: hello'); + expect(result.content).toContain('"name":"world"'); + expect(result.data?.serverName).toBe('srv'); + expect(result.data?.serverToolName).toBe('hello'); + } finally { + await handle.close(); + } + }, 20_000); + + it('connectAllMcpServers continues on individual failures', async () => { + const goodScript = await writeFakeServer(tmp, 'good', [ + { + name: 't', + description: 'd', + inputSchema: { type: 'object', properties: {} }, + }, + ]); + const result = await connectAllMcpServers({ + good: { command: 'node', args: [goodScript] }, + broken: { command: 'no-such-command-xyzabc' }, + }); + expect(result.handles).toHaveLength(1); + expect(result.handles[0]?.serverName).toBe('good'); + expect(result.errors).toHaveLength(1); + expect(result.errors[0]?.serverName).toBe('broken'); + await result.handles[0]?.close(); + }, 20_000); + + it('honors disabled list', async () => { + const script = await writeFakeServer(tmp, 's', [ + { + name: 't', + description: 'd', + inputSchema: { type: 'object', properties: {} }, + }, + ]); + const result = await connectAllMcpServers( + { s: { command: 'node', args: [script] } }, + { disabled: ['s'] }, + ); + expect(result.handles).toHaveLength(0); + expect(result.errors).toHaveLength(0); + }); + + it('honors enabledOnly list (M3c equivalent of enabledMcpjsonServers)', async () => { + const script1 = await writeFakeServer(tmp, 's1', [ + { + name: 't', + description: 'd', + inputSchema: { type: 'object', properties: {} }, + }, + ]); + const script2 = await writeFakeServer(tmp, 's2', [ + { + name: 't', + description: 'd', + inputSchema: { type: 'object', properties: {} }, + }, + ]); + const result = await connectAllMcpServers( + { + s1: { command: 'node', args: [script1] }, + s2: { command: 'node', args: [script2] }, + }, + { enabledOnly: ['s1'] }, + ); + expect(result.handles.map((h) => h.serverName)).toEqual(['s1']); + await result.handles[0]?.close(); + }, 20_000); + + it('rejects a server config missing `command`', async () => { + await expect(connectMcpServer('bad', {})).rejects.toThrow(/command/); + }); +}); + +// Silence unused-import warning — Server/Transport are used via the spawned script +void Server; +void StdioServerTransport; +void CallToolRequestSchema; +void ListToolsRequestSchema; diff --git a/packages/core/src/mcp/client.ts b/packages/core/src/mcp/client.ts new file mode 100644 index 0000000..cb7afc2 --- /dev/null +++ b/packages/core/src/mcp/client.ts @@ -0,0 +1,132 @@ +// MCP client — wraps @modelcontextprotocol/sdk for stdio transport. +// Spec: docs/DEVELOPMENT_PLAN.md §3.3 +// M3c: stdio transport only. http/sse + OAuth + headersHelper + Elicitation +// in M3c-ext (next PR). + +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; +import type { McpServerConfig } from '../config/types.js'; +import type { ToolDefinition, ToolHandler, ToolResult } from '../types.js'; + +export interface McpToolMeta { + /** Original tool name as exposed by the MCP server. */ + serverToolName: string; + /** Server name (key in settings.mcpServers). */ + serverName: string; +} + +export interface McpClientHandle { + serverName: string; + client: Client; + transport: StdioClientTransport; + tools: ToolHandler[]; + close(): Promise; +} + +/** + * Connect to one MCP server via stdio. Returns a handle containing the + * registered tools (qualified as `mcp____`). + * + * Caller is responsible for calling `handle.close()` on shutdown. + */ +export async function connectMcpServer( + serverName: string, + config: McpServerConfig, +): Promise { + if (!config.command) { + throw new Error(`MCP server "${serverName}" must specify a command (stdio transport)`); + } + const transport = new StdioClientTransport({ + command: config.command, + args: config.args ?? [], + env: { ...(process.env as Record), ...(config.env ?? {}) }, + }); + + const client = new Client({ name: 'deepcode', version: '0.1.0' }, { capabilities: {} }); + + await client.connect(transport); + + // List the tools the server exposes + const listed = await client.listTools(); + const tools: ToolHandler[] = listed.tools.map((t) => { + const qualified = `mcp__${serverName}__${t.name}`; + const def: ToolDefinition = { + name: qualified, + description: t.description ?? `(MCP tool from ${serverName})`, + inputSchema: (t.inputSchema ?? { type: 'object', properties: {} }) as Record, + }; + return { + name: qualified, + definition: def, + async execute(input: Record): Promise { + try { + const result = (await client.callTool({ + name: t.name, + arguments: input, + })) as { content?: Array<{ type?: string; text?: string }>; isError?: boolean }; + // MCP returns { content: [{type:'text', text:'...'}, ...] } + const textParts = + (result.content ?? []) + .filter((c) => c.type === 'text') + .map((c) => c.text ?? '') + .join('\n') || ''; + return { + content: textParts || '(MCP tool returned no text content)', + isError: result.isError === true, + data: { serverName, serverToolName: t.name }, + }; + } catch (err) { + return { + content: `MCP call failed: ${(err as Error).message}`, + isError: true, + }; + } + }, + }; + }); + + return { + serverName, + client, + transport, + tools, + async close() { + await client.close(); + }, + }; +} + +/** + * Connect to many MCP servers — used at session start by the CLI. + * Failures are individual (one bad server doesn't kill the rest). + */ +export interface ConnectAllResult { + handles: McpClientHandle[]; + errors: Array<{ serverName: string; error: string }>; +} + +export async function connectAllMcpServers( + servers: Record, + opts: { enabledOnly?: string[]; disabled?: string[] } = {}, +): Promise { + const handles: McpClientHandle[] = []; + const errors: Array<{ serverName: string; error: string }> = []; + const enabled = opts.enabledOnly ? new Set(opts.enabledOnly) : null; + const disabled = new Set(opts.disabled ?? []); + + for (const [name, cfg] of Object.entries(servers)) { + if (enabled && !enabled.has(name)) continue; + if (disabled.has(name)) continue; + try { + const handle = await connectMcpServer(name, cfg); + handles.push(handle); + } catch (err) { + errors.push({ serverName: name, error: (err as Error).message }); + } + } + return { handles, errors }; +} + +export async function closeAllMcpServers(handles: McpClientHandle[]): Promise { + await Promise.allSettled(handles.map((h) => h.close())); +} diff --git a/packages/core/src/mcp/index.ts b/packages/core/src/mcp/index.ts index 4b8b87d..3072585 100644 --- a/packages/core/src/mcp/index.ts +++ b/packages/core/src/mcp/index.ts @@ -1,6 +1,12 @@ -// Module: mcp -// Milestone: M3 -// Spec: docs/DEVELOPMENT_PLAN.md §3.3 MCP client — 3 scope / OAuth / headersHelper / Elicitation / mcp serve -// Status: placeholder — implemented in M3 +// MCP client subsystem entry — stdio transport. +// Spec: docs/DEVELOPMENT_PLAN.md §3.3 +// Milestone: M3c (stdio). http/sse/OAuth/headersHelper/Elicitation/serve → M3c-ext. -export {}; +export { + connectMcpServer, + connectAllMcpServers, + closeAllMcpServers, + type McpClientHandle, + type McpToolMeta, + type ConnectAllResult, +} from './client.js'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7090adb..7009795 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,9 +58,12 @@ importers: packages/core: dependencies: + '@modelcontextprotocol/sdk': + specifier: ^1.29.0 + version: 1.29.0(zod@4.4.3) openai: specifier: ^6.0.0 - version: 6.39.0 + version: 6.39.0(zod@4.4.3) devDependencies: '@types/node': specifier: ^22.10.0 @@ -218,9 +221,25 @@ packages: cpu: [x64] os: [win32] + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@rollup/rollup-android-arm-eabi@4.60.4': resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} cpu: [arm] @@ -384,14 +403,45 @@ packages: '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + body-parser@2.2.2: + resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} + engines: {node: '>=18'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} @@ -400,6 +450,34 @@ packages: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -413,32 +491,183 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + express-rate-limit@8.5.2: + resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.3: + resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + engines: {node: '>= 0.4'} + + hono@4.12.23: + resolution: {integrity: sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==} + engines: {node: '>=16.9.0'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -447,6 +676,25 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + openai@6.39.0: resolution: {integrity: sha512-O61LIsimY3acVabwvomwFhwrnN36yvHY2quIfy9keEcFytGgWeV35yLHQ6NVMLSBxRpHmcg2yuhCnlu2HT4pLQ==} hasBin: true @@ -459,6 +707,17 @@ packages: zod: optional: true + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -469,6 +728,10 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -478,11 +741,73 @@ packages: engines: {node: '>=14'} hasBin: true + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + rollup@4.60.4: resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -493,6 +818,10 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -514,6 +843,14 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -522,6 +859,14 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + vite-node@2.1.9: resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -583,11 +928,27 @@ packages: jsdom: optional: true + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} hasBin: true + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + snapshots: '@esbuild/aix-ppc64@0.21.5': @@ -659,8 +1020,34 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true + '@hono/node-server@1.19.14(hono@4.12.23)': + dependencies: + hono: 4.12.23 + '@jridgewell/sourcemap-codec@1.5.5': {} + '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.23) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1 + express-rate-limit: 8.5.2(express@5.2.1) + hono: 4.12.23 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + '@rollup/rollup-android-arm-eabi@4.60.4': optional: true @@ -784,10 +1171,52 @@ snapshots: loupe: 3.2.1 tinyrainbow: 1.2.0 + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + assertion-error@2.0.1: {} + body-parser@2.2.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + on-finished: 2.4.1 + qs: 6.15.2 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + bytes@3.1.2: {} + cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -798,14 +1227,55 @@ snapshots: check-error@2.1.3: {} + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + debug@4.4.3: dependencies: ms: 2.1.3 deep-eql@5.0.2: {} + depd@2.0.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + encodeurl@2.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -832,26 +1302,185 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + escape-html@1.0.3: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 + etag@1.8.1: {} + + eventsource-parser@3.1.0: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.0 + expect-type@1.3.0: {} + express-rate-limit@8.5.2(express@5.2.1): + dependencies: + express: 5.2.1 + ip-address: 10.2.0 + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.2 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.2: {} + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.3 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.3: + dependencies: + function-bind: 1.1.2 + + hono@4.12.23: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + inherits@2.0.4: {} + + ip-address@10.2.0: {} + + ipaddr.js@1.9.1: {} + + is-promise@4.0.0: {} + + isexe@2.0.0: {} + + jose@6.2.3: {} + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + loupe@3.2.1: {} magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} + + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + + mime-db@1.54.0: {} + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + ms@2.1.3: {} nanoid@3.3.12: {} - openai@6.39.0: {} + negotiator@1.0.0: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + openai@6.39.0(zod@4.4.3): + optionalDependencies: + zod: 4.4.3 + + parseurl@1.3.3: {} + + path-key@3.1.1: {} + + path-to-regexp@8.4.2: {} pathe@1.1.2: {} @@ -859,6 +1488,8 @@ snapshots: picocolors@1.1.1: {} + pkce-challenge@5.0.1: {} + postcss@8.5.15: dependencies: nanoid: 3.3.12 @@ -867,6 +1498,26 @@ snapshots: prettier@3.8.3: {} + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + qs@6.15.2: + dependencies: + side-channel: 1.1.0 + + range-parser@1.2.1: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + unpipe: 1.0.0 + + require-from-string@2.0.2: {} + rollup@4.60.4: dependencies: '@types/estree': 1.0.8 @@ -898,12 +1549,87 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.60.4 fsevents: 2.3.3 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + + safer-buffer@2.1.2: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} source-map-js@1.2.1: {} stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@3.10.0: {} tinybench@2.9.0: {} @@ -916,10 +1642,22 @@ snapshots: tinyspy@3.0.2: {} + toidentifier@1.0.1: {} + + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.0 + mime-types: 3.0.2 + typescript@5.9.3: {} undici-types@6.21.0: {} + unpipe@1.0.0: {} + + vary@1.1.2: {} + vite-node@2.1.9(@types/node@22.19.19): dependencies: cac: 6.7.14 @@ -982,7 +1720,19 @@ snapshots: - supports-color - terser + which@2.0.2: + dependencies: + isexe: 2.0.0 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 + + wrappy@1.0.2: {} + + zod-to-json-schema@3.25.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + + zod@4.4.3: {}