@contractspec/lib.ai-agent 1.57.0 → 1.59.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.
- package/dist/agent/agent-factory.d.ts +67 -71
- package/dist/agent/agent-factory.d.ts.map +1 -1
- package/dist/agent/agent-factory.js +658 -100
- package/dist/agent/agent.test.d.ts +2 -0
- package/dist/agent/agent.test.d.ts.map +1 -0
- package/dist/agent/contract-spec-agent.d.ts +48 -52
- package/dist/agent/contract-spec-agent.d.ts.map +1 -1
- package/dist/agent/contract-spec-agent.js +605 -146
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +2102 -4
- package/dist/agent/json-runner.d.ts +15 -19
- package/dist/agent/json-runner.d.ts.map +1 -1
- package/dist/agent/json-runner.js +672 -57
- package/dist/agent/json-runner.test.d.ts +2 -0
- package/dist/agent/json-runner.test.d.ts.map +1 -0
- package/dist/agent/unified-agent.d.ts +132 -109
- package/dist/agent/unified-agent.d.ts.map +1 -1
- package/dist/agent/unified-agent.js +2011 -293
- package/dist/approval/index.d.ts +3 -2
- package/dist/approval/index.d.ts.map +1 -0
- package/dist/approval/index.js +128 -2
- package/dist/approval/workflow.d.ts +106 -110
- package/dist/approval/workflow.d.ts.map +1 -1
- package/dist/approval/workflow.js +126 -157
- package/dist/exporters/claude-agent-exporter.d.ts +50 -48
- package/dist/exporters/claude-agent-exporter.d.ts.map +1 -1
- package/dist/exporters/claude-agent-exporter.js +258 -203
- package/dist/exporters/index.d.ts +28 -4
- package/dist/exporters/index.d.ts.map +1 -0
- package/dist/exporters/index.js +737 -3
- package/dist/exporters/opencode-exporter.d.ts +47 -45
- package/dist/exporters/opencode-exporter.d.ts.map +1 -1
- package/dist/exporters/opencode-exporter.js +507 -191
- package/dist/exporters/types.d.ts +171 -169
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/exporters/types.js +1 -0
- package/dist/index.d.ts +15 -39
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3337 -32
- package/dist/interop/index.d.ts +48 -4
- package/dist/interop/index.d.ts.map +1 -0
- package/dist/interop/index.js +709 -3
- package/dist/interop/spec-consumer.d.ts +57 -53
- package/dist/interop/spec-consumer.d.ts.map +1 -1
- package/dist/interop/spec-consumer.js +302 -282
- package/dist/interop/tool-consumer.d.ts +57 -53
- package/dist/interop/tool-consumer.d.ts.map +1 -1
- package/dist/interop/tool-consumer.js +412 -213
- package/dist/interop/types.d.ts +173 -171
- package/dist/interop/types.d.ts.map +1 -1
- package/dist/interop/types.js +1 -0
- package/dist/knowledge/index.d.ts +2 -2
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +66 -2
- package/dist/knowledge/injector.d.ts +16 -20
- package/dist/knowledge/injector.d.ts.map +1 -1
- package/dist/knowledge/injector.js +56 -47
- package/dist/memory/in-memory.d.ts +15 -19
- package/dist/memory/in-memory.d.ts.map +1 -1
- package/dist/memory/in-memory.js +152 -46
- package/dist/memory/index.d.ts +3 -3
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +155 -3
- package/dist/memory/manager.d.ts +32 -36
- package/dist/memory/manager.d.ts.map +1 -1
- package/dist/memory/manager.js +96 -70
- package/dist/memory/memory.test.d.ts +2 -0
- package/dist/memory/memory.test.d.ts.map +1 -0
- package/dist/node/agent/agent-factory.js +661 -0
- package/dist/node/agent/contract-spec-agent.js +607 -0
- package/dist/node/agent/index.js +2103 -0
- package/dist/node/agent/json-runner.js +684 -0
- package/dist/node/agent/unified-agent.js +2019 -0
- package/dist/node/approval/index.js +129 -0
- package/dist/node/approval/workflow.js +129 -0
- package/dist/node/exporters/claude-agent-exporter.js +265 -0
- package/dist/node/exporters/index.js +738 -0
- package/dist/node/exporters/opencode-exporter.js +516 -0
- package/dist/node/exporters/types.js +0 -0
- package/dist/node/index.js +3337 -0
- package/dist/node/interop/index.js +710 -0
- package/dist/node/interop/spec-consumer.js +307 -0
- package/dist/node/interop/tool-consumer.js +419 -0
- package/dist/node/interop/types.js +0 -0
- package/dist/node/knowledge/index.js +67 -0
- package/dist/node/knowledge/injector.js +67 -0
- package/dist/node/memory/in-memory.js +154 -0
- package/dist/node/memory/index.js +156 -0
- package/dist/node/memory/manager.js +105 -0
- package/dist/node/providers/claude-agent-sdk/adapter.js +624 -0
- package/dist/node/providers/claude-agent-sdk/index.js +673 -0
- package/dist/node/providers/claude-agent-sdk/session-bridge.js +149 -0
- package/dist/node/providers/claude-agent-sdk/tool-bridge.js +118 -0
- package/dist/node/providers/index.js +1261 -0
- package/dist/node/providers/opencode-sdk/adapter.js +669 -0
- package/dist/node/providers/opencode-sdk/agent-bridge.js +299 -0
- package/dist/node/providers/opencode-sdk/index.js +703 -0
- package/dist/node/providers/opencode-sdk/tool-bridge.js +141 -0
- package/dist/node/providers/registry.js +89 -0
- package/dist/node/providers/types.js +56 -0
- package/dist/node/schema/index.js +195 -0
- package/dist/node/schema/json-schema-to-zod.js +152 -0
- package/dist/node/schema/schema-output.js +190 -0
- package/dist/node/session/index.js +90 -0
- package/dist/node/session/store.js +90 -0
- package/dist/node/spec/index.js +85 -0
- package/dist/node/spec/registry.js +56 -0
- package/dist/node/spec/spec.js +44 -0
- package/dist/node/telemetry/adapter.js +85 -0
- package/dist/node/telemetry/index.js +86 -0
- package/dist/node/tools/index.js +345 -0
- package/dist/node/tools/knowledge-tool.js +74 -0
- package/dist/node/tools/mcp-client.js +47 -0
- package/dist/node/tools/mcp-server.js +205 -0
- package/dist/node/tools/tool-adapter.js +197 -0
- package/dist/node/types.js +0 -0
- package/dist/providers/claude-agent-sdk/adapter.d.ts +60 -52
- package/dist/providers/claude-agent-sdk/adapter.d.ts.map +1 -1
- package/dist/providers/claude-agent-sdk/adapter.js +622 -304
- package/dist/providers/claude-agent-sdk/index.d.ts +22 -4
- package/dist/providers/claude-agent-sdk/index.d.ts.map +1 -0
- package/dist/providers/claude-agent-sdk/index.js +672 -4
- package/dist/providers/claude-agent-sdk/session-bridge.d.ts +43 -40
- package/dist/providers/claude-agent-sdk/session-bridge.d.ts.map +1 -1
- package/dist/providers/claude-agent-sdk/session-bridge.js +121 -130
- package/dist/providers/claude-agent-sdk/tool-bridge.d.ts +63 -60
- package/dist/providers/claude-agent-sdk/tool-bridge.d.ts.map +1 -1
- package/dist/providers/claude-agent-sdk/tool-bridge.js +104 -108
- package/dist/providers/index.d.ts +28 -7
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +1261 -8
- package/dist/providers/opencode-sdk/adapter.d.ts +56 -48
- package/dist/providers/opencode-sdk/adapter.d.ts.map +1 -1
- package/dist/providers/opencode-sdk/adapter.js +667 -274
- package/dist/providers/opencode-sdk/agent-bridge.d.ts +62 -57
- package/dist/providers/opencode-sdk/agent-bridge.d.ts.map +1 -1
- package/dist/providers/opencode-sdk/agent-bridge.js +289 -155
- package/dist/providers/opencode-sdk/index.d.ts +22 -4
- package/dist/providers/opencode-sdk/index.d.ts.map +1 -0
- package/dist/providers/opencode-sdk/index.js +702 -4
- package/dist/providers/opencode-sdk/tool-bridge.d.ts +41 -42
- package/dist/providers/opencode-sdk/tool-bridge.d.ts.map +1 -1
- package/dist/providers/opencode-sdk/tool-bridge.js +121 -107
- package/dist/providers/registry.d.ts +10 -11
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +86 -49
- package/dist/providers/types.d.ts +169 -166
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js +54 -42
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +194 -3
- package/dist/schema/json-schema-to-zod.d.ts +23 -26
- package/dist/schema/json-schema-to-zod.d.ts.map +1 -1
- package/dist/schema/json-schema-to-zod.js +138 -110
- package/dist/schema/schema-output.d.ts +29 -32
- package/dist/schema/schema-output.d.ts.map +1 -1
- package/dist/schema/schema-output.js +178 -53
- package/dist/session/index.d.ts +2 -2
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +89 -2
- package/dist/session/store.d.ts +51 -55
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +85 -74
- package/dist/spec/index.d.ts +3 -3
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +84 -3
- package/dist/spec/registry.d.ts +32 -36
- package/dist/spec/registry.d.ts.map +1 -1
- package/dist/spec/registry.js +51 -60
- package/dist/spec/spec.d.ts +80 -84
- package/dist/spec/spec.d.ts.map +1 -1
- package/dist/spec/spec.js +40 -26
- package/dist/telemetry/adapter.d.ts +33 -37
- package/dist/telemetry/adapter.d.ts.map +1 -1
- package/dist/telemetry/adapter.js +78 -96
- package/dist/telemetry/index.d.ts +2 -2
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +85 -2
- package/dist/tools/index.d.ts +5 -5
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +344 -5
- package/dist/tools/knowledge-tool.d.ts +4 -8
- package/dist/tools/knowledge-tool.d.ts.map +1 -1
- package/dist/tools/knowledge-tool.js +68 -48
- package/dist/tools/mcp-client.d.ts +17 -21
- package/dist/tools/mcp-client.d.ts.map +1 -1
- package/dist/tools/mcp-client.js +42 -53
- package/dist/tools/mcp-server.d.ts +14 -18
- package/dist/tools/mcp-server.d.ts.map +1 -1
- package/dist/tools/mcp-server.js +200 -64
- package/dist/tools/tool-adapter.d.ts +7 -11
- package/dist/tools/tool-adapter.d.ts.map +1 -1
- package/dist/tools/tool-adapter.js +187 -70
- package/dist/tools/tools.test.d.ts +2 -0
- package/dist/tools/tools.test.d.ts.map +1 -0
- package/dist/types.d.ts +108 -111
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/package.json +448 -90
- package/dist/_virtual/_rolldown/runtime.js +0 -8
- package/dist/agent/agent-factory.js.map +0 -1
- package/dist/agent/contract-spec-agent.js.map +0 -1
- package/dist/agent/json-runner.js.map +0 -1
- package/dist/agent/unified-agent.js.map +0 -1
- package/dist/approval/workflow.js.map +0 -1
- package/dist/exporters/claude-agent-exporter.js.map +0 -1
- package/dist/exporters/opencode-exporter.js.map +0 -1
- package/dist/interop/spec-consumer.js.map +0 -1
- package/dist/interop/tool-consumer.js.map +0 -1
- package/dist/knowledge/injector.js.map +0 -1
- package/dist/memory/in-memory.js.map +0 -1
- package/dist/memory/manager.js.map +0 -1
- package/dist/providers/claude-agent-sdk/adapter.js.map +0 -1
- package/dist/providers/claude-agent-sdk/session-bridge.js.map +0 -1
- package/dist/providers/claude-agent-sdk/tool-bridge.js.map +0 -1
- package/dist/providers/opencode-sdk/adapter.js.map +0 -1
- package/dist/providers/opencode-sdk/agent-bridge.js.map +0 -1
- package/dist/providers/opencode-sdk/tool-bridge.js.map +0 -1
- package/dist/providers/registry.js.map +0 -1
- package/dist/providers/types.js.map +0 -1
- package/dist/schema/json-schema-to-zod.js.map +0 -1
- package/dist/schema/schema-output.js.map +0 -1
- package/dist/session/store.js.map +0 -1
- package/dist/spec/registry.js.map +0 -1
- package/dist/spec/spec.js.map +0 -1
- package/dist/telemetry/adapter.js.map +0 -1
- package/dist/tools/knowledge-tool.js.map +0 -1
- package/dist/tools/mcp-client.js.map +0 -1
- package/dist/tools/mcp-server.js.map +0 -1
- package/dist/tools/tool-adapter.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract-spec-agent.js","names":["z","ToolLoopAgent"],"sources":["../../src/agent/contract-spec-agent.ts"],"sourcesContent":["import {\n Experimental_Agent as ToolLoopAgent,\n type LanguageModel,\n stepCountIs,\n type StepResult,\n type Tool,\n type ToolSet,\n} from 'ai';\nimport * as z from 'zod';\nimport type { KnowledgeRetriever } from '@contractspec/lib.knowledge/retriever';\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n AgentCallOptions,\n AgentGenerateParams,\n AgentGenerateResult,\n AgentStreamParams,\n ToolHandler,\n} from '../types';\nimport { specToolsToAISDKTools } from '../tools/tool-adapter';\nimport { createKnowledgeQueryTool } from '../tools/knowledge-tool';\nimport { injectStaticKnowledge } from '../knowledge/injector';\nimport { type AgentSessionStore, generateSessionId } from '../session/store';\nimport { type TelemetryCollector, trackAgentStep } from '../telemetry/adapter';\n\n/**\n * Call options schema for AI SDK v6.\n * Maps ContractSpec's tenant/actor system to AI SDK callOptionsSchema.\n */\nconst ContractSpecCallOptionsSchema = z.object({\n tenantId: z.string().optional(),\n actorId: z.string().optional(),\n sessionId: z.string().optional(),\n // Zod v4: z.record() requires both key and value schemas\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Type for tool with execute function (compatible with AI SDK Tool)\n */\ntype ExecutableTool = Tool;\n\n/**\n * Configuration for creating a ContractSpecAgent.\n */\nexport interface ContractSpecAgentConfig {\n /** The agent specification */\n spec: AgentSpec;\n /** AI SDK language model */\n model: LanguageModel;\n /** Map of tool name to handler function */\n toolHandlers: Map<string, ToolHandler>;\n /** Optional knowledge retriever for RAG */\n knowledgeRetriever?: KnowledgeRetriever;\n /** Optional session store for persistence */\n sessionStore?: AgentSessionStore;\n /** Optional telemetry collector for evolution */\n telemetryCollector?: TelemetryCollector;\n /** Additional AI SDK tools (e.g., from MCP servers) */\n additionalTools?: Record<string, ExecutableTool>;\n}\n\n/**\n * ContractSpec Agent implementation using AI SDK v6.\n *\n * Integrates ContractSpec's spec-first governance with AI SDK's\n * ToolLoopAgent, providing:\n * - Spec-defined tools with type-safe handlers\n * - Hybrid knowledge injection (static + dynamic RAG)\n * - Session persistence\n * - Telemetry for evolution\n * - MCP interoperability\n */\nexport class ContractSpecAgent {\n readonly version = 'agent-v1';\n readonly id: string;\n readonly spec: AgentSpec;\n readonly tools: Record<string, ExecutableTool>;\n\n private readonly inner: ToolLoopAgent<\n z.infer<typeof ContractSpecCallOptionsSchema>,\n ToolSet,\n never\n >;\n private readonly config: ContractSpecAgentConfig;\n private instructions: string;\n\n private constructor(\n config: ContractSpecAgentConfig,\n instructions: string,\n tools: Record<string, ExecutableTool>\n ) {\n this.config = config;\n this.spec = config.spec;\n this.id = agentKey(config.spec.meta);\n this.tools = tools;\n this.instructions = instructions;\n\n // Create the inner ToolLoopAgent with AI SDK v6 settings\n this.inner = new ToolLoopAgent({\n model: config.model,\n instructions,\n tools: tools as ToolSet,\n // Use stopWhen instead of maxSteps (AI SDK v6 API)\n stopWhen: stepCountIs(config.spec.maxSteps ?? 10),\n // Schema for call options (tenant/actor context)\n callOptionsSchema: ContractSpecCallOptionsSchema,\n // Step-level telemetry callback\n onStepFinish: async (step: StepResult<ToolSet>) => {\n await this.handleStepFinish(step);\n },\n });\n }\n\n /**\n * Create a ContractSpecAgent instance.\n * This is async because knowledge injection may need to fetch static content.\n */\n static async create(\n config: ContractSpecAgentConfig\n ): Promise<ContractSpecAgent> {\n // 1. Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n config.spec.instructions,\n config.spec.knowledge ?? [],\n config.knowledgeRetriever\n );\n\n // 2. Build tools from spec\n const specTools = specToolsToAISDKTools(\n config.spec.tools,\n config.toolHandlers,\n { agentId: agentKey(config.spec.meta) }\n );\n\n // 3. Add dynamic knowledge query tool\n const knowledgeTool = config.knowledgeRetriever\n ? createKnowledgeQueryTool(\n config.knowledgeRetriever,\n config.spec.knowledge ?? []\n )\n : null;\n\n // 4. Combine all tools\n const tools: Record<string, ExecutableTool> = {\n ...specTools,\n ...(knowledgeTool ? { query_knowledge: knowledgeTool } : {}),\n ...(config.additionalTools ?? {}),\n };\n\n return new ContractSpecAgent(config, instructions, tools);\n }\n\n /**\n * Generate a response (non-streaming).\n */\n async generate(params: AgentGenerateParams): Promise<AgentGenerateResult> {\n const sessionId = params.options?.sessionId ?? generateSessionId();\n\n // Ensure session exists\n if (this.config.sessionStore) {\n const existing = await this.config.sessionStore.get(sessionId);\n if (!existing) {\n await this.config.sessionStore.create({\n sessionId,\n agentId: this.id,\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n status: 'running',\n messages: [],\n steps: [],\n metadata: params.options?.metadata,\n });\n }\n }\n\n // Build prompt with optional system override\n const prompt = params.systemOverride\n ? `${this.instructions}\\n\\n${params.systemOverride}\\n\\n${params.prompt}`\n : params.prompt;\n\n // AI SDK v6: maxSteps is controlled via stopWhen in agent settings\n const result = await this.inner.generate({\n prompt,\n abortSignal: params.signal,\n options: {\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n sessionId,\n metadata: params.options?.metadata,\n },\n });\n\n // Update session status\n if (this.config.sessionStore) {\n await this.config.sessionStore.update(sessionId, {\n status: 'completed',\n });\n }\n\n return {\n text: result.text,\n steps: result.steps,\n // Map AI SDK types to our simplified types\n toolCalls: result.toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n args: 'args' in tc ? tc.args : 'input' in tc ? tc.input : undefined,\n })),\n toolResults: result.toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.toolCallId,\n toolName: tr.toolName,\n output: tr.output,\n })),\n finishReason: result.finishReason,\n usage: result.usage,\n };\n }\n\n /**\n * Stream a response with real-time updates.\n */\n async stream(params: AgentStreamParams) {\n const sessionId = params.options?.sessionId ?? generateSessionId();\n\n const prompt = params.systemOverride\n ? `${this.instructions}\\n\\n${params.systemOverride}\\n\\n${params.prompt}`\n : params.prompt;\n\n // AI SDK v6: maxSteps is controlled via stopWhen in agent settings\n // onStepFinish callback is already set in agent construction\n return this.inner.stream({\n prompt,\n abortSignal: params.signal,\n options: {\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n sessionId,\n metadata: params.options?.metadata,\n },\n });\n }\n\n /**\n * Handle step completion for persistence and telemetry.\n */\n private async handleStepFinish(step: StepResult<ToolSet>): Promise<void> {\n // 1. Persist to session store\n const sessionId = (step as { options?: AgentCallOptions }).options\n ?.sessionId;\n if (sessionId && this.config.sessionStore) {\n await this.config.sessionStore.appendStep(sessionId, step);\n }\n\n // 2. Feed telemetry to evolution engine\n if (this.config.telemetryCollector) {\n await trackAgentStep(this.config.telemetryCollector, this.id, step);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA6BA,MAAM,gCAAgCA,IAAE,OAAO;CAC7C,UAAUA,IAAE,QAAQ,CAAC,UAAU;CAC/B,SAASA,IAAE,QAAQ,CAAC,UAAU;CAC9B,WAAWA,IAAE,QAAQ,CAAC,UAAU;CAEhC,UAAUA,IAAE,OAAOA,IAAE,QAAQ,EAAEA,IAAE,SAAS,CAAC,CAAC,UAAU;CACvD,CAAC;;;;;;;;;;;;AAsCF,IAAa,oBAAb,MAAa,kBAAkB;CAC7B,AAAS,UAAU;CACnB,AAAS;CACT,AAAS;CACT,AAAS;CAET,AAAiB;CAKjB,AAAiB;CACjB,AAAQ;CAER,AAAQ,YACN,QACA,cACA,OACA;AACA,OAAK,SAAS;AACd,OAAK,OAAO,OAAO;AACnB,OAAK,KAAK,SAAS,OAAO,KAAK,KAAK;AACpC,OAAK,QAAQ;AACb,OAAK,eAAe;AAGpB,OAAK,QAAQ,IAAIC,mBAAc;GAC7B,OAAO,OAAO;GACd;GACO;GAEP,UAAU,YAAY,OAAO,KAAK,YAAY,GAAG;GAEjD,mBAAmB;GAEnB,cAAc,OAAO,SAA8B;AACjD,UAAM,KAAK,iBAAiB,KAAK;;GAEpC,CAAC;;;;;;CAOJ,aAAa,OACX,QAC4B;EAE5B,MAAM,eAAe,MAAM,sBACzB,OAAO,KAAK,cACZ,OAAO,KAAK,aAAa,EAAE,EAC3B,OAAO,mBACR;EAGD,MAAM,YAAY,sBAChB,OAAO,KAAK,OACZ,OAAO,cACP,EAAE,SAAS,SAAS,OAAO,KAAK,KAAK,EAAE,CACxC;EAGD,MAAM,gBAAgB,OAAO,qBACzB,yBACE,OAAO,oBACP,OAAO,KAAK,aAAa,EAAE,CAC5B,GACD;AASJ,SAAO,IAAI,kBAAkB,QAAQ,cANS;GAC5C,GAAG;GACH,GAAI,gBAAgB,EAAE,iBAAiB,eAAe,GAAG,EAAE;GAC3D,GAAI,OAAO,mBAAmB,EAAE;GACjC,CAEwD;;;;;CAM3D,MAAM,SAAS,QAA2D;EACxE,MAAM,YAAY,OAAO,SAAS,aAAa,mBAAmB;AAGlE,MAAI,KAAK,OAAO,cAEd;OAAI,CADa,MAAM,KAAK,OAAO,aAAa,IAAI,UAAU,CAE5D,OAAM,KAAK,OAAO,aAAa,OAAO;IACpC;IACA,SAAS,KAAK;IACd,UAAU,OAAO,SAAS;IAC1B,SAAS,OAAO,SAAS;IACzB,QAAQ;IACR,UAAU,EAAE;IACZ,OAAO,EAAE;IACT,UAAU,OAAO,SAAS;IAC3B,CAAC;;EAKN,MAAM,SAAS,OAAO,iBAClB,GAAG,KAAK,aAAa,MAAM,OAAO,eAAe,MAAM,OAAO,WAC9D,OAAO;EAGX,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS;GACvC;GACA,aAAa,OAAO;GACpB,SAAS;IACP,UAAU,OAAO,SAAS;IAC1B,SAAS,OAAO,SAAS;IACzB;IACA,UAAU,OAAO,SAAS;IAC3B;GACF,CAAC;AAGF,MAAI,KAAK,OAAO,aACd,OAAM,KAAK,OAAO,aAAa,OAAO,WAAW,EAC/C,QAAQ,aACT,CAAC;AAGJ,SAAO;GACL,MAAM,OAAO;GACb,OAAO,OAAO;GAEd,WAAW,OAAO,UAAU,KAAK,QAAQ;IACvC,MAAM;IACN,YAAY,GAAG;IACf,UAAU,GAAG;IACb,MAAM,UAAU,KAAK,GAAG,OAAO,WAAW,KAAK,GAAG,QAAQ;IAC3D,EAAE;GACH,aAAa,OAAO,YAAY,KAAK,QAAQ;IAC3C,MAAM;IACN,YAAY,GAAG;IACf,UAAU,GAAG;IACb,QAAQ,GAAG;IACZ,EAAE;GACH,cAAc,OAAO;GACrB,OAAO,OAAO;GACf;;;;;CAMH,MAAM,OAAO,QAA2B;EACtC,MAAM,YAAY,OAAO,SAAS,aAAa,mBAAmB;EAElE,MAAM,SAAS,OAAO,iBAClB,GAAG,KAAK,aAAa,MAAM,OAAO,eAAe,MAAM,OAAO,WAC9D,OAAO;AAIX,SAAO,KAAK,MAAM,OAAO;GACvB;GACA,aAAa,OAAO;GACpB,SAAS;IACP,UAAU,OAAO,SAAS;IAC1B,SAAS,OAAO,SAAS;IACzB;IACA,UAAU,OAAO,SAAS;IAC3B;GACF,CAAC;;;;;CAMJ,MAAc,iBAAiB,MAA0C;EAEvE,MAAM,YAAa,KAAwC,SACvD;AACJ,MAAI,aAAa,KAAK,OAAO,aAC3B,OAAM,KAAK,OAAO,aAAa,WAAW,WAAW,KAAK;AAI5D,MAAI,KAAK,OAAO,mBACd,OAAM,eAAe,KAAK,OAAO,oBAAoB,KAAK,IAAI,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"json-runner.js","names":[],"sources":["../../src/agent/json-runner.ts"],"sourcesContent":["import type { LanguageModel } from 'ai';\nimport { createProvider } from '@contractspec/lib.ai-providers/factory';\nimport type { ProviderConfig } from '@contractspec/lib.ai-providers/types';\nimport { StabilityEnum } from '@contractspec/lib.contracts/ownership';\nimport type { AgentSpec } from '../spec/spec';\nimport type { ToolHandler } from '../types';\nimport { ContractSpecAgent } from './contract-spec-agent';\n\nconst JSON_ONLY_RULES = [\n 'You MUST output valid JSON ONLY.',\n 'Do not wrap the output in markdown fences.',\n 'Do not include commentary or explanation.',\n 'Use double quotes for all keys and string values.',\n 'Do not include trailing commas.',\n].join('\\n');\n\nconst DEFAULT_SPEC: AgentSpec = {\n meta: {\n key: 'agent.json-runner',\n version: '1.0.0',\n description: 'JSON-only agent runner for deterministic pipelines.',\n stability: StabilityEnum.Experimental,\n owners: ['platform.core'],\n tags: ['json', 'agent'],\n },\n instructions: 'You are a precise JSON generator.',\n tools: [],\n};\n\nexport interface AgentJsonRunnerOptions {\n spec?: AgentSpec;\n model?: LanguageModel;\n provider?: ProviderConfig;\n system?: string;\n toolHandlers?: Map<string, ToolHandler>;\n maxSteps?: number;\n temperature?: number;\n}\n\nexport interface AgentJsonRunner {\n generateJson: (prompt: string) => Promise<string>;\n}\n\nfunction resolveModel(options: AgentJsonRunnerOptions): LanguageModel {\n if (options.model) return options.model;\n if (options.provider) {\n return createProvider(options.provider).getModel();\n }\n throw new Error('createAgentJsonRunner requires a model or provider config');\n}\n\nfunction applyModelSettings(\n model: LanguageModel,\n settings: { temperature?: number }\n): LanguageModel {\n const { temperature } = settings;\n if (temperature === undefined) return model;\n const withSettings = model as LanguageModel & {\n withSettings?: (settings: Record<string, unknown>) => LanguageModel;\n };\n if (typeof withSettings.withSettings === 'function') {\n return withSettings.withSettings({ temperature });\n }\n return model;\n}\n\nfunction buildInstructions(base: string, system?: string): string {\n return [base, JSON_ONLY_RULES, system].filter(Boolean).join('\\n\\n');\n}\n\nfunction ensureToolHandlers(\n spec: AgentSpec,\n handlers: Map<string, ToolHandler>\n): void {\n for (const tool of spec.tools) {\n if (!handlers.has(tool.name)) {\n throw new Error(`Missing handler for tool: ${tool.name}`);\n }\n }\n}\n\nexport async function createAgentJsonRunner(\n options: AgentJsonRunnerOptions\n): Promise<AgentJsonRunner> {\n const model = applyModelSettings(resolveModel(options), {\n temperature: options.temperature ?? 0,\n });\n const baseSpec = options.spec ?? DEFAULT_SPEC;\n const spec: AgentSpec = {\n ...baseSpec,\n instructions: buildInstructions(baseSpec.instructions, options.system),\n maxSteps: options.maxSteps ?? baseSpec.maxSteps,\n };\n\n const toolHandlers = options.toolHandlers ?? new Map<string, ToolHandler>();\n ensureToolHandlers(spec, toolHandlers);\n\n const agent = await ContractSpecAgent.create({\n spec,\n model,\n toolHandlers,\n });\n\n return {\n async generateJson(prompt: string) {\n const result = await agent.generate({ prompt });\n return result.text;\n },\n };\n}\n"],"mappings":";;;;;AAQA,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACD,CAAC,KAAK,KAAK;AAEZ,MAAM,eAA0B;CAC9B,MAAM;EACJ,KAAK;EACL,SAAS;EACT,aAAa;EACb,WAAW,cAAc;EACzB,QAAQ,CAAC,gBAAgB;EACzB,MAAM,CAAC,QAAQ,QAAQ;EACxB;CACD,cAAc;CACd,OAAO,EAAE;CACV;AAgBD,SAAS,aAAa,SAAgD;AACpE,KAAI,QAAQ,MAAO,QAAO,QAAQ;AAClC,KAAI,QAAQ,SACV,QAAO,eAAe,QAAQ,SAAS,CAAC,UAAU;AAEpD,OAAM,IAAI,MAAM,4DAA4D;;AAG9E,SAAS,mBACP,OACA,UACe;CACf,MAAM,EAAE,gBAAgB;AACxB,KAAI,gBAAgB,OAAW,QAAO;CACtC,MAAM,eAAe;AAGrB,KAAI,OAAO,aAAa,iBAAiB,WACvC,QAAO,aAAa,aAAa,EAAE,aAAa,CAAC;AAEnD,QAAO;;AAGT,SAAS,kBAAkB,MAAc,QAAyB;AAChE,QAAO;EAAC;EAAM;EAAiB;EAAO,CAAC,OAAO,QAAQ,CAAC,KAAK,OAAO;;AAGrE,SAAS,mBACP,MACA,UACM;AACN,MAAK,MAAM,QAAQ,KAAK,MACtB,KAAI,CAAC,SAAS,IAAI,KAAK,KAAK,CAC1B,OAAM,IAAI,MAAM,6BAA6B,KAAK,OAAO;;AAK/D,eAAsB,sBACpB,SAC0B;CAC1B,MAAM,QAAQ,mBAAmB,aAAa,QAAQ,EAAE,EACtD,aAAa,QAAQ,eAAe,GACrC,CAAC;CACF,MAAM,WAAW,QAAQ,QAAQ;CACjC,MAAM,OAAkB;EACtB,GAAG;EACH,cAAc,kBAAkB,SAAS,cAAc,QAAQ,OAAO;EACtE,UAAU,QAAQ,YAAY,SAAS;EACxC;CAED,MAAM,eAAe,QAAQ,gCAAgB,IAAI,KAA0B;AAC3E,oBAAmB,MAAM,aAAa;CAEtC,MAAM,QAAQ,MAAM,kBAAkB,OAAO;EAC3C;EACA;EACA;EACD,CAAC;AAEF,QAAO,EACL,MAAM,aAAa,QAAgB;AAEjC,UADe,MAAM,MAAM,SAAS,EAAE,QAAQ,CAAC,EACjC;IAEjB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unified-agent.js","names":[],"sources":["../../src/agent/unified-agent.ts"],"sourcesContent":["/**\n * Unified Agent Wrapper\n *\n * Provides a single API surface for running agents regardless of backend:\n * - AI SDK v6 (existing ContractSpec implementation)\n * - Claude Agent SDK (@anthropic-ai/claude-agent-sdk)\n * - OpenCode SDK (@opencode-ai/sdk)\n *\n * @example\n * ```typescript\n * import { UnifiedAgent, createUnifiedAgent } from '@contractspec/lib.ai-agent';\n *\n * // Create agent with AI SDK backend (default)\n * const agent = createUnifiedAgent(mySpec, {\n * backend: 'ai-sdk',\n * });\n *\n * // Create agent with Claude Agent SDK backend\n * const claudeAgent = createUnifiedAgent(mySpec, {\n * backend: 'claude-agent-sdk',\n * config: { extendedThinking: true },\n * });\n *\n * // All agents use the same API\n * const response = await agent.run('Hello');\n * ```\n */\nimport type { LanguageModel } from 'ai';\nimport type { ProviderConfig } from '@contractspec/lib.ai-providers/types';\nimport { createProvider } from '@contractspec/lib.ai-providers/factory';\nimport type { AgentSpec } from '../spec/spec';\nimport type {\n AgentCallOptions,\n AgentGenerateResult,\n ToolHandler,\n LanguageModelUsage,\n} from '../types';\nimport type {\n ExternalAgentProvider,\n ClaudeAgentSDKConfig,\n OpenCodeSDKConfig,\n ExternalExecuteResult,\n} from '../providers/types';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Supported backend types */\nexport type UnifiedAgentBackend =\n | 'ai-sdk'\n | 'claude-agent-sdk'\n | 'opencode-sdk';\n\n/** Backend-specific configuration */\nexport interface UnifiedAgentBackendConfig {\n 'ai-sdk'?: {\n model?: string;\n modelInstance?: LanguageModel;\n provider?: ProviderConfig;\n temperature?: number;\n maxTokens?: number;\n };\n 'claude-agent-sdk'?: ClaudeAgentSDKConfig;\n 'opencode-sdk'?: OpenCodeSDKConfig;\n}\n\n/** Unified agent configuration */\nexport interface UnifiedAgentConfig {\n /** Backend to use */\n backend: UnifiedAgentBackend;\n /** Backend-specific configuration */\n config?: UnifiedAgentBackendConfig[UnifiedAgentBackend];\n /** Tool handlers for the agent */\n tools?: Map<string, ToolHandler>;\n /** Fallback backend if primary fails */\n fallbackBackend?: UnifiedAgentBackend;\n /** Enable verbose logging */\n verbose?: boolean;\n}\n\n/** Unified agent run options */\nexport interface UnifiedAgentRunOptions extends AgentCallOptions {\n /** Override backend for this call */\n backend?: UnifiedAgentBackend;\n}\n\n/** Unified agent state */\nexport interface UnifiedAgentState {\n backend: UnifiedAgentBackend;\n isReady: boolean;\n sessionId?: string;\n messageCount: number;\n lastError?: Error;\n}\n\n// =============================================================================\n// Unified Agent Implementation\n// =============================================================================\n\n/**\n * Unified agent that works across multiple backends.\n */\nexport class UnifiedAgent {\n private readonly spec: AgentSpec;\n private readonly config: UnifiedAgentConfig;\n private readonly tools: Map<string, ToolHandler>;\n private provider?: ExternalAgentProvider;\n private context?: unknown;\n private state: UnifiedAgentState;\n\n constructor(spec: AgentSpec, config: UnifiedAgentConfig) {\n this.spec = spec;\n this.config = config;\n this.tools = config.tools ?? new Map();\n this.state = {\n backend: config.backend,\n isReady: false,\n messageCount: 0,\n };\n }\n\n /**\n * Initialize the agent with its backend.\n */\n async initialize(): Promise<void> {\n const backend = this.config.backend;\n\n try {\n switch (backend) {\n case 'ai-sdk':\n // AI SDK is always available\n this.state.isReady = true;\n break;\n\n case 'claude-agent-sdk':\n await this.initializeClaudeAgentSDK();\n break;\n\n case 'opencode-sdk':\n await this.initializeOpenCodeSDK();\n break;\n\n default:\n throw new Error(`Unknown backend: ${backend}`);\n }\n } catch (error) {\n this.state.lastError =\n error instanceof Error ? error : new Error(String(error));\n\n // Try fallback if configured\n if (\n this.config.fallbackBackend &&\n this.config.fallbackBackend !== backend\n ) {\n console.warn(\n `[UnifiedAgent] ${backend} failed, falling back to ${this.config.fallbackBackend}`\n );\n this.state.backend = this.config.fallbackBackend;\n await this.initialize();\n } else {\n throw error;\n }\n }\n }\n\n private async initializeClaudeAgentSDK(): Promise<void> {\n // Dynamic import to avoid requiring the dependency\n try {\n const { ClaudeAgentSDKProvider } =\n await import('../providers/claude-agent-sdk');\n const config = this.config.config as ClaudeAgentSDKConfig | undefined;\n this.provider = new ClaudeAgentSDKProvider(config ?? {});\n\n if (!this.provider.isAvailable()) {\n throw new Error(\n 'Claude Agent SDK not available. Install @anthropic-ai/claude-agent-sdk'\n );\n }\n\n this.context = await this.provider.createContext(this.spec);\n this.state.isReady = true;\n } catch (error) {\n if ((error as { code?: string }).code === 'MODULE_NOT_FOUND') {\n throw new Error(\n 'Claude Agent SDK not installed. Run: npm install @anthropic-ai/claude-agent-sdk'\n );\n }\n throw error;\n }\n }\n\n private async initializeOpenCodeSDK(): Promise<void> {\n // Dynamic import to avoid requiring the dependency\n try {\n const { OpenCodeSDKProvider } = await import('../providers/opencode-sdk');\n const config = this.config.config as OpenCodeSDKConfig | undefined;\n this.provider = new OpenCodeSDKProvider(config ?? {});\n\n if (!this.provider.isAvailable()) {\n throw new Error('OpenCode SDK not available. Install @opencode-ai/sdk');\n }\n\n this.context = await this.provider.createContext(this.spec);\n this.state.isReady = true;\n } catch (error) {\n if ((error as { code?: string }).code === 'MODULE_NOT_FOUND') {\n throw new Error(\n 'OpenCode SDK not installed. Run: npm install @opencode-ai/sdk'\n );\n }\n throw error;\n }\n }\n\n /**\n * Run the agent with a message.\n */\n async run(\n message: string,\n options?: UnifiedAgentRunOptions\n ): Promise<AgentGenerateResult> {\n if (!this.state.isReady) {\n await this.initialize();\n }\n\n const backend = options?.backend ?? this.state.backend;\n this.state.messageCount++;\n\n try {\n switch (backend) {\n case 'ai-sdk':\n return await this.runWithAISDK(message, options);\n\n case 'claude-agent-sdk':\n case 'opencode-sdk':\n return await this.runWithExternalProvider(message, options);\n\n default:\n throw new Error(`Unknown backend: ${backend}`);\n }\n } catch (error) {\n this.state.lastError =\n error instanceof Error ? error : new Error(String(error));\n throw error;\n }\n }\n\n private async runWithAISDK(\n message: string,\n options?: UnifiedAgentRunOptions\n ): Promise<AgentGenerateResult> {\n // Import the existing ContractSpec agent factory\n const { ContractSpecAgent } = await import('./contract-spec-agent');\n const model = await this.resolveAISDKModel();\n const agent = await ContractSpecAgent.create({\n spec: this.spec,\n model,\n toolHandlers: this.tools,\n });\n\n return await agent.generate({\n prompt: message,\n options,\n });\n }\n\n private async runWithExternalProvider(\n message: string,\n options?: UnifiedAgentRunOptions\n ): Promise<AgentGenerateResult> {\n if (!this.provider || !this.context) {\n throw new Error('Provider not initialized');\n }\n\n const result: ExternalExecuteResult = await this.provider.execute(\n this.context as Parameters<ExternalAgentProvider['execute']>[0],\n {\n prompt: message,\n options,\n }\n );\n\n return this.convertExternalResult(result);\n }\n\n private convertExternalResult(\n result: ExternalExecuteResult\n ): AgentGenerateResult {\n return {\n text: result.text,\n steps: [],\n toolCalls: result.toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n args: tc.args,\n })),\n toolResults: result.toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.toolCallId,\n toolName: tr.toolName,\n output: tr.output,\n })),\n finishReason: result.finishReason,\n usage: result.usage\n ? ({\n promptTokens: result.usage.inputTokens,\n completionTokens: result.usage.outputTokens,\n totalTokens:\n result.usage.totalTokens ??\n result.usage.inputTokens + result.usage.outputTokens,\n } as unknown as LanguageModelUsage)\n : undefined,\n };\n }\n\n private getAISDKConfig(): UnifiedAgentBackendConfig['ai-sdk'] | undefined {\n if (this.config.backend !== 'ai-sdk') return undefined;\n return this.config.config as UnifiedAgentBackendConfig['ai-sdk'];\n }\n\n private async resolveAISDKModel(): Promise<LanguageModel> {\n const backendConfig = this.getAISDKConfig();\n let model: LanguageModel;\n\n if (backendConfig?.modelInstance) {\n model = backendConfig.modelInstance;\n } else if (backendConfig?.provider) {\n model = createProvider(backendConfig.provider).getModel();\n } else {\n const { anthropic } = await import('@ai-sdk/anthropic');\n model = anthropic(backendConfig?.model ?? 'claude-3-5-sonnet-20240620');\n }\n\n return this.applyModelSettings(model, {\n temperature: backendConfig?.temperature,\n maxTokens: backendConfig?.maxTokens,\n });\n }\n\n private applyModelSettings(\n model: LanguageModel,\n settings: { temperature?: number; maxTokens?: number }\n ): LanguageModel {\n if (\n settings.temperature === undefined &&\n settings.maxTokens === undefined\n ) {\n return model;\n }\n\n const withSettings = model as LanguageModel & {\n withSettings?: (settings: Record<string, unknown>) => LanguageModel;\n };\n\n if (typeof withSettings.withSettings === 'function') {\n return withSettings.withSettings({\n temperature: settings.temperature,\n maxTokens: settings.maxTokens,\n });\n }\n\n return model;\n }\n\n /**\n * Get agent state.\n */\n getState(): UnifiedAgentState {\n return { ...this.state };\n }\n\n /**\n * Get the agent spec.\n */\n getSpec(): AgentSpec {\n return this.spec;\n }\n\n /**\n * Get the current backend.\n */\n getBackend(): UnifiedAgentBackend {\n return this.state.backend;\n }\n\n /**\n * Check if a specific backend is available.\n */\n async isBackendAvailable(backend: UnifiedAgentBackend): Promise<boolean> {\n switch (backend) {\n case 'ai-sdk':\n return true;\n\n case 'claude-agent-sdk':\n try {\n const { ClaudeAgentSDKProvider } =\n await import('../providers/claude-agent-sdk');\n const provider = new ClaudeAgentSDKProvider({});\n return provider.isAvailable();\n } catch {\n return false;\n }\n\n case 'opencode-sdk':\n try {\n const { OpenCodeSDKProvider } =\n await import('../providers/opencode-sdk');\n const provider = new OpenCodeSDKProvider({});\n return provider.isAvailable();\n } catch {\n return false;\n }\n\n default:\n return false;\n }\n }\n\n /**\n * Switch to a different backend.\n */\n async switchBackend(backend: UnifiedAgentBackend): Promise<void> {\n if (backend === this.state.backend) {\n return;\n }\n\n this.state.backend = backend;\n this.state.isReady = false;\n this.provider = undefined;\n this.context = undefined;\n\n await this.initialize();\n }\n\n /**\n * Reset the agent state.\n */\n reset(): void {\n this.state.messageCount = 0;\n this.state.sessionId = undefined;\n this.state.lastError = undefined;\n this.context = undefined;\n }\n\n /**\n * Add a tool handler.\n */\n addTool(name: string, handler: ToolHandler): void {\n this.tools.set(name, handler);\n }\n\n /**\n * Remove a tool handler.\n */\n removeTool(name: string): boolean {\n return this.tools.delete(name);\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a unified agent.\n */\nexport function createUnifiedAgent(\n spec: AgentSpec,\n config: UnifiedAgentConfig\n): UnifiedAgent {\n return new UnifiedAgent(spec, config);\n}\n\n/**\n * Create a unified agent with AI SDK backend (default).\n */\nexport function createAISDKAgent(\n spec: AgentSpec,\n options?: {\n tools?: Map<string, ToolHandler>;\n model?: string;\n modelInstance?: LanguageModel;\n provider?: ProviderConfig;\n temperature?: number;\n maxTokens?: number;\n }\n): UnifiedAgent {\n return new UnifiedAgent(spec, {\n backend: 'ai-sdk',\n tools: options?.tools,\n config: {\n model: options?.model,\n modelInstance: options?.modelInstance,\n provider: options?.provider,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n },\n });\n}\n\n/**\n * Create a unified agent with Claude Agent SDK backend.\n */\nexport function createClaudeAgentSDKAgent(\n spec: AgentSpec,\n config?: ClaudeAgentSDKConfig & {\n tools?: Map<string, ToolHandler>;\n }\n): UnifiedAgent {\n const { tools, ...sdkConfig } = config ?? {};\n return new UnifiedAgent(spec, {\n backend: 'claude-agent-sdk',\n tools,\n config: sdkConfig,\n });\n}\n\n/**\n * Create a unified agent with OpenCode SDK backend.\n */\nexport function createOpenCodeSDKAgent(\n spec: AgentSpec,\n config?: OpenCodeSDKConfig & {\n tools?: Map<string, ToolHandler>;\n }\n): UnifiedAgent {\n const { tools, ...sdkConfig } = config ?? {};\n return new UnifiedAgent(spec, {\n backend: 'opencode-sdk',\n tools,\n config: sdkConfig,\n });\n}\n\n/**\n * Get available backends.\n */\nexport async function getAvailableBackends(): Promise<UnifiedAgentBackend[]> {\n const backends: UnifiedAgentBackend[] = ['ai-sdk'];\n\n try {\n const { ClaudeAgentSDKProvider } =\n await import('../providers/claude-agent-sdk');\n const provider = new ClaudeAgentSDKProvider({});\n if (provider.isAvailable()) {\n backends.push('claude-agent-sdk');\n }\n } catch {\n // Not available\n }\n\n try {\n const { OpenCodeSDKProvider } = await import('../providers/opencode-sdk');\n const provider = new OpenCodeSDKProvider({});\n if (provider.isAvailable()) {\n backends.push('opencode-sdk');\n }\n } catch {\n // Not available\n }\n\n return backends;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.js","names":[],"sources":["../../src/approval/workflow.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { ToolCallInfo } from '../types';\n\nexport type ApprovalStatus = 'pending' | 'approved' | 'rejected';\n\n/**\n * Approval request for a tool execution.\n *\n * When a tool has `needsApproval: true` in AI SDK v6, the agent\n * will pause and wait for approval before executing the tool.\n */\nexport interface ApprovalRequest {\n /** Unique request ID */\n id: string;\n /** Agent session ID */\n sessionId: string;\n /** Agent ID */\n agentId: string;\n /** Tenant ID for scoping */\n tenantId?: string;\n /** Tool name requiring approval */\n toolName: string;\n /** Tool call ID from AI SDK */\n toolCallId: string;\n /** Tool arguments */\n toolArgs: unknown;\n /** Human-readable reason for approval */\n reason: string;\n /** When the approval was requested */\n requestedAt: Date;\n /** Current status */\n status: ApprovalStatus;\n /** Additional context payload */\n payload?: Record<string, unknown>;\n /** Who resolved the approval */\n reviewer?: string;\n /** When the approval was resolved */\n resolvedAt?: Date;\n /** Reviewer notes */\n notes?: string;\n}\n\n/**\n * Storage interface for approval requests.\n */\nexport interface ApprovalStore {\n create(request: ApprovalRequest): Promise<void>;\n get(id: string): Promise<ApprovalRequest | null>;\n getByToolCallId(toolCallId: string): Promise<ApprovalRequest | null>;\n update(\n id: string,\n updates: Partial<Omit<ApprovalRequest, 'id' | 'sessionId'>>\n ): Promise<void>;\n list(options?: {\n status?: ApprovalStatus;\n agentId?: string;\n tenantId?: string;\n }): Promise<ApprovalRequest[]>;\n}\n\n/**\n * In-memory approval store for development and testing.\n */\nexport class InMemoryApprovalStore implements ApprovalStore {\n private readonly items = new Map<string, ApprovalRequest>();\n\n async create(request: ApprovalRequest): Promise<void> {\n this.items.set(request.id, request);\n }\n\n async get(id: string): Promise<ApprovalRequest | null> {\n return this.items.get(id) ?? null;\n }\n\n async getByToolCallId(toolCallId: string): Promise<ApprovalRequest | null> {\n for (const request of this.items.values()) {\n if (request.toolCallId === toolCallId) {\n return request;\n }\n }\n return null;\n }\n\n async update(\n id: string,\n updates: Partial<Omit<ApprovalRequest, 'id' | 'sessionId'>>\n ): Promise<void> {\n const existing = this.items.get(id);\n if (existing) {\n this.items.set(id, { ...existing, ...updates });\n }\n }\n\n async list(options?: {\n status?: ApprovalStatus;\n agentId?: string;\n tenantId?: string;\n }): Promise<ApprovalRequest[]> {\n let results = [...this.items.values()];\n\n if (options?.status) {\n results = results.filter((r) => r.status === options.status);\n }\n if (options?.agentId) {\n results = results.filter((r) => r.agentId === options.agentId);\n }\n if (options?.tenantId) {\n results = results.filter((r) => r.tenantId === options.tenantId);\n }\n\n return results.sort(\n (a, b) => b.requestedAt.getTime() - a.requestedAt.getTime()\n );\n }\n\n clear(): void {\n this.items.clear();\n }\n}\n\n/**\n * Approval workflow for managing tool execution approvals.\n *\n * Integrates with AI SDK v6's `needsApproval` feature on tools.\n *\n * @example\n * ```typescript\n * const workflow = new ApprovalWorkflow();\n *\n * // When a tool needs approval\n * const request = await workflow.requestApproval({\n * sessionId: 'sess_123',\n * agentId: 'support.bot.v1',\n * toolName: 'delete_account',\n * toolCallId: 'call_abc',\n * toolArgs: { userId: 'user_123' },\n * reason: 'Account deletion requires human approval',\n * });\n *\n * // When approval is granted\n * await workflow.approve(request.id, 'admin@example.com', 'Verified identity');\n *\n * // Or rejected\n * await workflow.reject(request.id, 'admin@example.com', 'Suspicious activity');\n * ```\n */\nexport class ApprovalWorkflow {\n constructor(\n private readonly store: ApprovalStore = new InMemoryApprovalStore()\n ) {}\n\n /**\n * Request approval for a tool execution.\n */\n async requestApproval(params: {\n sessionId: string;\n agentId: string;\n tenantId?: string;\n toolName: string;\n toolCallId: string;\n toolArgs: unknown;\n reason: string;\n payload?: Record<string, unknown>;\n }): Promise<ApprovalRequest> {\n const request: ApprovalRequest = {\n id: randomUUID(),\n sessionId: params.sessionId,\n agentId: params.agentId,\n tenantId: params.tenantId,\n toolName: params.toolName,\n toolCallId: params.toolCallId,\n toolArgs: params.toolArgs,\n reason: params.reason,\n requestedAt: new Date(),\n status: 'pending',\n payload: params.payload,\n };\n\n await this.store.create(request);\n return request;\n }\n\n /**\n * Request approval from an AI SDK tool call.\n */\n async requestApprovalFromToolCall(\n toolCall: ToolCallInfo,\n context: {\n sessionId: string;\n agentId: string;\n tenantId?: string;\n reason?: string;\n }\n ): Promise<ApprovalRequest> {\n return this.requestApproval({\n sessionId: context.sessionId,\n agentId: context.agentId,\n tenantId: context.tenantId,\n toolName: toolCall.toolName,\n toolCallId: toolCall.toolCallId,\n toolArgs: toolCall.args,\n reason: context.reason ?? `Tool \"${toolCall.toolName}\" requires approval`,\n });\n }\n\n /**\n * Approve a pending request.\n */\n async approve(id: string, reviewer: string, notes?: string): Promise<void> {\n await this.store.update(id, {\n status: 'approved',\n reviewer,\n resolvedAt: new Date(),\n notes,\n });\n }\n\n /**\n * Reject a pending request.\n */\n async reject(id: string, reviewer: string, notes?: string): Promise<void> {\n await this.store.update(id, {\n status: 'rejected',\n reviewer,\n resolvedAt: new Date(),\n notes,\n });\n }\n\n /**\n * Get approval status for a tool call.\n */\n async getStatus(toolCallId: string): Promise<ApprovalStatus | null> {\n const request = await this.store.getByToolCallId(toolCallId);\n return request?.status ?? null;\n }\n\n /**\n * Check if a tool call is approved.\n */\n async isApproved(toolCallId: string): Promise<boolean> {\n const status = await this.getStatus(toolCallId);\n return status === 'approved';\n }\n\n /**\n * List pending approvals.\n */\n async listPending(options?: {\n agentId?: string;\n tenantId?: string;\n }): Promise<ApprovalRequest[]> {\n return this.store.list({ ...options, status: 'pending' });\n }\n\n /**\n * Get approval request by ID.\n */\n async get(id: string): Promise<ApprovalRequest | null> {\n return this.store.get(id);\n }\n}\n\n/**\n * Create an approval workflow instance.\n */\nexport function createApprovalWorkflow(\n store?: ApprovalStore\n): ApprovalWorkflow {\n return new ApprovalWorkflow(store);\n}\n"],"mappings":";;;;;;AA+DA,IAAa,wBAAb,MAA4D;CAC1D,AAAiB,wBAAQ,IAAI,KAA8B;CAE3D,MAAM,OAAO,SAAyC;AACpD,OAAK,MAAM,IAAI,QAAQ,IAAI,QAAQ;;CAGrC,MAAM,IAAI,IAA6C;AACrD,SAAO,KAAK,MAAM,IAAI,GAAG,IAAI;;CAG/B,MAAM,gBAAgB,YAAqD;AACzE,OAAK,MAAM,WAAW,KAAK,MAAM,QAAQ,CACvC,KAAI,QAAQ,eAAe,WACzB,QAAO;AAGX,SAAO;;CAGT,MAAM,OACJ,IACA,SACe;EACf,MAAM,WAAW,KAAK,MAAM,IAAI,GAAG;AACnC,MAAI,SACF,MAAK,MAAM,IAAI,IAAI;GAAE,GAAG;GAAU,GAAG;GAAS,CAAC;;CAInD,MAAM,KAAK,SAIoB;EAC7B,IAAI,UAAU,CAAC,GAAG,KAAK,MAAM,QAAQ,CAAC;AAEtC,MAAI,SAAS,OACX,WAAU,QAAQ,QAAQ,MAAM,EAAE,WAAW,QAAQ,OAAO;AAE9D,MAAI,SAAS,QACX,WAAU,QAAQ,QAAQ,MAAM,EAAE,YAAY,QAAQ,QAAQ;AAEhE,MAAI,SAAS,SACX,WAAU,QAAQ,QAAQ,MAAM,EAAE,aAAa,QAAQ,SAAS;AAGlE,SAAO,QAAQ,MACZ,GAAG,MAAM,EAAE,YAAY,SAAS,GAAG,EAAE,YAAY,SAAS,CAC5D;;CAGH,QAAc;AACZ,OAAK,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BtB,IAAa,mBAAb,MAA8B;CAC5B,YACE,AAAiB,QAAuB,IAAI,uBAAuB,EACnE;EADiB;;;;;CAMnB,MAAM,gBAAgB,QASO;EAC3B,MAAM,UAA2B;GAC/B,IAAI,YAAY;GAChB,WAAW,OAAO;GAClB,SAAS,OAAO;GAChB,UAAU,OAAO;GACjB,UAAU,OAAO;GACjB,YAAY,OAAO;GACnB,UAAU,OAAO;GACjB,QAAQ,OAAO;GACf,6BAAa,IAAI,MAAM;GACvB,QAAQ;GACR,SAAS,OAAO;GACjB;AAED,QAAM,KAAK,MAAM,OAAO,QAAQ;AAChC,SAAO;;;;;CAMT,MAAM,4BACJ,UACA,SAM0B;AAC1B,SAAO,KAAK,gBAAgB;GAC1B,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB,UAAU,QAAQ;GAClB,UAAU,SAAS;GACnB,YAAY,SAAS;GACrB,UAAU,SAAS;GACnB,QAAQ,QAAQ,UAAU,SAAS,SAAS,SAAS;GACtD,CAAC;;;;;CAMJ,MAAM,QAAQ,IAAY,UAAkB,OAA+B;AACzE,QAAM,KAAK,MAAM,OAAO,IAAI;GAC1B,QAAQ;GACR;GACA,4BAAY,IAAI,MAAM;GACtB;GACD,CAAC;;;;;CAMJ,MAAM,OAAO,IAAY,UAAkB,OAA+B;AACxE,QAAM,KAAK,MAAM,OAAO,IAAI;GAC1B,QAAQ;GACR;GACA,4BAAY,IAAI,MAAM;GACtB;GACD,CAAC;;;;;CAMJ,MAAM,UAAU,YAAoD;AAElE,UADgB,MAAM,KAAK,MAAM,gBAAgB,WAAW,GAC5C,UAAU;;;;;CAM5B,MAAM,WAAW,YAAsC;AAErD,SADe,MAAM,KAAK,UAAU,WAAW,KAC7B;;;;;CAMpB,MAAM,YAAY,SAGa;AAC7B,SAAO,KAAK,MAAM,KAAK;GAAE,GAAG;GAAS,QAAQ;GAAW,CAAC;;;;;CAM3D,MAAM,IAAI,IAA6C;AACrD,SAAO,KAAK,MAAM,IAAI,GAAG;;;;;;AAO7B,SAAgB,uBACd,OACkB;AAClB,QAAO,IAAI,iBAAiB,MAAM"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-agent-exporter.js","names":[],"sources":["../../src/exporters/claude-agent-exporter.ts"],"sourcesContent":["/**\n * Claude Agent SDK Exporter\n *\n * Exports ContractSpec AgentSpec definitions to formats compatible with\n * @anthropic-ai/claude-agent-sdk and Claude Code CLI.\n */\n\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n Exporter,\n ClaudeAgentExportOptions,\n ClaudeAgentExportResult,\n ClaudeAgentConfig,\n ClaudeToolDefinition,\n} from './types';\n\n// ============================================================================\n// Exporter Implementation\n// ============================================================================\n\n/**\n * Claude Agent SDK Exporter.\n */\nexport class ClaudeAgentExporter implements Exporter<\n ClaudeAgentExportOptions,\n ClaudeAgentExportResult\n> {\n readonly format = 'claude-agent' as const;\n\n /**\n * Export an AgentSpec to Claude Agent SDK format.\n */\n export(\n spec: AgentSpec,\n options: ClaudeAgentExportOptions = {}\n ): ClaudeAgentExportResult {\n const tools = this.exportTools(spec);\n const config = this.buildConfig(spec, tools, options);\n const claudeMd = options.generateClaudeMd\n ? this.generateClaudeMd(spec, options)\n : undefined;\n\n return {\n config,\n claudeMd,\n tools,\n exportedAt: new Date(),\n sourceSpec: agentKey(spec.meta),\n };\n }\n\n /**\n * Export multiple specs.\n */\n exportMany(\n specs: AgentSpec[],\n options: ClaudeAgentExportOptions = {}\n ): ClaudeAgentExportResult[] {\n return specs.map((spec) => this.export(spec, options));\n }\n\n /**\n * Validate that a spec can be exported.\n */\n validate(spec: AgentSpec): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n if (!spec.meta?.key) {\n errors.push('Spec must have a meta.key');\n }\n\n if (!spec.instructions) {\n errors.push('Spec must have instructions');\n }\n\n if (!spec.tools || spec.tools.length === 0) {\n errors.push('Spec must have at least one tool');\n }\n\n for (const tool of spec.tools ?? []) {\n if (!tool.name) {\n errors.push('All tools must have a name');\n }\n if (!tool.description && !tool.name) {\n errors.push(`Tool must have a description or name`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Build Claude Agent SDK configuration.\n */\n private buildConfig(\n spec: AgentSpec,\n tools: ClaudeToolDefinition[],\n options: ClaudeAgentExportOptions\n ): ClaudeAgentConfig {\n const config: ClaudeAgentConfig = {\n model: options.model ?? 'claude-sonnet-4-20250514',\n system: this.buildSystemPrompt(spec, options),\n tools,\n max_turns: spec.maxSteps ?? 10,\n };\n\n if (options.computerUse) {\n config.computer_use = true;\n }\n\n if (options.extendedThinking) {\n config.extended_thinking = true;\n }\n\n if (options.mcpServers && options.mcpServers.length > 0) {\n config.mcp_servers = options.mcpServers;\n }\n\n return config;\n }\n\n /**\n * Build system prompt from spec.\n */\n private buildSystemPrompt(\n spec: AgentSpec,\n options: ClaudeAgentExportOptions\n ): string {\n const parts: string[] = [];\n\n // Base instructions\n parts.push(spec.instructions);\n\n // Add knowledge context if available\n if (spec.knowledge && spec.knowledge.length > 0) {\n parts.push('');\n parts.push('## Knowledge Sources');\n for (const k of spec.knowledge) {\n if (k.instructions) {\n parts.push(`- ${k.key}: ${k.instructions}`);\n }\n }\n }\n\n // Add policy information if available\n if (spec.policy) {\n parts.push('');\n parts.push('## Policy');\n if (spec.policy.confidence?.min) {\n parts.push(`- Minimum confidence: ${spec.policy.confidence.min}`);\n }\n if (spec.policy.escalation) {\n parts.push('- Escalation policy is configured');\n }\n }\n\n // Add custom metadata if provided\n if (options.metadata) {\n parts.push('');\n parts.push('## Additional Context');\n for (const [key, value] of Object.entries(options.metadata)) {\n parts.push(`- ${key}: ${String(value)}`);\n }\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Export tools to Claude Agent SDK format.\n */\n private exportTools(spec: AgentSpec): ClaudeToolDefinition[] {\n return spec.tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n input_schema: this.normalizeSchema(tool.schema),\n requires_confirmation: tool.requiresApproval ?? !tool.automationSafe,\n }));\n }\n\n /**\n * Normalize schema to Claude Agent SDK format.\n */\n private normalizeSchema(\n schema?: Record<string, unknown>\n ): ClaudeToolDefinition['input_schema'] {\n if (!schema) {\n return { type: 'object' };\n }\n\n if (schema.type === 'object') {\n return {\n type: 'object',\n properties: schema.properties as Record<string, unknown> | undefined,\n required: schema.required as string[] | undefined,\n };\n }\n\n // Wrap non-object schemas\n return {\n type: 'object',\n properties: { value: schema },\n required: ['value'],\n };\n }\n\n /**\n * Generate CLAUDE.md content for Claude Code CLI integration.\n */\n private generateClaudeMd(\n spec: AgentSpec,\n options: ClaudeAgentExportOptions\n ): string {\n const lines: string[] = [];\n\n // Header\n lines.push('# Agent Configuration');\n lines.push('');\n\n // Description\n if (spec.description) {\n lines.push(`> ${spec.description}`);\n lines.push('');\n }\n\n // Metadata\n lines.push('## Metadata');\n lines.push('');\n lines.push(`- **Name**: ${spec.meta.key}`);\n lines.push(`- **Version**: ${spec.meta.version}`);\n if (spec.meta.owners && spec.meta.owners.length > 0) {\n lines.push(`- **Owners**: ${spec.meta.owners.join(', ')}`);\n }\n if (options.model) {\n lines.push(`- **Model**: ${options.model}`);\n }\n lines.push('');\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('## Available Tools');\n lines.push('');\n for (const tool of spec.tools) {\n const flags: string[] = [];\n if (tool.requiresApproval) {\n flags.push('requires approval');\n }\n if (tool.automationSafe === false) {\n flags.push('not automation safe');\n }\n const flagStr = flags.length > 0 ? ` (${flags.join(', ')})` : '';\n\n lines.push(`### ${tool.name}${flagStr}`);\n lines.push('');\n if (tool.description) {\n lines.push(tool.description);\n lines.push('');\n }\n if (tool.schema) {\n lines.push('**Parameters:**');\n lines.push('```json');\n lines.push(JSON.stringify(tool.schema, null, 2));\n lines.push('```');\n lines.push('');\n }\n }\n }\n\n // Knowledge\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 if (k.instructions) {\n lines.push(` - ${k.instructions}`);\n }\n }\n lines.push('');\n }\n\n // Policy\n if (spec.policy) {\n lines.push('## Policy');\n lines.push('');\n if (spec.policy.confidence?.min) {\n lines.push(`- Minimum confidence: ${spec.policy.confidence.min}`);\n }\n if (spec.policy.escalation) {\n lines.push('- Escalation policy configured');\n }\n if (spec.policy.flags && spec.policy.flags.length > 0) {\n lines.push(`- Feature flags: ${spec.policy.flags.join(', ')}`);\n }\n lines.push('');\n }\n\n // MCP Servers\n if (options.mcpServers && options.mcpServers.length > 0) {\n lines.push('## MCP Servers');\n lines.push('');\n for (const server of options.mcpServers) {\n lines.push(\n `- **${server.name}**: \\`${server.command}${server.args ? ' ' + server.args.join(' ') : ''}\\``\n );\n }\n lines.push('');\n }\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push(`*Generated from ContractSpec: ${agentKey(spec.meta)}*`);\n\n return lines.join('\\n');\n }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Export an AgentSpec to Claude Agent SDK format.\n */\nexport function exportToClaudeAgent(\n spec: AgentSpec,\n options?: ClaudeAgentExportOptions\n): ClaudeAgentExportResult {\n const exporter = new ClaudeAgentExporter();\n return exporter.export(spec, options);\n}\n\n/**\n * Generate CLAUDE.md content from an AgentSpec.\n */\nexport function generateClaudeMd(\n spec: AgentSpec,\n options?: Omit<ClaudeAgentExportOptions, 'generateClaudeMd'>\n): string {\n const exporter = new ClaudeAgentExporter();\n const result = exporter.export(spec, { ...options, generateClaudeMd: true });\n return result.claudeMd ?? '';\n}\n\n/**\n * Validate an AgentSpec for Claude Agent SDK export.\n */\nexport function validateForClaudeAgent(spec: AgentSpec): {\n valid: boolean;\n errors: string[];\n} {\n const exporter = new ClaudeAgentExporter();\n return exporter.validate(spec);\n}\n"],"mappings":";;;;;;AAwBA,IAAa,sBAAb,MAGE;CACA,AAAS,SAAS;;;;CAKlB,OACE,MACA,UAAoC,EAAE,EACb;EACzB,MAAM,QAAQ,KAAK,YAAY,KAAK;AAMpC,SAAO;GACL,QANa,KAAK,YAAY,MAAM,OAAO,QAAQ;GAOnD,UANe,QAAQ,mBACrB,KAAK,iBAAiB,MAAM,QAAQ,GACpC;GAKF;GACA,4BAAY,IAAI,MAAM;GACtB,YAAY,SAAS,KAAK,KAAK;GAChC;;;;;CAMH,WACE,OACA,UAAoC,EAAE,EACX;AAC3B,SAAO,MAAM,KAAK,SAAS,KAAK,OAAO,MAAM,QAAQ,CAAC;;;;;CAMxD,SAAS,MAAuD;EAC9D,MAAM,SAAmB,EAAE;AAE3B,MAAI,CAAC,KAAK,MAAM,IACd,QAAO,KAAK,4BAA4B;AAG1C,MAAI,CAAC,KAAK,aACR,QAAO,KAAK,8BAA8B;AAG5C,MAAI,CAAC,KAAK,SAAS,KAAK,MAAM,WAAW,EACvC,QAAO,KAAK,mCAAmC;AAGjD,OAAK,MAAM,QAAQ,KAAK,SAAS,EAAE,EAAE;AACnC,OAAI,CAAC,KAAK,KACR,QAAO,KAAK,6BAA6B;AAE3C,OAAI,CAAC,KAAK,eAAe,CAAC,KAAK,KAC7B,QAAO,KAAK,uCAAuC;;AAIvD,SAAO;GAAE,OAAO,OAAO,WAAW;GAAG;GAAQ;;;;;CAU/C,AAAQ,YACN,MACA,OACA,SACmB;EACnB,MAAM,SAA4B;GAChC,OAAO,QAAQ,SAAS;GACxB,QAAQ,KAAK,kBAAkB,MAAM,QAAQ;GAC7C;GACA,WAAW,KAAK,YAAY;GAC7B;AAED,MAAI,QAAQ,YACV,QAAO,eAAe;AAGxB,MAAI,QAAQ,iBACV,QAAO,oBAAoB;AAG7B,MAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,EACpD,QAAO,cAAc,QAAQ;AAG/B,SAAO;;;;;CAMT,AAAQ,kBACN,MACA,SACQ;EACR,MAAM,QAAkB,EAAE;AAG1B,QAAM,KAAK,KAAK,aAAa;AAG7B,MAAI,KAAK,aAAa,KAAK,UAAU,SAAS,GAAG;AAC/C,SAAM,KAAK,GAAG;AACd,SAAM,KAAK,uBAAuB;AAClC,QAAK,MAAM,KAAK,KAAK,UACnB,KAAI,EAAE,aACJ,OAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,eAAe;;AAMjD,MAAI,KAAK,QAAQ;AACf,SAAM,KAAK,GAAG;AACd,SAAM,KAAK,YAAY;AACvB,OAAI,KAAK,OAAO,YAAY,IAC1B,OAAM,KAAK,yBAAyB,KAAK,OAAO,WAAW,MAAM;AAEnE,OAAI,KAAK,OAAO,WACd,OAAM,KAAK,oCAAoC;;AAKnD,MAAI,QAAQ,UAAU;AACpB,SAAM,KAAK,GAAG;AACd,SAAM,KAAK,wBAAwB;AACnC,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,SAAS,CACzD,OAAM,KAAK,KAAK,IAAI,IAAI,OAAO,MAAM,GAAG;;AAI5C,SAAO,MAAM,KAAK,KAAK;;;;;CAMzB,AAAQ,YAAY,MAAyC;AAC3D,SAAO,KAAK,MAAM,KAAK,UAAU;GAC/B,MAAM,KAAK;GACX,aAAa,KAAK,eAAe,WAAW,KAAK;GACjD,cAAc,KAAK,gBAAgB,KAAK,OAAO;GAC/C,uBAAuB,KAAK,oBAAoB,CAAC,KAAK;GACvD,EAAE;;;;;CAML,AAAQ,gBACN,QACsC;AACtC,MAAI,CAAC,OACH,QAAO,EAAE,MAAM,UAAU;AAG3B,MAAI,OAAO,SAAS,SAClB,QAAO;GACL,MAAM;GACN,YAAY,OAAO;GACnB,UAAU,OAAO;GAClB;AAIH,SAAO;GACL,MAAM;GACN,YAAY,EAAE,OAAO,QAAQ;GAC7B,UAAU,CAAC,QAAQ;GACpB;;;;;CAMH,AAAQ,iBACN,MACA,SACQ;EACR,MAAM,QAAkB,EAAE;AAG1B,QAAM,KAAK,wBAAwB;AACnC,QAAM,KAAK,GAAG;AAGd,MAAI,KAAK,aAAa;AACpB,SAAM,KAAK,KAAK,KAAK,cAAc;AACnC,SAAM,KAAK,GAAG;;AAIhB,QAAM,KAAK,cAAc;AACzB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,eAAe,KAAK,KAAK,MAAM;AAC1C,QAAM,KAAK,kBAAkB,KAAK,KAAK,UAAU;AACjD,MAAI,KAAK,KAAK,UAAU,KAAK,KAAK,OAAO,SAAS,EAChD,OAAM,KAAK,iBAAiB,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAE5D,MAAI,QAAQ,MACV,OAAM,KAAK,gBAAgB,QAAQ,QAAQ;AAE7C,QAAM,KAAK,GAAG;AAGd,QAAM,KAAK,kBAAkB;AAC7B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,KAAK,aAAa;AAC7B,QAAM,KAAK,GAAG;AAGd,MAAI,KAAK,MAAM,SAAS,GAAG;AACzB,SAAM,KAAK,qBAAqB;AAChC,SAAM,KAAK,GAAG;AACd,QAAK,MAAM,QAAQ,KAAK,OAAO;IAC7B,MAAM,QAAkB,EAAE;AAC1B,QAAI,KAAK,iBACP,OAAM,KAAK,oBAAoB;AAEjC,QAAI,KAAK,mBAAmB,MAC1B,OAAM,KAAK,sBAAsB;IAEnC,MAAM,UAAU,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,KAAK,CAAC,KAAK;AAE9D,UAAM,KAAK,OAAO,KAAK,OAAO,UAAU;AACxC,UAAM,KAAK,GAAG;AACd,QAAI,KAAK,aAAa;AACpB,WAAM,KAAK,KAAK,YAAY;AAC5B,WAAM,KAAK,GAAG;;AAEhB,QAAI,KAAK,QAAQ;AACf,WAAM,KAAK,kBAAkB;AAC7B,WAAM,KAAK,UAAU;AACrB,WAAM,KAAK,KAAK,UAAU,KAAK,QAAQ,MAAM,EAAE,CAAC;AAChD,WAAM,KAAK,MAAM;AACjB,WAAM,KAAK,GAAG;;;;AAMpB,MAAI,KAAK,aAAa,KAAK,UAAU,SAAS,GAAG;AAC/C,SAAM,KAAK,uBAAuB;AAClC,SAAM,KAAK,GAAG;AACd,QAAK,MAAM,KAAK,KAAK,WAAW;IAC9B,MAAM,WAAW,EAAE,WAAW,eAAe;AAC7C,UAAM,KAAK,OAAO,EAAE,IAAI,KAAK,WAAW;AACxC,QAAI,EAAE,aACJ,OAAM,KAAK,OAAO,EAAE,eAAe;;AAGvC,SAAM,KAAK,GAAG;;AAIhB,MAAI,KAAK,QAAQ;AACf,SAAM,KAAK,YAAY;AACvB,SAAM,KAAK,GAAG;AACd,OAAI,KAAK,OAAO,YAAY,IAC1B,OAAM,KAAK,yBAAyB,KAAK,OAAO,WAAW,MAAM;AAEnE,OAAI,KAAK,OAAO,WACd,OAAM,KAAK,iCAAiC;AAE9C,OAAI,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM,SAAS,EAClD,OAAM,KAAK,oBAAoB,KAAK,OAAO,MAAM,KAAK,KAAK,GAAG;AAEhE,SAAM,KAAK,GAAG;;AAIhB,MAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,GAAG;AACvD,SAAM,KAAK,iBAAiB;AAC5B,SAAM,KAAK,GAAG;AACd,QAAK,MAAM,UAAU,QAAQ,WAC3B,OAAM,KACJ,OAAO,OAAO,KAAK,QAAQ,OAAO,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK,KAAK,IAAI,GAAG,GAAG,IAC5F;AAEH,SAAM,KAAK,GAAG;;AAIhB,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,iCAAiC,SAAS,KAAK,KAAK,CAAC,GAAG;AAEnE,SAAO,MAAM,KAAK,KAAK;;;;;;AAW3B,SAAgB,oBACd,MACA,SACyB;AAEzB,QADiB,IAAI,qBAAqB,CAC1B,OAAO,MAAM,QAAQ;;;;;AAMvC,SAAgB,iBACd,MACA,SACQ;AAGR,QAFiB,IAAI,qBAAqB,CAClB,OAAO,MAAM;EAAE,GAAG;EAAS,kBAAkB;EAAM,CAAC,CAC9D,YAAY;;;;;AAM5B,SAAgB,uBAAuB,MAGrC;AAEA,QADiB,IAAI,qBAAqB,CAC1B,SAAS,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-exporter.js","names":[],"sources":["../../src/exporters/opencode-exporter.ts"],"sourcesContent":["/**\n * OpenCode SDK Exporter\n *\n * Exports ContractSpec AgentSpec definitions to formats compatible with\n * @opencode-ai/sdk (JSON config and markdown agent files).\n */\n\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n Exporter,\n OpenCodeAgentJSON,\n OpenCodeExportOptions,\n OpenCodeExportResult,\n OpenCodeToolJSON,\n} from './types';\nimport type { OpenCodeAgentType } from '../providers/types';\nimport { inferAgentType } from '../providers/opencode-sdk/agent-bridge';\n\n// ============================================================================\n// Exporter Implementation\n// ============================================================================\n\n/**\n * OpenCode SDK Exporter.\n */\nexport class OpenCodeExporter implements Exporter<\n OpenCodeExportOptions,\n OpenCodeExportResult\n> {\n readonly format = 'opencode' as const;\n\n /**\n * Export an AgentSpec to OpenCode SDK format.\n */\n export(\n spec: AgentSpec,\n options: OpenCodeExportOptions = {}\n ): OpenCodeExportResult {\n const jsonConfig = this.buildJsonConfig(spec, options);\n const markdownConfig = this.generateMarkdown(spec, jsonConfig, options);\n\n return {\n jsonConfig,\n markdownConfig,\n exportedAt: new Date(),\n sourceSpec: agentKey(spec.meta),\n };\n }\n\n /**\n * Export multiple specs.\n */\n exportMany(\n specs: AgentSpec[],\n options: OpenCodeExportOptions = {}\n ): OpenCodeExportResult[] {\n return specs.map((spec) => this.export(spec, options));\n }\n\n /**\n * Validate that a spec can be exported.\n */\n validate(spec: AgentSpec): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n if (!spec.meta?.key) {\n errors.push('Spec must have a meta.key');\n }\n\n if (!spec.instructions) {\n errors.push('Spec must have instructions');\n }\n\n // OpenCode doesn't require tools, but we check for valid tool names\n for (const tool of spec.tools ?? []) {\n if (!tool.name) {\n errors.push('All tools must have a name');\n }\n // OpenCode tool names should be valid identifiers\n if (tool.name && !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tool.name)) {\n errors.push(\n `Tool name '${tool.name}' should be a valid identifier (letters, numbers, underscores)`\n );\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Build OpenCode agent JSON configuration.\n */\n private buildJsonConfig(\n spec: AgentSpec,\n options: OpenCodeExportOptions\n ): OpenCodeAgentJSON {\n const agentType: OpenCodeAgentType =\n options.agentType ?? inferAgentType(spec);\n\n return {\n name: spec.meta.key,\n version: spec.meta.version,\n description: spec.description,\n type: agentType,\n instructions: spec.instructions,\n tools: this.exportTools(spec),\n config: {\n max_steps: options.maxSteps ?? spec.maxSteps ?? 10,\n temperature: options.temperature ?? 0.7,\n model: options.model,\n },\n };\n }\n\n /**\n * Export tools to OpenCode format.\n */\n private exportTools(spec: AgentSpec): OpenCodeToolJSON[] {\n return spec.tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? `Execute ${tool.name}`,\n schema: tool.schema ?? { type: 'object' },\n requires_approval: tool.requiresApproval ?? !tool.automationSafe,\n }));\n }\n\n /**\n * Generate markdown agent file content.\n */\n private generateMarkdown(\n spec: AgentSpec,\n jsonConfig: OpenCodeAgentJSON,\n options: OpenCodeExportOptions\n ): string {\n const lines: string[] = [];\n\n // Frontmatter\n lines.push('---');\n lines.push(`name: ${jsonConfig.name}`);\n lines.push(`type: ${jsonConfig.type}`);\n\n if (jsonConfig.version) {\n lines.push(`version: ${jsonConfig.version}`);\n }\n\n if (jsonConfig.config.model) {\n lines.push(`model: ${jsonConfig.config.model}`);\n }\n\n if (jsonConfig.config.temperature !== undefined) {\n lines.push(`temperature: ${jsonConfig.config.temperature}`);\n }\n\n if (jsonConfig.config.max_steps !== undefined) {\n lines.push(`max_steps: ${jsonConfig.config.max_steps}`);\n }\n\n // Tool list in frontmatter\n if (jsonConfig.tools.length > 0) {\n lines.push('tools:');\n for (const tool of jsonConfig.tools) {\n const permission = tool.requires_approval ? ' # requires approval' : '';\n lines.push(` - ${tool.name}${permission}`);\n }\n }\n\n lines.push('---');\n lines.push('');\n\n // Title\n lines.push(`# ${spec.meta.key}`);\n lines.push('');\n\n // Description\n if (spec.description) {\n lines.push(spec.description);\n lines.push('');\n }\n\n // Agent type explanation\n lines.push(`> Agent type: **${jsonConfig.type}**`);\n lines.push('');\n lines.push(this.getAgentTypeDescription(jsonConfig.type));\n lines.push('');\n\n // Instructions\n lines.push('## Instructions');\n lines.push('');\n lines.push(spec.instructions);\n lines.push('');\n\n // Tools section\n if (spec.tools.length > 0) {\n lines.push('## Tools');\n lines.push('');\n for (const tool of spec.tools) {\n const approval = tool.requiresApproval ? ' *(requires approval)*' : '';\n const safe =\n tool.automationSafe === false ? ' *(not automation safe)*' : '';\n lines.push(`### ${tool.name}${approval}${safe}`);\n lines.push('');\n if (tool.description) {\n lines.push(tool.description);\n lines.push('');\n }\n if (tool.schema && options.includeComments !== false) {\n lines.push('**Parameters:**');\n lines.push('');\n lines.push('```json');\n lines.push(\n JSON.stringify(\n tool.schema,\n null,\n options.prettyPrint !== false ? 2 : 0\n )\n );\n lines.push('```');\n lines.push('');\n }\n }\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 if (k.instructions) {\n lines.push(` - ${k.instructions}`);\n }\n }\n lines.push('');\n }\n\n // Policy\n if (spec.policy) {\n lines.push('## Policy');\n lines.push('');\n if (spec.policy.confidence?.min) {\n lines.push(`- Minimum confidence: ${spec.policy.confidence.min}`);\n }\n if (spec.policy.escalation) {\n lines.push('- Escalation policy configured');\n }\n lines.push('');\n }\n\n // Configuration (JSON)\n lines.push('## Configuration');\n lines.push('');\n lines.push('```json');\n lines.push(\n JSON.stringify(\n jsonConfig.config,\n null,\n options.prettyPrint !== false ? 2 : 0\n )\n );\n lines.push('```');\n lines.push('');\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push(`*Generated from ContractSpec: ${agentKey(spec.meta)}*`);\n lines.push(`*Exported at: ${new Date().toISOString()}*`);\n\n return lines.join('\\n');\n }\n\n /**\n * Get description for agent type.\n */\n private getAgentTypeDescription(type: OpenCodeAgentType): string {\n switch (type) {\n case 'build':\n return 'Primary agent with full tool access for code generation and modification.';\n case 'plan':\n return 'Restricted agent for analysis and planning. File edits and bash commands require approval.';\n case 'general':\n return 'General-purpose subagent for complex questions and multi-step tasks.';\n case 'explore':\n return 'Fast subagent optimized for codebase exploration and pattern searching.';\n default:\n return '';\n }\n }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Export an AgentSpec to OpenCode SDK format.\n */\nexport function exportToOpenCode(\n spec: AgentSpec,\n options?: OpenCodeExportOptions\n): OpenCodeExportResult {\n const exporter = new OpenCodeExporter();\n return exporter.export(spec, options);\n}\n\n/**\n * Generate OpenCode agent markdown from an AgentSpec.\n */\nexport function generateOpenCodeMarkdown(\n spec: AgentSpec,\n options?: OpenCodeExportOptions\n): string {\n const exporter = new OpenCodeExporter();\n const result = exporter.export(spec, options);\n return result.markdownConfig;\n}\n\n/**\n * Generate OpenCode agent JSON from an AgentSpec.\n */\nexport function generateOpenCodeJSON(\n spec: AgentSpec,\n options?: OpenCodeExportOptions\n): OpenCodeAgentJSON {\n const exporter = new OpenCodeExporter();\n const result = exporter.export(spec, options);\n return result.jsonConfig;\n}\n\n/**\n * Validate an AgentSpec for OpenCode SDK export.\n */\nexport function validateForOpenCode(spec: AgentSpec): {\n valid: boolean;\n errors: string[];\n} {\n const exporter = new OpenCodeExporter();\n return exporter.validate(spec);\n}\n"],"mappings":";;;;;;;AA0BA,IAAa,mBAAb,MAGE;CACA,AAAS,SAAS;;;;CAKlB,OACE,MACA,UAAiC,EAAE,EACb;EACtB,MAAM,aAAa,KAAK,gBAAgB,MAAM,QAAQ;AAGtD,SAAO;GACL;GACA,gBAJqB,KAAK,iBAAiB,MAAM,YAAY,QAAQ;GAKrE,4BAAY,IAAI,MAAM;GACtB,YAAY,SAAS,KAAK,KAAK;GAChC;;;;;CAMH,WACE,OACA,UAAiC,EAAE,EACX;AACxB,SAAO,MAAM,KAAK,SAAS,KAAK,OAAO,MAAM,QAAQ,CAAC;;;;;CAMxD,SAAS,MAAuD;EAC9D,MAAM,SAAmB,EAAE;AAE3B,MAAI,CAAC,KAAK,MAAM,IACd,QAAO,KAAK,4BAA4B;AAG1C,MAAI,CAAC,KAAK,aACR,QAAO,KAAK,8BAA8B;AAI5C,OAAK,MAAM,QAAQ,KAAK,SAAS,EAAE,EAAE;AACnC,OAAI,CAAC,KAAK,KACR,QAAO,KAAK,6BAA6B;AAG3C,OAAI,KAAK,QAAQ,CAAC,2BAA2B,KAAK,KAAK,KAAK,CAC1D,QAAO,KACL,cAAc,KAAK,KAAK,gEACzB;;AAIL,SAAO;GAAE,OAAO,OAAO,WAAW;GAAG;GAAQ;;;;;CAU/C,AAAQ,gBACN,MACA,SACmB;EACnB,MAAM,YACJ,QAAQ,aAAa,eAAe,KAAK;AAE3C,SAAO;GACL,MAAM,KAAK,KAAK;GAChB,SAAS,KAAK,KAAK;GACnB,aAAa,KAAK;GAClB,MAAM;GACN,cAAc,KAAK;GACnB,OAAO,KAAK,YAAY,KAAK;GAC7B,QAAQ;IACN,WAAW,QAAQ,YAAY,KAAK,YAAY;IAChD,aAAa,QAAQ,eAAe;IACpC,OAAO,QAAQ;IAChB;GACF;;;;;CAMH,AAAQ,YAAY,MAAqC;AACvD,SAAO,KAAK,MAAM,KAAK,UAAU;GAC/B,MAAM,KAAK;GACX,aAAa,KAAK,eAAe,WAAW,KAAK;GACjD,QAAQ,KAAK,UAAU,EAAE,MAAM,UAAU;GACzC,mBAAmB,KAAK,oBAAoB,CAAC,KAAK;GACnD,EAAE;;;;;CAML,AAAQ,iBACN,MACA,YACA,SACQ;EACR,MAAM,QAAkB,EAAE;AAG1B,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,SAAS,WAAW,OAAO;AACtC,QAAM,KAAK,SAAS,WAAW,OAAO;AAEtC,MAAI,WAAW,QACb,OAAM,KAAK,YAAY,WAAW,UAAU;AAG9C,MAAI,WAAW,OAAO,MACpB,OAAM,KAAK,UAAU,WAAW,OAAO,QAAQ;AAGjD,MAAI,WAAW,OAAO,gBAAgB,OACpC,OAAM,KAAK,gBAAgB,WAAW,OAAO,cAAc;AAG7D,MAAI,WAAW,OAAO,cAAc,OAClC,OAAM,KAAK,cAAc,WAAW,OAAO,YAAY;AAIzD,MAAI,WAAW,MAAM,SAAS,GAAG;AAC/B,SAAM,KAAK,SAAS;AACpB,QAAK,MAAM,QAAQ,WAAW,OAAO;IACnC,MAAM,aAAa,KAAK,oBAAoB,yBAAyB;AACrE,UAAM,KAAK,OAAO,KAAK,OAAO,aAAa;;;AAI/C,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;AAGd,QAAM,KAAK,KAAK,KAAK,KAAK,MAAM;AAChC,QAAM,KAAK,GAAG;AAGd,MAAI,KAAK,aAAa;AACpB,SAAM,KAAK,KAAK,YAAY;AAC5B,SAAM,KAAK,GAAG;;AAIhB,QAAM,KAAK,mBAAmB,WAAW,KAAK,IAAI;AAClD,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,KAAK,wBAAwB,WAAW,KAAK,CAAC;AACzD,QAAM,KAAK,GAAG;AAGd,QAAM,KAAK,kBAAkB;AAC7B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,KAAK,aAAa;AAC7B,QAAM,KAAK,GAAG;AAGd,MAAI,KAAK,MAAM,SAAS,GAAG;AACzB,SAAM,KAAK,WAAW;AACtB,SAAM,KAAK,GAAG;AACd,QAAK,MAAM,QAAQ,KAAK,OAAO;IAC7B,MAAM,WAAW,KAAK,mBAAmB,2BAA2B;IACpE,MAAM,OACJ,KAAK,mBAAmB,QAAQ,6BAA6B;AAC/D,UAAM,KAAK,OAAO,KAAK,OAAO,WAAW,OAAO;AAChD,UAAM,KAAK,GAAG;AACd,QAAI,KAAK,aAAa;AACpB,WAAM,KAAK,KAAK,YAAY;AAC5B,WAAM,KAAK,GAAG;;AAEhB,QAAI,KAAK,UAAU,QAAQ,oBAAoB,OAAO;AACpD,WAAM,KAAK,kBAAkB;AAC7B,WAAM,KAAK,GAAG;AACd,WAAM,KAAK,UAAU;AACrB,WAAM,KACJ,KAAK,UACH,KAAK,QACL,MACA,QAAQ,gBAAgB,QAAQ,IAAI,EACrC,CACF;AACD,WAAM,KAAK,MAAM;AACjB,WAAM,KAAK,GAAG;;;;AAMpB,MAAI,KAAK,aAAa,KAAK,UAAU,SAAS,GAAG;AAC/C,SAAM,KAAK,uBAAuB;AAClC,SAAM,KAAK,GAAG;AACd,QAAK,MAAM,KAAK,KAAK,WAAW;IAC9B,MAAM,WAAW,EAAE,WAAW,eAAe;AAC7C,UAAM,KAAK,OAAO,EAAE,IAAI,KAAK,WAAW;AACxC,QAAI,EAAE,aACJ,OAAM,KAAK,OAAO,EAAE,eAAe;;AAGvC,SAAM,KAAK,GAAG;;AAIhB,MAAI,KAAK,QAAQ;AACf,SAAM,KAAK,YAAY;AACvB,SAAM,KAAK,GAAG;AACd,OAAI,KAAK,OAAO,YAAY,IAC1B,OAAM,KAAK,yBAAyB,KAAK,OAAO,WAAW,MAAM;AAEnE,OAAI,KAAK,OAAO,WACd,OAAM,KAAK,iCAAiC;AAE9C,SAAM,KAAK,GAAG;;AAIhB,QAAM,KAAK,mBAAmB;AAC9B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,UAAU;AACrB,QAAM,KACJ,KAAK,UACH,WAAW,QACX,MACA,QAAQ,gBAAgB,QAAQ,IAAI,EACrC,CACF;AACD,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;AAGd,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,iCAAiC,SAAS,KAAK,KAAK,CAAC,GAAG;AACnE,QAAM,KAAK,kCAAiB,IAAI,MAAM,EAAC,aAAa,CAAC,GAAG;AAExD,SAAO,MAAM,KAAK,KAAK;;;;;CAMzB,AAAQ,wBAAwB,MAAiC;AAC/D,UAAQ,MAAR;GACE,KAAK,QACH,QAAO;GACT,KAAK,OACH,QAAO;GACT,KAAK,UACH,QAAO;GACT,KAAK,UACH,QAAO;GACT,QACE,QAAO;;;;;;;AAYf,SAAgB,iBACd,MACA,SACsB;AAEtB,QADiB,IAAI,kBAAkB,CACvB,OAAO,MAAM,QAAQ;;;;;AAMvC,SAAgB,yBACd,MACA,SACQ;AAGR,QAFiB,IAAI,kBAAkB,CACf,OAAO,MAAM,QAAQ,CAC/B;;;;;AAMhB,SAAgB,qBACd,MACA,SACmB;AAGnB,QAFiB,IAAI,kBAAkB,CACf,OAAO,MAAM,QAAQ,CAC/B;;;;;AAMhB,SAAgB,oBAAoB,MAGlC;AAEA,QADiB,IAAI,kBAAkB,CACvB,SAAS,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spec-consumer.js","names":[],"sources":["../../src/interop/spec-consumer.ts"],"sourcesContent":["/**\n * Spec consumer for external agents.\n *\n * Enables external agent SDKs to consume ContractSpec specs:\n * - Read spec definitions as markdown/prompts\n * - List available specs\n * - Query spec metadata\n */\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n SpecConsumer,\n SpecConsumerConfig,\n SpecMarkdownOptions,\n SpecPromptOptions,\n SpecQueryResult,\n SpecListOptions,\n SpecListResult,\n} from './types';\n\n// =============================================================================\n// Spec Consumer Implementation\n// =============================================================================\n\n/**\n * ContractSpec consumer for external agents.\n *\n * @example\n * ```typescript\n * const consumer = createSpecConsumer({\n * specs: [myAgentSpec, anotherSpec],\n * includeMetadata: true,\n * });\n *\n * // Get markdown representation\n * const markdown = consumer.getSpecMarkdown('my-agent.v1.0.0');\n *\n * // Get prompt for LLM\n * const prompt = consumer.getSpecPrompt('my-agent.v1.0.0', {\n * includeTools: true,\n * });\n * ```\n */\nexport class ContractSpecConsumer implements SpecConsumer {\n private readonly specs: Map<string, AgentSpec>;\n private readonly includeMetadata: boolean;\n private readonly baseUrl?: string;\n\n constructor(config: SpecConsumerConfig) {\n this.specs = new Map();\n this.includeMetadata = config.includeMetadata ?? true;\n this.baseUrl = config.baseUrl;\n\n // Index specs by key\n for (const spec of config.specs) {\n const key = agentKey(spec.meta);\n this.specs.set(key, spec);\n }\n }\n\n /**\n * Get a spec as markdown.\n */\n getSpecMarkdown(specKey: string, options?: SpecMarkdownOptions): string {\n const spec = this.specs.get(specKey);\n if (!spec) {\n throw new Error(`Spec not found: ${specKey}`);\n }\n\n const sections: string[] = [];\n const opts = {\n includeToc: options?.includeToc ?? true,\n includeTools: options?.includeTools ?? true,\n ...options,\n };\n\n // Custom header\n if (opts.customHeader) {\n sections.push(opts.customHeader);\n sections.push('');\n }\n\n // Header - use key as name\n const specName = spec.meta.key;\n sections.push(`# ${specName}`);\n sections.push('');\n\n if (spec.description) {\n sections.push(spec.description);\n sections.push('');\n }\n\n // Table of contents\n if (opts.includeToc) {\n sections.push('## Table of Contents');\n sections.push('');\n sections.push('- [Overview](#overview)');\n sections.push('- [Instructions](#instructions)');\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('- [Tools](#tools)');\n }\n if (spec.knowledge && spec.knowledge.length > 0) {\n sections.push('- [Knowledge](#knowledge)');\n }\n sections.push('');\n }\n\n // Overview\n sections.push('## Overview');\n sections.push('');\n if (this.includeMetadata) {\n sections.push(`- **Key**: \\`${spec.meta.key}\\``);\n sections.push(`- **Version**: ${spec.meta.version}`);\n if (spec.meta.stability) {\n sections.push(`- **Stability**: ${spec.meta.stability}`);\n }\n if (spec.meta.owners && spec.meta.owners.length > 0) {\n sections.push(`- **Owners**: ${spec.meta.owners.join(', ')}`);\n }\n if (spec.tags && spec.tags.length > 0) {\n sections.push(`- **Tags**: ${spec.tags.join(', ')}`);\n }\n }\n sections.push('');\n\n // Instructions\n sections.push('## Instructions');\n sections.push('');\n sections.push(spec.instructions);\n sections.push('');\n\n // Tools\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('## Tools');\n sections.push('');\n for (const tool of spec.tools) {\n sections.push(`### ${tool.name}`);\n sections.push('');\n if (tool.description) {\n sections.push(tool.description);\n sections.push('');\n }\n if (tool.schema) {\n sections.push('**Schema:**');\n sections.push('');\n sections.push('```json');\n sections.push(JSON.stringify(tool.schema, null, 2));\n sections.push('```');\n sections.push('');\n }\n if (tool.automationSafe !== undefined) {\n sections.push(\n `**Automation Safe**: ${tool.automationSafe ? 'Yes' : 'No'}`\n );\n sections.push('');\n }\n }\n }\n\n // Knowledge\n if (spec.knowledge && spec.knowledge.length > 0) {\n sections.push('## Knowledge');\n sections.push('');\n for (const k of spec.knowledge) {\n sections.push(`- **${k.key}**${k.required ? ' (required)' : ''}`);\n if (k.instructions) {\n sections.push(` - ${k.instructions}`);\n }\n }\n sections.push('');\n }\n\n // Policy\n if (spec.policy) {\n sections.push('## Policy');\n sections.push('');\n if (spec.policy.confidence) {\n sections.push(\n `- **Minimum Confidence**: ${spec.policy.confidence.min ?? 0.7}`\n );\n }\n if (spec.policy.escalation) {\n const esc = spec.policy.escalation;\n if (esc.confidenceThreshold) {\n sections.push(\n `- **Escalation Threshold**: ${esc.confidenceThreshold}`\n );\n }\n if (esc.onToolFailure) {\n sections.push('- **Escalate on Tool Failure**: Yes');\n }\n if (esc.onTimeout) {\n sections.push('- **Escalate on Timeout**: Yes');\n }\n }\n sections.push('');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Get a spec as an LLM prompt.\n */\n getSpecPrompt(specKey: string, options?: SpecPromptOptions): string {\n const spec = this.specs.get(specKey);\n if (!spec) {\n throw new Error(`Spec not found: ${specKey}`);\n }\n\n const sections: string[] = [];\n const opts = {\n includeTools: options?.includeTools ?? true,\n format: options?.format ?? 'structured',\n ...options,\n };\n\n // Identity section\n sections.push('# Agent Identity');\n sections.push('');\n sections.push(`You are ${spec.meta.key} (v${spec.meta.version}).`);\n sections.push('');\n\n // Description\n if (spec.description) {\n sections.push('## Description');\n sections.push('');\n sections.push(spec.description);\n sections.push('');\n }\n\n // Instructions\n sections.push('## Instructions');\n sections.push('');\n sections.push(spec.instructions);\n sections.push('');\n\n // Tools\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('## Available Tools');\n sections.push('');\n sections.push('You have access to the following tools:');\n sections.push('');\n\n for (const tool of spec.tools) {\n sections.push(`### ${tool.name}`);\n sections.push('');\n if (tool.description) {\n sections.push(tool.description);\n sections.push('');\n }\n if (tool.schema && opts.format === 'structured') {\n sections.push('Parameters:');\n sections.push('```json');\n sections.push(JSON.stringify(tool.schema, null, 2));\n sections.push('```');\n sections.push('');\n }\n }\n }\n\n // Knowledge instructions\n if (spec.knowledge && spec.knowledge.length > 0) {\n const requiredKnowledge = spec.knowledge.filter((k) => k.required);\n if (requiredKnowledge.length > 0) {\n sections.push('## Knowledge Context');\n sections.push('');\n for (const k of requiredKnowledge) {\n if (k.instructions) {\n sections.push(k.instructions);\n sections.push('');\n }\n }\n }\n }\n\n // Custom context\n if (options?.customContext) {\n sections.push('## Additional Context');\n sections.push('');\n sections.push(options.customContext);\n sections.push('');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * List available specs.\n */\n listSpecs(options?: SpecListOptions): SpecListResult[] {\n const results: SpecListResult[] = [];\n\n for (const [key, spec] of this.specs) {\n // Apply filters\n if (options?.stability && spec.meta.stability !== options.stability) {\n continue;\n }\n if (options?.tags && options.tags.length > 0) {\n const specTags = spec.tags ?? [];\n const hasMatchingTag = options.tags.some((tag) =>\n specTags.includes(tag)\n );\n if (!hasMatchingTag) {\n continue;\n }\n }\n\n results.push({\n key,\n name: spec.meta.key,\n version: spec.meta.version,\n description: spec.description,\n stability: spec.meta.stability,\n tags: spec.tags,\n toolCount: spec.tools?.length ?? 0,\n });\n }\n\n return results;\n }\n\n /**\n * Query a spec by key.\n */\n querySpec(specKey: string): SpecQueryResult | undefined {\n const spec = this.specs.get(specKey);\n if (!spec) {\n return undefined;\n }\n\n return {\n key: specKey,\n spec,\n markdown: this.getSpecMarkdown(specKey),\n prompt: this.getSpecPrompt(specKey),\n };\n }\n\n /**\n * Check if a spec exists.\n */\n hasSpec(specKey: string): boolean {\n return this.specs.has(specKey);\n }\n\n /**\n * Get a spec by key.\n */\n getSpec(specKey: string): AgentSpec | undefined {\n return this.specs.get(specKey);\n }\n\n /**\n * Get all specs.\n */\n getAllSpecs(): AgentSpec[] {\n return Array.from(this.specs.values());\n }\n\n /**\n * Get spec count.\n */\n getSpecCount(): number {\n return this.specs.size;\n }\n\n /**\n * Add a spec to the consumer.\n */\n addSpec(spec: AgentSpec): void {\n const key = agentKey(spec.meta);\n this.specs.set(key, spec);\n }\n\n /**\n * Remove a spec from the consumer.\n */\n removeSpec(specKey: string): boolean {\n return this.specs.delete(specKey);\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a new spec consumer.\n */\nexport function createSpecConsumer(config: SpecConsumerConfig): SpecConsumer {\n return new ContractSpecConsumer(config);\n}\n\n/**\n * Create a spec consumer from a single spec.\n */\nexport function createSingleSpecConsumer(\n spec: AgentSpec,\n options?: Omit<SpecConsumerConfig, 'specs'>\n): SpecConsumer {\n return new ContractSpecConsumer({\n specs: [spec],\n ...options,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-consumer.js","names":[],"sources":["../../src/interop/tool-consumer.ts"],"sourcesContent":["/**\n * Tool consumer for external agents.\n *\n * Enables external agent SDKs to consume ContractSpec tools:\n * - Create MCP servers exposing tools\n * - Export tools for specific SDK formats\n * - Bridge tool execution\n */\nimport type { AgentToolConfig } from '../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../types';\nimport type {\n ToolConsumer,\n ToolConsumerConfig,\n ToolServerConfig,\n ToolServer,\n ToolExportFormat,\n} from './types';\nimport { specToolToClaudeAgentTool } from '../providers/claude-agent-sdk/tool-bridge';\nimport { specToolToOpenCodeTool } from '../providers/opencode-sdk/tool-bridge';\n\n// =============================================================================\n// Tool Server Implementation\n// =============================================================================\n\n/**\n * Simple MCP-compatible tool server.\n */\nclass MCPToolServer implements ToolServer {\n private readonly tools: Map<\n string,\n { config: AgentToolConfig; handler?: ToolHandler }\n >;\n private readonly name: string;\n private readonly version: string;\n private running = false;\n\n constructor(config: ToolServerConfig) {\n this.tools = new Map();\n this.name = config.name ?? 'contractspec-tools';\n this.version = config.version ?? '1.0.0';\n\n // Register tools\n for (const tool of config.tools) {\n this.tools.set(tool.config.name, tool);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) {\n return;\n }\n\n // In a real implementation, this would start an HTTP/stdio server\n // For now, we just mark as running\n this.running = true;\n\n console.log(\n `[MCPToolServer] Started ${this.name}@${this.version} with ${this.tools.size} tools`\n );\n }\n\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n this.running = false;\n console.log(`[MCPToolServer] Stopped ${this.name}`);\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getTools(): AgentToolConfig[] {\n return Array.from(this.tools.values()).map((t) => t.config);\n }\n\n async executeTool(\n toolName: string,\n args: Record<string, unknown>,\n context?: ToolExecutionContext\n ): Promise<string> {\n const tool = this.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n if (!tool.handler) {\n throw new Error(`No handler registered for tool: ${toolName}`);\n }\n\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'mcp-server',\n sessionId: context?.sessionId ?? 'mcp-session',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n\n return await tool.handler(args, fullContext);\n }\n\n /**\n * Get MCP-compatible tool definitions.\n */\n getMCPToolDefinitions(): {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[] {\n const definitions: {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[] = [];\n\n for (const [name, tool] of this.tools) {\n definitions.push({\n name,\n description: tool.config.description ?? '',\n inputSchema: tool.config.schema ?? { type: 'object', properties: {} },\n });\n }\n\n return definitions;\n }\n\n /**\n * Get server info for MCP.\n */\n getServerInfo(): {\n name: string;\n version: string;\n tools: number;\n running: boolean;\n } {\n return {\n name: this.name,\n version: this.version,\n tools: this.tools.size,\n running: this.running,\n };\n }\n}\n\n// =============================================================================\n// Tool Consumer Implementation\n// =============================================================================\n\n/**\n * ContractSpec tool consumer for external agents.\n */\nexport class ContractSpecToolConsumer implements ToolConsumer {\n private readonly tools: Map<\n string,\n { config: AgentToolConfig; handler?: ToolHandler }\n >;\n\n constructor(config: ToolConsumerConfig) {\n this.tools = new Map();\n\n // Register tools\n for (const tool of config.tools) {\n this.tools.set(tool.config.name, tool);\n }\n }\n\n /**\n * Create an MCP server exposing the tools.\n */\n createToolServer(config?: Partial<ToolServerConfig>): ToolServer {\n return new MCPToolServer({\n tools: Array.from(this.tools.values()),\n ...config,\n });\n }\n\n /**\n * Export tools for a specific SDK format.\n */\n exportToolsForSDK(format: ToolExportFormat): unknown[] {\n const tools = Array.from(this.tools.values());\n const defaultContext: Partial<ToolExecutionContext> = {\n agentId: 'export',\n sessionId: 'export',\n };\n\n switch (format) {\n case 'claude-agent':\n return tools\n .filter(\n (\n tool\n ): tool is typeof tool & {\n handler: NonNullable<typeof tool.handler>;\n } => !!tool.handler\n )\n .map((tool) =>\n specToolToClaudeAgentTool(tool.config, tool.handler, defaultContext)\n );\n\n case 'opencode':\n return tools.map((tool) => specToolToOpenCodeTool(tool.config));\n\n case 'mcp':\n return tools.map((tool) => ({\n name: tool.config.name,\n description: tool.config.description ?? '',\n inputSchema: tool.config.schema ?? { type: 'object', properties: {} },\n }));\n\n case 'openai':\n return tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.config.name,\n description: tool.config.description ?? '',\n parameters: tool.config.schema ?? {\n type: 'object',\n properties: {},\n },\n },\n }));\n\n default:\n throw new Error(`Unknown export format: ${format}`);\n }\n }\n\n /**\n * Create a bridged handler for a specific SDK.\n */\n createBridgedHandler(\n toolName: string,\n _format: ToolExportFormat\n ): ((args: Record<string, unknown>) => Promise<unknown>) | undefined {\n const tool = this.tools.get(toolName);\n if (!tool || !tool.handler) {\n return undefined;\n }\n\n const handler = tool.handler;\n\n // Return a simple wrapper that works for any format\n return async (args: Record<string, unknown>) => {\n const context: ToolExecutionContext = {\n agentId: 'bridge',\n sessionId: 'bridge',\n };\n // ToolHandler returns Promise<string>, but bridge expects Promise<unknown>\n // The types are compatible in this direction\n return handler(args, context);\n };\n }\n\n /**\n * Get all tools.\n */\n getTools(): AgentToolConfig[] {\n return Array.from(this.tools.values()).map((t) => t.config);\n }\n\n /**\n * Get a specific tool.\n */\n getTool(name: string): AgentToolConfig | undefined {\n return this.tools.get(name)?.config;\n }\n\n /**\n * Check if a tool exists.\n */\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Execute a tool.\n */\n async executeTool(\n name: string,\n args: Record<string, unknown>,\n context?: ToolExecutionContext\n ): Promise<string> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new Error(`Tool not found: ${name}`);\n }\n\n if (!tool.handler) {\n throw new Error(`No handler for tool: ${name}`);\n }\n\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'consumer',\n sessionId: context?.sessionId ?? 'consumer-session',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n\n return await tool.handler(args, fullContext);\n }\n\n /**\n * Add a tool.\n */\n addTool(config: AgentToolConfig, handler?: ToolHandler): void {\n this.tools.set(config.name, { config, handler });\n }\n\n /**\n * Remove a tool.\n */\n removeTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n /**\n * Get tool count.\n */\n getToolCount(): number {\n return this.tools.size;\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a new tool consumer.\n */\nexport function createToolConsumer(config: ToolConsumerConfig): ToolConsumer {\n return new ContractSpecToolConsumer(config);\n}\n\n/**\n * Create an MCP tool server from tools.\n */\nexport function createToolServer(config: ToolServerConfig): ToolServer {\n return new MCPToolServer(config);\n}\n\n/**\n * Export tools to a specific SDK format.\n */\nexport function exportToolsForExternalSDK(\n tools: AgentToolConfig[],\n format: ToolExportFormat\n): unknown[] {\n const consumer = new ContractSpecToolConsumer({\n tools: tools.map((config) => ({ config })),\n });\n return consumer.exportToolsForSDK(format);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"injector.js","names":[],"sources":["../../src/knowledge/injector.ts"],"sourcesContent":["import type { KnowledgeRetriever } from '@contractspec/lib.knowledge/retriever';\nimport type { AgentKnowledgeRef } from '../spec/spec';\n\n/**\n * Inject static knowledge into agent instructions.\n *\n * This function handles the \"required\" knowledge that should be\n * injected into the system prompt at agent initialization time.\n * Optional knowledge is handled by the knowledge query tool.\n *\n * @param instructions - Base agent instructions\n * @param knowledgeRefs - Knowledge references from the agent spec\n * @param retriever - Optional knowledge retriever\n * @returns Instructions with injected knowledge\n */\nexport async function injectStaticKnowledge(\n instructions: string,\n knowledgeRefs: AgentKnowledgeRef[],\n retriever?: KnowledgeRetriever\n): Promise<string> {\n if (!retriever) return instructions;\n\n const requiredRefs = knowledgeRefs.filter((ref) => ref.required);\n if (requiredRefs.length === 0) return instructions;\n\n const blocks: string[] = [];\n\n for (const ref of requiredRefs) {\n if (!retriever.supportsSpace(ref.key)) {\n console.warn(`Required knowledge space \"${ref.key}\" is not available`);\n continue;\n }\n\n try {\n const content = await retriever.getStatic(ref.key);\n if (content) {\n const header = ref.instructions\n ? `## ${ref.key}\\n${ref.instructions}`\n : `## ${ref.key}`;\n blocks.push(`${header}\\n\\n${content}`);\n }\n } catch (error) {\n console.warn(`Failed to load required knowledge \"${ref.key}\":`, error);\n }\n }\n\n if (blocks.length === 0) return instructions;\n\n return `${instructions}\n\n---\n\n# Reference Knowledge\n\nThe following information is provided for your reference. Use it to inform your responses.\n\n${blocks.join('\\n\\n---\\n\\n')}`;\n}\n\n/**\n * Create a knowledge injector instance for reuse.\n */\nexport function createKnowledgeInjector(retriever?: KnowledgeRetriever) {\n return {\n /**\n * Inject static knowledge into instructions.\n */\n inject: (instructions: string, knowledgeRefs: AgentKnowledgeRef[]) =>\n injectStaticKnowledge(instructions, knowledgeRefs, retriever),\n\n /**\n * Check if a knowledge space is available.\n */\n hasSpace: (spaceKey: string) => retriever?.supportsSpace(spaceKey) ?? false,\n\n /**\n * List available knowledge spaces.\n */\n listSpaces: () => retriever?.listSpaces() ?? [],\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,eAAsB,sBACpB,cACA,eACA,WACiB;AACjB,KAAI,CAAC,UAAW,QAAO;CAEvB,MAAM,eAAe,cAAc,QAAQ,QAAQ,IAAI,SAAS;AAChE,KAAI,aAAa,WAAW,EAAG,QAAO;CAEtC,MAAM,SAAmB,EAAE;AAE3B,MAAK,MAAM,OAAO,cAAc;AAC9B,MAAI,CAAC,UAAU,cAAc,IAAI,IAAI,EAAE;AACrC,WAAQ,KAAK,6BAA6B,IAAI,IAAI,oBAAoB;AACtE;;AAGF,MAAI;GACF,MAAM,UAAU,MAAM,UAAU,UAAU,IAAI,IAAI;AAClD,OAAI,SAAS;IACX,MAAM,SAAS,IAAI,eACf,MAAM,IAAI,IAAI,IAAI,IAAI,iBACtB,MAAM,IAAI;AACd,WAAO,KAAK,GAAG,OAAO,MAAM,UAAU;;WAEjC,OAAO;AACd,WAAQ,KAAK,sCAAsC,IAAI,IAAI,KAAK,MAAM;;;AAI1E,KAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAO,GAAG,aAAa;;;;;;;;EAQvB,OAAO,KAAK,cAAc;;;;;AAM5B,SAAgB,wBAAwB,WAAgC;AACtE,QAAO;EAIL,SAAS,cAAsB,kBAC7B,sBAAsB,cAAc,eAAe,UAAU;EAK/D,WAAW,aAAqB,WAAW,cAAc,SAAS,IAAI;EAKtE,kBAAkB,WAAW,YAAY,IAAI,EAAE;EAChD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"in-memory.js","names":[],"sources":["../../src/memory/in-memory.ts"],"sourcesContent":["import type { AgentSessionState } from '../types';\nimport {\n BaseAgentMemoryManager,\n type AgentMemoryEntry,\n type AgentMemorySnapshot,\n type AgentSessionMemory,\n} from './manager';\n\ninterface StoredSession {\n data: AgentSessionMemory;\n expiresAt: number;\n}\n\nexport interface InMemoryAgentMemoryOptions {\n ttlMinutes?: number;\n maxEntries?: number;\n}\n\nexport class InMemoryAgentMemory extends BaseAgentMemoryManager {\n private readonly ttlMs: number;\n private readonly maxEntries: number;\n private readonly store = new Map<string, StoredSession>();\n\n constructor(options?: InMemoryAgentMemoryOptions) {\n super();\n this.ttlMs = (options?.ttlMinutes ?? 60) * 60 * 1000;\n this.maxEntries = options?.maxEntries ?? 250;\n }\n\n async load(sessionId: string): Promise<AgentSessionMemory | null> {\n this.evictExpired();\n const stored = this.store.get(sessionId);\n if (!stored) return null;\n stored.data.session.updatedAt = new Date();\n stored.expiresAt = Date.now() + this.ttlMs;\n return stored.data;\n }\n\n async save(snapshot: AgentSessionMemory): Promise<void> {\n this.trim(snapshot.memory.entries);\n this.store.set(snapshot.session.sessionId, {\n data: snapshot,\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n async summarize(session: AgentSessionState): Promise<AgentMemorySnapshot> {\n const current =\n (await this.load(session.sessionId)) ?? this.bootstrapMemory(session);\n const content = current.memory.entries\n .slice(-10)\n .map((entry) => `- ${entry.type}: ${entry.content}`)\n .join('\\n');\n current.memory.summary = content;\n current.memory.lastSummarizedAt = new Date();\n await this.save(current);\n return current.memory;\n }\n\n private trim(entries: AgentMemoryEntry[]) {\n if (entries.length <= this.maxEntries) return;\n entries.splice(0, entries.length - this.maxEntries);\n }\n\n private evictExpired() {\n const now = Date.now();\n for (const [sessionId, stored] of this.store.entries()) {\n if (stored.expiresAt <= now) {\n this.store.delete(sessionId);\n }\n }\n }\n}\n"],"mappings":";;;AAkBA,IAAa,sBAAb,cAAyC,uBAAuB;CAC9D,AAAiB;CACjB,AAAiB;CACjB,AAAiB,wBAAQ,IAAI,KAA4B;CAEzD,YAAY,SAAsC;AAChD,SAAO;AACP,OAAK,SAAS,SAAS,cAAc,MAAM,KAAK;AAChD,OAAK,aAAa,SAAS,cAAc;;CAG3C,MAAM,KAAK,WAAuD;AAChE,OAAK,cAAc;EACnB,MAAM,SAAS,KAAK,MAAM,IAAI,UAAU;AACxC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,KAAK,QAAQ,4BAAY,IAAI,MAAM;AAC1C,SAAO,YAAY,KAAK,KAAK,GAAG,KAAK;AACrC,SAAO,OAAO;;CAGhB,MAAM,KAAK,UAA6C;AACtD,OAAK,KAAK,SAAS,OAAO,QAAQ;AAClC,OAAK,MAAM,IAAI,SAAS,QAAQ,WAAW;GACzC,MAAM;GACN,WAAW,KAAK,KAAK,GAAG,KAAK;GAC9B,CAAC;;CAGJ,MAAM,UAAU,SAA0D;EACxE,MAAM,UACH,MAAM,KAAK,KAAK,QAAQ,UAAU,IAAK,KAAK,gBAAgB,QAAQ;EACvE,MAAM,UAAU,QAAQ,OAAO,QAC5B,MAAM,IAAI,CACV,KAAK,UAAU,KAAK,MAAM,KAAK,IAAI,MAAM,UAAU,CACnD,KAAK,KAAK;AACb,UAAQ,OAAO,UAAU;AACzB,UAAQ,OAAO,mCAAmB,IAAI,MAAM;AAC5C,QAAM,KAAK,KAAK,QAAQ;AACxB,SAAO,QAAQ;;CAGjB,AAAQ,KAAK,SAA6B;AACxC,MAAI,QAAQ,UAAU,KAAK,WAAY;AACvC,UAAQ,OAAO,GAAG,QAAQ,SAAS,KAAK,WAAW;;CAGrD,AAAQ,eAAe;EACrB,MAAM,MAAM,KAAK,KAAK;AACtB,OAAK,MAAM,CAAC,WAAW,WAAW,KAAK,MAAM,SAAS,CACpD,KAAI,OAAO,aAAa,IACtB,MAAK,MAAM,OAAO,UAAU"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","names":[],"sources":["../../src/memory/manager.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { ModelMessage } from 'ai';\nimport type { AgentMessage, AgentSessionState } from '../types';\n\nexport interface AgentMemoryEntry {\n id: string;\n type: 'user' | 'assistant' | 'tool' | 'system';\n content: string;\n createdAt: Date;\n metadata?: Record<string, string>;\n}\n\nexport interface AgentMemorySnapshot {\n entries: AgentMemoryEntry[];\n summary?: string;\n lastSummarizedAt?: Date;\n}\n\nexport interface AgentSessionMemory {\n session: AgentSessionState;\n memory: AgentMemorySnapshot;\n}\n\nexport interface AgentMemoryManager {\n load(sessionId: string): Promise<AgentSessionMemory | null>;\n save(snapshot: AgentSessionMemory): Promise<void>;\n append(\n session: AgentSessionState,\n entry: Omit<AgentMemoryEntry, 'id' | 'createdAt'> & { createdAt?: Date }\n ): Promise<AgentSessionMemory>;\n summarize(\n session: AgentSessionState\n ): Promise<AgentMemorySnapshot | undefined>;\n prune(session: AgentSessionState): Promise<void>;\n}\n\n/**\n * Extract text content from a ModelMessage.\n * Handles both string content and array content parts.\n */\nfunction extractMessageContent(message: ModelMessage): string {\n const content = message.content;\n\n // Handle string content directly\n if (typeof content === 'string') {\n return content;\n }\n\n // Handle array content (parts)\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (typeof part === 'string') return part;\n if ('text' in part && typeof part.text === 'string') return part.text;\n return '';\n })\n .filter(Boolean)\n .join('');\n }\n\n return '';\n}\n\n/**\n * Extract text content from an AgentMessage.\n */\nfunction extractAgentMessageContent(message: AgentMessage): string {\n const content = message.content;\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (typeof part === 'string') return part;\n if ('text' in part && typeof part.text === 'string') return part.text;\n return '';\n })\n .filter(Boolean)\n .join('');\n }\n\n return '';\n}\n\n/**\n * Map ModelMessage role to memory entry type.\n */\nfunction roleToEntryType(\n role: ModelMessage['role']\n): 'user' | 'assistant' | 'tool' | 'system' {\n switch (role) {\n case 'assistant':\n return 'assistant';\n case 'system':\n return 'system';\n case 'tool':\n return 'tool';\n case 'user':\n default:\n return 'user';\n }\n}\n\nexport abstract class BaseAgentMemoryManager implements AgentMemoryManager {\n abstract load(sessionId: string): Promise<AgentSessionMemory | null>;\n abstract save(snapshot: AgentSessionMemory): Promise<void>;\n\n async append(\n session: AgentSessionState,\n entry: Omit<AgentMemoryEntry, 'id' | 'createdAt'> & { createdAt?: Date }\n ): Promise<AgentSessionMemory> {\n const current =\n (await this.load(session.sessionId)) ?? this.bootstrapMemory(session);\n const finalEntry: AgentMemoryEntry = {\n id: randomUUID(),\n createdAt: entry.createdAt ?? new Date(),\n ...entry,\n };\n current.memory.entries.push(finalEntry);\n await this.save(current);\n return current;\n }\n\n async summarize(\n _session: AgentSessionState\n ): Promise<AgentMemorySnapshot | undefined> {\n return undefined;\n }\n\n async prune(_session: AgentSessionState): Promise<void> {\n // noop by default\n }\n\n protected bootstrapMemory(session: AgentSessionState): AgentSessionMemory {\n return {\n session,\n memory: {\n entries: session.messages.map<AgentMemoryEntry>((message) => ({\n id: randomUUID(),\n createdAt: new Date(),\n type: roleToEntryType(message.role),\n content: extractMessageContent(message),\n })),\n },\n };\n }\n}\n\nexport function trackMessageInMemory(\n manager: AgentMemoryManager | undefined,\n session: AgentSessionState,\n message: AgentMessage\n) {\n if (!manager) return;\n void manager.append(session, {\n type: message.role,\n content: extractAgentMessageContent(message),\n metadata: message.metadata,\n });\n}\n"],"mappings":";;;;;;;AAwCA,SAAS,sBAAsB,SAA+B;CAC5D,MAAM,UAAU,QAAQ;AAGxB,KAAI,OAAO,YAAY,SACrB,QAAO;AAIT,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO,QACJ,KAAK,SAAS;AACb,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,UAAU,QAAQ,OAAO,KAAK,SAAS,SAAU,QAAO,KAAK;AACjE,SAAO;GACP,CACD,OAAO,QAAQ,CACf,KAAK,GAAG;AAGb,QAAO;;;;;AAMT,SAAS,2BAA2B,SAA+B;CACjE,MAAM,UAAU,QAAQ;AAExB,KAAI,OAAO,YAAY,SACrB,QAAO;AAGT,KAAI,MAAM,QAAQ,QAAQ,CACxB,QAAO,QACJ,KAAK,SAAS;AACb,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,UAAU,QAAQ,OAAO,KAAK,SAAS,SAAU,QAAO,KAAK;AACjE,SAAO;GACP,CACD,OAAO,QAAQ,CACf,KAAK,GAAG;AAGb,QAAO;;;;;AAMT,SAAS,gBACP,MAC0C;AAC1C,SAAQ,MAAR;EACE,KAAK,YACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,OACH,QAAO;EAET,QACE,QAAO;;;AAIb,IAAsB,yBAAtB,MAA2E;CAIzE,MAAM,OACJ,SACA,OAC6B;EAC7B,MAAM,UACH,MAAM,KAAK,KAAK,QAAQ,UAAU,IAAK,KAAK,gBAAgB,QAAQ;EACvE,MAAM,aAA+B;GACnC,IAAI,YAAY;GAChB,WAAW,MAAM,6BAAa,IAAI,MAAM;GACxC,GAAG;GACJ;AACD,UAAQ,OAAO,QAAQ,KAAK,WAAW;AACvC,QAAM,KAAK,KAAK,QAAQ;AACxB,SAAO;;CAGT,MAAM,UACJ,UAC0C;CAI5C,MAAM,MAAM,UAA4C;CAIxD,AAAU,gBAAgB,SAAgD;AACxE,SAAO;GACL;GACA,QAAQ,EACN,SAAS,QAAQ,SAAS,KAAuB,aAAa;IAC5D,IAAI,YAAY;IAChB,2BAAW,IAAI,MAAM;IACrB,MAAM,gBAAgB,QAAQ,KAAK;IACnC,SAAS,sBAAsB,QAAQ;IACxC,EAAE,EACJ;GACF;;;AAIL,SAAgB,qBACd,SACA,SACA,SACA;AACA,KAAI,CAAC,QAAS;AACd,CAAK,QAAQ,OAAO,SAAS;EAC3B,MAAM,QAAQ;EACd,SAAS,2BAA2B,QAAQ;EAC5C,UAAU,QAAQ;EACnB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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":";;;;;;;;;;;AAkFA,SAAgB,eAAe,MAAoC;CAEjE,MAAM,eAAe,KAAK,MAAM,MAAM,SACpC;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,SAAS,KAAK,KAAK,aAAa,CAAC,CACpC;CAGD,MAAM,oBAAoB,KAAK,aAAa,aAAa;CACzD,MAAM,sBACJ,sEAAsE,KACpE,kBACD;CAGH,MAAM,yBACJ,yDAAyD,KACvD,kBACD;CAGH,MAAM,sBACJ,6DAA6D,KAC3D,kBACD;AAGH,KAAI,aACF,QAAO;AAGT,KAAI,uBAAuB,CAAC,aAC1B,QAAO;AAGT,KAAI,0BAA0B,CAAC,oBAC7B,QAAO;AAIT,QAAO;;;;;AAUT,SAAgB,qBACd,MACA,SAMmB;CACnB,MAAM,YAAY,SAAS,aAAa,eAAe,KAAK;AAE5D,QAAO;EACL,MAAM,KAAK,KAAK;EAChB,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,eAAe,KAAK,KAAK;EAC3C,cAAc,KAAK;EACnB,YAAY;EACZ,OAAO,yBAAyB,KAAK,MAAM;EAC3C,QAAQ;GACN,WAAW,SAAS,YAAY,KAAK,YAAY;GACjD,aAAa,SAAS,eAAe;GACrC,OAAO,SAAS;GAChB,aAAa,iBAAiB,KAAK;GACpC;EACF;;;;;AAMH,SAAS,iBACP,MAC0C;CAC1C,MAAM,cAAwD,EAAE;AAEhE,MAAK,MAAM,QAAQ,KAAK,MACtB,KAAI,KAAK,iBACP,aAAY,KAAK,QAAQ;UAChB,KAAK,mBAAmB,MACjC,aAAY,KAAK,QAAQ;KAEzB,aAAY,KAAK,QAAQ;AAI7B,QAAO;;;;;AAMT,SAAgB,uBACd,MACA,SAMuB;CACvB,MAAM,YAAY,SAAS,aAAa,eAAe,KAAK;AAE5D,QAAO;EACL,aAAa;GACX,MAAM,KAAK,KAAK;GAChB,MAAM;GACN,SAAS,KAAK,KAAK;GACnB,OAAO,SAAS;GAChB,aAAa,SAAS,eAAe;GACrC,WAAW,SAAS,YAAY,KAAK,YAAY;GACjD,OAAO,KAAK,MAAM,KAAK,MAAM,EAAE,KAAK;GACrC;EACD,MAAM,kBAAkB,KAAK;EAC9B;;;;;AAMH,SAAS,kBAAkB,MAAyB;CAClD,MAAM,QAAkB,EAAE;AAG1B,OAAM,KAAK,KAAK,KAAK,KAAK,MAAM;AAChC,OAAM,KAAK,GAAG;AAGd,KAAI,KAAK,eAAe,KAAK,KAAK,aAAa;AAC7C,QAAM,KAAK,KAAK,eAAe,KAAK,KAAK,eAAe,GAAG;AAC3D,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,kBAAkB;AAC7B,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,KAAK,aAAa;AAC7B,OAAM,KAAK,GAAG;AAGd,KAAI,KAAK,MAAM,SAAS,GAAG;AACzB,QAAM,KAAK,WAAW;AACtB,QAAM,KAAK,GAAG;AACd,OAAK,MAAM,QAAQ,KAAK,OAAO;GAC7B,MAAM,aAAa,KAAK,mBACpB,wBACA,KAAK,mBAAmB,QACtB,eACA;AACN,SAAM,KACJ,OAAO,KAAK,KAAK,MAAM,KAAK,eAAe,iBAAiB,GAAG,aAAa,MAAM,CACnF;;AAEH,QAAM,KAAK,GAAG;;AAIhB,KAAI,KAAK,aAAa,KAAK,UAAU,SAAS,GAAG;AAC/C,QAAM,KAAK,uBAAuB;AAClC,QAAM,KAAK,GAAG;AACd,OAAK,MAAM,KAAK,KAAK,WAAW;GAC9B,MAAM,WAAW,EAAE,WAAW,eAAe;AAC7C,SAAM,KAAK,KAAK,EAAE,IAAI,GAAG,WAAW;;AAEtC,QAAM,KAAK,GAAG;;AAGhB,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,0BACd,UACQ;CACR,MAAM,QAAkB,EAAE;AAG1B,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,SAAS,SAAS,YAAY,OAAO;AAChD,OAAM,KAAK,SAAS,SAAS,YAAY,OAAO;AAEhD,KAAI,SAAS,YAAY,QACvB,OAAM,KAAK,YAAY,SAAS,YAAY,UAAU;AAGxD,KAAI,SAAS,YAAY,MACvB,OAAM,KAAK,UAAU,SAAS,YAAY,QAAQ;AAGpD,KAAI,SAAS,YAAY,gBAAgB,OACvC,OAAM,KAAK,gBAAgB,SAAS,YAAY,cAAc;AAGhE,KAAI,SAAS,YAAY,cAAc,OACrC,OAAM,KAAK,cAAc,SAAS,YAAY,YAAY;AAG5D,KAAI,SAAS,YAAY,SAAS,SAAS,YAAY,MAAM,SAAS,GAAG;AACvE,QAAM,KAAK,SAAS;AACpB,OAAK,MAAM,QAAQ,SAAS,YAAY,MACtC,OAAM,KAAK,OAAO,OAAO;;AAI7B,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,SAAS,KAAK;AAEzB,QAAO,MAAM,KAAK,KAAK;;;;;;AAWzB,SAAgB,qBACd,QACoB;AACpB,QAAO;EACL,MAAM;GACJ,KAAK,OAAO;GACZ,SAAS,OAAO,WAAW;GAC3B,aAAa,OAAO,eAAe;GACnC,WAAW;GACX,QAAQ,EAAE;GACV,MAAM,EAAE;GACT;EACD,aAAa,OAAO;EACpB,cAAc,OAAO,gBAAgB;EACrC,OACE,OAAO,OAAO,KAAK,UAAU;GAC3B,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,QAAQ,KAAK;GACb,kBAAkB,KAAK,eAAe;GACtC,gBAAgB,KAAK,eAAe;GAErC,EAAE,IAAI,EAAE;EACX,UAAU,OAAO,QAAQ,aAAa;EACvC"}
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../../src/providers/registry.ts"],"sourcesContent":["/**\n * Provider registry for managing external SDK providers.\n */\n\nimport type { ExternalAgentProvider, ProviderRegistry } from './types';\nimport { ProviderNotAvailableError } from './types';\n\n/**\n * In-memory implementation of the provider registry.\n */\nclass InMemoryProviderRegistry implements ProviderRegistry {\n private providers = new Map<string, ExternalAgentProvider>();\n\n get(name: string): ExternalAgentProvider | undefined {\n return this.providers.get(name);\n }\n\n register(name: string, provider: ExternalAgentProvider): void {\n this.providers.set(name, provider);\n }\n\n list(): string[] {\n return Array.from(this.providers.keys());\n }\n\n isAvailable(name: string): boolean {\n const provider = this.providers.get(name);\n return provider !== undefined && provider.isAvailable();\n }\n\n /**\n * Get a provider, throwing if not found or not available.\n */\n require(name: string): ExternalAgentProvider {\n const provider = this.providers.get(name);\n if (!provider) {\n throw new ProviderNotAvailableError(name, 'not registered');\n }\n if (!provider.isAvailable()) {\n throw new ProviderNotAvailableError(\n name,\n 'dependencies not installed or not configured'\n );\n }\n return provider;\n }\n\n /**\n * Clear all registered providers.\n */\n clear(): void {\n this.providers.clear();\n }\n}\n\n/**\n * Create a new provider registry.\n */\nexport function createProviderRegistry(): ProviderRegistry & {\n require: (name: string) => ExternalAgentProvider;\n clear: () => void;\n} {\n return new InMemoryProviderRegistry();\n}\n\n/**\n * Global default provider registry.\n * Use this for convenience when you don't need multiple registries.\n */\nexport const defaultProviderRegistry = createProviderRegistry();\n"],"mappings":";;;;;;AAUA,IAAM,2BAAN,MAA2D;CACzD,AAAQ,4BAAY,IAAI,KAAoC;CAE5D,IAAI,MAAiD;AACnD,SAAO,KAAK,UAAU,IAAI,KAAK;;CAGjC,SAAS,MAAc,UAAuC;AAC5D,OAAK,UAAU,IAAI,MAAM,SAAS;;CAGpC,OAAiB;AACf,SAAO,MAAM,KAAK,KAAK,UAAU,MAAM,CAAC;;CAG1C,YAAY,MAAuB;EACjC,MAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,SAAO,aAAa,UAAa,SAAS,aAAa;;;;;CAMzD,QAAQ,MAAqC;EAC3C,MAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,MAAI,CAAC,SACH,OAAM,IAAI,0BAA0B,MAAM,iBAAiB;AAE7D,MAAI,CAAC,SAAS,aAAa,CACzB,OAAM,IAAI,0BACR,MACA,+CACD;AAEH,SAAO;;;;;CAMT,QAAc;AACZ,OAAK,UAAU,OAAO;;;;;;AAO1B,SAAgB,yBAGd;AACA,QAAO,IAAI,0BAA0B;;;;;;AAOvC,MAAa,0BAA0B,wBAAwB"}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|