{"version":3,"file":"agent-orchestrator.mjs","names":[],"sources":["../../../src/services/agent-orchestrator.ts"],"sourcesContent":["/**\n * Agent Orchestrator — executes sub-agent tasks via direct LLM API calls.\n *\n * The orchestrator:\n * 1. Detects the active LLM provider and API key\n * 2. Resolves the sub-agent's model shortcut to a provider-specific model ID\n * 3. Makes direct Messages API calls (Anthropic format) or Chat Completions\n *    calls (OpenAI-compatible format for OpenRouter/OpenAI/Bankr)\n * 4. Handles the tool-use loop: sub-agent requests tool calls → orchestrator\n *    executes them via the dispatcher → feeds results back to the LLM\n * 5. Enforces budget (max tool calls) and timeout\n *\n * No new dependencies — uses native fetch() and the existing guardedFetch()\n * for endpoint allowlisting.\n */\n\nimport { jsonResult, errorResult } from '../lib/tool-helpers.js';\nimport { getCredentialVault } from './credential-vault.js';\nimport type { SubAgentDef } from './agent-pool.js';\nimport type { ToolDispatcher } from './sandbox-runtime.js';\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport type LlmProvider = 'anthropic' | 'openrouter' | 'openai' | 'bankr';\n\nexport interface OrchestratorResult {\n  /** The sub-agent's final text response. */\n  response: string;\n  /** Tool calls made during execution. */\n  toolCalls: ToolCallRecord[];\n  /** Total LLM tokens used (input + output). Estimated. */\n  tokensUsed: number;\n  /** Execution time in ms. */\n  durationMs: number;\n  /** Whether the task completed or was cut short. */\n  status: 'completed' | 'timeout' | 'max_calls' | 'error';\n  /** Error message if status is 'error'. */\n  error?: string;\n}\n\nexport interface ToolCallRecord {\n  tool: string;\n  args: Record<string, unknown>;\n  result: string;\n  durationMs: number;\n}\n\n/** Tool schema for the sub-agent (simplified JSON Schema). */\ninterface ToolSchema {\n  name: string;\n  description: string;\n  input_schema: Record<string, unknown>;\n}\n\n// ─── Provider Detection ─────────────────────────────────────────────────\n\nexport function detectProvider(): LlmProvider {\n  const explicit = process.env.OPENCLAWNCH_LLM_PROVIDER;\n  if (explicit === 'bankr' || explicit === 'openrouter' || explicit === 'openai' || explicit === 'anthropic') {\n    return explicit as LlmProvider;\n  }\n  // Priority: Anthropic > OpenRouter > OpenAI > Bankr\n  if (process.env.ANTHROPIC_API_KEY) return 'anthropic';\n  if (process.env.OPENROUTER_API_KEY) return 'openrouter';\n  if (process.env.OPENAI_API_KEY) return 'openai';\n  if (process.env.BANKR_LLM_KEY) return 'bankr';\n  return 'anthropic'; // fallback\n}\n\nexport function getApiKey(provider: LlmProvider): string | null {\n  const vault = getCredentialVault();\n  switch (provider) {\n    case 'anthropic':\n      return vault.getSecret('llm.anthropic.apiKey', 'agent_orchestrator') ?? null;\n    case 'openrouter':\n      return vault.getSecret('llm.openrouter.apiKey', 'agent_orchestrator') ?? null;\n    case 'openai':\n      return vault.getSecret('llm.openai.apiKey', 'agent_orchestrator') ?? null;\n    case 'bankr':\n      return vault.getSecret('llm.bankr.key', 'agent_orchestrator') ?? null;\n    default:\n      return null;\n  }\n}\n\n// ─── Model Resolution ───────────────────────────────────────────────────\n\n/** Same model map as model-command.ts — maps shortcuts to provider-specific IDs. */\nconst SUB_AGENT_MODELS: Record<string, Record<LlmProvider, string>> = {\n  'haiku':    { anthropic: 'claude-haiku-4-20250514',      openrouter: 'anthropic/claude-haiku-4-20250514',      openai: 'claude-haiku-4-20250514',      bankr: 'claude-haiku-4.5' },\n  'sonnet':   { anthropic: 'claude-sonnet-4-20250514',     openrouter: 'anthropic/claude-sonnet-4-20250514',     openai: 'claude-sonnet-4-20250514',     bankr: 'claude-sonnet-4.6' },\n  'opus':     { anthropic: 'claude-opus-4-20250514',       openrouter: 'anthropic/claude-opus-4-20250514',       openai: 'claude-opus-4-20250514',       bankr: 'claude-opus-4.6' },\n  'gpt-mini': { anthropic: 'claude-haiku-4-20250514',      openrouter: 'openai/gpt-5-mini',                     openai: 'gpt-5-mini',                   bankr: 'gpt-5-mini' },\n  'gpt':      { anthropic: 'claude-sonnet-4-20250514',     openrouter: 'openai/gpt-5.2',                        openai: 'gpt-5.2',                      bankr: 'gpt-5.2' },\n};\n\nfunction resolveModel(shortcut: string, provider: LlmProvider): string {\n  const mapping = SUB_AGENT_MODELS[shortcut];\n  if (mapping) return mapping[provider];\n  // Not a shortcut — use as-is\n  return shortcut;\n}\n\n// ─── Anthropic Messages API ─────────────────────────────────────────────\n\ninterface AnthropicMessage {\n  role: 'user' | 'assistant';\n  content: AnthropicContent[];\n}\n\ntype AnthropicContent =\n  | { type: 'text'; text: string }\n  | { type: 'tool_use'; id: string; name: string; input: Record<string, unknown> }\n  | { type: 'tool_result'; tool_use_id: string; content: string; is_error?: boolean };\n\nasync function callAnthropic(\n  apiKey: string,\n  model: string,\n  system: string,\n  messages: AnthropicMessage[],\n  tools: ToolSchema[],\n  maxTokens: number,\n  temperature: number,\n  signal: AbortSignal,\n): Promise<{ content: AnthropicContent[]; usage: { input_tokens: number; output_tokens: number } }> {\n  const body: Record<string, unknown> = {\n    model,\n    max_tokens: maxTokens,\n    temperature,\n    system,\n    messages,\n  };\n  if (tools.length > 0) {\n    body.tools = tools;\n  }\n\n  const response = await fetch('https://api.anthropic.com/v1/messages', {\n    method: 'POST',\n    headers: {\n      'x-api-key': apiKey,\n      'anthropic-version': '2023-06-01',\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify(body),\n    signal,\n  });\n\n  if (!response.ok) {\n    const text = await response.text().catch(() => '');\n    throw new Error(`Anthropic API ${response.status}: ${text.slice(0, 200)}`);\n  }\n\n  const data = await response.json() as any;\n  return {\n    content: data.content ?? [],\n    usage: data.usage ?? { input_tokens: 0, output_tokens: 0 },\n  };\n}\n\n// ─── OpenAI-Compatible API (OpenRouter, OpenAI, Bankr) ──────────────────\n\nconst PROVIDER_URLS: Record<string, string> = {\n  openrouter: 'https://openrouter.ai/api/v1/chat/completions',\n  openai: 'https://api.openai.com/v1/chat/completions',\n  bankr: 'https://llm.bankr.bot/v1/chat/completions',\n};\n\ninterface OaiMessage {\n  role: 'system' | 'user' | 'assistant' | 'tool';\n  content?: string;\n  tool_calls?: Array<{ id: string; type: 'function'; function: { name: string; arguments: string } }>;\n  tool_call_id?: string;\n}\n\nasync function callOpenAICompat(\n  provider: LlmProvider,\n  apiKey: string,\n  model: string,\n  system: string,\n  messages: OaiMessage[],\n  tools: Array<{ type: 'function'; function: { name: string; description: string; parameters: Record<string, unknown> } }>,\n  maxTokens: number,\n  temperature: number,\n  signal: AbortSignal,\n): Promise<{ message: OaiMessage; usage: { prompt_tokens: number; completion_tokens: number } }> {\n  const url = PROVIDER_URLS[provider];\n  if (!url) throw new Error(`Unknown provider: ${provider}`);\n\n  const allMessages: OaiMessage[] = [\n    { role: 'system', content: system },\n    ...messages,\n  ];\n\n  const body: Record<string, unknown> = {\n    model,\n    max_tokens: maxTokens,\n    temperature,\n    messages: allMessages,\n  };\n  if (tools.length > 0) {\n    body.tools = tools;\n  }\n\n  const response = await fetch(url, {\n    method: 'POST',\n    headers: {\n      'Authorization': `Bearer ${apiKey}`,\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify(body),\n    signal,\n  });\n\n  if (!response.ok) {\n    const text = await response.text().catch(() => '');\n    throw new Error(`${provider} API ${response.status}: ${text.slice(0, 200)}`);\n  }\n\n  const data = await response.json() as any;\n  const choice = data.choices?.[0];\n  return {\n    message: choice?.message ?? { role: 'assistant', content: '' },\n    usage: data.usage ?? { prompt_tokens: 0, completion_tokens: 0 },\n  };\n}\n\n// ─── Tool Schema Builder ────────────────────────────────────────────────\n\n/**\n * Build tool schemas for the sub-agent from the registered tool list.\n * Only includes tools that are in the agent's allowedTools list.\n */\nexport function buildToolSchemas(\n  allowedTools: string[],\n  registeredTools: Array<{ name: string; description: string; parameters: any }>,\n): ToolSchema[] {\n  if (allowedTools.length === 0) return [];\n\n  const allowed = new Set(allowedTools);\n  return registeredTools\n    .filter(t => allowed.has(t.name))\n    .map(t => ({\n      name: t.name,\n      description: t.description,\n      input_schema: t.parameters ?? { type: 'object', properties: {} },\n    }));\n}\n\n// ─── Orchestrator ───────────────────────────────────────────────────────\n\n/**\n * Execute a task with a sub-agent.\n *\n * 1. Sends the task to the sub-agent's LLM with its system prompt\n * 2. If the LLM requests tool calls, executes them via the dispatcher\n * 3. Feeds tool results back and continues until the LLM produces a final response\n * 4. Enforces maxToolCalls and timeout\n */\nexport async function executeSubAgent(\n  agent: SubAgentDef,\n  task: string,\n  dispatcher: ToolDispatcher,\n  registeredTools: Array<{ name: string; description: string; parameters: any }>,\n): Promise<OrchestratorResult> {\n  const startTime = Date.now();\n  const provider = detectProvider();\n  const apiKey = getApiKey(provider);\n\n  if (!apiKey) {\n    return {\n      response: '',\n      toolCalls: [],\n      tokensUsed: 0,\n      durationMs: Date.now() - startTime,\n      status: 'error',\n      error: `No API key found for provider \"${provider}\". Set ANTHROPIC_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY, or BANKR_LLM_KEY.`,\n    };\n  }\n\n  const model = resolveModel(agent.model, provider);\n  const toolSchemas = buildToolSchemas(agent.allowedTools, registeredTools);\n  const toolCallRecords: ToolCallRecord[] = [];\n  let totalTokens = 0;\n  let callCount = 0;\n\n  const abort = AbortSignal.timeout(agent.timeoutMs);\n\n  try {\n    if (provider === 'anthropic') {\n      return await runAnthropicLoop(\n        apiKey, model, agent, task, toolSchemas, dispatcher,\n        toolCallRecords, startTime, abort,\n      );\n    } else {\n      return await runOpenAILoop(\n        provider, apiKey, model, agent, task, toolSchemas, dispatcher,\n        toolCallRecords, startTime, abort,\n      );\n    }\n  } catch (err) {\n    const isTimeout = err instanceof Error && (\n      err.name === 'TimeoutError' || err.name === 'AbortError' || err.message.includes('timed out')\n    );\n    return {\n      response: toolCallRecords.length > 0\n        ? `Sub-agent ${isTimeout ? 'timed out' : 'failed'} after ${toolCallRecords.length} tool call(s). Partial results may be available in the tool call log.`\n        : '',\n      toolCalls: toolCallRecords,\n      tokensUsed: totalTokens,\n      durationMs: Date.now() - startTime,\n      status: isTimeout ? 'timeout' : 'error',\n      error: err instanceof Error ? err.message : String(err),\n    };\n  }\n}\n\n// ─── Anthropic Tool-Use Loop ────────────────────────────────────────────\n\nasync function runAnthropicLoop(\n  apiKey: string,\n  model: string,\n  agent: SubAgentDef,\n  task: string,\n  toolSchemas: ToolSchema[],\n  dispatcher: ToolDispatcher,\n  toolCallRecords: ToolCallRecord[],\n  startTime: number,\n  signal: AbortSignal,\n): Promise<OrchestratorResult> {\n  const messages: AnthropicMessage[] = [\n    { role: 'user', content: [{ type: 'text', text: task }] },\n  ];\n\n  let totalTokens = 0;\n  let callCount = 0;\n\n  while (callCount <= agent.maxToolCalls) {\n    const result = await callAnthropic(\n      apiKey, model, agent.systemPrompt, messages, toolSchemas,\n      agent.maxTokens, agent.temperature, signal,\n    );\n\n    totalTokens += (result.usage.input_tokens + result.usage.output_tokens);\n\n    // Check if there are tool_use blocks\n    const toolUses = result.content.filter(c => c.type === 'tool_use') as\n      Array<{ type: 'tool_use'; id: string; name: string; input: Record<string, unknown> }>;\n\n    if (toolUses.length === 0) {\n      // Final response — extract text\n      const textParts = result.content.filter(c => c.type === 'text') as Array<{ type: 'text'; text: string }>;\n      const response = textParts.map(t => t.text).join('\\n');\n\n      return {\n        response,\n        toolCalls: toolCallRecords,\n        tokensUsed: totalTokens,\n        durationMs: Date.now() - startTime,\n        status: 'completed',\n      };\n    }\n\n    // Execute tool calls\n    messages.push({ role: 'assistant', content: result.content });\n\n    const toolResults: AnthropicContent[] = [];\n    for (const tu of toolUses) {\n      callCount++;\n      if (callCount > agent.maxToolCalls) {\n        toolResults.push({\n          type: 'tool_result',\n          tool_use_id: tu.id,\n          content: 'Error: Maximum tool calls reached. Please provide your final response.',\n          is_error: true,\n        });\n        break;\n      }\n\n      const callStart = Date.now();\n      try {\n        const toolResult = await dispatcher.call(tu.name, tu.input);\n        const resultText = typeof toolResult === 'string'\n          ? toolResult\n          : toolResult?.content?.[0]?.text ?? JSON.stringify(toolResult);\n\n        toolCallRecords.push({\n          tool: tu.name,\n          args: tu.input,\n          result: String(resultText).slice(0, 500),\n          durationMs: Date.now() - callStart,\n        });\n\n        toolResults.push({\n          type: 'tool_result',\n          tool_use_id: tu.id,\n          content: String(resultText),\n        });\n      } catch (err) {\n        const errMsg = err instanceof Error ? err.message : String(err);\n        toolCallRecords.push({\n          tool: tu.name,\n          args: tu.input,\n          result: `Error: ${errMsg}`,\n          durationMs: Date.now() - callStart,\n        });\n        toolResults.push({\n          type: 'tool_result',\n          tool_use_id: tu.id,\n          content: `Error: ${errMsg}`,\n          is_error: true,\n        });\n      }\n    }\n\n    messages.push({ role: 'user', content: toolResults });\n  }\n\n  // Max calls exceeded — ask for final response\n  return {\n    response: `Sub-agent reached maximum tool calls (${agent.maxToolCalls}). Results from ${toolCallRecords.length} call(s) are available.`,\n    toolCalls: toolCallRecords,\n    tokensUsed: totalTokens,\n    durationMs: Date.now() - startTime,\n    status: 'max_calls',\n  };\n}\n\n// ─── OpenAI-Compatible Tool-Use Loop ────────────────────────────────────\n\nasync function runOpenAILoop(\n  provider: LlmProvider,\n  apiKey: string,\n  model: string,\n  agent: SubAgentDef,\n  task: string,\n  toolSchemas: ToolSchema[],\n  dispatcher: ToolDispatcher,\n  toolCallRecords: ToolCallRecord[],\n  startTime: number,\n  signal: AbortSignal,\n): Promise<OrchestratorResult> {\n  // Convert tool schemas to OpenAI format\n  const oaiTools = toolSchemas.map(t => ({\n    type: 'function' as const,\n    function: {\n      name: t.name,\n      description: t.description,\n      parameters: t.input_schema,\n    },\n  }));\n\n  const messages: OaiMessage[] = [\n    { role: 'user', content: task },\n  ];\n\n  let totalTokens = 0;\n  let callCount = 0;\n\n  while (callCount <= agent.maxToolCalls) {\n    const result = await callOpenAICompat(\n      provider, apiKey, model, agent.systemPrompt, messages, oaiTools,\n      agent.maxTokens, agent.temperature, signal,\n    );\n\n    totalTokens += (result.usage.prompt_tokens + result.usage.completion_tokens);\n\n    const msg = result.message;\n    const toolCalls = msg.tool_calls ?? [];\n\n    if (toolCalls.length === 0) {\n      // Final response\n      return {\n        response: msg.content ?? '',\n        toolCalls: toolCallRecords,\n        tokensUsed: totalTokens,\n        durationMs: Date.now() - startTime,\n        status: 'completed',\n      };\n    }\n\n    // Execute tool calls\n    messages.push(msg);\n\n    for (const tc of toolCalls) {\n      callCount++;\n      if (callCount > agent.maxToolCalls) {\n        messages.push({\n          role: 'tool',\n          tool_call_id: tc.id,\n          content: 'Error: Maximum tool calls reached.',\n        });\n        break;\n      }\n\n      const callStart = Date.now();\n      let parsedArgs: Record<string, unknown> = {};\n      try {\n        parsedArgs = JSON.parse(tc.function.arguments);\n      } catch {\n        parsedArgs = {};\n      }\n\n      try {\n        const toolResult = await dispatcher.call(tc.function.name, parsedArgs);\n        const resultText = typeof toolResult === 'string'\n          ? toolResult\n          : toolResult?.content?.[0]?.text ?? JSON.stringify(toolResult);\n\n        toolCallRecords.push({\n          tool: tc.function.name,\n          args: parsedArgs,\n          result: String(resultText).slice(0, 500),\n          durationMs: Date.now() - callStart,\n        });\n\n        messages.push({\n          role: 'tool',\n          tool_call_id: tc.id,\n          content: String(resultText),\n        });\n      } catch (err) {\n        const errMsg = err instanceof Error ? err.message : String(err);\n        toolCallRecords.push({\n          tool: tc.function.name,\n          args: parsedArgs,\n          result: `Error: ${errMsg}`,\n          durationMs: Date.now() - callStart,\n        });\n        messages.push({\n          role: 'tool',\n          tool_call_id: tc.id,\n          content: `Error: ${errMsg}`,\n        });\n      }\n    }\n  }\n\n  return {\n    response: `Sub-agent reached maximum tool calls (${agent.maxToolCalls}).`,\n    toolCalls: toolCallRecords,\n    tokensUsed: totalTokens,\n    durationMs: Date.now() - startTime,\n    status: 'max_calls',\n  };\n}\n"],"mappings":"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"}