@contractspec/lib.ai-agent 1.46.2 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":["toolSet: ExternalToolSet","metadata: ClaudeAgentContextMetadata","session: ClaudeAgentSessionState","allToolCalls: {\n toolCallId: string;\n toolName: string;\n args: unknown;\n }[]","allToolResults: {\n toolCallId: string;\n toolName: string;\n output: unknown;\n }[]"],"sources":["../../../src/providers/claude-agent-sdk/adapter.ts"],"sourcesContent":["/**\n * Claude Agent SDK Provider\n *\n * Enables ContractSpec agents to leverage Claude's agentic capabilities:\n * - Computer use (file editing, bash execution)\n * - Extended thinking for complex reasoning\n * - Agentic search and subagents\n * - MCP server integration\n *\n * This adapter wraps @anthropic-ai/claude-agent-sdk to work as a backend\n * for ContractSpec agents.\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport { agentKey } from '../../spec/spec';\nimport type { ToolHandler } from '../../types';\nimport type {\n ExternalAgentProvider,\n ExternalAgentContext,\n ExternalExecuteParams,\n ExternalExecuteResult,\n ExternalStreamChunk,\n ExternalToolSet,\n ClaudeAgentSDKConfig,\n ClaudeAgentContextMetadata,\n} from '../types';\nimport {\n ContextCreationError,\n ProviderExecutionError,\n ProviderNotAvailableError,\n} from '../types';\nimport {\n specToolsToClaudeAgentTools,\n specToolToExternalTool,\n extractToolCalls,\n} from './tool-bridge';\nimport {\n buildClaudeAgentContext,\n createEmptyClaudeSession,\n appendUserMessage,\n appendAssistantMessage,\n type ClaudeAgentSessionState,\n type ClaudeAgentContentBlock,\n} from './session-bridge';\nimport { injectStaticKnowledge } from '../../knowledge/injector';\n\n// ============================================================================\n// Provider Implementation\n// ============================================================================\n\n/**\n * Claude Agent SDK Provider implementation.\n */\nexport class ClaudeAgentSDKProvider implements ExternalAgentProvider {\n readonly name = 'claude-agent-sdk';\n readonly version = '1.0.0';\n\n private config: ClaudeAgentSDKConfig;\n private sdkAvailable: boolean | null = null;\n\n constructor(config: ClaudeAgentSDKConfig = {}) {\n this.config = {\n model: 'claude-sonnet-4-20250514',\n extendedThinking: false,\n computerUse: false,\n maxTokens: 4096,\n temperature: 0.7,\n ...config,\n };\n }\n\n /**\n * Check if Claude Agent SDK is available.\n */\n isAvailable(): boolean {\n if (this.sdkAvailable !== null) {\n return this.sdkAvailable;\n }\n\n try {\n // Check if the SDK is installed\n require.resolve('@anthropic-ai/claude-agent-sdk');\n\n // Check for API key\n const apiKey = this.config.apiKey ?? process.env.ANTHROPIC_API_KEY;\n this.sdkAvailable = Boolean(apiKey);\n } catch {\n this.sdkAvailable = false;\n }\n\n return this.sdkAvailable;\n }\n\n /**\n * Create an execution context from an AgentSpec.\n */\n async createContext(spec: AgentSpec): Promise<ExternalAgentContext> {\n if (!this.isAvailable()) {\n throw new ProviderNotAvailableError(\n this.name,\n 'SDK not installed or API key not configured'\n );\n }\n\n try {\n // Build tools set\n const toolSet: ExternalToolSet = {};\n for (const tool of spec.tools) {\n toolSet[tool.name] = specToolToExternalTool(tool);\n }\n\n // Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n spec.instructions,\n spec.knowledge ?? [],\n undefined // Knowledge retriever would be passed if available\n );\n\n const contextId = `claude-${agentKey(spec.meta)}-${Date.now()}`;\n\n const metadata: ClaudeAgentContextMetadata = {\n computerUseEnabled: this.config.computerUse ?? false,\n extendedThinkingEnabled: this.config.extendedThinking ?? false,\n mcpServerIds: this.config.mcpServers?.map((s) => s.name) ?? [],\n };\n\n return {\n id: contextId,\n spec: {\n ...spec,\n instructions, // Use knowledge-injected instructions\n },\n tools: toolSet,\n metadata,\n cleanup: async () => {\n // Cleanup MCP connections if any\n // This would be implemented when MCP support is added\n },\n };\n } catch (error) {\n throw new ContextCreationError(\n this.name,\n `Failed to create context: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Execute a prompt using Claude Agent SDK.\n */\n async execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult> {\n try {\n // Dynamic import of Claude Agent SDK\n const sdk = await this.loadSDK();\n\n // Build system prompt\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Build Claude Agent SDK context\n const claudeContext = buildClaudeAgentContext(params.options);\n\n // Create session state\n let session: ClaudeAgentSessionState = createEmptyClaudeSession();\n session = appendUserMessage(session, params.prompt);\n\n // Prepare tools for Claude Agent SDK\n const claudeTools = this.prepareToolsForSDK(context, params);\n\n // Execute via SDK\n // Execute via SDK\n const rawResponse = await sdk.execute({\n model: this.config.model,\n system: systemPrompt,\n messages: session.messages,\n tools: claudeTools,\n max_tokens: this.config.maxTokens,\n temperature: this.config.temperature,\n metadata: claudeContext,\n extended_thinking: this.config.extendedThinking,\n computer_use: this.config.computerUse,\n });\n\n // Define expected response shape manually since direct import is tricky with dynamic import\n interface InternalClaudeResponse {\n content?: {\n type: string;\n id?: string;\n name?: string;\n input?: unknown;\n text?: string;\n }[];\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n stop_reason?: string;\n model?: string;\n }\n\n const response = rawResponse as unknown as InternalClaudeResponse;\n\n // Extract tool calls and results\n const toolCalls = extractToolCalls(response);\n const toolResults = await this.executeTools(toolCalls, context, params);\n\n // Update session with assistant response\n if (response.content) {\n // cast content to expected type\n const content =\n response.content as unknown as ClaudeAgentContentBlock[];\n session = appendAssistantMessage(session, content);\n }\n\n return {\n text: this.extractTextContent(response),\n toolCalls: toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n args: tc.args,\n })),\n toolResults: toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.toolCallId,\n toolName: tr.toolName,\n output: tr.output,\n })),\n usage: {\n inputTokens: response.usage?.input_tokens ?? 0,\n outputTokens: response.usage?.output_tokens ?? 0,\n },\n finishReason: this.mapStopReason(response.stop_reason),\n metadata: {\n sessionId: (context.metadata as ClaudeAgentContextMetadata)\n ?.sessionId,\n model: response.model,\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Stream execution with real-time updates.\n */\n async *stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk> {\n try {\n const sdk = await this.loadSDK();\n\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n const claudeContext = buildClaudeAgentContext(params.options);\n const claudeTools = this.prepareToolsForSDK(context, params);\n\n const stream = await sdk.stream({\n model: this.config.model,\n system: systemPrompt,\n messages: [{ role: 'user', content: params.prompt }],\n tools: claudeTools,\n max_tokens: this.config.maxTokens,\n temperature: this.config.temperature,\n metadata: claudeContext,\n extended_thinking: this.config.extendedThinking,\n computer_use: this.config.computerUse,\n });\n\n let fullText = '';\n const allToolCalls: {\n toolCallId: string;\n toolName: string;\n args: unknown;\n }[] = [];\n const allToolResults: {\n toolCallId: string;\n toolName: string;\n output: unknown;\n }[] = [];\n let stepIndex = 0;\n\n for await (const event of stream) {\n if (\n event.type === 'content_block_delta' &&\n event.delta?.type === 'text_delta'\n ) {\n const text = event.delta.text ?? '';\n fullText += text;\n yield { type: 'text', text };\n }\n\n if (\n event.type === 'content_block_start' &&\n event.content_block?.type === 'tool_use'\n ) {\n const toolCall = {\n toolCallId: event.content_block.id ?? '',\n toolName: event.content_block.name ?? '',\n args: event.content_block.input,\n };\n allToolCalls.push(toolCall);\n yield {\n type: 'tool-call',\n toolCall: {\n type: 'tool-call',\n ...toolCall,\n },\n };\n }\n\n if (event.type === 'message_stop') {\n stepIndex++;\n yield { type: 'step-complete', stepIndex };\n }\n }\n\n // Execute any pending tools\n for (const toolCall of allToolCalls) {\n const result = await this.executeTool(toolCall, context, params);\n allToolResults.push(result);\n yield {\n type: 'tool-result',\n toolResult: {\n type: 'tool-result',\n ...result,\n },\n };\n }\n\n // Final done event\n yield {\n type: 'done',\n result: {\n text: fullText,\n toolCalls: allToolCalls.map((tc) => ({\n type: 'tool-call' as const,\n ...tc,\n })),\n toolResults: allToolResults.map((tr) => ({\n type: 'tool-result' as const,\n ...tr,\n })),\n usage: { inputTokens: 0, outputTokens: 0 }, // Not available in stream\n finishReason: 'stop',\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Stream failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // ============================================================================\n // Private Helpers\n // ============================================================================\n\n /**\n * Load the Claude Agent SDK dynamically.\n */\n private async loadSDK(): Promise<ClaudeAgentSDKInterface> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = require('@anthropic-ai/claude-agent-sdk');\n return module.default ?? module;\n } catch {\n throw new ProviderNotAvailableError(\n this.name,\n '@anthropic-ai/claude-agent-sdk is not installed'\n );\n }\n }\n\n /**\n * Prepare tools for Claude Agent SDK format.\n */\n private prepareToolsForSDK(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): unknown[] {\n const handlers = new Map<string, ToolHandler>();\n\n for (const tool of context.spec.tools) {\n const externalTool = context.tools[tool.name];\n if (externalTool?.execute) {\n handlers.set(tool.name, async (input) => {\n if (!externalTool.execute) {\n throw new Error(`Tool ${tool.name} has no execute handler`);\n }\n const result = await externalTool.execute(input);\n return typeof result === 'string' ? result : JSON.stringify(result);\n });\n }\n }\n\n return specToolsToClaudeAgentTools(context.spec.tools, handlers, {\n agentId: context.id,\n sessionId: params.options?.sessionId,\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n metadata: params.options?.metadata,\n signal: params.signal,\n });\n }\n\n /**\n * Execute a single tool.\n */\n private async executeTool(\n toolCall: { toolCallId: string; toolName: string; args: unknown },\n context: ExternalAgentContext,\n _params: ExternalExecuteParams\n ): Promise<{ toolCallId: string; toolName: string; output: unknown }> {\n const tool = context.tools[toolCall.toolName];\n if (!tool?.execute) {\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output: `Error: Tool '${toolCall.toolName}' not found or has no handler`,\n };\n }\n\n try {\n const output = await tool.execute(toolCall.args);\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output,\n };\n } catch (error) {\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output: `Error: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n /**\n * Execute multiple tools.\n */\n private async executeTools(\n toolCalls: { toolCallId: string; toolName: string; args: unknown }[],\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<{ toolCallId: string; toolName: string; output: unknown }[]> {\n return Promise.all(\n toolCalls.map((tc) => this.executeTool(tc, context, params))\n );\n }\n\n /**\n * Extract text content from response.\n */\n private extractTextContent(response: { content?: unknown[] }): string {\n if (!response.content) {\n return '';\n }\n\n return response.content\n .filter(\n (block): block is { type: 'text'; text: string } =>\n typeof block === 'object' &&\n block !== null &&\n (block as { type?: string }).type === 'text'\n )\n .map((block) => block.text)\n .join('');\n }\n\n /**\n * Map Claude Agent SDK stop reason to ContractSpec finish reason.\n */\n private mapStopReason(\n stopReason?: string\n ): ExternalExecuteResult['finishReason'] {\n switch (stopReason) {\n case 'end_turn':\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool-calls';\n case 'max_tokens':\n return 'length';\n default:\n return 'stop';\n }\n }\n}\n\n// ============================================================================\n// SDK Interface Type (for dynamic import)\n// ============================================================================\n\n/**\n * Interface for Claude Agent SDK (used for dynamic import).\n */\ninterface ClaudeAgentSDKInterface {\n execute(options: {\n model?: string;\n system?: string;\n messages: unknown[];\n tools?: unknown[];\n max_tokens?: number;\n temperature?: number;\n metadata?: Record<string, unknown>;\n extended_thinking?: boolean;\n computer_use?: boolean;\n }): Promise<{\n content?: unknown[];\n usage?: { input_tokens?: number; output_tokens?: number };\n stop_reason?: string;\n model?: string;\n }>;\n\n stream(options: {\n model?: string;\n system?: string;\n messages: unknown[];\n tools?: unknown[];\n max_tokens?: number;\n temperature?: number;\n metadata?: Record<string, unknown>;\n extended_thinking?: boolean;\n computer_use?: boolean;\n }): AsyncIterable<{\n type: string;\n delta?: { type?: string; text?: string };\n content_block?: {\n type?: string;\n id?: string;\n name?: string;\n input?: unknown;\n };\n }>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../src/providers/claude-agent-sdk/adapter.ts"],"sourcesContent":["/**\n * Claude Agent SDK Provider\n *\n * Enables ContractSpec agents to leverage Claude's agentic capabilities:\n * - Computer use (file editing, bash execution)\n * - Extended thinking for complex reasoning\n * - Agentic search and subagents\n * - MCP server integration\n *\n * This adapter wraps @anthropic-ai/claude-agent-sdk to work as a backend\n * for ContractSpec agents.\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport { agentKey } from '../../spec/spec';\nimport type { ToolHandler } from '../../types';\nimport type {\n ExternalAgentProvider,\n ExternalAgentContext,\n ExternalExecuteParams,\n ExternalExecuteResult,\n ExternalStreamChunk,\n ExternalToolSet,\n ClaudeAgentSDKConfig,\n ClaudeAgentContextMetadata,\n} from '../types';\nimport {\n ContextCreationError,\n ProviderExecutionError,\n ProviderNotAvailableError,\n} from '../types';\nimport {\n specToolsToClaudeAgentTools,\n specToolToExternalTool,\n extractToolCalls,\n} from './tool-bridge';\nimport {\n buildClaudeAgentContext,\n createEmptyClaudeSession,\n appendUserMessage,\n appendAssistantMessage,\n type ClaudeAgentSessionState,\n type ClaudeAgentContentBlock,\n} from './session-bridge';\nimport { injectStaticKnowledge } from '../../knowledge/injector';\n\n// ============================================================================\n// Provider Implementation\n// ============================================================================\n\n/**\n * Claude Agent SDK Provider implementation.\n */\nexport class ClaudeAgentSDKProvider implements ExternalAgentProvider {\n readonly name = 'claude-agent-sdk';\n readonly version = '1.0.0';\n\n private config: ClaudeAgentSDKConfig;\n private sdkAvailable: boolean | null = null;\n\n constructor(config: ClaudeAgentSDKConfig = {}) {\n this.config = {\n model: 'claude-sonnet-4-20250514',\n extendedThinking: false,\n computerUse: false,\n maxTokens: 4096,\n temperature: 0.7,\n ...config,\n };\n }\n\n /**\n * Check if Claude Agent SDK is available.\n */\n isAvailable(): boolean {\n if (this.sdkAvailable !== null) {\n return this.sdkAvailable;\n }\n\n try {\n // Check if the SDK is installed\n require.resolve('@anthropic-ai/claude-agent-sdk');\n\n // Check for API key\n const apiKey = this.config.apiKey ?? process.env.ANTHROPIC_API_KEY;\n this.sdkAvailable = Boolean(apiKey);\n } catch {\n this.sdkAvailable = false;\n }\n\n return this.sdkAvailable;\n }\n\n /**\n * Create an execution context from an AgentSpec.\n */\n async createContext(spec: AgentSpec): Promise<ExternalAgentContext> {\n if (!this.isAvailable()) {\n throw new ProviderNotAvailableError(\n this.name,\n 'SDK not installed or API key not configured'\n );\n }\n\n try {\n // Build tools set\n const toolSet: ExternalToolSet = {};\n for (const tool of spec.tools) {\n toolSet[tool.name] = specToolToExternalTool(tool);\n }\n\n // Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n spec.instructions,\n spec.knowledge ?? [],\n undefined // Knowledge retriever would be passed if available\n );\n\n const contextId = `claude-${agentKey(spec.meta)}-${Date.now()}`;\n\n const metadata: ClaudeAgentContextMetadata = {\n computerUseEnabled: this.config.computerUse ?? false,\n extendedThinkingEnabled: this.config.extendedThinking ?? false,\n mcpServerIds: this.config.mcpServers?.map((s) => s.name) ?? [],\n };\n\n return {\n id: contextId,\n spec: {\n ...spec,\n instructions, // Use knowledge-injected instructions\n },\n tools: toolSet,\n metadata,\n cleanup: async () => {\n // Cleanup MCP connections if any\n // This would be implemented when MCP support is added\n },\n };\n } catch (error) {\n throw new ContextCreationError(\n this.name,\n `Failed to create context: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Execute a prompt using Claude Agent SDK.\n */\n async execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult> {\n try {\n // Dynamic import of Claude Agent SDK\n const sdk = await this.loadSDK();\n\n // Build system prompt\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Build Claude Agent SDK context\n const claudeContext = buildClaudeAgentContext(params.options);\n\n // Create session state\n let session: ClaudeAgentSessionState = createEmptyClaudeSession();\n session = appendUserMessage(session, params.prompt);\n\n // Prepare tools for Claude Agent SDK\n const claudeTools = this.prepareToolsForSDK(context, params);\n\n // Execute via SDK\n // Execute via SDK\n const rawResponse = await sdk.execute({\n model: this.config.model,\n system: systemPrompt,\n messages: session.messages,\n tools: claudeTools,\n max_tokens: this.config.maxTokens,\n temperature: this.config.temperature,\n metadata: claudeContext,\n extended_thinking: this.config.extendedThinking,\n computer_use: this.config.computerUse,\n });\n\n // Define expected response shape manually since direct import is tricky with dynamic import\n interface InternalClaudeResponse {\n content?: {\n type: string;\n id?: string;\n name?: string;\n input?: unknown;\n text?: string;\n }[];\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n stop_reason?: string;\n model?: string;\n }\n\n const response = rawResponse as unknown as InternalClaudeResponse;\n\n // Extract tool calls and results\n const toolCalls = extractToolCalls(response);\n const toolResults = await this.executeTools(toolCalls, context, params);\n\n // Update session with assistant response\n if (response.content) {\n // cast content to expected type\n const content =\n response.content as unknown as ClaudeAgentContentBlock[];\n session = appendAssistantMessage(session, content);\n }\n\n return {\n text: this.extractTextContent(response),\n toolCalls: toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n args: tc.args,\n })),\n toolResults: toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.toolCallId,\n toolName: tr.toolName,\n output: tr.output,\n })),\n usage: {\n inputTokens: response.usage?.input_tokens ?? 0,\n outputTokens: response.usage?.output_tokens ?? 0,\n },\n finishReason: this.mapStopReason(response.stop_reason),\n metadata: {\n sessionId: (context.metadata as ClaudeAgentContextMetadata)\n ?.sessionId,\n model: response.model,\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Stream execution with real-time updates.\n */\n async *stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk> {\n try {\n const sdk = await this.loadSDK();\n\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n const claudeContext = buildClaudeAgentContext(params.options);\n const claudeTools = this.prepareToolsForSDK(context, params);\n\n const stream = await sdk.stream({\n model: this.config.model,\n system: systemPrompt,\n messages: [{ role: 'user', content: params.prompt }],\n tools: claudeTools,\n max_tokens: this.config.maxTokens,\n temperature: this.config.temperature,\n metadata: claudeContext,\n extended_thinking: this.config.extendedThinking,\n computer_use: this.config.computerUse,\n });\n\n let fullText = '';\n const allToolCalls: {\n toolCallId: string;\n toolName: string;\n args: unknown;\n }[] = [];\n const allToolResults: {\n toolCallId: string;\n toolName: string;\n output: unknown;\n }[] = [];\n let stepIndex = 0;\n\n for await (const event of stream) {\n if (\n event.type === 'content_block_delta' &&\n event.delta?.type === 'text_delta'\n ) {\n const text = event.delta.text ?? '';\n fullText += text;\n yield { type: 'text', text };\n }\n\n if (\n event.type === 'content_block_start' &&\n event.content_block?.type === 'tool_use'\n ) {\n const toolCall = {\n toolCallId: event.content_block.id ?? '',\n toolName: event.content_block.name ?? '',\n args: event.content_block.input,\n };\n allToolCalls.push(toolCall);\n yield {\n type: 'tool-call',\n toolCall: {\n type: 'tool-call',\n ...toolCall,\n },\n };\n }\n\n if (event.type === 'message_stop') {\n stepIndex++;\n yield { type: 'step-complete', stepIndex };\n }\n }\n\n // Execute any pending tools\n for (const toolCall of allToolCalls) {\n const result = await this.executeTool(toolCall, context, params);\n allToolResults.push(result);\n yield {\n type: 'tool-result',\n toolResult: {\n type: 'tool-result',\n ...result,\n },\n };\n }\n\n // Final done event\n yield {\n type: 'done',\n result: {\n text: fullText,\n toolCalls: allToolCalls.map((tc) => ({\n type: 'tool-call' as const,\n ...tc,\n })),\n toolResults: allToolResults.map((tr) => ({\n type: 'tool-result' as const,\n ...tr,\n })),\n usage: { inputTokens: 0, outputTokens: 0 }, // Not available in stream\n finishReason: 'stop',\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Stream failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // ============================================================================\n // Private Helpers\n // ============================================================================\n\n /**\n * Load the Claude Agent SDK dynamically.\n */\n private async loadSDK(): Promise<ClaudeAgentSDKInterface> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = require('@anthropic-ai/claude-agent-sdk');\n return module.default ?? module;\n } catch {\n throw new ProviderNotAvailableError(\n this.name,\n '@anthropic-ai/claude-agent-sdk is not installed'\n );\n }\n }\n\n /**\n * Prepare tools for Claude Agent SDK format.\n */\n private prepareToolsForSDK(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): unknown[] {\n const handlers = new Map<string, ToolHandler>();\n\n for (const tool of context.spec.tools) {\n const externalTool = context.tools[tool.name];\n if (externalTool?.execute) {\n handlers.set(tool.name, async (input) => {\n if (!externalTool.execute) {\n throw new Error(`Tool ${tool.name} has no execute handler`);\n }\n const result = await externalTool.execute(input);\n return typeof result === 'string' ? result : JSON.stringify(result);\n });\n }\n }\n\n return specToolsToClaudeAgentTools(context.spec.tools, handlers, {\n agentId: context.id,\n sessionId: params.options?.sessionId,\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n metadata: params.options?.metadata,\n signal: params.signal,\n });\n }\n\n /**\n * Execute a single tool.\n */\n private async executeTool(\n toolCall: { toolCallId: string; toolName: string; args: unknown },\n context: ExternalAgentContext,\n _params: ExternalExecuteParams\n ): Promise<{ toolCallId: string; toolName: string; output: unknown }> {\n const tool = context.tools[toolCall.toolName];\n if (!tool?.execute) {\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output: `Error: Tool '${toolCall.toolName}' not found or has no handler`,\n };\n }\n\n try {\n const output = await tool.execute(toolCall.args);\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output,\n };\n } catch (error) {\n return {\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n output: `Error: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n /**\n * Execute multiple tools.\n */\n private async executeTools(\n toolCalls: { toolCallId: string; toolName: string; args: unknown }[],\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<{ toolCallId: string; toolName: string; output: unknown }[]> {\n return Promise.all(\n toolCalls.map((tc) => this.executeTool(tc, context, params))\n );\n }\n\n /**\n * Extract text content from response.\n */\n private extractTextContent(response: { content?: unknown[] }): string {\n if (!response.content) {\n return '';\n }\n\n return response.content\n .filter(\n (block): block is { type: 'text'; text: string } =>\n typeof block === 'object' &&\n block !== null &&\n (block as { type?: string }).type === 'text'\n )\n .map((block) => block.text)\n .join('');\n }\n\n /**\n * Map Claude Agent SDK stop reason to ContractSpec finish reason.\n */\n private mapStopReason(\n stopReason?: string\n ): ExternalExecuteResult['finishReason'] {\n switch (stopReason) {\n case 'end_turn':\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool-calls';\n case 'max_tokens':\n return 'length';\n default:\n return 'stop';\n }\n }\n}\n\n// ============================================================================\n// SDK Interface Type (for dynamic import)\n// ============================================================================\n\n/**\n * Interface for Claude Agent SDK (used for dynamic import).\n */\ninterface ClaudeAgentSDKInterface {\n execute(options: {\n model?: string;\n system?: string;\n messages: unknown[];\n tools?: unknown[];\n max_tokens?: number;\n temperature?: number;\n metadata?: Record<string, unknown>;\n extended_thinking?: boolean;\n computer_use?: boolean;\n }): Promise<{\n content?: unknown[];\n usage?: { input_tokens?: number; output_tokens?: number };\n stop_reason?: string;\n model?: string;\n }>;\n\n stream(options: {\n model?: string;\n system?: string;\n messages: unknown[];\n tools?: unknown[];\n max_tokens?: number;\n temperature?: number;\n metadata?: Record<string, unknown>;\n extended_thinking?: boolean;\n computer_use?: boolean;\n }): AsyncIterable<{\n type: string;\n delta?: { type?: string; text?: string };\n content_block?: {\n type?: string;\n id?: string;\n name?: string;\n input?: unknown;\n };\n }>;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-bridge.js","names":["messages: ClaudeAgentMessage[]"],"sources":["../../../src/providers/claude-agent-sdk/session-bridge.ts"],"sourcesContent":["/**\n * Session bridge for mapping between ContractSpec and Claude Agent SDK sessions.\n *\n * Handles session state synchronization, message history conversion,\n * and context preservation across the two systems.\n */\nimport type { AgentSessionState } from '../../types';\nimport type { AgentCallOptions } from '../../types';\n\n// =============================================================================\n// Claude Agent SDK Session Types\n// =============================================================================\n\n/**\n * Claude Agent SDK content block (text or tool use).\n */\nexport interface ClaudeAgentContentBlock {\n type: 'text' | 'tool_use' | 'tool_result';\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | ClaudeAgentContentBlock[];\n is_error?: boolean;\n}\n\n/**\n * Claude Agent SDK message format.\n */\nexport interface ClaudeAgentMessage {\n role: 'user' | 'assistant';\n content: string | ClaudeAgentContentBlock[];\n}\n\n/**\n * Claude Agent SDK session state.\n */\nexport interface ClaudeAgentSession {\n sessionId?: string;\n messages: ClaudeAgentMessage[];\n metadata?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Session Conversion\n// =============================================================================\n\n/**\n * Claude Agent SDK session state (alias).\n */\nexport type ClaudeAgentSessionState = ClaudeAgentSession;\n\n/**\n * Convert ContractSpec session to Claude Agent SDK session.\n */\nexport function toClaudeAgentSession(\n state: AgentSessionState\n): ClaudeAgentSession {\n const messages: ClaudeAgentMessage[] = [];\n\n for (const msg of state.messages) {\n if (msg.role === 'user' || msg.role === 'assistant') {\n const content =\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content);\n messages.push({\n role: msg.role,\n content,\n });\n }\n }\n\n return {\n sessionId: state.sessionId,\n messages,\n metadata: {\n agentId: state.agentId,\n tenantId: state.tenantId,\n actorId: state.actorId,\n },\n };\n}\n\n/**\n * Create a new Claude Agent session from call options.\n */\nexport function createClaudeAgentSession(\n options?: AgentCallOptions\n): ClaudeAgentSession {\n return {\n sessionId: options?.sessionId,\n messages: [],\n metadata: {\n tenantId: options?.tenantId,\n actorId: options?.actorId,\n ...options?.metadata,\n },\n };\n}\n\n/**\n * Create an empty Claude Agent session.\n */\nexport function createEmptyClaudeSession(): ClaudeAgentSession {\n return createClaudeAgentSession();\n}\n\n/**\n * Build Claude Agent context metadata from call options.\n */\nexport function buildClaudeAgentContext(\n options?: AgentCallOptions\n): Record<string, unknown> {\n return {\n tenantId: options?.tenantId,\n actorId: options?.actorId,\n sessionId: options?.sessionId,\n ...options?.metadata,\n };\n}\n\n/**\n * Append a user message to the session.\n */\nexport function appendUserMessage(\n session: ClaudeAgentSession,\n content: string\n): ClaudeAgentSession {\n return {\n ...session,\n messages: [...session.messages, { role: 'user', content }],\n };\n}\n\n/**\n * Append an assistant message to the session.\n */\nexport function appendAssistantMessage(\n session: ClaudeAgentSession,\n content: string | ClaudeAgentContentBlock[]\n): ClaudeAgentSession {\n return {\n ...session,\n messages: [...session.messages, { role: 'assistant', content }],\n };\n}\n\n/**\n * Clear the session history.\n */\nexport function clearSession(session: ClaudeAgentSession): ClaudeAgentSession {\n return {\n ...session,\n messages: [],\n };\n}\n\n/**\n * Get the last N messages from the session.\n */\nexport function getRecentMessages(\n session: ClaudeAgentSession,\n count: number\n): ClaudeAgentMessage[] {\n return session.messages.slice(-count);\n}\n\n/**\n * Extract tool calls from a message content.\n */\nexport function extractToolUseBlocks(\n content: string | ClaudeAgentContentBlock[]\n): ClaudeAgentContentBlock[] {\n if (typeof content === 'string') {\n return [];\n }\n return content.filter((block) => block.type === 'tool_use');\n}\n\n/**\n * Create a tool result block.\n */\nexport function createToolResultBlock(\n toolUseId: string,\n result: unknown,\n isError = false\n): ClaudeAgentContentBlock {\n return {\n type: 'tool_result',\n tool_use_id: toolUseId,\n content: typeof result === 'string' ? result : JSON.stringify(result),\n is_error: isError,\n };\n}\n\n// =============================================================================\n// Session Metadata\n// =============================================================================\n\n/**\n * Update session metadata.\n */\nexport function updateSessionMetadata(\n session: ClaudeAgentSession,\n metadata: Record<string, unknown>\n): ClaudeAgentSession {\n return {\n ...session,\n metadata: {\n ...session.metadata,\n ...metadata,\n },\n };\n}\n\n/**\n * Get session message count.\n */\nexport function getMessageCount(session: ClaudeAgentSession): number {\n return session.messages.length;\n}\n\n/**\n * Get the total token estimate for the session.\n * This is a rough estimate based on character count.\n */\nexport function estimateTokens(session: ClaudeAgentSession): number {\n let chars = 0;\n for (const msg of session.messages) {\n if (typeof msg.content === 'string') {\n chars += msg.content.length;\n } else {\n chars += JSON.stringify(msg.content).length;\n }\n }\n // Rough estimate: ~4 chars per token\n return Math.ceil(chars / 4);\n}\n\n/**\n * Summarize the session for logging.\n */\nexport function summarizeSession(session: ClaudeAgentSession): {\n messageCount: number;\n userMessages: number;\n assistantMessages: number;\n estimatedTokens: number;\n} {\n let userMessages = 0;\n let assistantMessages = 0;\n\n for (const msg of session.messages) {\n if (msg.role === 'user') {\n userMessages++;\n } else {\n assistantMessages++;\n }\n }\n\n return {\n messageCount: session.messages.length,\n userMessages,\n assistantMessages,\n estimatedTokens: estimateTokens(session),\n };\n}\n"],"mappings":";;;;AAwDA,SAAgB,qBACd,OACoB;CACpB,MAAMA,WAAiC,EAAE;AAEzC,MAAK,MAAM,OAAO,MAAM,SACtB,KAAI,IAAI,SAAS,UAAU,IAAI,SAAS,aAAa;EACnD,MAAM,UACJ,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,KAAK,UAAU,IAAI,QAAQ;AACjC,WAAS,KAAK;GACZ,MAAM,IAAI;GACV;GACD,CAAC;;AAIN,QAAO;EACL,WAAW,MAAM;EACjB;EACA,UAAU;GACR,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,SAAS,MAAM;GAChB;EACF;;;;;AAMH,SAAgB,yBACd,SACoB;AACpB,QAAO;EACL,WAAW,SAAS;EACpB,UAAU,EAAE;EACZ,UAAU;GACR,UAAU,SAAS;GACnB,SAAS,SAAS;GAClB,GAAG,SAAS;GACb;EACF;;;;;AAMH,SAAgB,2BAA+C;AAC7D,QAAO,0BAA0B;;;;;AAMnC,SAAgB,wBACd,SACyB;AACzB,QAAO;EACL,UAAU,SAAS;EACnB,SAAS,SAAS;EAClB,WAAW,SAAS;EACpB,GAAG,SAAS;EACb;;;;;AAMH,SAAgB,kBACd,SACA,SACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU,CAAC,GAAG,QAAQ,UAAU;GAAE,MAAM;GAAQ;GAAS,CAAC;EAC3D;;;;;AAMH,SAAgB,uBACd,SACA,SACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU,CAAC,GAAG,QAAQ,UAAU;GAAE,MAAM;GAAa;GAAS,CAAC;EAChE;;;;;AAMH,SAAgB,aAAa,SAAiD;AAC5E,QAAO;EACL,GAAG;EACH,UAAU,EAAE;EACb;;;;;AAMH,SAAgB,kBACd,SACA,OACsB;AACtB,QAAO,QAAQ,SAAS,MAAM,CAAC,MAAM;;;;;AAMvC,SAAgB,qBACd,SAC2B;AAC3B,KAAI,OAAO,YAAY,SACrB,QAAO,EAAE;AAEX,QAAO,QAAQ,QAAQ,UAAU,MAAM,SAAS,WAAW;;;;;AAM7D,SAAgB,sBACd,WACA,QACA,UAAU,OACe;AACzB,QAAO;EACL,MAAM;EACN,aAAa;EACb,SAAS,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,OAAO;EACrE,UAAU;EACX;;;;;AAUH,SAAgB,sBACd,SACA,UACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG,QAAQ;GACX,GAAG;GACJ;EACF;;;;;AAMH,SAAgB,gBAAgB,SAAqC;AACnE,QAAO,QAAQ,SAAS;;;;;;AAO1B,SAAgB,eAAe,SAAqC;CAClE,IAAI,QAAQ;AACZ,MAAK,MAAM,OAAO,QAAQ,SACxB,KAAI,OAAO,IAAI,YAAY,SACzB,UAAS,IAAI,QAAQ;KAErB,UAAS,KAAK,UAAU,IAAI,QAAQ,CAAC;AAIzC,QAAO,KAAK,KAAK,QAAQ,EAAE;;;;;AAM7B,SAAgB,iBAAiB,SAK/B;CACA,IAAI,eAAe;CACnB,IAAI,oBAAoB;AAExB,MAAK,MAAM,OAAO,QAAQ,SACxB,KAAI,IAAI,SAAS,OACf;KAEA;AAIJ,QAAO;EACL,cAAc,QAAQ,SAAS;EAC/B;EACA;EACA,iBAAiB,eAAe,QAAQ;EACzC"}
1
+ {"version":3,"file":"session-bridge.js","names":[],"sources":["../../../src/providers/claude-agent-sdk/session-bridge.ts"],"sourcesContent":["/**\n * Session bridge for mapping between ContractSpec and Claude Agent SDK sessions.\n *\n * Handles session state synchronization, message history conversion,\n * and context preservation across the two systems.\n */\nimport type { AgentSessionState } from '../../types';\nimport type { AgentCallOptions } from '../../types';\n\n// =============================================================================\n// Claude Agent SDK Session Types\n// =============================================================================\n\n/**\n * Claude Agent SDK content block (text or tool use).\n */\nexport interface ClaudeAgentContentBlock {\n type: 'text' | 'tool_use' | 'tool_result';\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | ClaudeAgentContentBlock[];\n is_error?: boolean;\n}\n\n/**\n * Claude Agent SDK message format.\n */\nexport interface ClaudeAgentMessage {\n role: 'user' | 'assistant';\n content: string | ClaudeAgentContentBlock[];\n}\n\n/**\n * Claude Agent SDK session state.\n */\nexport interface ClaudeAgentSession {\n sessionId?: string;\n messages: ClaudeAgentMessage[];\n metadata?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Session Conversion\n// =============================================================================\n\n/**\n * Claude Agent SDK session state (alias).\n */\nexport type ClaudeAgentSessionState = ClaudeAgentSession;\n\n/**\n * Convert ContractSpec session to Claude Agent SDK session.\n */\nexport function toClaudeAgentSession(\n state: AgentSessionState\n): ClaudeAgentSession {\n const messages: ClaudeAgentMessage[] = [];\n\n for (const msg of state.messages) {\n if (msg.role === 'user' || msg.role === 'assistant') {\n const content =\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content);\n messages.push({\n role: msg.role,\n content,\n });\n }\n }\n\n return {\n sessionId: state.sessionId,\n messages,\n metadata: {\n agentId: state.agentId,\n tenantId: state.tenantId,\n actorId: state.actorId,\n },\n };\n}\n\n/**\n * Create a new Claude Agent session from call options.\n */\nexport function createClaudeAgentSession(\n options?: AgentCallOptions\n): ClaudeAgentSession {\n return {\n sessionId: options?.sessionId,\n messages: [],\n metadata: {\n tenantId: options?.tenantId,\n actorId: options?.actorId,\n ...options?.metadata,\n },\n };\n}\n\n/**\n * Create an empty Claude Agent session.\n */\nexport function createEmptyClaudeSession(): ClaudeAgentSession {\n return createClaudeAgentSession();\n}\n\n/**\n * Build Claude Agent context metadata from call options.\n */\nexport function buildClaudeAgentContext(\n options?: AgentCallOptions\n): Record<string, unknown> {\n return {\n tenantId: options?.tenantId,\n actorId: options?.actorId,\n sessionId: options?.sessionId,\n ...options?.metadata,\n };\n}\n\n/**\n * Append a user message to the session.\n */\nexport function appendUserMessage(\n session: ClaudeAgentSession,\n content: string\n): ClaudeAgentSession {\n return {\n ...session,\n messages: [...session.messages, { role: 'user', content }],\n };\n}\n\n/**\n * Append an assistant message to the session.\n */\nexport function appendAssistantMessage(\n session: ClaudeAgentSession,\n content: string | ClaudeAgentContentBlock[]\n): ClaudeAgentSession {\n return {\n ...session,\n messages: [...session.messages, { role: 'assistant', content }],\n };\n}\n\n/**\n * Clear the session history.\n */\nexport function clearSession(session: ClaudeAgentSession): ClaudeAgentSession {\n return {\n ...session,\n messages: [],\n };\n}\n\n/**\n * Get the last N messages from the session.\n */\nexport function getRecentMessages(\n session: ClaudeAgentSession,\n count: number\n): ClaudeAgentMessage[] {\n return session.messages.slice(-count);\n}\n\n/**\n * Extract tool calls from a message content.\n */\nexport function extractToolUseBlocks(\n content: string | ClaudeAgentContentBlock[]\n): ClaudeAgentContentBlock[] {\n if (typeof content === 'string') {\n return [];\n }\n return content.filter((block) => block.type === 'tool_use');\n}\n\n/**\n * Create a tool result block.\n */\nexport function createToolResultBlock(\n toolUseId: string,\n result: unknown,\n isError = false\n): ClaudeAgentContentBlock {\n return {\n type: 'tool_result',\n tool_use_id: toolUseId,\n content: typeof result === 'string' ? result : JSON.stringify(result),\n is_error: isError,\n };\n}\n\n// =============================================================================\n// Session Metadata\n// =============================================================================\n\n/**\n * Update session metadata.\n */\nexport function updateSessionMetadata(\n session: ClaudeAgentSession,\n metadata: Record<string, unknown>\n): ClaudeAgentSession {\n return {\n ...session,\n metadata: {\n ...session.metadata,\n ...metadata,\n },\n };\n}\n\n/**\n * Get session message count.\n */\nexport function getMessageCount(session: ClaudeAgentSession): number {\n return session.messages.length;\n}\n\n/**\n * Get the total token estimate for the session.\n * This is a rough estimate based on character count.\n */\nexport function estimateTokens(session: ClaudeAgentSession): number {\n let chars = 0;\n for (const msg of session.messages) {\n if (typeof msg.content === 'string') {\n chars += msg.content.length;\n } else {\n chars += JSON.stringify(msg.content).length;\n }\n }\n // Rough estimate: ~4 chars per token\n return Math.ceil(chars / 4);\n}\n\n/**\n * Summarize the session for logging.\n */\nexport function summarizeSession(session: ClaudeAgentSession): {\n messageCount: number;\n userMessages: number;\n assistantMessages: number;\n estimatedTokens: number;\n} {\n let userMessages = 0;\n let assistantMessages = 0;\n\n for (const msg of session.messages) {\n if (msg.role === 'user') {\n userMessages++;\n } else {\n assistantMessages++;\n }\n }\n\n return {\n messageCount: session.messages.length,\n userMessages,\n assistantMessages,\n estimatedTokens: estimateTokens(session),\n };\n}\n"],"mappings":";;;;AAwDA,SAAgB,qBACd,OACoB;CACpB,MAAM,WAAiC,EAAE;AAEzC,MAAK,MAAM,OAAO,MAAM,SACtB,KAAI,IAAI,SAAS,UAAU,IAAI,SAAS,aAAa;EACnD,MAAM,UACJ,OAAO,IAAI,YAAY,WACnB,IAAI,UACJ,KAAK,UAAU,IAAI,QAAQ;AACjC,WAAS,KAAK;GACZ,MAAM,IAAI;GACV;GACD,CAAC;;AAIN,QAAO;EACL,WAAW,MAAM;EACjB;EACA,UAAU;GACR,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,SAAS,MAAM;GAChB;EACF;;;;;AAMH,SAAgB,yBACd,SACoB;AACpB,QAAO;EACL,WAAW,SAAS;EACpB,UAAU,EAAE;EACZ,UAAU;GACR,UAAU,SAAS;GACnB,SAAS,SAAS;GAClB,GAAG,SAAS;GACb;EACF;;;;;AAMH,SAAgB,2BAA+C;AAC7D,QAAO,0BAA0B;;;;;AAMnC,SAAgB,wBACd,SACyB;AACzB,QAAO;EACL,UAAU,SAAS;EACnB,SAAS,SAAS;EAClB,WAAW,SAAS;EACpB,GAAG,SAAS;EACb;;;;;AAMH,SAAgB,kBACd,SACA,SACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU,CAAC,GAAG,QAAQ,UAAU;GAAE,MAAM;GAAQ;GAAS,CAAC;EAC3D;;;;;AAMH,SAAgB,uBACd,SACA,SACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU,CAAC,GAAG,QAAQ,UAAU;GAAE,MAAM;GAAa;GAAS,CAAC;EAChE;;;;;AAMH,SAAgB,aAAa,SAAiD;AAC5E,QAAO;EACL,GAAG;EACH,UAAU,EAAE;EACb;;;;;AAMH,SAAgB,kBACd,SACA,OACsB;AACtB,QAAO,QAAQ,SAAS,MAAM,CAAC,MAAM;;;;;AAMvC,SAAgB,qBACd,SAC2B;AAC3B,KAAI,OAAO,YAAY,SACrB,QAAO,EAAE;AAEX,QAAO,QAAQ,QAAQ,UAAU,MAAM,SAAS,WAAW;;;;;AAM7D,SAAgB,sBACd,WACA,QACA,UAAU,OACe;AACzB,QAAO;EACL,MAAM;EACN,aAAa;EACb,SAAS,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,OAAO;EACrE,UAAU;EACX;;;;;AAUH,SAAgB,sBACd,SACA,UACoB;AACpB,QAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG,QAAQ;GACX,GAAG;GACJ;EACF;;;;;AAMH,SAAgB,gBAAgB,SAAqC;AACnE,QAAO,QAAQ,SAAS;;;;;;AAO1B,SAAgB,eAAe,SAAqC;CAClE,IAAI,QAAQ;AACZ,MAAK,MAAM,OAAO,QAAQ,SACxB,KAAI,OAAO,IAAI,YAAY,SACzB,UAAS,IAAI,QAAQ;KAErB,UAAS,KAAK,UAAU,IAAI,QAAQ,CAAC;AAIzC,QAAO,KAAK,KAAK,QAAQ,EAAE;;;;;AAM7B,SAAgB,iBAAiB,SAK/B;CACA,IAAI,eAAe;CACnB,IAAI,oBAAoB;AAExB,MAAK,MAAM,OAAO,QAAQ,SACxB,KAAI,IAAI,SAAS,OACf;KAEA;AAIJ,QAAO;EACL,cAAc,QAAQ,SAAS;EAC/B;EACA;EACA,iBAAiB,eAAe,QAAQ;EACzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-bridge.js","names":["configs: AgentToolConfig[]"],"sources":["../../../src/providers/claude-agent-sdk/tool-bridge.ts"],"sourcesContent":["/**\n * Tool bridge for converting between ContractSpec and Claude Agent SDK tool formats.\n *\n * Provides bidirectional conversion:\n * - ContractSpec AgentToolConfig → Claude Agent SDK tool\n * - Claude Agent SDK tool → ContractSpec AgentToolConfig\n */\n\nimport type { AgentToolConfig } from '../../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../../types';\nimport type { ExternalToolDefinition } from '../types';\n\n// ============================================================================\n// Claude Agent SDK Tool Types (based on SDK API)\n// ============================================================================\n\n/**\n * Claude Agent SDK tool definition.\n * Based on Anthropic's tool format.\n */\nexport interface ClaudeAgentTool {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input schema in JSON Schema format */\n input_schema: {\n type: 'object';\n properties?: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n /** Whether tool requires confirmation before execution */\n requires_confirmation?: boolean;\n /** Tool category for organization */\n category?: string;\n}\n\n/**\n * Claude Agent SDK tool result.\n */\nexport interface ClaudeAgentToolResult {\n /** Tool call ID this result corresponds to */\n tool_use_id: string;\n /** Result content */\n content: string | ClaudeAgentToolResultContent[];\n /** Whether the tool execution failed */\n is_error?: boolean;\n}\n\n/**\n * Claude Agent SDK tool result content block.\n */\nexport interface ClaudeAgentToolResultContent {\n type: 'text' | 'image';\n text?: string;\n source?: {\n type: 'base64';\n media_type: string;\n data: string;\n };\n}\n\n// ============================================================================\n// ContractSpec → Claude Agent SDK Conversion\n// ============================================================================\n\n/**\n * Convert a ContractSpec AgentToolConfig to Claude Agent SDK tool format.\n *\n * @param tool - ContractSpec tool configuration\n * @param handler - Tool handler function\n * @param context - Partial execution context to inject\n * @returns Claude Agent SDK tool definition with execute function\n */\nexport function specToolToClaudeAgentTool(\n tool: AgentToolConfig,\n handler: ToolHandler,\n context: Partial<ToolExecutionContext>\n): ClaudeAgentTool & { execute: (input: unknown) => Promise<unknown> } {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n input_schema: normalizeSchema(tool.schema),\n requires_confirmation: tool.requiresApproval ?? !tool.automationSafe,\n execute: async (input: unknown) => {\n const fullContext: ToolExecutionContext = {\n agentId: context.agentId ?? 'unknown',\n sessionId: context.sessionId ?? 'unknown',\n tenantId: context.tenantId,\n actorId: context.actorId,\n metadata: context.metadata,\n signal: context.signal,\n };\n return handler(input, fullContext);\n },\n };\n}\n\n/**\n * Convert multiple ContractSpec tools to Claude Agent SDK format.\n */\nexport function specToolsToClaudeAgentTools(\n tools: AgentToolConfig[],\n handlers: Map<string, ToolHandler>,\n context: Partial<ToolExecutionContext>\n): (ClaudeAgentTool & { execute: (input: unknown) => Promise<unknown> })[] {\n return tools\n .filter((tool) => handlers.has(tool.name))\n .map((tool) => {\n const handler = handlers.get(tool.name);\n if (!handler) {\n throw new Error(`Handler not found for tool ${tool.name}`);\n }\n return specToolToClaudeAgentTool(tool, handler, context);\n });\n}\n\n// ============================================================================\n// Claude Agent SDK → ContractSpec Conversion\n// ============================================================================\n\n/**\n * Convert a Claude Agent SDK tool to ContractSpec AgentToolConfig.\n * This enables importing tools defined in Claude Agent SDK format.\n *\n * @param claudeTool - Claude Agent SDK tool definition\n * @param execute - Optional execute function to wrap\n * @returns ContractSpec tool config and optional handler\n */\nexport function claudeAgentToolToSpecTool(\n claudeTool: ClaudeAgentTool,\n execute?: (input: unknown) => Promise<unknown>\n): {\n config: AgentToolConfig;\n handler?: ToolHandler;\n} {\n const config: AgentToolConfig = {\n name: claudeTool.name,\n description: claudeTool.description,\n schema: claudeTool.input_schema,\n requiresApproval: claudeTool.requires_confirmation,\n automationSafe: !claudeTool.requires_confirmation,\n };\n\n const handler: ToolHandler | undefined = execute\n ? async (input, _ctx) => String(await execute(input))\n : undefined;\n\n return { config, handler };\n}\n\n/**\n * Convert multiple Claude Agent SDK tools to ContractSpec format.\n */\nexport function claudeAgentToolsToSpecTools(\n claudeTools: (ClaudeAgentTool & {\n execute?: (input: unknown) => Promise<unknown>;\n })[]\n): {\n configs: AgentToolConfig[];\n handlers: Map<string, ToolHandler>;\n} {\n const configs: AgentToolConfig[] = [];\n const handlers = new Map<string, ToolHandler>();\n\n for (const claudeTool of claudeTools) {\n const { config, handler } = claudeAgentToolToSpecTool(\n claudeTool,\n claudeTool.execute\n );\n configs.push(config);\n if (handler) {\n handlers.set(config.name, handler);\n }\n }\n\n return { configs, handlers };\n}\n\n// ============================================================================\n// External Tool Definition Conversion\n// ============================================================================\n\n/**\n * Convert ContractSpec tool to ExternalToolDefinition format.\n */\nexport function specToolToExternalTool(\n tool: AgentToolConfig,\n handler?: ToolHandler,\n context?: Partial<ToolExecutionContext>\n): ExternalToolDefinition {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n inputSchema: tool.schema ?? { type: 'object' },\n requiresApproval: tool.requiresApproval ?? !tool.automationSafe,\n execute: handler\n ? async (input) => {\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'unknown',\n sessionId: context?.sessionId ?? 'unknown',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n return handler(input, fullContext);\n }\n : undefined,\n };\n}\n\n// ============================================================================\n// Schema Normalization\n// ============================================================================\n\n/**\n * Normalize a schema to Claude Agent SDK's expected format.\n * Ensures the schema is a valid JSON Schema object type.\n */\nfunction normalizeSchema(\n schema?: Record<string, unknown>\n): ClaudeAgentTool['input_schema'] {\n if (!schema) {\n return { type: 'object' };\n }\n\n // If it's already an object type schema, return as-is with type assertion\n if (schema.type === 'object') {\n return schema as ClaudeAgentTool['input_schema'];\n }\n\n // Wrap non-object schemas in an object\n return {\n type: 'object',\n properties: {\n value: schema,\n },\n required: ['value'],\n };\n}\n\n/**\n * Extract tool call info from Claude Agent SDK response.\n */\nexport function extractToolCalls(response: {\n content?: {\n type: string;\n id?: string;\n name?: string;\n input?: unknown;\n }[];\n}): {\n toolCallId: string;\n toolName: string;\n args: unknown;\n}[] {\n if (!response.content) {\n return [];\n }\n\n return response.content\n .filter((block) => block.type === 'tool_use')\n .map((block) => ({\n toolCallId: block.id ?? '',\n toolName: block.name ?? '',\n args: block.input,\n }));\n}\n"],"mappings":";;;;;;;;;AA2EA,SAAgB,0BACd,MACA,SACA,SACqE;AACrE,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,cAAc,gBAAgB,KAAK,OAAO;EAC1C,uBAAuB,KAAK,oBAAoB,CAAC,KAAK;EACtD,SAAS,OAAO,UAAmB;AASjC,UAAO,QAAQ,OAR2B;IACxC,SAAS,QAAQ,WAAW;IAC5B,WAAW,QAAQ,aAAa;IAChC,UAAU,QAAQ;IAClB,SAAS,QAAQ;IACjB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACjB,CACiC;;EAErC;;;;;AAMH,SAAgB,4BACd,OACA,UACA,SACyE;AACzE,QAAO,MACJ,QAAQ,SAAS,SAAS,IAAI,KAAK,KAAK,CAAC,CACzC,KAAK,SAAS;EACb,MAAM,UAAU,SAAS,IAAI,KAAK,KAAK;AACvC,MAAI,CAAC,QACH,OAAM,IAAI,MAAM,8BAA8B,KAAK,OAAO;AAE5D,SAAO,0BAA0B,MAAM,SAAS,QAAQ;GACxD;;;;;;;;;;AAeN,SAAgB,0BACd,YACA,SAIA;AAaA,QAAO;EAAE,QAZuB;GAC9B,MAAM,WAAW;GACjB,aAAa,WAAW;GACxB,QAAQ,WAAW;GACnB,kBAAkB,WAAW;GAC7B,gBAAgB,CAAC,WAAW;GAC7B;EAMgB,SAJwB,UACrC,OAAO,OAAO,SAAS,OAAO,MAAM,QAAQ,MAAM,CAAC,GACnD;EAEsB;;;;;AAM5B,SAAgB,4BACd,aAMA;CACA,MAAMA,UAA6B,EAAE;CACrC,MAAM,2BAAW,IAAI,KAA0B;AAE/C,MAAK,MAAM,cAAc,aAAa;EACpC,MAAM,EAAE,QAAQ,YAAY,0BAC1B,YACA,WAAW,QACZ;AACD,UAAQ,KAAK,OAAO;AACpB,MAAI,QACF,UAAS,IAAI,OAAO,MAAM,QAAQ;;AAItC,QAAO;EAAE;EAAS;EAAU;;;;;AAU9B,SAAgB,uBACd,MACA,SACA,SACwB;AACxB,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,aAAa,KAAK,UAAU,EAAE,MAAM,UAAU;EAC9C,kBAAkB,KAAK,oBAAoB,CAAC,KAAK;EACjD,SAAS,UACL,OAAO,UAAU;AASf,UAAO,QAAQ,OAR2B;IACxC,SAAS,SAAS,WAAW;IAC7B,WAAW,SAAS,aAAa;IACjC,UAAU,SAAS;IACnB,SAAS,SAAS;IAClB,UAAU,SAAS;IACnB,QAAQ,SAAS;IAClB,CACiC;MAEpC;EACL;;;;;;AAWH,SAAS,gBACP,QACiC;AACjC,KAAI,CAAC,OACH,QAAO,EAAE,MAAM,UAAU;AAI3B,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,QAAO;EACL,MAAM;EACN,YAAY,EACV,OAAO,QACR;EACD,UAAU,CAAC,QAAQ;EACpB;;;;;AAMH,SAAgB,iBAAiB,UAW7B;AACF,KAAI,CAAC,SAAS,QACZ,QAAO,EAAE;AAGX,QAAO,SAAS,QACb,QAAQ,UAAU,MAAM,SAAS,WAAW,CAC5C,KAAK,WAAW;EACf,YAAY,MAAM,MAAM;EACxB,UAAU,MAAM,QAAQ;EACxB,MAAM,MAAM;EACb,EAAE"}
1
+ {"version":3,"file":"tool-bridge.js","names":[],"sources":["../../../src/providers/claude-agent-sdk/tool-bridge.ts"],"sourcesContent":["/**\n * Tool bridge for converting between ContractSpec and Claude Agent SDK tool formats.\n *\n * Provides bidirectional conversion:\n * - ContractSpec AgentToolConfig → Claude Agent SDK tool\n * - Claude Agent SDK tool → ContractSpec AgentToolConfig\n */\n\nimport type { AgentToolConfig } from '../../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../../types';\nimport type { ExternalToolDefinition } from '../types';\n\n// ============================================================================\n// Claude Agent SDK Tool Types (based on SDK API)\n// ============================================================================\n\n/**\n * Claude Agent SDK tool definition.\n * Based on Anthropic's tool format.\n */\nexport interface ClaudeAgentTool {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input schema in JSON Schema format */\n input_schema: {\n type: 'object';\n properties?: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n /** Whether tool requires confirmation before execution */\n requires_confirmation?: boolean;\n /** Tool category for organization */\n category?: string;\n}\n\n/**\n * Claude Agent SDK tool result.\n */\nexport interface ClaudeAgentToolResult {\n /** Tool call ID this result corresponds to */\n tool_use_id: string;\n /** Result content */\n content: string | ClaudeAgentToolResultContent[];\n /** Whether the tool execution failed */\n is_error?: boolean;\n}\n\n/**\n * Claude Agent SDK tool result content block.\n */\nexport interface ClaudeAgentToolResultContent {\n type: 'text' | 'image';\n text?: string;\n source?: {\n type: 'base64';\n media_type: string;\n data: string;\n };\n}\n\n// ============================================================================\n// ContractSpec → Claude Agent SDK Conversion\n// ============================================================================\n\n/**\n * Convert a ContractSpec AgentToolConfig to Claude Agent SDK tool format.\n *\n * @param tool - ContractSpec tool configuration\n * @param handler - Tool handler function\n * @param context - Partial execution context to inject\n * @returns Claude Agent SDK tool definition with execute function\n */\nexport function specToolToClaudeAgentTool(\n tool: AgentToolConfig,\n handler: ToolHandler,\n context: Partial<ToolExecutionContext>\n): ClaudeAgentTool & { execute: (input: unknown) => Promise<unknown> } {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n input_schema: normalizeSchema(tool.schema),\n requires_confirmation: tool.requiresApproval ?? !tool.automationSafe,\n execute: async (input: unknown) => {\n const fullContext: ToolExecutionContext = {\n agentId: context.agentId ?? 'unknown',\n sessionId: context.sessionId ?? 'unknown',\n tenantId: context.tenantId,\n actorId: context.actorId,\n metadata: context.metadata,\n signal: context.signal,\n };\n return handler(input, fullContext);\n },\n };\n}\n\n/**\n * Convert multiple ContractSpec tools to Claude Agent SDK format.\n */\nexport function specToolsToClaudeAgentTools(\n tools: AgentToolConfig[],\n handlers: Map<string, ToolHandler>,\n context: Partial<ToolExecutionContext>\n): (ClaudeAgentTool & { execute: (input: unknown) => Promise<unknown> })[] {\n return tools\n .filter((tool) => handlers.has(tool.name))\n .map((tool) => {\n const handler = handlers.get(tool.name);\n if (!handler) {\n throw new Error(`Handler not found for tool ${tool.name}`);\n }\n return specToolToClaudeAgentTool(tool, handler, context);\n });\n}\n\n// ============================================================================\n// Claude Agent SDK → ContractSpec Conversion\n// ============================================================================\n\n/**\n * Convert a Claude Agent SDK tool to ContractSpec AgentToolConfig.\n * This enables importing tools defined in Claude Agent SDK format.\n *\n * @param claudeTool - Claude Agent SDK tool definition\n * @param execute - Optional execute function to wrap\n * @returns ContractSpec tool config and optional handler\n */\nexport function claudeAgentToolToSpecTool(\n claudeTool: ClaudeAgentTool,\n execute?: (input: unknown) => Promise<unknown>\n): {\n config: AgentToolConfig;\n handler?: ToolHandler;\n} {\n const config: AgentToolConfig = {\n name: claudeTool.name,\n description: claudeTool.description,\n schema: claudeTool.input_schema,\n requiresApproval: claudeTool.requires_confirmation,\n automationSafe: !claudeTool.requires_confirmation,\n };\n\n const handler: ToolHandler | undefined = execute\n ? async (input, _ctx) => String(await execute(input))\n : undefined;\n\n return { config, handler };\n}\n\n/**\n * Convert multiple Claude Agent SDK tools to ContractSpec format.\n */\nexport function claudeAgentToolsToSpecTools(\n claudeTools: (ClaudeAgentTool & {\n execute?: (input: unknown) => Promise<unknown>;\n })[]\n): {\n configs: AgentToolConfig[];\n handlers: Map<string, ToolHandler>;\n} {\n const configs: AgentToolConfig[] = [];\n const handlers = new Map<string, ToolHandler>();\n\n for (const claudeTool of claudeTools) {\n const { config, handler } = claudeAgentToolToSpecTool(\n claudeTool,\n claudeTool.execute\n );\n configs.push(config);\n if (handler) {\n handlers.set(config.name, handler);\n }\n }\n\n return { configs, handlers };\n}\n\n// ============================================================================\n// External Tool Definition Conversion\n// ============================================================================\n\n/**\n * Convert ContractSpec tool to ExternalToolDefinition format.\n */\nexport function specToolToExternalTool(\n tool: AgentToolConfig,\n handler?: ToolHandler,\n context?: Partial<ToolExecutionContext>\n): ExternalToolDefinition {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n inputSchema: tool.schema ?? { type: 'object' },\n requiresApproval: tool.requiresApproval ?? !tool.automationSafe,\n execute: handler\n ? async (input) => {\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'unknown',\n sessionId: context?.sessionId ?? 'unknown',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n return handler(input, fullContext);\n }\n : undefined,\n };\n}\n\n// ============================================================================\n// Schema Normalization\n// ============================================================================\n\n/**\n * Normalize a schema to Claude Agent SDK's expected format.\n * Ensures the schema is a valid JSON Schema object type.\n */\nfunction normalizeSchema(\n schema?: Record<string, unknown>\n): ClaudeAgentTool['input_schema'] {\n if (!schema) {\n return { type: 'object' };\n }\n\n // If it's already an object type schema, return as-is with type assertion\n if (schema.type === 'object') {\n return schema as ClaudeAgentTool['input_schema'];\n }\n\n // Wrap non-object schemas in an object\n return {\n type: 'object',\n properties: {\n value: schema,\n },\n required: ['value'],\n };\n}\n\n/**\n * Extract tool call info from Claude Agent SDK response.\n */\nexport function extractToolCalls(response: {\n content?: {\n type: string;\n id?: string;\n name?: string;\n input?: unknown;\n }[];\n}): {\n toolCallId: string;\n toolName: string;\n args: unknown;\n}[] {\n if (!response.content) {\n return [];\n }\n\n return response.content\n .filter((block) => block.type === 'tool_use')\n .map((block) => ({\n toolCallId: block.id ?? '',\n toolName: block.name ?? '',\n args: block.input,\n }));\n}\n"],"mappings":";;;;;;;;;AA2EA,SAAgB,0BACd,MACA,SACA,SACqE;AACrE,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,cAAc,gBAAgB,KAAK,OAAO;EAC1C,uBAAuB,KAAK,oBAAoB,CAAC,KAAK;EACtD,SAAS,OAAO,UAAmB;AASjC,UAAO,QAAQ,OAR2B;IACxC,SAAS,QAAQ,WAAW;IAC5B,WAAW,QAAQ,aAAa;IAChC,UAAU,QAAQ;IAClB,SAAS,QAAQ;IACjB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACjB,CACiC;;EAErC;;;;;AAMH,SAAgB,4BACd,OACA,UACA,SACyE;AACzE,QAAO,MACJ,QAAQ,SAAS,SAAS,IAAI,KAAK,KAAK,CAAC,CACzC,KAAK,SAAS;EACb,MAAM,UAAU,SAAS,IAAI,KAAK,KAAK;AACvC,MAAI,CAAC,QACH,OAAM,IAAI,MAAM,8BAA8B,KAAK,OAAO;AAE5D,SAAO,0BAA0B,MAAM,SAAS,QAAQ;GACxD;;;;;;;;;;AAeN,SAAgB,0BACd,YACA,SAIA;AAaA,QAAO;EAAE,QAZuB;GAC9B,MAAM,WAAW;GACjB,aAAa,WAAW;GACxB,QAAQ,WAAW;GACnB,kBAAkB,WAAW;GAC7B,gBAAgB,CAAC,WAAW;GAC7B;EAMgB,SAJwB,UACrC,OAAO,OAAO,SAAS,OAAO,MAAM,QAAQ,MAAM,CAAC,GACnD;EAEsB;;;;;AAM5B,SAAgB,4BACd,aAMA;CACA,MAAM,UAA6B,EAAE;CACrC,MAAM,2BAAW,IAAI,KAA0B;AAE/C,MAAK,MAAM,cAAc,aAAa;EACpC,MAAM,EAAE,QAAQ,YAAY,0BAC1B,YACA,WAAW,QACZ;AACD,UAAQ,KAAK,OAAO;AACpB,MAAI,QACF,UAAS,IAAI,OAAO,MAAM,QAAQ;;AAItC,QAAO;EAAE;EAAS;EAAU;;;;;AAU9B,SAAgB,uBACd,MACA,SACA,SACwB;AACxB,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,aAAa,KAAK,UAAU,EAAE,MAAM,UAAU;EAC9C,kBAAkB,KAAK,oBAAoB,CAAC,KAAK;EACjD,SAAS,UACL,OAAO,UAAU;AASf,UAAO,QAAQ,OAR2B;IACxC,SAAS,SAAS,WAAW;IAC7B,WAAW,SAAS,aAAa;IACjC,UAAU,SAAS;IACnB,SAAS,SAAS;IAClB,UAAU,SAAS;IACnB,QAAQ,SAAS;IAClB,CACiC;MAEpC;EACL;;;;;;AAWH,SAAS,gBACP,QACiC;AACjC,KAAI,CAAC,OACH,QAAO,EAAE,MAAM,UAAU;AAI3B,KAAI,OAAO,SAAS,SAClB,QAAO;AAIT,QAAO;EACL,MAAM;EACN,YAAY,EACV,OAAO,QACR;EACD,UAAU,CAAC,QAAQ;EACpB;;;;;AAMH,SAAgB,iBAAiB,UAW7B;AACF,KAAI,CAAC,SAAS,QACZ,QAAO,EAAE;AAGX,QAAO,SAAS,QACb,QAAQ,UAAU,MAAM,SAAS,WAAW,CAC5C,KAAK,WAAW;EACf,YAAY,MAAM,MAAM;EACxB,UAAU,MAAM,QAAQ;EACxB,MAAM,MAAM;EACb,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":["toolSet: ExternalToolSet","metadata: OpenCodeContextMetadata","allToolCalls: OpenCodeToolCall[]","toolCall: OpenCodeToolCall"],"sources":["../../../src/providers/opencode-sdk/adapter.ts"],"sourcesContent":["/**\n * OpenCode SDK Provider\n *\n * Enables ContractSpec agents to run via OpenCode server:\n * - Session-based execution\n * - Multiple agent types (Build, Plan, General, Explore)\n * - Type-safe client interface\n * - Real-time streaming support\n *\n * This adapter wraps @opencode-ai/sdk to work as a backend\n * for ContractSpec agents.\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport { agentKey } from '../../spec/spec';\nimport type {\n ExternalAgentProvider,\n ExternalAgentContext,\n ExternalExecuteParams,\n ExternalExecuteResult,\n ExternalStreamChunk,\n ExternalToolSet,\n OpenCodeSDKConfig,\n OpenCodeContextMetadata,\n OpenCodeAgentType,\n} from '../types';\nimport {\n ContextCreationError,\n ProviderExecutionError,\n ProviderNotAvailableError,\n} from '../types';\nimport {\n specToolToExternalToolForOpenCode,\n createToolHandlerMap,\n executeToolCall,\n type OpenCodeToolCall,\n} from './tool-bridge';\nimport { inferAgentType } from './agent-bridge';\nimport { injectStaticKnowledge } from '../../knowledge/injector';\n\n// ============================================================================\n// Provider Implementation\n// ============================================================================\n\n/**\n * OpenCode SDK Provider implementation.\n */\nexport class OpenCodeSDKProvider implements ExternalAgentProvider {\n readonly name = 'opencode-sdk';\n readonly version = '1.0.0';\n\n private config: OpenCodeSDKConfig;\n private sdkAvailable: boolean | null = null;\n\n constructor(config: OpenCodeSDKConfig = {}) {\n this.config = {\n serverUrl: 'http://127.0.0.1:4096',\n port: 4096,\n agentType: 'general',\n temperature: 0.7,\n timeout: 30000,\n ...config,\n };\n\n // Build server URL from port if not explicitly set\n if (!config.serverUrl && config.port) {\n this.config.serverUrl = `http://127.0.0.1:${config.port}`;\n }\n }\n\n /**\n * Check if OpenCode SDK is available.\n */\n isAvailable(): boolean {\n if (this.sdkAvailable !== null) {\n return this.sdkAvailable;\n }\n\n try {\n // Check if the SDK is installed\n require.resolve('@opencode-ai/sdk');\n this.sdkAvailable = true;\n } catch {\n this.sdkAvailable = false;\n }\n\n return this.sdkAvailable;\n }\n\n /**\n * Create an execution context from an AgentSpec.\n */\n async createContext(spec: AgentSpec): Promise<ExternalAgentContext> {\n if (!this.isAvailable()) {\n throw new ProviderNotAvailableError(this.name, 'SDK not installed');\n }\n\n try {\n const sdk = await this.loadSDK();\n\n // Create or connect to OpenCode client\n const { client } = await sdk.createOpencode({\n hostname: this.getHostname(),\n port: this.config.port ?? 4096,\n timeout: this.config.timeout,\n });\n\n // Create session\n const session = await client.session.create({\n agent: this.config.agentType ?? inferAgentType(spec),\n model: this.config.model,\n });\n\n // Build tools set\n const toolSet: ExternalToolSet = {};\n for (const tool of spec.tools) {\n toolSet[tool.name] = specToolToExternalToolForOpenCode(tool);\n }\n\n // Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n spec.instructions,\n spec.knowledge ?? [],\n undefined\n );\n\n const contextId = `opencode-${agentKey(spec.meta)}-${Date.now()}`;\n\n const metadata: OpenCodeContextMetadata = {\n sessionId: session.id,\n agentType: this.config.agentType ?? inferAgentType(spec),\n serverUrl:\n this.config.serverUrl ??\n `http://127.0.0.1:${this.config.port ?? 4096}`,\n };\n\n return {\n id: contextId,\n spec: {\n ...spec,\n instructions,\n },\n tools: toolSet,\n metadata: metadata as unknown as Record<string, unknown>,\n cleanup: async () => {\n // Cleanup session if needed\n try {\n await client.session.delete({ id: session.id });\n } catch {\n // Ignore cleanup errors\n }\n },\n };\n } catch (error) {\n throw new ContextCreationError(\n this.name,\n `Failed to create context: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Execute a prompt using OpenCode SDK.\n */\n async execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult> {\n try {\n const sdk = await this.loadSDK();\n const metadata = context.metadata as unknown as OpenCodeContextMetadata;\n\n // Connect to existing session\n const { client } = await sdk.createOpencodeClient({\n baseUrl: metadata.serverUrl,\n });\n\n // Build system prompt\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Execute prompt\n const response = await client.session.prompt({\n id: metadata.sessionId,\n body: {\n content: params.prompt,\n system: systemPrompt,\n },\n });\n\n // Extract tool calls from response\n const toolCalls = this.extractToolCalls(response);\n const toolHandlers = createToolHandlerMap(context.tools);\n\n // Execute tools\n const toolResults = await Promise.all(\n toolCalls.map((tc) => executeToolCall(tc, toolHandlers))\n );\n\n return {\n text: this.extractTextContent(response),\n toolCalls: toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.arguments,\n })),\n toolResults: toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.tool_call_id,\n toolName:\n toolCalls.find((tc) => tc.id === tr.tool_call_id)?.name ?? '',\n output: tr.output,\n })),\n usage: {\n inputTokens: response.usage?.input_tokens ?? 0,\n outputTokens: response.usage?.output_tokens ?? 0,\n },\n finishReason: this.mapFinishReason(response.finish_reason),\n metadata: {\n sessionId: metadata.sessionId,\n agentType: metadata.agentType,\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Stream execution with real-time updates.\n */\n async *stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk> {\n try {\n const sdk = await this.loadSDK();\n const metadata = context.metadata as unknown as OpenCodeContextMetadata;\n\n const { client } = await sdk.createOpencodeClient({\n baseUrl: metadata.serverUrl,\n });\n\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Subscribe to session events\n const events = client.session.subscribe({\n id: metadata.sessionId,\n });\n\n // Send prompt\n await client.session.prompt({\n id: metadata.sessionId,\n body: {\n content: params.prompt,\n system: systemPrompt,\n },\n });\n\n let fullText = '';\n const allToolCalls: OpenCodeToolCall[] = [];\n const toolHandlers = createToolHandlerMap(context.tools);\n let stepIndex = 0;\n\n for await (const event of events) {\n if (event.type === 'message.delta') {\n const text = event.delta?.content ?? '';\n fullText += text;\n yield { type: 'text', text };\n }\n\n if (event.type === 'tool.call') {\n const toolCall: OpenCodeToolCall = {\n id: event.tool_call_id ?? `tc-${Date.now()}`,\n name: event.tool_name ?? '',\n arguments: event.arguments ?? {},\n };\n allToolCalls.push(toolCall);\n yield {\n type: 'tool-call',\n toolCall: {\n type: 'tool-call',\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args: toolCall.arguments,\n },\n };\n }\n\n if (event.type === 'step.complete') {\n stepIndex++;\n yield { type: 'step-complete', stepIndex };\n }\n\n if (event.type === 'message.complete') {\n break;\n }\n }\n\n // Execute pending tools\n for (const toolCall of allToolCalls) {\n const result = await executeToolCall(toolCall, toolHandlers);\n yield {\n type: 'tool-result',\n toolResult: {\n type: 'tool-result',\n toolCallId: result.tool_call_id,\n toolName: toolCall.name,\n output: result.output,\n },\n };\n }\n\n // Final done event\n yield {\n type: 'done',\n result: {\n text: fullText,\n toolCalls: allToolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.arguments,\n })),\n toolResults: [],\n usage: { inputTokens: 0, outputTokens: 0 },\n finishReason: 'stop',\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Stream failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // ============================================================================\n // Private Helpers\n // ============================================================================\n\n /**\n * Load the OpenCode SDK dynamically.\n */\n private async loadSDK(): Promise<OpenCodeSDKInterface> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = require('@opencode-ai/sdk');\n return module;\n } catch {\n throw new ProviderNotAvailableError(\n this.name,\n '@opencode-ai/sdk is not installed'\n );\n }\n }\n\n /**\n * Get hostname from server URL.\n */\n private getHostname(): string {\n if (!this.config.serverUrl) {\n return '127.0.0.1';\n }\n try {\n const url = new URL(this.config.serverUrl);\n return url.hostname;\n } catch {\n return '127.0.0.1';\n }\n }\n\n /**\n * Extract tool calls from response.\n */\n private extractToolCalls(response: {\n tool_calls?: { id: string; name: string; arguments: unknown }[];\n }): OpenCodeToolCall[] {\n if (!response.tool_calls) {\n return [];\n }\n\n return response.tool_calls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n arguments: (tc.arguments ?? {}) as Record<string, unknown>,\n }));\n }\n\n /**\n * Extract text content from response.\n */\n private extractTextContent(response: {\n content?: string;\n message?: { content?: string };\n }): string {\n return response.content ?? response.message?.content ?? '';\n }\n\n /**\n * Map OpenCode finish reason to ContractSpec finish reason.\n */\n private mapFinishReason(\n finishReason?: string\n ): ExternalExecuteResult['finishReason'] {\n switch (finishReason) {\n case 'stop':\n case 'end':\n return 'stop';\n case 'tool_use':\n case 'tool_calls':\n return 'tool-calls';\n case 'length':\n case 'max_tokens':\n return 'length';\n default:\n return 'stop';\n }\n }\n}\n\n// ============================================================================\n// SDK Interface Type (for dynamic import)\n// ============================================================================\n\n/**\n * Interface for OpenCode SDK (used for dynamic import).\n */\ninterface OpenCodeSDKInterface {\n createOpencode(options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n config?: unknown;\n }): Promise<{\n client: OpenCodeClient;\n }>;\n\n createOpencodeClient(options: { baseUrl: string }): Promise<{\n client: OpenCodeClient;\n }>;\n}\n\n/**\n * OpenCode client interface.\n */\ninterface OpenCodeClient {\n session: {\n create(options: {\n agent?: OpenCodeAgentType;\n model?: string;\n }): Promise<{ id: string }>;\n\n prompt(options: {\n id: string;\n body: {\n content: string;\n system?: string;\n };\n }): Promise<{\n content?: string;\n message?: { content?: string };\n tool_calls?: { id: string; name: string; arguments: unknown }[];\n usage?: { input_tokens?: number; output_tokens?: number };\n finish_reason?: string;\n }>;\n\n delete(options: { id: string }): Promise<void>;\n\n subscribe(options: { id: string }): AsyncIterable<{\n type: string;\n delta?: { content?: string };\n tool_call_id?: string;\n tool_name?: string;\n arguments?: Record<string, unknown>;\n }>;\n };\n\n app: {\n agents(): Promise<{ name: string; type: OpenCodeAgentType }[]>;\n };\n\n global: {\n health(): Promise<{ status: string }>;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../src/providers/opencode-sdk/adapter.ts"],"sourcesContent":["/**\n * OpenCode SDK Provider\n *\n * Enables ContractSpec agents to run via OpenCode server:\n * - Session-based execution\n * - Multiple agent types (Build, Plan, General, Explore)\n * - Type-safe client interface\n * - Real-time streaming support\n *\n * This adapter wraps @opencode-ai/sdk to work as a backend\n * for ContractSpec agents.\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport { agentKey } from '../../spec/spec';\nimport type {\n ExternalAgentProvider,\n ExternalAgentContext,\n ExternalExecuteParams,\n ExternalExecuteResult,\n ExternalStreamChunk,\n ExternalToolSet,\n OpenCodeSDKConfig,\n OpenCodeContextMetadata,\n OpenCodeAgentType,\n} from '../types';\nimport {\n ContextCreationError,\n ProviderExecutionError,\n ProviderNotAvailableError,\n} from '../types';\nimport {\n specToolToExternalToolForOpenCode,\n createToolHandlerMap,\n executeToolCall,\n type OpenCodeToolCall,\n} from './tool-bridge';\nimport { inferAgentType } from './agent-bridge';\nimport { injectStaticKnowledge } from '../../knowledge/injector';\n\n// ============================================================================\n// Provider Implementation\n// ============================================================================\n\n/**\n * OpenCode SDK Provider implementation.\n */\nexport class OpenCodeSDKProvider implements ExternalAgentProvider {\n readonly name = 'opencode-sdk';\n readonly version = '1.0.0';\n\n private config: OpenCodeSDKConfig;\n private sdkAvailable: boolean | null = null;\n\n constructor(config: OpenCodeSDKConfig = {}) {\n this.config = {\n serverUrl: 'http://127.0.0.1:4096',\n port: 4096,\n agentType: 'general',\n temperature: 0.7,\n timeout: 30000,\n ...config,\n };\n\n // Build server URL from port if not explicitly set\n if (!config.serverUrl && config.port) {\n this.config.serverUrl = `http://127.0.0.1:${config.port}`;\n }\n }\n\n /**\n * Check if OpenCode SDK is available.\n */\n isAvailable(): boolean {\n if (this.sdkAvailable !== null) {\n return this.sdkAvailable;\n }\n\n try {\n // Check if the SDK is installed\n require.resolve('@opencode-ai/sdk');\n this.sdkAvailable = true;\n } catch {\n this.sdkAvailable = false;\n }\n\n return this.sdkAvailable;\n }\n\n /**\n * Create an execution context from an AgentSpec.\n */\n async createContext(spec: AgentSpec): Promise<ExternalAgentContext> {\n if (!this.isAvailable()) {\n throw new ProviderNotAvailableError(this.name, 'SDK not installed');\n }\n\n try {\n const sdk = await this.loadSDK();\n\n // Create or connect to OpenCode client\n const { client } = await sdk.createOpencode({\n hostname: this.getHostname(),\n port: this.config.port ?? 4096,\n timeout: this.config.timeout,\n });\n\n // Create session\n const session = await client.session.create({\n agent: this.config.agentType ?? inferAgentType(spec),\n model: this.config.model,\n });\n\n // Build tools set\n const toolSet: ExternalToolSet = {};\n for (const tool of spec.tools) {\n toolSet[tool.name] = specToolToExternalToolForOpenCode(tool);\n }\n\n // Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n spec.instructions,\n spec.knowledge ?? [],\n undefined\n );\n\n const contextId = `opencode-${agentKey(spec.meta)}-${Date.now()}`;\n\n const metadata: OpenCodeContextMetadata = {\n sessionId: session.id,\n agentType: this.config.agentType ?? inferAgentType(spec),\n serverUrl:\n this.config.serverUrl ??\n `http://127.0.0.1:${this.config.port ?? 4096}`,\n };\n\n return {\n id: contextId,\n spec: {\n ...spec,\n instructions,\n },\n tools: toolSet,\n metadata: metadata as unknown as Record<string, unknown>,\n cleanup: async () => {\n // Cleanup session if needed\n try {\n await client.session.delete({ id: session.id });\n } catch {\n // Ignore cleanup errors\n }\n },\n };\n } catch (error) {\n throw new ContextCreationError(\n this.name,\n `Failed to create context: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Execute a prompt using OpenCode SDK.\n */\n async execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult> {\n try {\n const sdk = await this.loadSDK();\n const metadata = context.metadata as unknown as OpenCodeContextMetadata;\n\n // Connect to existing session\n const { client } = await sdk.createOpencodeClient({\n baseUrl: metadata.serverUrl,\n });\n\n // Build system prompt\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Execute prompt\n const response = await client.session.prompt({\n id: metadata.sessionId,\n body: {\n content: params.prompt,\n system: systemPrompt,\n },\n });\n\n // Extract tool calls from response\n const toolCalls = this.extractToolCalls(response);\n const toolHandlers = createToolHandlerMap(context.tools);\n\n // Execute tools\n const toolResults = await Promise.all(\n toolCalls.map((tc) => executeToolCall(tc, toolHandlers))\n );\n\n return {\n text: this.extractTextContent(response),\n toolCalls: toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.arguments,\n })),\n toolResults: toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.tool_call_id,\n toolName:\n toolCalls.find((tc) => tc.id === tr.tool_call_id)?.name ?? '',\n output: tr.output,\n })),\n usage: {\n inputTokens: response.usage?.input_tokens ?? 0,\n outputTokens: response.usage?.output_tokens ?? 0,\n },\n finishReason: this.mapFinishReason(response.finish_reason),\n metadata: {\n sessionId: metadata.sessionId,\n agentType: metadata.agentType,\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Stream execution with real-time updates.\n */\n async *stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk> {\n try {\n const sdk = await this.loadSDK();\n const metadata = context.metadata as unknown as OpenCodeContextMetadata;\n\n const { client } = await sdk.createOpencodeClient({\n baseUrl: metadata.serverUrl,\n });\n\n const systemPrompt = params.systemOverride\n ? `${context.spec.instructions}\\n\\n${params.systemOverride}`\n : context.spec.instructions;\n\n // Subscribe to session events\n const events = client.session.subscribe({\n id: metadata.sessionId,\n });\n\n // Send prompt\n await client.session.prompt({\n id: metadata.sessionId,\n body: {\n content: params.prompt,\n system: systemPrompt,\n },\n });\n\n let fullText = '';\n const allToolCalls: OpenCodeToolCall[] = [];\n const toolHandlers = createToolHandlerMap(context.tools);\n let stepIndex = 0;\n\n for await (const event of events) {\n if (event.type === 'message.delta') {\n const text = event.delta?.content ?? '';\n fullText += text;\n yield { type: 'text', text };\n }\n\n if (event.type === 'tool.call') {\n const toolCall: OpenCodeToolCall = {\n id: event.tool_call_id ?? `tc-${Date.now()}`,\n name: event.tool_name ?? '',\n arguments: event.arguments ?? {},\n };\n allToolCalls.push(toolCall);\n yield {\n type: 'tool-call',\n toolCall: {\n type: 'tool-call',\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n args: toolCall.arguments,\n },\n };\n }\n\n if (event.type === 'step.complete') {\n stepIndex++;\n yield { type: 'step-complete', stepIndex };\n }\n\n if (event.type === 'message.complete') {\n break;\n }\n }\n\n // Execute pending tools\n for (const toolCall of allToolCalls) {\n const result = await executeToolCall(toolCall, toolHandlers);\n yield {\n type: 'tool-result',\n toolResult: {\n type: 'tool-result',\n toolCallId: result.tool_call_id,\n toolName: toolCall.name,\n output: result.output,\n },\n };\n }\n\n // Final done event\n yield {\n type: 'done',\n result: {\n text: fullText,\n toolCalls: allToolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.arguments,\n })),\n toolResults: [],\n usage: { inputTokens: 0, outputTokens: 0 },\n finishReason: 'stop',\n },\n };\n } catch (error) {\n throw new ProviderExecutionError(\n this.name,\n `Stream failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // ============================================================================\n // Private Helpers\n // ============================================================================\n\n /**\n * Load the OpenCode SDK dynamically.\n */\n private async loadSDK(): Promise<OpenCodeSDKInterface> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const module = require('@opencode-ai/sdk');\n return module;\n } catch {\n throw new ProviderNotAvailableError(\n this.name,\n '@opencode-ai/sdk is not installed'\n );\n }\n }\n\n /**\n * Get hostname from server URL.\n */\n private getHostname(): string {\n if (!this.config.serverUrl) {\n return '127.0.0.1';\n }\n try {\n const url = new URL(this.config.serverUrl);\n return url.hostname;\n } catch {\n return '127.0.0.1';\n }\n }\n\n /**\n * Extract tool calls from response.\n */\n private extractToolCalls(response: {\n tool_calls?: { id: string; name: string; arguments: unknown }[];\n }): OpenCodeToolCall[] {\n if (!response.tool_calls) {\n return [];\n }\n\n return response.tool_calls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n arguments: (tc.arguments ?? {}) as Record<string, unknown>,\n }));\n }\n\n /**\n * Extract text content from response.\n */\n private extractTextContent(response: {\n content?: string;\n message?: { content?: string };\n }): string {\n return response.content ?? response.message?.content ?? '';\n }\n\n /**\n * Map OpenCode finish reason to ContractSpec finish reason.\n */\n private mapFinishReason(\n finishReason?: string\n ): ExternalExecuteResult['finishReason'] {\n switch (finishReason) {\n case 'stop':\n case 'end':\n return 'stop';\n case 'tool_use':\n case 'tool_calls':\n return 'tool-calls';\n case 'length':\n case 'max_tokens':\n return 'length';\n default:\n return 'stop';\n }\n }\n}\n\n// ============================================================================\n// SDK Interface Type (for dynamic import)\n// ============================================================================\n\n/**\n * Interface for OpenCode SDK (used for dynamic import).\n */\ninterface OpenCodeSDKInterface {\n createOpencode(options: {\n hostname?: string;\n port?: number;\n timeout?: number;\n config?: unknown;\n }): Promise<{\n client: OpenCodeClient;\n }>;\n\n createOpencodeClient(options: { baseUrl: string }): Promise<{\n client: OpenCodeClient;\n }>;\n}\n\n/**\n * OpenCode client interface.\n */\ninterface OpenCodeClient {\n session: {\n create(options: {\n agent?: OpenCodeAgentType;\n model?: string;\n }): Promise<{ id: string }>;\n\n prompt(options: {\n id: string;\n body: {\n content: string;\n system?: string;\n };\n }): Promise<{\n content?: string;\n message?: { content?: string };\n tool_calls?: { id: string; name: string; arguments: unknown }[];\n usage?: { input_tokens?: number; output_tokens?: number };\n finish_reason?: string;\n }>;\n\n delete(options: { id: string }): Promise<void>;\n\n subscribe(options: { id: string }): AsyncIterable<{\n type: string;\n delta?: { content?: string };\n tool_call_id?: string;\n tool_name?: string;\n arguments?: Record<string, unknown>;\n }>;\n };\n\n app: {\n agents(): Promise<{ name: string; type: OpenCodeAgentType }[]>;\n };\n\n global: {\n health(): Promise<{ status: string }>;\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-bridge.js","names":["permissions: Record<string, 'allow' | 'ask' | 'deny'>","lines: string[]"],"sources":["../../../src/providers/opencode-sdk/agent-bridge.ts"],"sourcesContent":["/**\n * Agent bridge for mapping between ContractSpec AgentSpec and OpenCode agent configuration.\n *\n * OpenCode has four built-in agent types:\n * - build: Primary agent with all tools enabled (default for code generation)\n * - plan: Restricted agent for analysis/planning (file edits and bash in \"ask\" mode)\n * - general: Subagent for complex questions and multi-step tasks\n * - explore: Fast subagent for codebase exploration\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport type { OpenCodeAgentType } from '../types';\nimport { specToolsToOpenCodeTools, type OpenCodeTool } from './tool-bridge';\n\n// ============================================================================\n// OpenCode Agent Configuration Types\n// ============================================================================\n\n/**\n * OpenCode agent configuration in JSON format.\n */\nexport interface OpenCodeAgentJSON {\n /** Agent name */\n name: string;\n /** Agent version */\n version?: string;\n /** Agent description */\n description?: string;\n /** System instructions */\n instructions?: string;\n /** Agent type */\n agent_type: OpenCodeAgentType;\n /** Available tools */\n tools?: OpenCodeTool[];\n /** Configuration options */\n config?: OpenCodeAgentConfig;\n}\n\n/**\n * OpenCode agent configuration options.\n */\nexport interface OpenCodeAgentConfig {\n /** Maximum agentic iterations */\n max_steps?: number;\n /** Temperature for generation */\n temperature?: number;\n /** Model to use */\n model?: string;\n /** Tool permissions */\n permissions?: Record<string, 'allow' | 'ask' | 'deny'>;\n}\n\n/**\n * OpenCode agent markdown format (for .opencode/agent/*.md files).\n */\nexport interface OpenCodeAgentMarkdown {\n /** Frontmatter */\n frontmatter: {\n name: string;\n type: OpenCodeAgentType;\n version?: string;\n model?: string;\n temperature?: number;\n max_steps?: number;\n tools?: string[];\n };\n /** Body content */\n body: string;\n}\n\n// ============================================================================\n// Agent Type Inference\n// ============================================================================\n\n/**\n * Infer the appropriate OpenCode agent type from an AgentSpec.\n *\n * The inference is based on:\n * - Tool capabilities (file editing, bash execution → build)\n * - Instructions content (planning keywords → plan)\n * - Exploration keywords (search, find → explore)\n */\nexport function inferAgentType(spec: AgentSpec): OpenCodeAgentType {\n // Check for code-generation/modification tools\n const hasCodeTools = spec.tools.some((tool) =>\n [\n 'write_file',\n 'edit_file',\n 'create_file',\n 'delete_file',\n 'bash',\n 'execute',\n 'run_command',\n 'terminal',\n ].includes(tool.name.toLowerCase())\n );\n\n // Check instructions for planning-related keywords\n const instructionsLower = spec.instructions.toLowerCase();\n const hasPlanningKeywords =\n /\\b(plan|design|architect|strategy|analyze|review|assess|evaluate)\\b/.test(\n instructionsLower\n );\n\n // Check for exploration-related keywords\n const hasExplorationKeywords =\n /\\b(search|find|explore|discover|locate|grep|pattern)\\b/.test(\n instructionsLower\n );\n\n // Check for research/general keywords\n const hasResearchKeywords =\n /\\b(research|investigate|understand|learn|gather|collect)\\b/.test(\n instructionsLower\n );\n\n // Decision logic\n if (hasCodeTools) {\n return 'build';\n }\n\n if (hasPlanningKeywords && !hasCodeTools) {\n return 'plan';\n }\n\n if (hasExplorationKeywords && !hasResearchKeywords) {\n return 'explore';\n }\n\n // Default to general for most use cases\n return 'general';\n}\n\n// ============================================================================\n// Spec to OpenCode Conversion\n// ============================================================================\n\n/**\n * Convert an AgentSpec to OpenCode agent JSON configuration.\n */\nexport function specToOpenCodeConfig(\n spec: AgentSpec,\n options?: {\n agentType?: OpenCodeAgentType;\n model?: string;\n temperature?: number;\n maxSteps?: number;\n }\n): OpenCodeAgentJSON {\n const agentType = options?.agentType ?? inferAgentType(spec);\n\n return {\n name: spec.meta.key,\n version: spec.meta.version,\n description: spec.description ?? spec.meta.description,\n instructions: spec.instructions,\n agent_type: agentType,\n tools: specToolsToOpenCodeTools(spec.tools),\n config: {\n max_steps: options?.maxSteps ?? spec.maxSteps ?? 10,\n temperature: options?.temperature ?? 0.7,\n model: options?.model,\n permissions: buildPermissions(spec),\n },\n };\n}\n\n/**\n * Build tool permissions from spec.\n */\nfunction buildPermissions(\n spec: AgentSpec\n): Record<string, 'allow' | 'ask' | 'deny'> {\n const permissions: Record<string, 'allow' | 'ask' | 'deny'> = {};\n\n for (const tool of spec.tools) {\n if (tool.requiresApproval) {\n permissions[tool.name] = 'ask';\n } else if (tool.automationSafe === false) {\n permissions[tool.name] = 'ask';\n } else {\n permissions[tool.name] = 'allow';\n }\n }\n\n return permissions;\n}\n\n/**\n * Convert an AgentSpec to OpenCode agent markdown format.\n */\nexport function specToOpenCodeMarkdown(\n spec: AgentSpec,\n options?: {\n agentType?: OpenCodeAgentType;\n model?: string;\n temperature?: number;\n maxSteps?: number;\n }\n): OpenCodeAgentMarkdown {\n const agentType = options?.agentType ?? inferAgentType(spec);\n\n return {\n frontmatter: {\n name: spec.meta.key,\n type: agentType,\n version: spec.meta.version,\n model: options?.model,\n temperature: options?.temperature ?? 0.7,\n max_steps: options?.maxSteps ?? spec.maxSteps ?? 10,\n tools: spec.tools.map((t) => t.name),\n },\n body: buildMarkdownBody(spec),\n };\n}\n\n/**\n * Build markdown body content from spec.\n */\nfunction buildMarkdownBody(spec: AgentSpec): string {\n const lines: string[] = [];\n\n // Title\n lines.push(`# ${spec.meta.key}`);\n lines.push('');\n\n // Description\n if (spec.description ?? spec.meta.description) {\n lines.push(spec.description ?? spec.meta.description ?? '');\n lines.push('');\n }\n\n // Instructions\n lines.push('## Instructions');\n lines.push('');\n lines.push(spec.instructions);\n lines.push('');\n\n // Tools\n if (spec.tools.length > 0) {\n lines.push('## Tools');\n lines.push('');\n for (const tool of spec.tools) {\n const permission = tool.requiresApproval\n ? '(requires approval)'\n : tool.automationSafe === false\n ? '(ask mode)'\n : '';\n lines.push(\n `- **${tool.name}**: ${tool.description ?? 'No description'} ${permission}`.trim()\n );\n }\n lines.push('');\n }\n\n // Knowledge sources\n if (spec.knowledge && spec.knowledge.length > 0) {\n lines.push('## Knowledge Sources');\n lines.push('');\n for (const k of spec.knowledge) {\n const required = k.required ? '(required)' : '(optional)';\n lines.push(`- ${k.key} ${required}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Serialize OpenCode agent markdown to string.\n */\nexport function serializeOpenCodeMarkdown(\n markdown: OpenCodeAgentMarkdown\n): string {\n const lines: string[] = [];\n\n // Frontmatter\n lines.push('---');\n lines.push(`name: ${markdown.frontmatter.name}`);\n lines.push(`type: ${markdown.frontmatter.type}`);\n\n if (markdown.frontmatter.version) {\n lines.push(`version: ${markdown.frontmatter.version}`);\n }\n\n if (markdown.frontmatter.model) {\n lines.push(`model: ${markdown.frontmatter.model}`);\n }\n\n if (markdown.frontmatter.temperature !== undefined) {\n lines.push(`temperature: ${markdown.frontmatter.temperature}`);\n }\n\n if (markdown.frontmatter.max_steps !== undefined) {\n lines.push(`max_steps: ${markdown.frontmatter.max_steps}`);\n }\n\n if (markdown.frontmatter.tools && markdown.frontmatter.tools.length > 0) {\n lines.push(`tools:`);\n for (const tool of markdown.frontmatter.tools) {\n lines.push(` - ${tool}`);\n }\n }\n\n lines.push('---');\n lines.push('');\n lines.push(markdown.body);\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// OpenCode to Spec Conversion\n// ============================================================================\n\n/**\n * Convert OpenCode agent configuration to partial AgentSpec.\n * Note: This is a partial conversion as OpenCode config may not have all spec fields.\n */\nexport function openCodeConfigToSpec(\n config: OpenCodeAgentJSON\n): Partial<AgentSpec> {\n return {\n meta: {\n key: config.name,\n version: config.version ?? '1.0.0',\n description: config.description ?? '',\n stability: 'experimental',\n owners: [],\n tags: [],\n },\n description: config.description,\n instructions: config.instructions ?? '',\n tools:\n config.tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n schema: tool.parameters,\n requiresApproval: tool.permission === 'ask',\n automationSafe: tool.permission === 'allow',\n // category not supported in AgentToolConfig\n })) ?? [],\n maxSteps: config.config?.max_steps ?? 10,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-bridge.js","names":[],"sources":["../../../src/providers/opencode-sdk/agent-bridge.ts"],"sourcesContent":["/**\n * Agent bridge for mapping between ContractSpec AgentSpec and OpenCode agent configuration.\n *\n * OpenCode has four built-in agent types:\n * - build: Primary agent with all tools enabled (default for code generation)\n * - plan: Restricted agent for analysis/planning (file edits and bash in \"ask\" mode)\n * - general: Subagent for complex questions and multi-step tasks\n * - explore: Fast subagent for codebase exploration\n */\n\nimport type { AgentSpec } from '../../spec/spec';\nimport type { OpenCodeAgentType } from '../types';\nimport { specToolsToOpenCodeTools, type OpenCodeTool } from './tool-bridge';\n\n// ============================================================================\n// OpenCode Agent Configuration Types\n// ============================================================================\n\n/**\n * OpenCode agent configuration in JSON format.\n */\nexport interface OpenCodeAgentJSON {\n /** Agent name */\n name: string;\n /** Agent version */\n version?: string;\n /** Agent description */\n description?: string;\n /** System instructions */\n instructions?: string;\n /** Agent type */\n agent_type: OpenCodeAgentType;\n /** Available tools */\n tools?: OpenCodeTool[];\n /** Configuration options */\n config?: OpenCodeAgentConfig;\n}\n\n/**\n * OpenCode agent configuration options.\n */\nexport interface OpenCodeAgentConfig {\n /** Maximum agentic iterations */\n max_steps?: number;\n /** Temperature for generation */\n temperature?: number;\n /** Model to use */\n model?: string;\n /** Tool permissions */\n permissions?: Record<string, 'allow' | 'ask' | 'deny'>;\n}\n\n/**\n * OpenCode agent markdown format (for .opencode/agent/*.md files).\n */\nexport interface OpenCodeAgentMarkdown {\n /** Frontmatter */\n frontmatter: {\n name: string;\n type: OpenCodeAgentType;\n version?: string;\n model?: string;\n temperature?: number;\n max_steps?: number;\n tools?: string[];\n };\n /** Body content */\n body: string;\n}\n\n// ============================================================================\n// Agent Type Inference\n// ============================================================================\n\n/**\n * Infer the appropriate OpenCode agent type from an AgentSpec.\n *\n * The inference is based on:\n * - Tool capabilities (file editing, bash execution → build)\n * - Instructions content (planning keywords → plan)\n * - Exploration keywords (search, find → explore)\n */\nexport function inferAgentType(spec: AgentSpec): OpenCodeAgentType {\n // Check for code-generation/modification tools\n const hasCodeTools = spec.tools.some((tool) =>\n [\n 'write_file',\n 'edit_file',\n 'create_file',\n 'delete_file',\n 'bash',\n 'execute',\n 'run_command',\n 'terminal',\n ].includes(tool.name.toLowerCase())\n );\n\n // Check instructions for planning-related keywords\n const instructionsLower = spec.instructions.toLowerCase();\n const hasPlanningKeywords =\n /\\b(plan|design|architect|strategy|analyze|review|assess|evaluate)\\b/.test(\n instructionsLower\n );\n\n // Check for exploration-related keywords\n const hasExplorationKeywords =\n /\\b(search|find|explore|discover|locate|grep|pattern)\\b/.test(\n instructionsLower\n );\n\n // Check for research/general keywords\n const hasResearchKeywords =\n /\\b(research|investigate|understand|learn|gather|collect)\\b/.test(\n instructionsLower\n );\n\n // Decision logic\n if (hasCodeTools) {\n return 'build';\n }\n\n if (hasPlanningKeywords && !hasCodeTools) {\n return 'plan';\n }\n\n if (hasExplorationKeywords && !hasResearchKeywords) {\n return 'explore';\n }\n\n // Default to general for most use cases\n return 'general';\n}\n\n// ============================================================================\n// Spec to OpenCode Conversion\n// ============================================================================\n\n/**\n * Convert an AgentSpec to OpenCode agent JSON configuration.\n */\nexport function specToOpenCodeConfig(\n spec: AgentSpec,\n options?: {\n agentType?: OpenCodeAgentType;\n model?: string;\n temperature?: number;\n maxSteps?: number;\n }\n): OpenCodeAgentJSON {\n const agentType = options?.agentType ?? inferAgentType(spec);\n\n return {\n name: spec.meta.key,\n version: spec.meta.version,\n description: spec.description ?? spec.meta.description,\n instructions: spec.instructions,\n agent_type: agentType,\n tools: specToolsToOpenCodeTools(spec.tools),\n config: {\n max_steps: options?.maxSteps ?? spec.maxSteps ?? 10,\n temperature: options?.temperature ?? 0.7,\n model: options?.model,\n permissions: buildPermissions(spec),\n },\n };\n}\n\n/**\n * Build tool permissions from spec.\n */\nfunction buildPermissions(\n spec: AgentSpec\n): Record<string, 'allow' | 'ask' | 'deny'> {\n const permissions: Record<string, 'allow' | 'ask' | 'deny'> = {};\n\n for (const tool of spec.tools) {\n if (tool.requiresApproval) {\n permissions[tool.name] = 'ask';\n } else if (tool.automationSafe === false) {\n permissions[tool.name] = 'ask';\n } else {\n permissions[tool.name] = 'allow';\n }\n }\n\n return permissions;\n}\n\n/**\n * Convert an AgentSpec to OpenCode agent markdown format.\n */\nexport function specToOpenCodeMarkdown(\n spec: AgentSpec,\n options?: {\n agentType?: OpenCodeAgentType;\n model?: string;\n temperature?: number;\n maxSteps?: number;\n }\n): OpenCodeAgentMarkdown {\n const agentType = options?.agentType ?? inferAgentType(spec);\n\n return {\n frontmatter: {\n name: spec.meta.key,\n type: agentType,\n version: spec.meta.version,\n model: options?.model,\n temperature: options?.temperature ?? 0.7,\n max_steps: options?.maxSteps ?? spec.maxSteps ?? 10,\n tools: spec.tools.map((t) => t.name),\n },\n body: buildMarkdownBody(spec),\n };\n}\n\n/**\n * Build markdown body content from spec.\n */\nfunction buildMarkdownBody(spec: AgentSpec): string {\n const lines: string[] = [];\n\n // Title\n lines.push(`# ${spec.meta.key}`);\n lines.push('');\n\n // Description\n if (spec.description ?? spec.meta.description) {\n lines.push(spec.description ?? spec.meta.description ?? '');\n lines.push('');\n }\n\n // Instructions\n lines.push('## Instructions');\n lines.push('');\n lines.push(spec.instructions);\n lines.push('');\n\n // Tools\n if (spec.tools.length > 0) {\n lines.push('## Tools');\n lines.push('');\n for (const tool of spec.tools) {\n const permission = tool.requiresApproval\n ? '(requires approval)'\n : tool.automationSafe === false\n ? '(ask mode)'\n : '';\n lines.push(\n `- **${tool.name}**: ${tool.description ?? 'No description'} ${permission}`.trim()\n );\n }\n lines.push('');\n }\n\n // Knowledge sources\n if (spec.knowledge && spec.knowledge.length > 0) {\n lines.push('## Knowledge Sources');\n lines.push('');\n for (const k of spec.knowledge) {\n const required = k.required ? '(required)' : '(optional)';\n lines.push(`- ${k.key} ${required}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Serialize OpenCode agent markdown to string.\n */\nexport function serializeOpenCodeMarkdown(\n markdown: OpenCodeAgentMarkdown\n): string {\n const lines: string[] = [];\n\n // Frontmatter\n lines.push('---');\n lines.push(`name: ${markdown.frontmatter.name}`);\n lines.push(`type: ${markdown.frontmatter.type}`);\n\n if (markdown.frontmatter.version) {\n lines.push(`version: ${markdown.frontmatter.version}`);\n }\n\n if (markdown.frontmatter.model) {\n lines.push(`model: ${markdown.frontmatter.model}`);\n }\n\n if (markdown.frontmatter.temperature !== undefined) {\n lines.push(`temperature: ${markdown.frontmatter.temperature}`);\n }\n\n if (markdown.frontmatter.max_steps !== undefined) {\n lines.push(`max_steps: ${markdown.frontmatter.max_steps}`);\n }\n\n if (markdown.frontmatter.tools && markdown.frontmatter.tools.length > 0) {\n lines.push(`tools:`);\n for (const tool of markdown.frontmatter.tools) {\n lines.push(` - ${tool}`);\n }\n }\n\n lines.push('---');\n lines.push('');\n lines.push(markdown.body);\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// OpenCode to Spec Conversion\n// ============================================================================\n\n/**\n * Convert OpenCode agent configuration to partial AgentSpec.\n * Note: This is a partial conversion as OpenCode config may not have all spec fields.\n */\nexport function openCodeConfigToSpec(\n config: OpenCodeAgentJSON\n): Partial<AgentSpec> {\n return {\n meta: {\n key: config.name,\n version: config.version ?? '1.0.0',\n description: config.description ?? '',\n stability: 'experimental',\n owners: [],\n tags: [],\n },\n description: config.description,\n instructions: config.instructions ?? '',\n tools:\n config.tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n schema: tool.parameters,\n requiresApproval: tool.permission === 'ask',\n automationSafe: tool.permission === 'allow',\n // category not supported in AgentToolConfig\n })) ?? [],\n maxSteps: config.config?.max_steps ?? 10,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-bridge.js","names":["param: OpenCodeParameter"],"sources":["../../../src/providers/opencode-sdk/tool-bridge.ts"],"sourcesContent":["/**\n * Tool bridge for converting between ContractSpec and OpenCode SDK tool formats.\n */\n\nimport type { AgentToolConfig } from '../../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../../types';\nimport type { ExternalToolDefinition } from '../types';\n\n// ============================================================================\n// OpenCode SDK Tool Types\n// ============================================================================\n\n/**\n * OpenCode SDK tool definition.\n */\nexport interface OpenCodeTool {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input parameters schema */\n parameters: {\n type: 'object';\n properties?: Record<string, OpenCodeParameter>;\n required?: string[];\n };\n /** Tool category */\n category?: string;\n /** Permission level */\n permission?: 'allow' | 'ask' | 'deny';\n}\n\n/**\n * OpenCode parameter definition.\n */\nexport interface OpenCodeParameter {\n type: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n}\n\n/**\n * OpenCode tool call from session.\n */\nexport interface OpenCodeToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\n/**\n * OpenCode tool result.\n */\nexport interface OpenCodeToolResult {\n tool_call_id: string;\n output: string;\n is_error?: boolean;\n}\n\n// ============================================================================\n// ContractSpec → OpenCode Conversion\n// ============================================================================\n\n/**\n * Convert a ContractSpec AgentToolConfig to OpenCode tool format.\n */\nexport function specToolToOpenCodeTool(tool: AgentToolConfig): OpenCodeTool {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n parameters: normalizeToOpenCodeParameters(tool.schema),\n // category property not in AgentToolConfig\n permission: getPermissionLevel(tool),\n };\n}\n\n/**\n * Convert multiple ContractSpec tools to OpenCode format.\n */\nexport function specToolsToOpenCodeTools(\n tools: AgentToolConfig[]\n): OpenCodeTool[] {\n return tools.map(specToolToOpenCodeTool);\n}\n\n/**\n * Determine permission level from tool config.\n */\nfunction getPermissionLevel(tool: AgentToolConfig): OpenCodeTool['permission'] {\n if (tool.requiresApproval) {\n return 'ask';\n }\n if (tool.automationSafe === false) {\n return 'ask';\n }\n return 'allow';\n}\n\n// ============================================================================\n// OpenCode → ContractSpec Conversion\n// ============================================================================\n\n/**\n * Convert an OpenCode tool to ContractSpec AgentToolConfig.\n */\nexport function openCodeToolToSpecTool(\n openCodeTool: OpenCodeTool\n): AgentToolConfig {\n return {\n name: openCodeTool.name,\n description: openCodeTool.description,\n schema: openCodeTool.parameters,\n requiresApproval: openCodeTool.permission === 'ask',\n automationSafe: openCodeTool.permission === 'allow',\n // category property not in AgentToolConfig\n };\n}\n\n/**\n * Convert multiple OpenCode tools to ContractSpec format.\n */\nexport function openCodeToolsToSpecTools(\n openCodeTools: OpenCodeTool[]\n): AgentToolConfig[] {\n return openCodeTools.map(openCodeToolToSpecTool);\n}\n\n// ============================================================================\n// External Tool Definition Conversion\n// ============================================================================\n\n/**\n * Convert ContractSpec tool to ExternalToolDefinition format for OpenCode.\n */\nexport function specToolToExternalToolForOpenCode(\n tool: AgentToolConfig,\n handler?: ToolHandler,\n context?: Partial<ToolExecutionContext>\n): ExternalToolDefinition {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n inputSchema: tool.schema ?? { type: 'object' },\n requiresApproval: tool.requiresApproval ?? !tool.automationSafe,\n execute: handler\n ? async (input) => {\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'unknown',\n sessionId: context?.sessionId ?? 'unknown',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n return handler(input, fullContext);\n }\n : undefined,\n };\n}\n\n// ============================================================================\n// Schema Conversion\n// ============================================================================\n\n/**\n * Normalize a schema to OpenCode's expected parameter format.\n */\nfunction normalizeToOpenCodeParameters(\n schema?: Record<string, unknown>\n): OpenCodeTool['parameters'] {\n if (!schema) {\n return { type: 'object' };\n }\n\n // Already in correct format\n if (schema.type === 'object') {\n return {\n type: 'object',\n properties: schema.properties as\n | Record<string, OpenCodeParameter>\n | undefined,\n required: schema.required as string[] | undefined,\n };\n }\n\n // Wrap non-object schemas\n return {\n type: 'object',\n properties: {\n value: convertToOpenCodeParameter(schema),\n },\n required: ['value'],\n };\n}\n\n/**\n * Convert a JSON Schema property to OpenCode parameter format.\n */\nfunction convertToOpenCodeParameter(\n schema: Record<string, unknown>\n): OpenCodeParameter {\n const param: OpenCodeParameter = {\n type: (schema.type as string) ?? 'string',\n };\n\n if (schema.description) {\n param.description = schema.description as string;\n }\n\n if (schema.enum) {\n param.enum = schema.enum as string[];\n }\n\n if (schema.default !== undefined) {\n param.default = schema.default;\n }\n\n return param;\n}\n\n// ============================================================================\n// Tool Execution Helpers\n// ============================================================================\n\n/**\n * Create a tool handler map from ExternalToolSet.\n */\nexport function createToolHandlerMap(\n tools: Record<string, ExternalToolDefinition>\n): Map<string, (input: unknown) => Promise<unknown>> {\n const handlers = new Map<string, (input: unknown) => Promise<unknown>>();\n\n for (const [name, tool] of Object.entries(tools)) {\n if (tool.execute) {\n handlers.set(name, tool.execute);\n }\n }\n\n return handlers;\n}\n\n/**\n * Execute a tool call and format the result.\n */\nexport async function executeToolCall(\n toolCall: OpenCodeToolCall,\n handlers: Map<string, (input: unknown) => Promise<unknown>>\n): Promise<OpenCodeToolResult> {\n const handler = handlers.get(toolCall.name);\n\n if (!handler) {\n return {\n tool_call_id: toolCall.id,\n output: `Error: Tool '${toolCall.name}' not found`,\n is_error: true,\n };\n }\n\n try {\n const result = await handler(toolCall.arguments);\n return {\n tool_call_id: toolCall.id,\n output: typeof result === 'string' ? result : JSON.stringify(result),\n };\n } catch (error) {\n return {\n tool_call_id: toolCall.id,\n output: `Error: ${error instanceof Error ? error.message : String(error)}`,\n is_error: true,\n };\n }\n}\n"],"mappings":";;;;AAmEA,SAAgB,uBAAuB,MAAqC;AAC1E,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,YAAY,8BAA8B,KAAK,OAAO;EAEtD,YAAY,mBAAmB,KAAK;EACrC;;;;;AAMH,SAAgB,yBACd,OACgB;AAChB,QAAO,MAAM,IAAI,uBAAuB;;;;;AAM1C,SAAS,mBAAmB,MAAmD;AAC7E,KAAI,KAAK,iBACP,QAAO;AAET,KAAI,KAAK,mBAAmB,MAC1B,QAAO;AAET,QAAO;;;;;AAUT,SAAgB,uBACd,cACiB;AACjB,QAAO;EACL,MAAM,aAAa;EACnB,aAAa,aAAa;EAC1B,QAAQ,aAAa;EACrB,kBAAkB,aAAa,eAAe;EAC9C,gBAAgB,aAAa,eAAe;EAE7C;;;;;AAMH,SAAgB,yBACd,eACmB;AACnB,QAAO,cAAc,IAAI,uBAAuB;;;;;AAUlD,SAAgB,kCACd,MACA,SACA,SACwB;AACxB,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,aAAa,KAAK,UAAU,EAAE,MAAM,UAAU;EAC9C,kBAAkB,KAAK,oBAAoB,CAAC,KAAK;EACjD,SAAS,UACL,OAAO,UAAU;AASf,UAAO,QAAQ,OAR2B;IACxC,SAAS,SAAS,WAAW;IAC7B,WAAW,SAAS,aAAa;IACjC,UAAU,SAAS;IACnB,SAAS,SAAS;IAClB,UAAU,SAAS;IACnB,QAAQ,SAAS;IAClB,CACiC;MAEpC;EACL;;;;;AAUH,SAAS,8BACP,QAC4B;AAC5B,KAAI,CAAC,OACH,QAAO,EAAE,MAAM,UAAU;AAI3B,KAAI,OAAO,SAAS,SAClB,QAAO;EACL,MAAM;EACN,YAAY,OAAO;EAGnB,UAAU,OAAO;EAClB;AAIH,QAAO;EACL,MAAM;EACN,YAAY,EACV,OAAO,2BAA2B,OAAO,EAC1C;EACD,UAAU,CAAC,QAAQ;EACpB;;;;;AAMH,SAAS,2BACP,QACmB;CACnB,MAAMA,QAA2B,EAC/B,MAAO,OAAO,QAAmB,UAClC;AAED,KAAI,OAAO,YACT,OAAM,cAAc,OAAO;AAG7B,KAAI,OAAO,KACT,OAAM,OAAO,OAAO;AAGtB,KAAI,OAAO,YAAY,OACrB,OAAM,UAAU,OAAO;AAGzB,QAAO;;;;;AAUT,SAAgB,qBACd,OACmD;CACnD,MAAM,2BAAW,IAAI,KAAmD;AAExE,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,CAC9C,KAAI,KAAK,QACP,UAAS,IAAI,MAAM,KAAK,QAAQ;AAIpC,QAAO;;;;;AAMT,eAAsB,gBACpB,UACA,UAC6B;CAC7B,MAAM,UAAU,SAAS,IAAI,SAAS,KAAK;AAE3C,KAAI,CAAC,QACH,QAAO;EACL,cAAc,SAAS;EACvB,QAAQ,gBAAgB,SAAS,KAAK;EACtC,UAAU;EACX;AAGH,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,SAAS,UAAU;AAChD,SAAO;GACL,cAAc,SAAS;GACvB,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,OAAO;GACrE;UACM,OAAO;AACd,SAAO;GACL,cAAc,SAAS;GACvB,QAAQ,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACxE,UAAU;GACX"}
1
+ {"version":3,"file":"tool-bridge.js","names":[],"sources":["../../../src/providers/opencode-sdk/tool-bridge.ts"],"sourcesContent":["/**\n * Tool bridge for converting between ContractSpec and OpenCode SDK tool formats.\n */\n\nimport type { AgentToolConfig } from '../../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../../types';\nimport type { ExternalToolDefinition } from '../types';\n\n// ============================================================================\n// OpenCode SDK Tool Types\n// ============================================================================\n\n/**\n * OpenCode SDK tool definition.\n */\nexport interface OpenCodeTool {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input parameters schema */\n parameters: {\n type: 'object';\n properties?: Record<string, OpenCodeParameter>;\n required?: string[];\n };\n /** Tool category */\n category?: string;\n /** Permission level */\n permission?: 'allow' | 'ask' | 'deny';\n}\n\n/**\n * OpenCode parameter definition.\n */\nexport interface OpenCodeParameter {\n type: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n}\n\n/**\n * OpenCode tool call from session.\n */\nexport interface OpenCodeToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\n/**\n * OpenCode tool result.\n */\nexport interface OpenCodeToolResult {\n tool_call_id: string;\n output: string;\n is_error?: boolean;\n}\n\n// ============================================================================\n// ContractSpec → OpenCode Conversion\n// ============================================================================\n\n/**\n * Convert a ContractSpec AgentToolConfig to OpenCode tool format.\n */\nexport function specToolToOpenCodeTool(tool: AgentToolConfig): OpenCodeTool {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n parameters: normalizeToOpenCodeParameters(tool.schema),\n // category property not in AgentToolConfig\n permission: getPermissionLevel(tool),\n };\n}\n\n/**\n * Convert multiple ContractSpec tools to OpenCode format.\n */\nexport function specToolsToOpenCodeTools(\n tools: AgentToolConfig[]\n): OpenCodeTool[] {\n return tools.map(specToolToOpenCodeTool);\n}\n\n/**\n * Determine permission level from tool config.\n */\nfunction getPermissionLevel(tool: AgentToolConfig): OpenCodeTool['permission'] {\n if (tool.requiresApproval) {\n return 'ask';\n }\n if (tool.automationSafe === false) {\n return 'ask';\n }\n return 'allow';\n}\n\n// ============================================================================\n// OpenCode → ContractSpec Conversion\n// ============================================================================\n\n/**\n * Convert an OpenCode tool to ContractSpec AgentToolConfig.\n */\nexport function openCodeToolToSpecTool(\n openCodeTool: OpenCodeTool\n): AgentToolConfig {\n return {\n name: openCodeTool.name,\n description: openCodeTool.description,\n schema: openCodeTool.parameters,\n requiresApproval: openCodeTool.permission === 'ask',\n automationSafe: openCodeTool.permission === 'allow',\n // category property not in AgentToolConfig\n };\n}\n\n/**\n * Convert multiple OpenCode tools to ContractSpec format.\n */\nexport function openCodeToolsToSpecTools(\n openCodeTools: OpenCodeTool[]\n): AgentToolConfig[] {\n return openCodeTools.map(openCodeToolToSpecTool);\n}\n\n// ============================================================================\n// External Tool Definition Conversion\n// ============================================================================\n\n/**\n * Convert ContractSpec tool to ExternalToolDefinition format for OpenCode.\n */\nexport function specToolToExternalToolForOpenCode(\n tool: AgentToolConfig,\n handler?: ToolHandler,\n context?: Partial<ToolExecutionContext>\n): ExternalToolDefinition {\n return {\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n inputSchema: tool.schema ?? { type: 'object' },\n requiresApproval: tool.requiresApproval ?? !tool.automationSafe,\n execute: handler\n ? async (input) => {\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'unknown',\n sessionId: context?.sessionId ?? 'unknown',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n return handler(input, fullContext);\n }\n : undefined,\n };\n}\n\n// ============================================================================\n// Schema Conversion\n// ============================================================================\n\n/**\n * Normalize a schema to OpenCode's expected parameter format.\n */\nfunction normalizeToOpenCodeParameters(\n schema?: Record<string, unknown>\n): OpenCodeTool['parameters'] {\n if (!schema) {\n return { type: 'object' };\n }\n\n // Already in correct format\n if (schema.type === 'object') {\n return {\n type: 'object',\n properties: schema.properties as\n | Record<string, OpenCodeParameter>\n | undefined,\n required: schema.required as string[] | undefined,\n };\n }\n\n // Wrap non-object schemas\n return {\n type: 'object',\n properties: {\n value: convertToOpenCodeParameter(schema),\n },\n required: ['value'],\n };\n}\n\n/**\n * Convert a JSON Schema property to OpenCode parameter format.\n */\nfunction convertToOpenCodeParameter(\n schema: Record<string, unknown>\n): OpenCodeParameter {\n const param: OpenCodeParameter = {\n type: (schema.type as string) ?? 'string',\n };\n\n if (schema.description) {\n param.description = schema.description as string;\n }\n\n if (schema.enum) {\n param.enum = schema.enum as string[];\n }\n\n if (schema.default !== undefined) {\n param.default = schema.default;\n }\n\n return param;\n}\n\n// ============================================================================\n// Tool Execution Helpers\n// ============================================================================\n\n/**\n * Create a tool handler map from ExternalToolSet.\n */\nexport function createToolHandlerMap(\n tools: Record<string, ExternalToolDefinition>\n): Map<string, (input: unknown) => Promise<unknown>> {\n const handlers = new Map<string, (input: unknown) => Promise<unknown>>();\n\n for (const [name, tool] of Object.entries(tools)) {\n if (tool.execute) {\n handlers.set(name, tool.execute);\n }\n }\n\n return handlers;\n}\n\n/**\n * Execute a tool call and format the result.\n */\nexport async function executeToolCall(\n toolCall: OpenCodeToolCall,\n handlers: Map<string, (input: unknown) => Promise<unknown>>\n): Promise<OpenCodeToolResult> {\n const handler = handlers.get(toolCall.name);\n\n if (!handler) {\n return {\n tool_call_id: toolCall.id,\n output: `Error: Tool '${toolCall.name}' not found`,\n is_error: true,\n };\n }\n\n try {\n const result = await handler(toolCall.arguments);\n return {\n tool_call_id: toolCall.id,\n output: typeof result === 'string' ? result : JSON.stringify(result),\n };\n } catch (error) {\n return {\n tool_call_id: toolCall.id,\n output: `Error: ${error instanceof Error ? error.message : String(error)}`,\n is_error: true,\n };\n }\n}\n"],"mappings":";;;;AAmEA,SAAgB,uBAAuB,MAAqC;AAC1E,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,YAAY,8BAA8B,KAAK,OAAO;EAEtD,YAAY,mBAAmB,KAAK;EACrC;;;;;AAMH,SAAgB,yBACd,OACgB;AAChB,QAAO,MAAM,IAAI,uBAAuB;;;;;AAM1C,SAAS,mBAAmB,MAAmD;AAC7E,KAAI,KAAK,iBACP,QAAO;AAET,KAAI,KAAK,mBAAmB,MAC1B,QAAO;AAET,QAAO;;;;;AAUT,SAAgB,uBACd,cACiB;AACjB,QAAO;EACL,MAAM,aAAa;EACnB,aAAa,aAAa;EAC1B,QAAQ,aAAa;EACrB,kBAAkB,aAAa,eAAe;EAC9C,gBAAgB,aAAa,eAAe;EAE7C;;;;;AAMH,SAAgB,yBACd,eACmB;AACnB,QAAO,cAAc,IAAI,uBAAuB;;;;;AAUlD,SAAgB,kCACd,MACA,SACA,SACwB;AACxB,QAAO;EACL,MAAM,KAAK;EACX,aAAa,KAAK,eAAe,WAAW,KAAK;EACjD,aAAa,KAAK,UAAU,EAAE,MAAM,UAAU;EAC9C,kBAAkB,KAAK,oBAAoB,CAAC,KAAK;EACjD,SAAS,UACL,OAAO,UAAU;AASf,UAAO,QAAQ,OAR2B;IACxC,SAAS,SAAS,WAAW;IAC7B,WAAW,SAAS,aAAa;IACjC,UAAU,SAAS;IACnB,SAAS,SAAS;IAClB,UAAU,SAAS;IACnB,QAAQ,SAAS;IAClB,CACiC;MAEpC;EACL;;;;;AAUH,SAAS,8BACP,QAC4B;AAC5B,KAAI,CAAC,OACH,QAAO,EAAE,MAAM,UAAU;AAI3B,KAAI,OAAO,SAAS,SAClB,QAAO;EACL,MAAM;EACN,YAAY,OAAO;EAGnB,UAAU,OAAO;EAClB;AAIH,QAAO;EACL,MAAM;EACN,YAAY,EACV,OAAO,2BAA2B,OAAO,EAC1C;EACD,UAAU,CAAC,QAAQ;EACpB;;;;;AAMH,SAAS,2BACP,QACmB;CACnB,MAAM,QAA2B,EAC/B,MAAO,OAAO,QAAmB,UAClC;AAED,KAAI,OAAO,YACT,OAAM,cAAc,OAAO;AAG7B,KAAI,OAAO,KACT,OAAM,OAAO,OAAO;AAGtB,KAAI,OAAO,YAAY,OACrB,OAAM,UAAU,OAAO;AAGzB,QAAO;;;;;AAUT,SAAgB,qBACd,OACmD;CACnD,MAAM,2BAAW,IAAI,KAAmD;AAExE,MAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,CAC9C,KAAI,KAAK,QACP,UAAS,IAAI,MAAM,KAAK,QAAQ;AAIpC,QAAO;;;;;AAMT,eAAsB,gBACpB,UACA,UAC6B;CAC7B,MAAM,UAAU,SAAS,IAAI,SAAS,KAAK;AAE3C,KAAI,CAAC,QACH,QAAO;EACL,cAAc,SAAS;EACvB,QAAQ,gBAAgB,SAAS,KAAK;EACtC,UAAU;EACX;AAGH,KAAI;EACF,MAAM,SAAS,MAAM,QAAQ,SAAS,UAAU;AAChD,SAAO;GACL,cAAc,SAAS;GACvB,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,OAAO;GACrE;UACM,OAAO;AACd,SAAO;GACL,cAAc,SAAS;GACvB,QAAQ,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACxE,UAAU;GACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":["provider: string","code: string","cause?: Error"],"sources":["../../src/providers/types.ts"],"sourcesContent":["/**\n * External SDK provider types for ContractSpec agents.\n *\n * These interfaces define the contract for integrating external agent SDKs\n * (like @anthropic-ai/claude-agent-sdk and @opencode-ai/sdk) with ContractSpec's\n * agent system.\n */\n\nimport type { AgentSpec } from '../spec/spec';\nimport type {\n AgentCallOptions,\n AgentFinishReason,\n ToolCallInfo,\n ToolResultInfo,\n} from '../types';\nimport type { McpClientConfig } from '../tools/mcp-client';\n\n// ============================================================================\n// Core Provider Interface\n// ============================================================================\n\n/**\n * External SDK provider interface for ContractSpec agents.\n * Allows external SDKs to be used as execution backends.\n */\nexport interface ExternalAgentProvider {\n /** Provider name identifier */\n readonly name: string;\n /** Provider version */\n readonly version: string;\n\n /**\n * Check if this provider is available (dependencies installed, configured).\n * Should be a quick synchronous check.\n */\n isAvailable(): boolean;\n\n /**\n * Create an execution context from an AgentSpec.\n * This prepares the provider for execution with the given spec.\n */\n createContext(spec: AgentSpec): Promise<ExternalAgentContext>;\n\n /**\n * Execute a prompt using this provider.\n * Non-streaming execution that returns the complete result.\n */\n execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult>;\n\n /**\n * Stream execution with real-time updates.\n * Returns an async iterable of stream chunks.\n */\n stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk>;\n}\n\n// ============================================================================\n// Context and Execution Types\n// ============================================================================\n\n/**\n * Execution context created by a provider.\n * Holds the prepared state for executing prompts.\n */\nexport interface ExternalAgentContext {\n /** Unique context ID */\n id: string;\n /** The spec this context was created from */\n spec: AgentSpec;\n /** Tools available in this context */\n tools: ExternalToolSet;\n /** Cleanup function to release resources */\n cleanup: () => Promise<void>;\n /** Provider-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for executing a prompt.\n */\nexport interface ExternalExecuteParams {\n /** The prompt to execute */\n prompt: string;\n /** Optional system prompt override/addition */\n systemOverride?: string;\n /** Call options (tenant, actor, session, metadata) */\n options?: AgentCallOptions;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n /** Maximum steps/iterations (provider may interpret differently) */\n maxSteps?: number;\n}\n\n/**\n * Result from a non-streaming execution.\n */\nexport interface ExternalExecuteResult {\n /** Final text response */\n text: string;\n /** Tool calls made during execution */\n toolCalls: ToolCallInfo[];\n /** Results from tool executions */\n toolResults: ToolResultInfo[];\n /** Token usage statistics */\n usage?: ExternalUsage;\n /** Reason the execution finished */\n finishReason: AgentFinishReason;\n /** Provider-specific result metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Token usage statistics.\n */\nexport interface ExternalUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens?: number;\n}\n\n/**\n * Stream chunk from streaming execution.\n */\nexport interface ExternalStreamChunk {\n /** Chunk type */\n type: 'text' | 'tool-call' | 'tool-result' | 'step-complete' | 'done';\n /** Text content (for text chunks) */\n text?: string;\n /** Tool call info (for tool-call chunks) */\n toolCall?: ToolCallInfo;\n /** Tool result info (for tool-result chunks) */\n toolResult?: ToolResultInfo;\n /** Step index (for step-complete chunks) */\n stepIndex?: number;\n /** Final result (for done chunks) */\n result?: ExternalExecuteResult;\n}\n\n/**\n * Set of tools available to an external provider.\n */\nexport type ExternalToolSet = Record<string, ExternalToolDefinition>;\n\n/**\n * External tool definition in a provider-agnostic format.\n */\nexport interface ExternalToolDefinition {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input schema (JSON Schema format) */\n inputSchema: Record<string, unknown>;\n /** Whether tool requires user approval */\n requiresApproval?: boolean;\n /** Tool handler function */\n execute?: (input: unknown) => Promise<unknown>;\n}\n\n// ============================================================================\n// Claude Agent SDK Configuration\n// ============================================================================\n\n/**\n * Configuration for Claude Agent SDK provider.\n */\nexport interface ClaudeAgentSDKConfig {\n /** API key (defaults to ANTHROPIC_API_KEY env var) */\n apiKey?: string;\n /** Model to use (defaults to claude-sonnet-4-20250514) */\n model?: string;\n /** Enable extended thinking mode */\n extendedThinking?: boolean;\n /** Enable computer use capabilities (file editing, bash) */\n computerUse?: boolean;\n /** MCP servers to connect */\n mcpServers?: McpClientConfig[];\n /** Maximum tokens for response */\n maxTokens?: number;\n /** Temperature for generation */\n temperature?: number;\n}\n\n/**\n * Claude Agent SDK specific context metadata.\n */\nexport interface ClaudeAgentContextMetadata {\n /** Session ID for Claude Agent SDK */\n sessionId?: string;\n /** Whether computer use is enabled */\n computerUseEnabled: boolean;\n /** Whether extended thinking is enabled */\n extendedThinkingEnabled: boolean;\n /** Connected MCP servers */\n mcpServerIds?: string[];\n /** Allow additional metadata properties */\n [key: string]: unknown;\n}\n\n// ============================================================================\n// OpenCode SDK Configuration\n// ============================================================================\n\n/**\n * Configuration for OpenCode SDK provider.\n */\nexport interface OpenCodeSDKConfig {\n /** Server URL (defaults to http://127.0.0.1:4096) */\n serverUrl?: string;\n /** Server port (alternative to full URL) */\n port?: number;\n /** Agent type to use */\n agentType?: OpenCodeAgentType;\n /** Session ID for resuming sessions */\n sessionId?: string;\n /** Model to use */\n model?: string;\n /** Temperature for generation */\n temperature?: number;\n /** Connection timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * OpenCode agent types.\n */\nexport type OpenCodeAgentType = 'build' | 'plan' | 'general' | 'explore';\n\n/**\n * OpenCode SDK specific context metadata.\n */\nexport interface OpenCodeContextMetadata {\n /** Session ID from OpenCode */\n sessionId: string;\n /** Agent type being used */\n agentType: OpenCodeAgentType;\n /** Server URL */\n serverUrl: string;\n}\n\n// ============================================================================\n// Provider Factory Types\n// ============================================================================\n\n/**\n * Factory function type for creating providers.\n */\nexport type ExternalProviderFactory<TConfig> = (\n config: TConfig\n) => ExternalAgentProvider;\n\n/**\n * Registry of available providers.\n */\nexport interface ProviderRegistry {\n /** Get a provider by name */\n get(name: string): ExternalAgentProvider | undefined;\n /** Register a provider */\n register(name: string, provider: ExternalAgentProvider): void;\n /** List available provider names */\n list(): string[];\n /** Check if a provider is registered and available */\n isAvailable(name: string): boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * Base error for external provider operations.\n */\nexport class ExternalProviderError extends Error {\n constructor(\n message: string,\n public readonly provider: string,\n public readonly code: string,\n public readonly cause?: Error\n ) {\n super(message);\n this.name = 'ExternalProviderError';\n }\n}\n\n/**\n * Error when provider is not available.\n */\nexport class ProviderNotAvailableError extends ExternalProviderError {\n constructor(provider: string, reason?: string) {\n super(\n `Provider '${provider}' is not available${reason ? `: ${reason}` : ''}`,\n provider,\n 'PROVIDER_NOT_AVAILABLE'\n );\n this.name = 'ProviderNotAvailableError';\n }\n}\n\n/**\n * Error when provider execution fails.\n */\nexport class ProviderExecutionError extends ExternalProviderError {\n constructor(provider: string, message: string, cause?: Error) {\n super(message, provider, 'EXECUTION_FAILED', cause);\n this.name = 'ProviderExecutionError';\n }\n}\n\n/**\n * Error when context creation fails.\n */\nexport class ContextCreationError extends ExternalProviderError {\n constructor(provider: string, message: string, cause?: Error) {\n super(message, provider, 'CONTEXT_CREATION_FAILED', cause);\n this.name = 'ContextCreationError';\n }\n}\n"],"mappings":";;;;AAsRA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YACE,SACA,AAAgBA,UAChB,AAAgBC,MAChB,AAAgBC,OAChB;AACA,QAAM,QAAQ;EAJE;EACA;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,IAAa,4BAAb,cAA+C,sBAAsB;CACnE,YAAY,UAAkB,QAAiB;AAC7C,QACE,aAAa,SAAS,oBAAoB,SAAS,KAAK,WAAW,MACnE,UACA,yBACD;AACD,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,sBAAsB;CAChE,YAAY,UAAkB,SAAiB,OAAe;AAC5D,QAAM,SAAS,UAAU,oBAAoB,MAAM;AACnD,OAAK,OAAO;;;;;;AAOhB,IAAa,uBAAb,cAA0C,sBAAsB;CAC9D,YAAY,UAAkB,SAAiB,OAAe;AAC5D,QAAM,SAAS,UAAU,2BAA2B,MAAM;AAC1D,OAAK,OAAO"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/providers/types.ts"],"sourcesContent":["/**\n * External SDK provider types for ContractSpec agents.\n *\n * These interfaces define the contract for integrating external agent SDKs\n * (like @anthropic-ai/claude-agent-sdk and @opencode-ai/sdk) with ContractSpec's\n * agent system.\n */\n\nimport type { AgentSpec } from '../spec/spec';\nimport type {\n AgentCallOptions,\n AgentFinishReason,\n ToolCallInfo,\n ToolResultInfo,\n} from '../types';\nimport type { McpClientConfig } from '../tools/mcp-client';\n\n// ============================================================================\n// Core Provider Interface\n// ============================================================================\n\n/**\n * External SDK provider interface for ContractSpec agents.\n * Allows external SDKs to be used as execution backends.\n */\nexport interface ExternalAgentProvider {\n /** Provider name identifier */\n readonly name: string;\n /** Provider version */\n readonly version: string;\n\n /**\n * Check if this provider is available (dependencies installed, configured).\n * Should be a quick synchronous check.\n */\n isAvailable(): boolean;\n\n /**\n * Create an execution context from an AgentSpec.\n * This prepares the provider for execution with the given spec.\n */\n createContext(spec: AgentSpec): Promise<ExternalAgentContext>;\n\n /**\n * Execute a prompt using this provider.\n * Non-streaming execution that returns the complete result.\n */\n execute(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): Promise<ExternalExecuteResult>;\n\n /**\n * Stream execution with real-time updates.\n * Returns an async iterable of stream chunks.\n */\n stream(\n context: ExternalAgentContext,\n params: ExternalExecuteParams\n ): AsyncIterable<ExternalStreamChunk>;\n}\n\n// ============================================================================\n// Context and Execution Types\n// ============================================================================\n\n/**\n * Execution context created by a provider.\n * Holds the prepared state for executing prompts.\n */\nexport interface ExternalAgentContext {\n /** Unique context ID */\n id: string;\n /** The spec this context was created from */\n spec: AgentSpec;\n /** Tools available in this context */\n tools: ExternalToolSet;\n /** Cleanup function to release resources */\n cleanup: () => Promise<void>;\n /** Provider-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Parameters for executing a prompt.\n */\nexport interface ExternalExecuteParams {\n /** The prompt to execute */\n prompt: string;\n /** Optional system prompt override/addition */\n systemOverride?: string;\n /** Call options (tenant, actor, session, metadata) */\n options?: AgentCallOptions;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n /** Maximum steps/iterations (provider may interpret differently) */\n maxSteps?: number;\n}\n\n/**\n * Result from a non-streaming execution.\n */\nexport interface ExternalExecuteResult {\n /** Final text response */\n text: string;\n /** Tool calls made during execution */\n toolCalls: ToolCallInfo[];\n /** Results from tool executions */\n toolResults: ToolResultInfo[];\n /** Token usage statistics */\n usage?: ExternalUsage;\n /** Reason the execution finished */\n finishReason: AgentFinishReason;\n /** Provider-specific result metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Token usage statistics.\n */\nexport interface ExternalUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens?: number;\n}\n\n/**\n * Stream chunk from streaming execution.\n */\nexport interface ExternalStreamChunk {\n /** Chunk type */\n type: 'text' | 'tool-call' | 'tool-result' | 'step-complete' | 'done';\n /** Text content (for text chunks) */\n text?: string;\n /** Tool call info (for tool-call chunks) */\n toolCall?: ToolCallInfo;\n /** Tool result info (for tool-result chunks) */\n toolResult?: ToolResultInfo;\n /** Step index (for step-complete chunks) */\n stepIndex?: number;\n /** Final result (for done chunks) */\n result?: ExternalExecuteResult;\n}\n\n/**\n * Set of tools available to an external provider.\n */\nexport type ExternalToolSet = Record<string, ExternalToolDefinition>;\n\n/**\n * External tool definition in a provider-agnostic format.\n */\nexport interface ExternalToolDefinition {\n /** Tool name */\n name: string;\n /** Tool description */\n description: string;\n /** Input schema (JSON Schema format) */\n inputSchema: Record<string, unknown>;\n /** Whether tool requires user approval */\n requiresApproval?: boolean;\n /** Tool handler function */\n execute?: (input: unknown) => Promise<unknown>;\n}\n\n// ============================================================================\n// Claude Agent SDK Configuration\n// ============================================================================\n\n/**\n * Configuration for Claude Agent SDK provider.\n */\nexport interface ClaudeAgentSDKConfig {\n /** API key (defaults to ANTHROPIC_API_KEY env var) */\n apiKey?: string;\n /** Model to use (defaults to claude-sonnet-4-20250514) */\n model?: string;\n /** Enable extended thinking mode */\n extendedThinking?: boolean;\n /** Enable computer use capabilities (file editing, bash) */\n computerUse?: boolean;\n /** MCP servers to connect */\n mcpServers?: McpClientConfig[];\n /** Maximum tokens for response */\n maxTokens?: number;\n /** Temperature for generation */\n temperature?: number;\n}\n\n/**\n * Claude Agent SDK specific context metadata.\n */\nexport interface ClaudeAgentContextMetadata {\n /** Session ID for Claude Agent SDK */\n sessionId?: string;\n /** Whether computer use is enabled */\n computerUseEnabled: boolean;\n /** Whether extended thinking is enabled */\n extendedThinkingEnabled: boolean;\n /** Connected MCP servers */\n mcpServerIds?: string[];\n /** Allow additional metadata properties */\n [key: string]: unknown;\n}\n\n// ============================================================================\n// OpenCode SDK Configuration\n// ============================================================================\n\n/**\n * Configuration for OpenCode SDK provider.\n */\nexport interface OpenCodeSDKConfig {\n /** Server URL (defaults to http://127.0.0.1:4096) */\n serverUrl?: string;\n /** Server port (alternative to full URL) */\n port?: number;\n /** Agent type to use */\n agentType?: OpenCodeAgentType;\n /** Session ID for resuming sessions */\n sessionId?: string;\n /** Model to use */\n model?: string;\n /** Temperature for generation */\n temperature?: number;\n /** Connection timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * OpenCode agent types.\n */\nexport type OpenCodeAgentType = 'build' | 'plan' | 'general' | 'explore';\n\n/**\n * OpenCode SDK specific context metadata.\n */\nexport interface OpenCodeContextMetadata {\n /** Session ID from OpenCode */\n sessionId: string;\n /** Agent type being used */\n agentType: OpenCodeAgentType;\n /** Server URL */\n serverUrl: string;\n}\n\n// ============================================================================\n// Provider Factory Types\n// ============================================================================\n\n/**\n * Factory function type for creating providers.\n */\nexport type ExternalProviderFactory<TConfig> = (\n config: TConfig\n) => ExternalAgentProvider;\n\n/**\n * Registry of available providers.\n */\nexport interface ProviderRegistry {\n /** Get a provider by name */\n get(name: string): ExternalAgentProvider | undefined;\n /** Register a provider */\n register(name: string, provider: ExternalAgentProvider): void;\n /** List available provider names */\n list(): string[];\n /** Check if a provider is registered and available */\n isAvailable(name: string): boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * Base error for external provider operations.\n */\nexport class ExternalProviderError extends Error {\n constructor(\n message: string,\n public readonly provider: string,\n public readonly code: string,\n public readonly cause?: Error\n ) {\n super(message);\n this.name = 'ExternalProviderError';\n }\n}\n\n/**\n * Error when provider is not available.\n */\nexport class ProviderNotAvailableError extends ExternalProviderError {\n constructor(provider: string, reason?: string) {\n super(\n `Provider '${provider}' is not available${reason ? `: ${reason}` : ''}`,\n provider,\n 'PROVIDER_NOT_AVAILABLE'\n );\n this.name = 'ProviderNotAvailableError';\n }\n}\n\n/**\n * Error when provider execution fails.\n */\nexport class ProviderExecutionError extends ExternalProviderError {\n constructor(provider: string, message: string, cause?: Error) {\n super(message, provider, 'EXECUTION_FAILED', cause);\n this.name = 'ProviderExecutionError';\n }\n}\n\n/**\n * Error when context creation fails.\n */\nexport class ContextCreationError extends ExternalProviderError {\n constructor(provider: string, message: string, cause?: Error) {\n super(message, provider, 'CONTEXT_CREATION_FAILED', cause);\n this.name = 'ContextCreationError';\n }\n}\n"],"mappings":";;;;AAsRA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YACE,SACA,AAAgB,UAChB,AAAgB,MAChB,AAAgB,OAChB;AACA,QAAM,QAAQ;EAJE;EACA;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,IAAa,4BAAb,cAA+C,sBAAsB;CACnE,YAAY,UAAkB,QAAiB;AAC7C,QACE,aAAa,SAAS,oBAAoB,SAAS,KAAK,WAAW,MACnE,UACA,yBACD;AACD,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,sBAAsB;CAChE,YAAY,UAAkB,SAAiB,OAAe;AAC5D,QAAM,SAAS,UAAU,oBAAoB,MAAM;AACnD,OAAK,OAAO;;;;;;AAOhB,IAAa,uBAAb,cAA0C,sBAAsB;CAC9D,YAAY,UAAkB,SAAiB,OAAe;AAC5D,QAAM,SAAS,UAAU,2BAA2B,MAAM;AAC1D,OAAK,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema-to-zod.js","names":["shape: Record<string, ZodType>"],"sources":["../../src/schema/json-schema-to-zod.ts"],"sourcesContent":["import { z, type ZodType } from 'zod';\n\n/**\n * JSON Schema type definitions for conversion.\n */\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n items?: JsonSchema;\n enum?: (string | number | boolean)[];\n const?: unknown;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n description?: string;\n default?: unknown;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n format?: string;\n nullable?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Convert a JSON Schema to a Zod schema.\n *\n * Supports common JSON Schema types and constraints:\n * - string, number, integer, boolean, null\n * - object with properties and required\n * - array with items\n * - enum and const\n * - anyOf, oneOf, allOf\n * - format constraints (email, uri, uuid, date-time)\n * - numeric constraints (minimum, maximum)\n * - string constraints (minLength, maxLength, pattern)\n *\n * @param schema - JSON Schema object\n * @returns Zod schema\n */\nexport function jsonSchemaToZod(\n schema: JsonSchema | Record<string, unknown>\n): ZodType {\n const s = schema as JsonSchema;\n\n // Handle nullable\n const makeNullable = (zodSchema: ZodType): ZodType => {\n return s.nullable ? z.union([zodSchema, z.null()]) : zodSchema;\n };\n\n // Handle const\n if (s.const !== undefined) {\n return z.literal(s.const as string | number | boolean);\n }\n\n // Handle enum\n if (s.enum) {\n const values = s.enum as [\n string | number | boolean,\n ...(string | number | boolean)[],\n ];\n return makeNullable(z.enum(values.map(String) as [string, ...string[]]));\n }\n\n // Handle anyOf\n if (s.anyOf && s.anyOf.length > 0) {\n const schemas = s.anyOf.map((sub) => jsonSchemaToZod(sub));\n if (schemas.length === 1) return schemas[0] ?? z.unknown();\n return z.union([\n schemas[0] ?? z.unknown(),\n schemas[1] ?? z.unknown(),\n ...schemas.slice(2),\n ]);\n }\n\n // Handle oneOf (same as anyOf for Zod purposes)\n if (s.oneOf && s.oneOf.length > 0) {\n const schemas = s.oneOf.map((sub) => jsonSchemaToZod(sub));\n if (schemas.length === 1) return schemas[0] ?? z.unknown();\n return z.union([\n schemas[0] ?? z.unknown(),\n schemas[1] ?? z.unknown(),\n ...schemas.slice(2),\n ]);\n }\n\n // Handle allOf (intersection)\n if (s.allOf && s.allOf.length > 0) {\n const schemas = s.allOf.map((sub) => jsonSchemaToZod(sub));\n return schemas.reduce((acc, curr) => z.intersection(acc, curr));\n }\n\n // Handle type\n switch (s.type) {\n case 'string':\n return makeNullable(buildStringSchema(s));\n case 'number':\n case 'integer':\n return makeNullable(buildNumberSchema(s));\n case 'boolean':\n return makeNullable(z.boolean());\n case 'null':\n return z.null();\n case 'array':\n return makeNullable(buildArraySchema(s));\n case 'object':\n return makeNullable(buildObjectSchema(s));\n default:\n // Unknown type, accept anything\n return z.unknown();\n }\n}\n\nfunction buildStringSchema(schema: JsonSchema): ZodType {\n let zodSchema = z.string();\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n // Format constraints\n switch (schema.format) {\n case 'email':\n zodSchema = zodSchema.email();\n break;\n case 'uri':\n case 'url':\n zodSchema = zodSchema.url();\n break;\n case 'uuid':\n zodSchema = zodSchema.uuid();\n break;\n case 'date-time':\n zodSchema = zodSchema.datetime();\n break;\n case 'date':\n zodSchema = zodSchema.date();\n break;\n }\n\n // Length constraints\n if (schema.minLength !== undefined) {\n zodSchema = zodSchema.min(schema.minLength);\n }\n if (schema.maxLength !== undefined) {\n zodSchema = zodSchema.max(schema.maxLength);\n }\n\n // Pattern constraint\n if (schema.pattern) {\n zodSchema = zodSchema.regex(new RegExp(schema.pattern));\n }\n\n return zodSchema;\n}\n\nfunction buildNumberSchema(schema: JsonSchema): ZodType {\n let zodSchema = schema.type === 'integer' ? z.number().int() : z.number();\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n if (schema.minimum !== undefined) {\n zodSchema = zodSchema.min(schema.minimum);\n }\n if (schema.maximum !== undefined) {\n zodSchema = zodSchema.max(schema.maximum);\n }\n\n return zodSchema;\n}\n\nfunction buildArraySchema(schema: JsonSchema): ZodType {\n const itemsSchema = schema.items\n ? jsonSchemaToZod(schema.items)\n : z.unknown();\n let zodSchema = z.array(itemsSchema);\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n return zodSchema;\n}\n\nfunction buildObjectSchema(schema: JsonSchema): ZodType {\n const properties = schema.properties ?? {};\n const required = new Set(schema.required ?? []);\n\n const shape: Record<string, ZodType> = {};\n for (const [key, propSchema] of Object.entries(properties)) {\n const zodProp = jsonSchemaToZod(propSchema);\n shape[key] = required.has(key) ? zodProp : zodProp.optional();\n }\n\n let zodSchema = z.object(shape);\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n return zodSchema;\n}\n\n/**\n * Convert a JSON Schema to a Zod schema with a default empty object fallback.\n *\n * @param schema - Optional JSON Schema object\n * @returns Zod schema (defaults to empty object schema)\n */\nexport function jsonSchemaToZodSafe(schema?: Record<string, unknown>): ZodType {\n if (!schema || Object.keys(schema).length === 0) {\n return z.object({});\n }\n return jsonSchemaToZod(schema);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"json-schema-to-zod.js","names":[],"sources":["../../src/schema/json-schema-to-zod.ts"],"sourcesContent":["import { z, type ZodType } from 'zod';\n\n/**\n * JSON Schema type definitions for conversion.\n */\ninterface JsonSchema {\n type?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n items?: JsonSchema;\n enum?: (string | number | boolean)[];\n const?: unknown;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n description?: string;\n default?: unknown;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n format?: string;\n nullable?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Convert a JSON Schema to a Zod schema.\n *\n * Supports common JSON Schema types and constraints:\n * - string, number, integer, boolean, null\n * - object with properties and required\n * - array with items\n * - enum and const\n * - anyOf, oneOf, allOf\n * - format constraints (email, uri, uuid, date-time)\n * - numeric constraints (minimum, maximum)\n * - string constraints (minLength, maxLength, pattern)\n *\n * @param schema - JSON Schema object\n * @returns Zod schema\n */\nexport function jsonSchemaToZod(\n schema: JsonSchema | Record<string, unknown>\n): ZodType {\n const s = schema as JsonSchema;\n\n // Handle nullable\n const makeNullable = (zodSchema: ZodType): ZodType => {\n return s.nullable ? z.union([zodSchema, z.null()]) : zodSchema;\n };\n\n // Handle const\n if (s.const !== undefined) {\n return z.literal(s.const as string | number | boolean);\n }\n\n // Handle enum\n if (s.enum) {\n const values = s.enum as [\n string | number | boolean,\n ...(string | number | boolean)[],\n ];\n return makeNullable(z.enum(values.map(String) as [string, ...string[]]));\n }\n\n // Handle anyOf\n if (s.anyOf && s.anyOf.length > 0) {\n const schemas = s.anyOf.map((sub) => jsonSchemaToZod(sub));\n if (schemas.length === 1) return schemas[0] ?? z.unknown();\n return z.union([\n schemas[0] ?? z.unknown(),\n schemas[1] ?? z.unknown(),\n ...schemas.slice(2),\n ]);\n }\n\n // Handle oneOf (same as anyOf for Zod purposes)\n if (s.oneOf && s.oneOf.length > 0) {\n const schemas = s.oneOf.map((sub) => jsonSchemaToZod(sub));\n if (schemas.length === 1) return schemas[0] ?? z.unknown();\n return z.union([\n schemas[0] ?? z.unknown(),\n schemas[1] ?? z.unknown(),\n ...schemas.slice(2),\n ]);\n }\n\n // Handle allOf (intersection)\n if (s.allOf && s.allOf.length > 0) {\n const schemas = s.allOf.map((sub) => jsonSchemaToZod(sub));\n return schemas.reduce((acc, curr) => z.intersection(acc, curr));\n }\n\n // Handle type\n switch (s.type) {\n case 'string':\n return makeNullable(buildStringSchema(s));\n case 'number':\n case 'integer':\n return makeNullable(buildNumberSchema(s));\n case 'boolean':\n return makeNullable(z.boolean());\n case 'null':\n return z.null();\n case 'array':\n return makeNullable(buildArraySchema(s));\n case 'object':\n return makeNullable(buildObjectSchema(s));\n default:\n // Unknown type, accept anything\n return z.unknown();\n }\n}\n\nfunction buildStringSchema(schema: JsonSchema): ZodType {\n let zodSchema = z.string();\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n // Format constraints\n switch (schema.format) {\n case 'email':\n zodSchema = zodSchema.email();\n break;\n case 'uri':\n case 'url':\n zodSchema = zodSchema.url();\n break;\n case 'uuid':\n zodSchema = zodSchema.uuid();\n break;\n case 'date-time':\n zodSchema = zodSchema.datetime();\n break;\n case 'date':\n zodSchema = zodSchema.date();\n break;\n }\n\n // Length constraints\n if (schema.minLength !== undefined) {\n zodSchema = zodSchema.min(schema.minLength);\n }\n if (schema.maxLength !== undefined) {\n zodSchema = zodSchema.max(schema.maxLength);\n }\n\n // Pattern constraint\n if (schema.pattern) {\n zodSchema = zodSchema.regex(new RegExp(schema.pattern));\n }\n\n return zodSchema;\n}\n\nfunction buildNumberSchema(schema: JsonSchema): ZodType {\n let zodSchema = schema.type === 'integer' ? z.number().int() : z.number();\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n if (schema.minimum !== undefined) {\n zodSchema = zodSchema.min(schema.minimum);\n }\n if (schema.maximum !== undefined) {\n zodSchema = zodSchema.max(schema.maximum);\n }\n\n return zodSchema;\n}\n\nfunction buildArraySchema(schema: JsonSchema): ZodType {\n const itemsSchema = schema.items\n ? jsonSchemaToZod(schema.items)\n : z.unknown();\n let zodSchema = z.array(itemsSchema);\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n return zodSchema;\n}\n\nfunction buildObjectSchema(schema: JsonSchema): ZodType {\n const properties = schema.properties ?? {};\n const required = new Set(schema.required ?? []);\n\n const shape: Record<string, ZodType> = {};\n for (const [key, propSchema] of Object.entries(properties)) {\n const zodProp = jsonSchemaToZod(propSchema);\n shape[key] = required.has(key) ? zodProp : zodProp.optional();\n }\n\n let zodSchema = z.object(shape);\n\n if (schema.description) {\n zodSchema = zodSchema.describe(schema.description);\n }\n\n return zodSchema;\n}\n\n/**\n * Convert a JSON Schema to a Zod schema with a default empty object fallback.\n *\n * @param schema - Optional JSON Schema object\n * @returns Zod schema (defaults to empty object schema)\n */\nexport function jsonSchemaToZodSafe(schema?: Record<string, unknown>): ZodType {\n if (!schema || Object.keys(schema).length === 0) {\n return z.object({});\n }\n return jsonSchemaToZod(schema);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","names":["fullSession: AgentSessionState","results: AgentSessionState[]"],"sources":["../../src/session/store.ts"],"sourcesContent":["import type { ModelMessage, StepResult, ToolSet } from 'ai';\nimport type { AgentSessionState } from '../types';\n\n/**\n * Interface for persisting agent session state.\n *\n * Implementations can use in-memory storage, databases,\n * or external services like Redis.\n */\nexport interface AgentSessionStore {\n /**\n * Get a session by ID.\n */\n get(sessionId: string): Promise<AgentSessionState | null>;\n\n /**\n * Create a new session.\n */\n create(\n session: Omit<AgentSessionState, 'createdAt' | 'updatedAt'>\n ): Promise<AgentSessionState>;\n\n /**\n * Append a step to a session.\n */\n appendStep(sessionId: string, step: StepResult<ToolSet>): Promise<void>;\n\n /**\n * Append a message to a session.\n */\n appendMessage(sessionId: string, message: ModelMessage): Promise<void>;\n\n /**\n * Update session properties.\n */\n update(\n sessionId: string,\n updates: Partial<Pick<AgentSessionState, 'status' | 'metadata'>>\n ): Promise<void>;\n\n /**\n * Delete a session.\n */\n delete(sessionId: string): Promise<boolean>;\n\n /**\n * List sessions by agent ID.\n */\n listByAgent(agentId: string, limit?: number): Promise<AgentSessionState[]>;\n\n /**\n * List sessions by tenant ID.\n */\n listByTenant(tenantId: string, limit?: number): Promise<AgentSessionState[]>;\n}\n\n/**\n * In-memory session store for development and testing.\n */\nexport class InMemorySessionStore implements AgentSessionStore {\n private readonly sessions = new Map<string, AgentSessionState>();\n\n async get(sessionId: string): Promise<AgentSessionState | null> {\n return this.sessions.get(sessionId) ?? null;\n }\n\n async create(\n session: Omit<AgentSessionState, 'createdAt' | 'updatedAt'>\n ): Promise<AgentSessionState> {\n const now = new Date();\n const fullSession: AgentSessionState = {\n ...session,\n createdAt: now,\n updatedAt: now,\n };\n this.sessions.set(session.sessionId, fullSession);\n return fullSession;\n }\n\n async appendStep(\n sessionId: string,\n step: StepResult<ToolSet>\n ): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.steps.push(step);\n session.updatedAt = new Date();\n }\n }\n\n async appendMessage(sessionId: string, message: ModelMessage): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.messages.push(message);\n session.updatedAt = new Date();\n }\n }\n\n async update(\n sessionId: string,\n updates: Partial<Pick<AgentSessionState, 'status' | 'metadata'>>\n ): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n Object.assign(session, updates, { updatedAt: new Date() });\n }\n }\n\n async delete(sessionId: string): Promise<boolean> {\n return this.sessions.delete(sessionId);\n }\n\n async listByAgent(\n agentId: string,\n limit = 100\n ): Promise<AgentSessionState[]> {\n const results: AgentSessionState[] = [];\n for (const session of this.sessions.values()) {\n if (session.agentId === agentId) {\n results.push(session);\n if (results.length >= limit) break;\n }\n }\n return results.sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()\n );\n }\n\n async listByTenant(\n tenantId: string,\n limit = 100\n ): Promise<AgentSessionState[]> {\n const results: AgentSessionState[] = [];\n for (const session of this.sessions.values()) {\n if (session.tenantId === tenantId) {\n results.push(session);\n if (results.length >= limit) break;\n }\n }\n return results.sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()\n );\n }\n\n /**\n * Clear all sessions (for testing).\n */\n clear(): void {\n this.sessions.clear();\n }\n}\n\n/**\n * Create an in-memory session store.\n */\nexport function createInMemorySessionStore(): AgentSessionStore {\n return new InMemorySessionStore();\n}\n\n/**\n * Generate a unique session ID.\n */\nexport function generateSessionId(): string {\n return `sess_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n}\n"],"mappings":";;;;AA2DA,IAAa,uBAAb,MAA+D;CAC7D,AAAiB,2BAAW,IAAI,KAAgC;CAEhE,MAAM,IAAI,WAAsD;AAC9D,SAAO,KAAK,SAAS,IAAI,UAAU,IAAI;;CAGzC,MAAM,OACJ,SAC4B;EAC5B,MAAM,sBAAM,IAAI,MAAM;EACtB,MAAMA,cAAiC;GACrC,GAAG;GACH,WAAW;GACX,WAAW;GACZ;AACD,OAAK,SAAS,IAAI,QAAQ,WAAW,YAAY;AACjD,SAAO;;CAGT,MAAM,WACJ,WACA,MACe;EACf,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,SAAS;AACX,WAAQ,MAAM,KAAK,KAAK;AACxB,WAAQ,4BAAY,IAAI,MAAM;;;CAIlC,MAAM,cAAc,WAAmB,SAAsC;EAC3E,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,SAAS;AACX,WAAQ,SAAS,KAAK,QAAQ;AAC9B,WAAQ,4BAAY,IAAI,MAAM;;;CAIlC,MAAM,OACJ,WACA,SACe;EACf,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,QACF,QAAO,OAAO,SAAS,SAAS,EAAE,2BAAW,IAAI,MAAM,EAAE,CAAC;;CAI9D,MAAM,OAAO,WAAqC;AAChD,SAAO,KAAK,SAAS,OAAO,UAAU;;CAGxC,MAAM,YACJ,SACA,QAAQ,KACsB;EAC9B,MAAMC,UAA+B,EAAE;AACvC,OAAK,MAAM,WAAW,KAAK,SAAS,QAAQ,CAC1C,KAAI,QAAQ,YAAY,SAAS;AAC/B,WAAQ,KAAK,QAAQ;AACrB,OAAI,QAAQ,UAAU,MAAO;;AAGjC,SAAO,QAAQ,MACZ,GAAG,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,UAAU,SAAS,CACxD;;CAGH,MAAM,aACJ,UACA,QAAQ,KACsB;EAC9B,MAAMA,UAA+B,EAAE;AACvC,OAAK,MAAM,WAAW,KAAK,SAAS,QAAQ,CAC1C,KAAI,QAAQ,aAAa,UAAU;AACjC,WAAQ,KAAK,QAAQ;AACrB,OAAI,QAAQ,UAAU,MAAO;;AAGjC,SAAO,QAAQ,MACZ,GAAG,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,UAAU,SAAS,CACxD;;;;;CAMH,QAAc;AACZ,OAAK,SAAS,OAAO;;;;;;AAOzB,SAAgB,6BAAgD;AAC9D,QAAO,IAAI,sBAAsB;;;;;AAMnC,SAAgB,oBAA4B;AAC1C,QAAO,QAAQ,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,GAAG"}
1
+ {"version":3,"file":"store.js","names":[],"sources":["../../src/session/store.ts"],"sourcesContent":["import type { ModelMessage, StepResult, ToolSet } from 'ai';\nimport type { AgentSessionState } from '../types';\n\n/**\n * Interface for persisting agent session state.\n *\n * Implementations can use in-memory storage, databases,\n * or external services like Redis.\n */\nexport interface AgentSessionStore {\n /**\n * Get a session by ID.\n */\n get(sessionId: string): Promise<AgentSessionState | null>;\n\n /**\n * Create a new session.\n */\n create(\n session: Omit<AgentSessionState, 'createdAt' | 'updatedAt'>\n ): Promise<AgentSessionState>;\n\n /**\n * Append a step to a session.\n */\n appendStep(sessionId: string, step: StepResult<ToolSet>): Promise<void>;\n\n /**\n * Append a message to a session.\n */\n appendMessage(sessionId: string, message: ModelMessage): Promise<void>;\n\n /**\n * Update session properties.\n */\n update(\n sessionId: string,\n updates: Partial<Pick<AgentSessionState, 'status' | 'metadata'>>\n ): Promise<void>;\n\n /**\n * Delete a session.\n */\n delete(sessionId: string): Promise<boolean>;\n\n /**\n * List sessions by agent ID.\n */\n listByAgent(agentId: string, limit?: number): Promise<AgentSessionState[]>;\n\n /**\n * List sessions by tenant ID.\n */\n listByTenant(tenantId: string, limit?: number): Promise<AgentSessionState[]>;\n}\n\n/**\n * In-memory session store for development and testing.\n */\nexport class InMemorySessionStore implements AgentSessionStore {\n private readonly sessions = new Map<string, AgentSessionState>();\n\n async get(sessionId: string): Promise<AgentSessionState | null> {\n return this.sessions.get(sessionId) ?? null;\n }\n\n async create(\n session: Omit<AgentSessionState, 'createdAt' | 'updatedAt'>\n ): Promise<AgentSessionState> {\n const now = new Date();\n const fullSession: AgentSessionState = {\n ...session,\n createdAt: now,\n updatedAt: now,\n };\n this.sessions.set(session.sessionId, fullSession);\n return fullSession;\n }\n\n async appendStep(\n sessionId: string,\n step: StepResult<ToolSet>\n ): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.steps.push(step);\n session.updatedAt = new Date();\n }\n }\n\n async appendMessage(sessionId: string, message: ModelMessage): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.messages.push(message);\n session.updatedAt = new Date();\n }\n }\n\n async update(\n sessionId: string,\n updates: Partial<Pick<AgentSessionState, 'status' | 'metadata'>>\n ): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n Object.assign(session, updates, { updatedAt: new Date() });\n }\n }\n\n async delete(sessionId: string): Promise<boolean> {\n return this.sessions.delete(sessionId);\n }\n\n async listByAgent(\n agentId: string,\n limit = 100\n ): Promise<AgentSessionState[]> {\n const results: AgentSessionState[] = [];\n for (const session of this.sessions.values()) {\n if (session.agentId === agentId) {\n results.push(session);\n if (results.length >= limit) break;\n }\n }\n return results.sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()\n );\n }\n\n async listByTenant(\n tenantId: string,\n limit = 100\n ): Promise<AgentSessionState[]> {\n const results: AgentSessionState[] = [];\n for (const session of this.sessions.values()) {\n if (session.tenantId === tenantId) {\n results.push(session);\n if (results.length >= limit) break;\n }\n }\n return results.sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()\n );\n }\n\n /**\n * Clear all sessions (for testing).\n */\n clear(): void {\n this.sessions.clear();\n }\n}\n\n/**\n * Create an in-memory session store.\n */\nexport function createInMemorySessionStore(): AgentSessionStore {\n return new InMemorySessionStore();\n}\n\n/**\n * Generate a unique session ID.\n */\nexport function generateSessionId(): string {\n return `sess_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n}\n"],"mappings":";;;;AA2DA,IAAa,uBAAb,MAA+D;CAC7D,AAAiB,2BAAW,IAAI,KAAgC;CAEhE,MAAM,IAAI,WAAsD;AAC9D,SAAO,KAAK,SAAS,IAAI,UAAU,IAAI;;CAGzC,MAAM,OACJ,SAC4B;EAC5B,MAAM,sBAAM,IAAI,MAAM;EACtB,MAAM,cAAiC;GACrC,GAAG;GACH,WAAW;GACX,WAAW;GACZ;AACD,OAAK,SAAS,IAAI,QAAQ,WAAW,YAAY;AACjD,SAAO;;CAGT,MAAM,WACJ,WACA,MACe;EACf,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,SAAS;AACX,WAAQ,MAAM,KAAK,KAAK;AACxB,WAAQ,4BAAY,IAAI,MAAM;;;CAIlC,MAAM,cAAc,WAAmB,SAAsC;EAC3E,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,SAAS;AACX,WAAQ,SAAS,KAAK,QAAQ;AAC9B,WAAQ,4BAAY,IAAI,MAAM;;;CAIlC,MAAM,OACJ,WACA,SACe;EACf,MAAM,UAAU,KAAK,SAAS,IAAI,UAAU;AAC5C,MAAI,QACF,QAAO,OAAO,SAAS,SAAS,EAAE,2BAAW,IAAI,MAAM,EAAE,CAAC;;CAI9D,MAAM,OAAO,WAAqC;AAChD,SAAO,KAAK,SAAS,OAAO,UAAU;;CAGxC,MAAM,YACJ,SACA,QAAQ,KACsB;EAC9B,MAAM,UAA+B,EAAE;AACvC,OAAK,MAAM,WAAW,KAAK,SAAS,QAAQ,CAC1C,KAAI,QAAQ,YAAY,SAAS;AAC/B,WAAQ,KAAK,QAAQ;AACrB,OAAI,QAAQ,UAAU,MAAO;;AAGjC,SAAO,QAAQ,MACZ,GAAG,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,UAAU,SAAS,CACxD;;CAGH,MAAM,aACJ,UACA,QAAQ,KACsB;EAC9B,MAAM,UAA+B,EAAE;AACvC,OAAK,MAAM,WAAW,KAAK,SAAS,QAAQ,CAC1C,KAAI,QAAQ,aAAa,UAAU;AACjC,WAAQ,KAAK,QAAQ;AACrB,OAAI,QAAQ,UAAU,MAAO;;AAGjC,SAAO,QAAQ,MACZ,GAAG,MAAM,EAAE,UAAU,SAAS,GAAG,EAAE,UAAU,SAAS,CACxD;;;;;CAMH,QAAc;AACZ,OAAK,SAAS,OAAO;;;;;;AAOzB,SAAgB,6BAAgD;AAC9D,QAAO,IAAI,sBAAsB;;;;;AAMnC,SAAgB,oBAA4B;AAC1C,QAAO,QAAQ,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":["versions: AgentSpec[]"],"sources":["../../src/spec/registry.ts"],"sourcesContent":["import type { AgentSpec } from './spec';\nimport { compareVersions } from 'compare-versions';\nimport { SpecContractRegistry } from '@contractspec/lib.contracts/registry';\n\n/**\n * Registry for managing agent specifications.\n *\n * Provides registration, lookup, and version management for agent specs.\n */\nexport class AgentRegistry extends SpecContractRegistry<'agent', AgentSpec> {\n public constructor(items?: AgentSpec[]) {\n super('agent', items);\n }\n\n /**\n * List all unique agent names (without versions).\n */\n listNames(): string[] {\n const names = new Set<string>();\n for (const spec of this.items.values()) {\n names.add(spec.meta.key);\n }\n return [...names];\n }\n\n /**\n * Get an agent specification or throw if not found.\n *\n * @param name - Agent name\n * @param version - Optional version\n * @returns The agent spec\n * @throws Error if the spec is not found\n */\n require(name: string, version?: string): AgentSpec {\n const spec = this.get(name, version);\n if (!spec) {\n throw new Error(\n `Agent spec not found for ${name}${version != null ? `.v${version}` : ''}`\n );\n }\n return spec;\n }\n\n /**\n * Check if an agent is registered.\n *\n * @param name - Agent name\n * @param version - Optional version\n */\n has(name: string, version?: string): boolean {\n return this.get(name, version) !== undefined;\n }\n\n /**\n * Get all versions of an agent.\n *\n * @param name - Agent name\n * @returns Array of specs sorted by version (ascending)\n */\n getVersions(name: string): AgentSpec[] {\n const versions: AgentSpec[] = [];\n for (const spec of this.items.values()) {\n if (spec.meta.key === name) {\n versions.push(spec);\n }\n }\n return versions.sort((a, b) =>\n compareVersions(a.meta.version, b.meta.version)\n );\n }\n}\n\n/**\n * Create a new agent registry.\n */\nexport function createAgentRegistry(): AgentRegistry {\n return new AgentRegistry();\n}\n"],"mappings":";;;;;;;;;AASA,IAAa,gBAAb,cAAmC,qBAAyC;CAC1E,AAAO,YAAY,OAAqB;AACtC,QAAM,SAAS,MAAM;;;;;CAMvB,YAAsB;EACpB,MAAM,wBAAQ,IAAI,KAAa;AAC/B,OAAK,MAAM,QAAQ,KAAK,MAAM,QAAQ,CACpC,OAAM,IAAI,KAAK,KAAK,IAAI;AAE1B,SAAO,CAAC,GAAG,MAAM;;;;;;;;;;CAWnB,QAAQ,MAAc,SAA6B;EACjD,MAAM,OAAO,KAAK,IAAI,MAAM,QAAQ;AACpC,MAAI,CAAC,KACH,OAAM,IAAI,MACR,4BAA4B,OAAO,WAAW,OAAO,KAAK,YAAY,KACvE;AAEH,SAAO;;;;;;;;CAST,IAAI,MAAc,SAA2B;AAC3C,SAAO,KAAK,IAAI,MAAM,QAAQ,KAAK;;;;;;;;CASrC,YAAY,MAA2B;EACrC,MAAMA,WAAwB,EAAE;AAChC,OAAK,MAAM,QAAQ,KAAK,MAAM,QAAQ,CACpC,KAAI,KAAK,KAAK,QAAQ,KACpB,UAAS,KAAK,KAAK;AAGvB,SAAO,SAAS,MAAM,GAAG,MACvB,gBAAgB,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,CAChD;;;;;;AAOL,SAAgB,sBAAqC;AACnD,QAAO,IAAI,eAAe"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../src/spec/registry.ts"],"sourcesContent":["import type { AgentSpec } from './spec';\nimport { compareVersions } from 'compare-versions';\nimport { SpecContractRegistry } from '@contractspec/lib.contracts/registry';\n\n/**\n * Registry for managing agent specifications.\n *\n * Provides registration, lookup, and version management for agent specs.\n */\nexport class AgentRegistry extends SpecContractRegistry<'agent', AgentSpec> {\n public constructor(items?: AgentSpec[]) {\n super('agent', items);\n }\n\n /**\n * List all unique agent names (without versions).\n */\n listNames(): string[] {\n const names = new Set<string>();\n for (const spec of this.items.values()) {\n names.add(spec.meta.key);\n }\n return [...names];\n }\n\n /**\n * Get an agent specification or throw if not found.\n *\n * @param name - Agent name\n * @param version - Optional version\n * @returns The agent spec\n * @throws Error if the spec is not found\n */\n require(name: string, version?: string): AgentSpec {\n const spec = this.get(name, version);\n if (!spec) {\n throw new Error(\n `Agent spec not found for ${name}${version != null ? `.v${version}` : ''}`\n );\n }\n return spec;\n }\n\n /**\n * Check if an agent is registered.\n *\n * @param name - Agent name\n * @param version - Optional version\n */\n has(name: string, version?: string): boolean {\n return this.get(name, version) !== undefined;\n }\n\n /**\n * Get all versions of an agent.\n *\n * @param name - Agent name\n * @returns Array of specs sorted by version (ascending)\n */\n getVersions(name: string): AgentSpec[] {\n const versions: AgentSpec[] = [];\n for (const spec of this.items.values()) {\n if (spec.meta.key === name) {\n versions.push(spec);\n }\n }\n return versions.sort((a, b) =>\n compareVersions(a.meta.version, b.meta.version)\n );\n }\n}\n\n/**\n * Create a new agent registry.\n */\nexport function createAgentRegistry(): AgentRegistry {\n return new AgentRegistry();\n}\n"],"mappings":";;;;;;;;;AASA,IAAa,gBAAb,cAAmC,qBAAyC;CAC1E,AAAO,YAAY,OAAqB;AACtC,QAAM,SAAS,MAAM;;;;;CAMvB,YAAsB;EACpB,MAAM,wBAAQ,IAAI,KAAa;AAC/B,OAAK,MAAM,QAAQ,KAAK,MAAM,QAAQ,CACpC,OAAM,IAAI,KAAK,KAAK,IAAI;AAE1B,SAAO,CAAC,GAAG,MAAM;;;;;;;;;;CAWnB,QAAQ,MAAc,SAA6B;EACjD,MAAM,OAAO,KAAK,IAAI,MAAM,QAAQ;AACpC,MAAI,CAAC,KACH,OAAM,IAAI,MACR,4BAA4B,OAAO,WAAW,OAAO,KAAK,YAAY,KACvE;AAEH,SAAO;;;;;;;;CAST,IAAI,MAAc,SAA2B;AAC3C,SAAO,KAAK,IAAI,MAAM,QAAQ,KAAK;;;;;;;;CASrC,YAAY,MAA2B;EACrC,MAAM,WAAwB,EAAE;AAChC,OAAK,MAAM,QAAQ,KAAK,MAAM,QAAQ,CACpC,KAAI,KAAK,KAAK,QAAQ,KACpB,UAAS,KAAK,KAAK;AAGvB,SAAO,SAAS,MAAM,GAAG,MACvB,gBAAgB,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,CAChD;;;;;;AAOL,SAAgB,sBAAqC;AACnD,QAAO,IAAI,eAAe"}