@contractspec/lib.ai-agent 1.46.2 → 1.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/unified-agent.js.map +1 -1
- package/dist/approval/workflow.js.map +1 -1
- package/dist/exporters/claude-agent-exporter.js.map +1 -1
- package/dist/exporters/opencode-exporter.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/interop/spec-consumer.js.map +1 -1
- package/dist/interop/tool-consumer.js.map +1 -1
- package/dist/knowledge/injector.js.map +1 -1
- package/dist/memory/manager.js.map +1 -1
- package/dist/providers/claude-agent-sdk/adapter.js.map +1 -1
- package/dist/providers/claude-agent-sdk/session-bridge.js.map +1 -1
- package/dist/providers/claude-agent-sdk/tool-bridge.js.map +1 -1
- package/dist/providers/opencode-sdk/adapter.js.map +1 -1
- package/dist/providers/opencode-sdk/agent-bridge.js.map +1 -1
- package/dist/providers/opencode-sdk/tool-bridge.js.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/schema/json-schema-to-zod.js.map +1 -1
- package/dist/session/store.js.map +1 -1
- package/dist/spec/registry.js.map +1 -1
- package/dist/telemetry/adapter.js.map +1 -1
- package/dist/tools/knowledge-tool.js.map +1 -1
- package/dist/tools/mcp-client.js.map +1 -1
- package/dist/tools/tool-adapter.js.map +1 -1
- package/package.json +14 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-agent.js","names":["result: ExternalExecuteResult","backends: UnifiedAgentBackend[]"],"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 { 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 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 { anthropic } = await import('@ai-sdk/anthropic');\n\n // Use factory method create() instead of new\n const backendConfig =\n this.config.backend === 'ai-sdk'\n ? (this.config.config as Record<string, unknown>)\n : {};\n\n const agent = await ContractSpecAgent.create({\n spec: this.spec,\n model: anthropic(\n (backendConfig?.model as string) ?? 'claude-3-5-sonnet-20240620'\n ),\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 /**\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 }\n): UnifiedAgent {\n return new UnifiedAgent(spec, {\n backend: 'ai-sdk',\n tools: options?.tools,\n config: { model: options?.model },\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
|
+
{"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 { 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 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 { anthropic } = await import('@ai-sdk/anthropic');\n\n // Use factory method create() instead of new\n const backendConfig =\n this.config.backend === 'ai-sdk'\n ? (this.config.config as Record<string, unknown>)\n : {};\n\n const agent = await ContractSpecAgent.create({\n spec: this.spec,\n model: anthropic(\n (backendConfig?.model as string) ?? 'claude-3-5-sonnet-20240620'\n ),\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 /**\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 }\n): UnifiedAgent {\n return new UnifiedAgent(spec, {\n backend: 'ai-sdk',\n tools: options?.tools,\n config: { model: options?.model },\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.js","names":[
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-agent-exporter.js","names":["errors: string[]","config: ClaudeAgentConfig","parts: string[]","lines: string[]","flags: string[]"],"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":"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"}
|
|
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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-exporter.js","names":["errors: string[]","agentType: OpenCodeAgentType","lines: string[]"],"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":"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"}
|
|
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":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,5 +33,5 @@ import { ExecutionMode, ExternalToolConfig, ImplementationPromptOptions, Impleme
|
|
|
33
33
|
import { ContractSpecConsumer, createSingleSpecConsumer, createSpecConsumer } from "./interop/spec-consumer.js";
|
|
34
34
|
import { ContractSpecToolConsumer, createToolConsumer, createToolServer, exportToolsForExternalSDK } from "./interop/tool-consumer.js";
|
|
35
35
|
import "./interop/index.js";
|
|
36
|
-
import { Experimental_Agent as ToolLoopAgent, LanguageModel, LanguageModelUsage, ModelMessage, StepResult, Tool, ToolSet } from "ai";
|
|
37
|
-
export { AgentCallOptions, AgentConfidencePolicy, AgentEscalationPolicy, AgentEventEmitter, AgentEventName, AgentEventPayload, AgentFinishReason, AgentGenerateParams, AgentGenerateResult, AgentKnowledgeRef, AgentMcpServerConfig, AgentMemoryConfig, AgentMessage, AgentMeta, AgentPolicy, AgentRegistry, AgentSessionState, AgentSessionStore, AgentSpec, AgentStatus, AgentStepMetrics, AgentStreamParams, AgentToolConfig, ApprovalRequest, ApprovalStatus, ApprovalStore, ApprovalWorkflow, ClaudeAgentConfig, ClaudeAgentContextMetadata, ClaudeAgentExportOptions, ClaudeAgentExportResult, ClaudeAgentExporter, ClaudeAgentSDKConfig, ClaudeAgentSDKProvider, ClaudeToolDefinition, ContextCreationError, ContractSpecAgent, ContractSpecAgentConfig, ContractSpecConsumer, ContractSpecToolConsumer, ExecutionMode, ExportFormat, ExportOptions, Exporter, ExternalAgentContext, ExternalAgentProvider, ExternalExecuteParams, ExternalExecuteResult, ExternalProviderError, ExternalProviderFactory, ExternalStreamChunk, ExternalToolConfig, ExternalToolDefinition, ExternalToolSet, ExternalUsage, ImplementationPromptOptions, ImplementationTaskType, InMemoryApprovalStore, InMemorySessionStore, InMemoryTelemetryCollector, type LanguageModel, type LanguageModelUsage, MCPExportOptions, MCPExportResult, MCPPromptDefinition, MCPResourceDefinition, MCPServerDefinition, MCPToolDefinition, McpClientConfig, McpClientResult, McpServerConfig, McpToolDefinition, type ModelMessage, OpenCodeAgentJSON, OpenCodeAgentType, OpenCodeContextMetadata, OpenCodeExportOptions, OpenCodeExportResult, OpenCodeExporter, OpenCodeSDKConfig, OpenCodeSDKProvider, OpenCodeToolJSON, OperationMetricSample, ProviderExecutionError, ProviderNotAvailableError, ProviderRegistry, SchemaOutput, SpecConsumer, SpecConsumerConfig, SpecExportFormat, SpecListEntry, SpecListOptions, SpecListResult, SpecMarkdownOptions, SpecPromptOptions, SpecQueryResult, type StepResult, TelemetryCollector, type Tool, ToolCallInfo, ToolConsumer, ToolConsumerConfig, ToolExecutionContext, ToolExportFormat, ToolExportTarget, ToolHandler, ToolLoopAgent, ToolResultInfo, ToolServer, ToolServerConfig, type ToolSet, ToolWithHandler, UnifiedAgent, UnifiedAgentBackend, UnifiedAgentBackendConfig, UnifiedAgentConfig, UnifiedAgentProvider, UnifiedAgentRunOptions, UnifiedAgentState, UnifiedAgentStatus, agentKey, agentToMcpServer, buildToolHandlers, createAISDKAgent, createAgentMcpServer, createAgentRegistry, createApprovalWorkflow, createClaudeAgentSDKAgent, createInMemorySessionStore, createInMemoryTelemetryCollector, createKnowledgeInjector, createKnowledgeQueryTool, createMcpToolsets, createOpenCodeSDKAgent, createProviderRegistry, createSingleSpecConsumer, createSpecConsumer, createToolConsumer, createToolHandler, createToolServer, createUnifiedAgent, defaultProviderRegistry, defineAgent, enumToChoiceOutput, exportToClaudeAgent, exportToOpenCode, exportToolsForExternalSDK, generateClaudeMd, generateOpenCodeJSON, generateOpenCodeMarkdown, generateSessionId, getAvailableBackends, injectStaticKnowledge, jsonSchemaToArrayOutput, jsonSchemaToOutput, jsonSchemaToZod, jsonSchemaToZodSafe, mcpServerToTools, noopTelemetryCollector, specToolToAISDKTool, specToolsToAISDKTools, textOutput, trackAgentStep, validateForClaudeAgent, validateForOpenCode, zodToOutput };
|
|
36
|
+
import { Experimental_Agent as ToolLoopAgent, LanguageModel, LanguageModelUsage, ModelMessage, StepResult, Tool, ToolSet, generateText } from "ai";
|
|
37
|
+
export { AgentCallOptions, AgentConfidencePolicy, AgentEscalationPolicy, AgentEventEmitter, AgentEventName, AgentEventPayload, AgentFinishReason, AgentGenerateParams, AgentGenerateResult, AgentKnowledgeRef, AgentMcpServerConfig, AgentMemoryConfig, AgentMessage, AgentMeta, AgentPolicy, AgentRegistry, AgentSessionState, AgentSessionStore, AgentSpec, AgentStatus, AgentStepMetrics, AgentStreamParams, AgentToolConfig, ApprovalRequest, ApprovalStatus, ApprovalStore, ApprovalWorkflow, ClaudeAgentConfig, ClaudeAgentContextMetadata, ClaudeAgentExportOptions, ClaudeAgentExportResult, ClaudeAgentExporter, ClaudeAgentSDKConfig, ClaudeAgentSDKProvider, ClaudeToolDefinition, ContextCreationError, ContractSpecAgent, ContractSpecAgentConfig, ContractSpecConsumer, ContractSpecToolConsumer, ExecutionMode, ExportFormat, ExportOptions, Exporter, ExternalAgentContext, ExternalAgentProvider, ExternalExecuteParams, ExternalExecuteResult, ExternalProviderError, ExternalProviderFactory, ExternalStreamChunk, ExternalToolConfig, ExternalToolDefinition, ExternalToolSet, ExternalUsage, ImplementationPromptOptions, ImplementationTaskType, InMemoryApprovalStore, InMemorySessionStore, InMemoryTelemetryCollector, type LanguageModel, type LanguageModelUsage, MCPExportOptions, MCPExportResult, MCPPromptDefinition, MCPResourceDefinition, MCPServerDefinition, MCPToolDefinition, McpClientConfig, McpClientResult, McpServerConfig, McpToolDefinition, type ModelMessage, OpenCodeAgentJSON, OpenCodeAgentType, OpenCodeContextMetadata, OpenCodeExportOptions, OpenCodeExportResult, OpenCodeExporter, OpenCodeSDKConfig, OpenCodeSDKProvider, OpenCodeToolJSON, OperationMetricSample, ProviderExecutionError, ProviderNotAvailableError, ProviderRegistry, SchemaOutput, SpecConsumer, SpecConsumerConfig, SpecExportFormat, SpecListEntry, SpecListOptions, SpecListResult, SpecMarkdownOptions, SpecPromptOptions, SpecQueryResult, type StepResult, TelemetryCollector, type Tool, ToolCallInfo, ToolConsumer, ToolConsumerConfig, ToolExecutionContext, ToolExportFormat, ToolExportTarget, ToolHandler, ToolLoopAgent, ToolResultInfo, ToolServer, ToolServerConfig, type ToolSet, ToolWithHandler, UnifiedAgent, UnifiedAgentBackend, UnifiedAgentBackendConfig, UnifiedAgentConfig, UnifiedAgentProvider, UnifiedAgentRunOptions, UnifiedAgentState, UnifiedAgentStatus, agentKey, agentToMcpServer, buildToolHandlers, createAISDKAgent, createAgentMcpServer, createAgentRegistry, createApprovalWorkflow, createClaudeAgentSDKAgent, createInMemorySessionStore, createInMemoryTelemetryCollector, createKnowledgeInjector, createKnowledgeQueryTool, createMcpToolsets, createOpenCodeSDKAgent, createProviderRegistry, createSingleSpecConsumer, createSpecConsumer, createToolConsumer, createToolHandler, createToolServer, createUnifiedAgent, defaultProviderRegistry, defineAgent, enumToChoiceOutput, exportToClaudeAgent, exportToOpenCode, exportToolsForExternalSDK, generateClaudeMd, generateOpenCodeJSON, generateOpenCodeMarkdown, generateSessionId, type generateText, getAvailableBackends, injectStaticKnowledge, jsonSchemaToArrayOutput, jsonSchemaToOutput, jsonSchemaToZod, jsonSchemaToZodSafe, mcpServerToTools, noopTelemetryCollector, specToolToAISDKTool, specToolsToAISDKTools, textOutput, trackAgentStep, validateForClaudeAgent, validateForOpenCode, zodToOutput };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-consumer.js","names":["sections: string[]","results: SpecListResult[]"],"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
|
+
{"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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-consumer.js","names":["fullContext: ToolExecutionContext","definitions: {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[]","defaultContext: Partial<ToolExecutionContext>"],"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
|
+
{"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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injector.js","names":[
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","names":[
|
|
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;EACT,KAAK;EACL,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"}
|