@khalilgharbaoui/opencode-claude-code-plugin 0.12.1 → 0.13.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/README.md +17 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +128 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/claude-code-language-model.ts","../src/logger.ts","../src/todo-ledger.ts","../src/tool-mapping.ts","../src/message-builder.ts","../src/plan-mode-question.ts","../src/mcp-bridge.ts","../src/tmp.ts","../src/runtime-status.ts","../src/session-manager.ts","../src/cli-version.ts","../src/claude-session-wrapper.ts","../src/claude-session-bun.ts","../src/proxy-mcp.ts","../src/proxy-broker.ts","../src/models.ts","../src/accounts.ts","../src/cleanup-stale.ts","../src/startup-diagnostics.ts","../src/index.ts"],"sourcesContent":["import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n SharedV3Warning,\n} from \"@ai-sdk/provider\"\nimport { generateId } from \"@ai-sdk/provider-utils\"\nimport type {\n ClaudeCodeConfig,\n ControlRequestBehavior,\n ClaudeStreamMessage,\n ReasoningEffort,\n} from \"./types.js\"\nimport { mapTool, isWebSearchTool, isWebSearchHandledByCli } from \"./tool-mapping.js\"\nimport { applyTaskCreateToolResult } from \"./todo-ledger.js\"\nimport { getClaudeUserMessage } from \"./message-builder.js\"\nimport {\n QUESTION_TOOL_NAME,\n consumeExitPlanModeQuestionResult,\n createExitPlanModeQuestionCall,\n isPlanModeQuestionActive,\n} from \"./plan-mode-question.js\"\nimport { bridgeOpencodeMcp, type RuntimeMcpStatus } from \"./mcp-bridge.js\"\nimport {\n getRuntimeMcpStatus,\n fetchOpencodeToolList,\n resolveSpawnCwd,\n} from \"./runtime-status.js\"\nimport {\n getActiveProcess,\n setActiveProcess,\n spawnClaudeProcess,\n buildCliArgs,\n setClaudeSessionId,\n getClaudeSessionId,\n deleteClaudeSessionId,\n deleteActiveProcess,\n deleteActiveProcessAndWait,\n respawnActiveProcess,\n claudeSpawnEnv,\n isClaudeThinkingDisabled,\n sessionKey,\n} from \"./session-manager.js\"\nimport { spawnInteractiveProcess } from \"./claude-session-wrapper.js\"\nimport { log } from \"./logger.js\"\nimport { detectCliVersion } from \"./cli-version.js\"\nimport {\n createProxyMcpServer,\n disallowedToolFlags,\n DEFAULT_PROXY_TOOLS,\n overlayTaskProxyDescription,\n overlayQuestionProxyDescription,\n filterQuestionProxyByOpencodeSupport,\n PROXY_TOOL_PREFIX,\n type ProxyMcpServer,\n type ProxyToolCall,\n type ProxyToolDef,\n type ProxyToolResult,\n} from \"./proxy-mcp.js\"\nimport {\n getPendingProxyCalls,\n onPendingProxyCall,\n queuePendingProxyCall,\n rejectAllPendingProxyCallsForSession,\n rejectPendingProxyCallById,\n resolvePendingProxyCallById,\n type PendingProxyCall,\n} from \"./proxy-broker.js\"\nimport { readFileSync, writeFileSync } from \"node:fs\"\nimport { unlink } from \"node:fs/promises\"\nimport { homedir, tmpdir } from \"node:os\"\nimport { randomUUID } from \"node:crypto\"\nimport { dirname, join } from \"node:path\"\n\n/**\n * Default model used for opencode `/compact`. Haiku 4.5 is fast\n * (~150 tok/s), has a hard 8k output cap that bounds latency, and is a\n * strong structured summarizer. Override per-project via the\n * `compactionModel` provider setting in opencode.json / opencode.jsonc,\n * or per-run via the `CLAUDE_CODE_COMPACTION_MODEL` env var (env wins).\n */\nexport const DEFAULT_COMPACTION_MODEL = \"claude-haiku-4-5\"\n\n/**\n * Pick the model used to handle /compact. Precedence:\n * 1. `CLAUDE_CODE_COMPACTION_MODEL` env var (per-process override)\n * 2. `configured` argument (the `compactionModel` provider setting)\n * 3. `DEFAULT_COMPACTION_MODEL`\n *\n * Exported as a free function so it can be unit-tested without\n * instantiating the language model class.\n */\nexport function resolveCompactionModel(configured?: string): string {\n const env = process.env.CLAUDE_CODE_COMPACTION_MODEL?.trim()\n if (env) return env\n const trimmed = configured?.trim()\n if (trimmed) return trimmed\n return DEFAULT_COMPACTION_MODEL\n}\n\n/**\n * Resolve the session affinity token for a given LLM call. The affinity\n * token is part of the session key in session-manager so two different\n * opencode sessions sharing the same cwd+model still get separate Claude\n * CLI processes.\n *\n * Priority:\n * 1. `x-session-affinity` request header (primary — opencode sets it for\n * third-party providers in packages/opencode/src/session/llm.ts).\n * 2. `opencodeSessionID` inside `providerOptions` (injected by the\n * `chat.params` hook in index.ts). Covers cases where the header is\n * absent: provider switch mid-session, title synthesis paths, older\n * opencode versions. opencode wraps `output.options` under the\n * providerID before passing it to the language model, so we look up\n * both the configured provider key and the canonical `\"claude-code\"`.\n * 3. `\"default\"` — safe fallback when neither source is available.\n *\n * Exported as a free function so it can be unit-tested without\n * instantiating the language model class.\n */\nexport function resolveSessionAffinity(\n headers: Record<string, string | undefined> | undefined,\n providerOptions: Record<string, unknown> | undefined,\n providerKey: string,\n): string {\n if (headers) {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === \"x-session-affinity\") {\n const v = headers[key]\n if (typeof v === \"string\" && v.length > 0) return v\n }\n }\n }\n if (providerOptions) {\n const bag =\n (providerOptions as any)[providerKey] ??\n (providerOptions as any)[\"claude-code\"]\n const sid = bag?.opencodeSessionID\n if (typeof sid === \"string\" && sid.length > 0) return sid\n }\n return \"default\"\n}\n\n/**\n * Stream delta types we handle explicitly. `signature_delta` is listed as\n * known-and-silent: it carries encrypted thinking-block signatures that\n * are opaque to clients (the server uses them to reconstitute thinking\n * across turns), so there's nothing for us to do but ignore it.\n */\nconst KNOWN_DELTA_TYPES = new Set([\n \"thinking_delta\",\n \"text_delta\",\n \"input_json_delta\",\n \"signature_delta\",\n])\n\n/**\n * True if the prompt has any user-side content after the last assistant\n * message (text, tool_result, or any user role entry). False when the\n * prompt ends with an assistant message and there is nothing for Claude\n * to respond to — opencode sometimes iterates the agent loop one more\n * time after a turn naturally completed; without short-circuiting we'd\n * spawn Claude CLI on an empty turn and the model would reply with a\n * stub like \"Did you mean to send a message?\".\n */\nexport function hasNewUserContent(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n): boolean {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role === \"assistant\") return false\n // Tool-result turns from opencode's outer loop arrive in `tool`-role\n // messages (AI SDK V3 shape). Treat any tool-result part as new\n // content so the short-circuit doesn't drop turns where opencode is\n // delivering the result for a still-pending proxy MCP call — letting\n // that fire `stop` is what was forcing the user to press \"continue\".\n if (msg.role === \"tool\") {\n const content: any = msg.content\n if (Array.isArray(content)) {\n for (const part of content as any[]) {\n if (part?.type === \"tool-result\") return true\n }\n }\n continue\n }\n if (msg.role !== \"user\") continue\n const content: any = msg.content\n if (typeof content === \"string\") {\n if (content.trim()) return true\n continue\n }\n if (Array.isArray(content)) {\n for (const part of content as any[]) {\n if (part.type === \"text\" && part.text && part.text.trim()) return true\n if (part.type === \"tool-result\") return true\n // Image/file-only user turns count as new input — without this the\n // short-circuit drops them as if the turn were empty.\n if (part.type === \"image\" || part.type === \"file\") return true\n }\n }\n }\n return false\n}\n\nconst AUTO_CONTINUE_MAX_ATTEMPTS = 8\nconst AUTO_CONTINUE_MAX_ELAPSED_MS = 10 * 60 * 1000\nconst AUTO_CONTINUE_NO_PROGRESS_LIMIT = 2\nconst PROXY_RESULT_BOUNDARY_GRACE_MS = 250\n\nconst AUTO_CONTINUE_PROMPT =\n \"Continue the task from where you stopped. Do not summarize; keep working until the requested task is complete, you need clarification, or you hit a real blocker.\"\n\n/** One per-turn snapshot of opencode's live tool registry. */\ninterface LiveToolInfo {\n /** False when nothing answered (no SDK client, fetch failed). */\n resolved: boolean\n taskDescription: string | undefined\n questionDescription: string | undefined\n hasQuestion: boolean\n}\n\ninterface AutoContinueState {\n enabled: boolean | \"smart\" | undefined\n attempts: number\n startedAt: number\n noProgressCount: number\n lastSignature?: string\n aborted?: boolean\n /**\n * Latched true once AskUserQuestion is rendered this turn. Auto-continue\n * must never fire afterwards: the model has handed control to the operator\n * and is waiting for a real reply. Without this, a short trailing text after\n * the question (one that doesn't trip looksLikeQuestion) would let the turn\n * look \"incomplete\", and the auto-continue nudge would make the model\n * proceed on its own — which the operator sees as the question being\n * answered/cancelled without them ever interacting.\n */\n sawAskUserQuestion?: boolean\n}\n\ninterface AutoContinueSnapshot {\n text: string\n /**\n * Text of the most recent assistant text block only. Used for final-answer\n * detection so mid-task narration like \"Implementing now. Updated the\n * search index.\" in an earlier block doesn't trip the keyword regex.\n */\n lastVisibleText: string\n hadReasoning: boolean\n hadToolActivity: boolean\n hadProxyActivity: boolean\n isError?: boolean\n /**\n * Protocol-level stop signal from the Claude API (forwarded by Claude\n * CLI). When present and non-empty, we trust it as authoritative — the\n * model itself signaled why the turn ended (`end_turn`, `max_tokens`,\n * `stop_sequence`, `refusal`, `pause_turn`, `tool_use`, etc.) — and stop\n * without running the keyword regex. The heuristic only runs as a\n * fallback when `stop_reason` is missing (older CLI versions, abrupt\n * termination).\n */\n stopReason?: string | null\n now?: number\n}\n\ninterface AutoContinueDecision {\n continue: boolean\n reason: string\n}\n\nfunction normalizeVisibleText(text: string): string {\n return text.replace(/\\s+/g, \" \").trim()\n}\n\n/** Tool names that mean \"ask the human a question\" (CLI casing variants). */\nexport function isAskUserQuestionTool(name: string | undefined): boolean {\n if (!name) return false\n const n = name.toLowerCase()\n return n === \"askuserquestion\" || n === \"ask_user_question\"\n}\n\n/**\n * Deny message returned to the model when it invokes AskUserQuestion.\n *\n * AskUserQuestion is denied (see controlRequestBehaviorForTool) so the\n * headless CLI cannot self-answer against an empty TTY. The question is\n * already rendered to the operator by formatAskUserQuestion, so this text\n * tells the model to stop and wait — unconditionally. Earlier versions\n * offered an \"if this is non-interactive, proceed with a reasonable guess\"\n * escape hatch, but the model could not reliably tell interactive opencode\n * from a headless run and routinely took it, so questions appeared to be\n * skipped (issue #8). Stopping is the correct default for opencode; a\n * headless run simply ends the turn with the question as its final output.\n */\nconst ASK_USER_QUESTION_DENY_MESSAGE =\n \"Your question and its options have already been presented to the\" +\n \" operator verbatim. This is NOT a cancellation or a refusal — the\" +\n \" operator simply has not answered yet. Stop now: end your turn without\" +\n \" calling any more tools and without answering the question yourself. Do\" +\n \" not say the question was cancelled, skipped, or declined, and do not\" +\n \" guess, assume, or proceed on their behalf. Wait for the operator's\" +\n \" reply, which arrives as the next user message.\"\n\n/** Build the deny message for an auto-denied control request. */\nexport function denyMessageForTool(\n toolName: string | undefined,\n configuredDenyMessage?: string,\n): string {\n if (isAskUserQuestionTool(toolName)) return ASK_USER_QUESTION_DENY_MESSAGE\n return (\n configuredDenyMessage ??\n `Denied by opencode-claude-code policy for tool ${toolName}`\n )\n}\n\n/**\n * Render Claude Code's `AskUserQuestion` tool input as visible markdown.\n *\n * This is the fallback path used when the `Question` proxy is off or the\n * opencode build lacks the `question` registry entry. When the proxy is\n * enabled, `AskUserQuestion` is disabled via `--disallowedTools` and the\n * model calls `mcp__opencode_proxy__question` instead (opencode's native\n * `question` tool renders the TUI form). Here, the question + every\n * option is rendered as readable assistant text and the user answers in\n * the next turn — same approach as the `ExitPlanMode` handling. The\n * previous behavior collapsed the whole payload to a single faint\n * `_Asking: <q>_` line, dropping all options and any question past the\n * first.\n */\nfunction formatAskUserQuestion(input: Record<string, unknown>): string {\n const anyInput = input as any\n const questions: any[] = Array.isArray(anyInput?.questions)\n ? anyInput.questions\n : []\n\n if (questions.length === 0) {\n const single = anyInput?.question ?? anyInput?.text\n const q =\n typeof single === \"string\" && single.trim() ? single.trim() : \"Question?\"\n return `\\n\\n**${q}**\\n\\n_Reply with your answer to continue._\\n\\n`\n }\n\n const out: string[] = [\"\\n\\n\"]\n const multiQ = questions.length > 1\n questions.forEach((q, i) => {\n const text =\n (typeof q?.question === \"string\" && q.question.trim()) ||\n (typeof q?.text === \"string\" && q.text.trim()) ||\n \"Question?\"\n const header =\n typeof q?.header === \"string\" && q.header.trim() ? q.header.trim() : \"\"\n out.push(`**${multiQ ? `${i + 1}. ` : \"\"}${text}**`)\n if (header) out.push(` _(${header})_`)\n out.push(\"\\n\\n\")\n\n const options: any[] = Array.isArray(q?.options) ? q.options : []\n options.forEach((opt, j) => {\n const label =\n (typeof opt?.label === \"string\" && opt.label.trim()) ||\n (typeof opt === \"string\" && opt.trim()) ||\n `Option ${j + 1}`\n const desc =\n typeof opt?.description === \"string\" && opt.description.trim()\n ? ` — ${opt.description.trim()}`\n : \"\"\n out.push(`${j + 1}. **${label}**${desc}\\n`)\n })\n\n out.push(\n q?.multiSelect === true\n ? \"\\n_Select one or more — reply with the numbers or labels._\\n\\n\"\n : \"\\n_Reply with your choice (the number or label)._\\n\\n\",\n )\n })\n return out.join(\"\")\n}\n\nfunction looksLikeQuestion(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (!normalized) return false\n // v0.4.10 tweak 5a: '?' anywhere in the last block, not just trailing.\n // Catches long answers that pose a question mid-text then list options\n // and end with a period. FP risk on inline code (`result?.value`) is\n // accepted — cost is one extra \"continue\" press, in the safe direction.\n if (normalized.includes(\"?\")) return true\n // v0.4.11 additions: ready when you are / standing by / i'll stand by /\n // let me know when. These are awaiting-input idioms with no '?'. The\n // \"standing by\" addition has historical significance — it's the exact\n // stub phrase Claude CLI emits on empty turns that commit 49345e3 was\n // designed to suppress at the message-builder layer. This adds a second\n // line of defense at the model-output layer for cases where the model\n // organically produces the same idiom.\n //\n // v0.4.12 additions: over to you / your turn / all yours / let me know\n // how / i'm here. Defensive coverage of soft-proceed idioms in the\n // model's vocabulary. \"i'm here\" has the highest FP risk (\"I'm here to\n // help with X\" is a conversational opener) but cost of FP is one extra\n // continue press — safe direction.\n return /\\b(please confirm|can you confirm|should i|would you like|do you want|which option|choose|pick one|need your|need you to|what would you like|let me know if|let me know whether|let me know what|let me know when|let me know how|if you'?d like|if you want to|tell me if|tell me which|tell me whether|say (?:go|yes|no)|push back|sign off|sounds? (?:good|right)|your call|your move|your turn|over to you|all yours|up to you|ready to (?:ship|go|proceed|merge)|ready (?:when|whenever|once|if) you|standing by|i'?ll stand ?by|i'?m here|happy to (?:ship|go|proceed|merge))\\b/.test(normalized)\n}\n\nfunction looksLikeBlocker(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (!normalized) return false\n // v0.4.10 tweak 3: 'needs your' / 'needs you to' / 'action required'\n // are intent-equivalent to 'requires your' but use the verb-with-s form.\n return /\\b(blocked|blocker|cannot proceed|can't proceed|unable to proceed|need clarification|need more information|permission denied|failed and needs|requires your|needs your|needs you to|action required|manual step|required from you)\\b/.test(normalized)\n}\n\nfunction looksLikeFinalAnswer(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (looksLikeQuestion(normalized) || looksLikeBlocker(normalized)) return false\n // v0.4.15: strong-completion phrases bypass the 30-char length floor.\n // These are unambiguous end-of-turn signals at any text length — even\n // a short standalone \"We're done.\" should stop.\n if (/\\b(we'?re done|we are done|all done|all set)\\b/.test(normalized)) {\n return true\n }\n // v0.4.10 tweak 4: floor lowered 40 → 30 chars. Catches short clean\n // completions like \"Task is now completely done. Pushed.\" (36 chars)\n // while keeping a buffer against ambiguous short narration.\n if (normalized.length < 30) return false\n // v0.4.15: keyword list extended with deploy/ship verbs the model\n // routinely uses at turn end (shipped, deployed, merged, tagged, live,\n // pinned). FP risk highest on \"live\" — \"live data\" mid-turn could match\n // — but cost of FP is one extra continue press, safe direction.\n return /\\b(done|completed|fixed|implemented|verified|published|released|sent|delivered|updated|shipped|deployed|merged|tagged|live|pinned)\\b/.test(normalized) ||\n // v0.4.15: also accept present-tense \"tests pass\" / \"checks pass\".\n // Real fire 03:31 ended in \"78/78 tests pass\" — past-tense-only regex\n // missed it.\n /\\b(checks?|tests?) (?:pass|passes|passed)\\b/.test(normalized) ||\n /\\b(summary|what changed|verification)\\b/.test(normalized)\n}\n\nfunction continuationSignature(snapshot: AutoContinueSnapshot): string {\n const text = normalizeVisibleText(snapshot.text).slice(-500)\n return JSON.stringify({\n text,\n reasoning: snapshot.hadReasoning,\n tools: snapshot.hadToolActivity,\n proxy: snapshot.hadProxyActivity,\n })\n}\n\nexport function shouldAutoContinueIncompleteTurn(\n state: AutoContinueState,\n snapshot: AutoContinueSnapshot,\n): AutoContinueDecision {\n if (state.enabled === false) return { continue: false, reason: \"disabled\" }\n if (snapshot.isError) return { continue: false, reason: \"error\" }\n if (state.aborted) return { continue: false, reason: \"aborted\" }\n // Once the model asked the operator a question this turn, never nudge it to\n // continue — it is waiting for a reply, not stalled. Latched so it holds\n // even when the trailing text after the question doesn't read as a question.\n if (state.sawAskUserQuestion) return { continue: false, reason: \"question\" }\n // v0.4.17: trust ANY protocol-level stop_reason as authoritative. If\n // Claude CLI emitted a stop_reason value at all, the model has signaled\n // a stop — honor it without consulting the keyword heuristic. The\n // heuristic only runs as a fallback when stop_reason is missing (older\n // CLI versions / edge cases). Maps snake_case → kebab-case for reason\n // label consistency with other reasons.\n if (snapshot.stopReason) {\n return {\n continue: false,\n reason: snapshot.stopReason.replace(/_/g, \"-\"),\n }\n }\n if (state.attempts >= AUTO_CONTINUE_MAX_ATTEMPTS) {\n return { continue: false, reason: \"max-attempts\" }\n }\n const now = snapshot.now ?? Date.now()\n if (now - state.startedAt > AUTO_CONTINUE_MAX_ELAPSED_MS) {\n return { continue: false, reason: \"max-elapsed\" }\n }\n\n const text = normalizeVisibleText(snapshot.text)\n const lastText = normalizeVisibleText(snapshot.lastVisibleText)\n if (looksLikeQuestion(text)) return { continue: false, reason: \"question\" }\n if (looksLikeBlocker(text)) return { continue: false, reason: \"blocker\" }\n // Final-answer detection runs on the most recent text block only. Earlier\n // blocks may contain mid-task narration that would false-positive the\n // keyword regex; the model's actual \"I'm done\" sentence is in the last\n // block before result/end_turn.\n if (looksLikeFinalAnswer(lastText)) {\n return { continue: false, reason: \"final-answer\" }\n }\n\n const hadActivity =\n snapshot.hadReasoning || snapshot.hadToolActivity || snapshot.hadProxyActivity\n if (!hadActivity) return { continue: false, reason: \"no-activity\" }\n\n const signature = continuationSignature(snapshot)\n const noProgress = signature === state.lastSignature\n if (noProgress && state.noProgressCount + 1 >= AUTO_CONTINUE_NO_PROGRESS_LIMIT) {\n return { continue: false, reason: \"no-progress\" }\n }\n\n if (!text) {\n return { continue: true, reason: \"activity-without-visible-answer\" }\n }\n\n return { continue: true, reason: \"non-final-progress\" }\n}\n\nfunction makeAutoContinueMessage(): string {\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: AUTO_CONTINUE_PROMPT }],\n },\n })\n}\n\nfunction readPromptFileIfPresent(path: string): string | undefined {\n try {\n const content = readFileSync(path, \"utf8\").trim()\n return content || undefined\n } catch {\n return undefined\n }\n}\n\nfunction nearestWorkspaceAgentsPrompt(cwd: string): string | undefined {\n let dir = cwd\n while (true) {\n const content = readPromptFileIfPresent(join(dir, \"AGENTS.md\"))\n if (content) return content\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nconst AGENTS_MAINTENANCE_HINT = `## Keeping AGENTS.md up to date\n\nWhen you complete a task, phase, or to-do item that is listed in AGENTS.md, update the file\nimmediately after the work is done — mark it ✅, check it off, or remove it. Do this inside\nthe same turn so the next session does not repeat work that is already finished.`\n\nconst MULTI_STEP_TASK_HINT = `## Continuing through multi-step tasks\n\nopencode requires the user to press \"continue\" after each turn ends. When a\ntask has multiple steps, do them all in one turn — chain tool calls rather\nthan pausing for user confirmation between subtasks. End the turn only\nwhen the task is done, you need clarification on intent, or you hit a real\nblocker. The user can interrupt or abort at any time; turn endings should\nmark meaningful checkpoints, not every completed substep.`\n\n/**\n * Appended to the system prompt whenever the `task` proxy tool is\n * enabled. Live sessions (2026-07-04) showed models resolving opencode's\n * \"call the task tool with subagent: X\" mention hint to Claude Code's\n * native TaskCreate: haiku created a todo and narrated a dispatch that\n * never happened; sonnet probed TaskCreate's schema before recovering.\n * The proxy tool can also be deferred behind ToolSearch, in which case\n * \"the task tool\" is invisible while TaskCreate is not. Name the exact\n * tool, the recovery path, and the failure mode.\n */\nexport const SUBAGENT_DISPATCH_HINT = `## opencode subagents\n\nSubagent dispatch in this environment goes through exactly one tool: \\`mcp__opencode_proxy__task\\`.\n\n- When the user mentions \\`@<agent>\\` or an instruction says \"call the task tool with subagent: <name>\", call \\`mcp__opencode_proxy__task\\` with \\`subagent_type: \"<name>\"\\`.\n- If that tool is not in your visible tool list it is deferred — load it with ToolSearch (\\`select:mcp__opencode_proxy__task\\`), then call it.\n- Claude Code's built-in TaskCreate/TaskUpdate/TaskList manage a local todo list. They cannot dispatch subagents; creating a task there runs nothing. Never report a subagent as dispatched unless \\`mcp__opencode_proxy__task\\` returned its result.\n- Do not verify a subagent's existence by searching config files — the tool's description lists the available agent types, and invalid types fail fast with a clear error.`\n\n/**\n * Appended to the system prompt whenever the `question` proxy tool is\n * enabled. Live testing (2026-07-05, haiku) showed the model's reasoning\n * correctly identified `mcp__opencode_proxy__question` as the tool to use,\n * but then emitted a tool call for bare `question` — stripping the MCP\n * prefix. opencode's AI SDK bridge has no bare `question` tool, so the\n * call rendered as `⚙ invalid`. Same near-miss pattern the task proxy\n * hit (TaskCreate vs mcp__opencode_proxy__task); the fix is the same:\n * name the exact tool in the system prompt so the model doesn't\n * abbreviate.\n */\nexport const QUESTION_PROXY_HINT = `## Asking the operator questions\n\nStructured questions in this environment go through exactly one tool: \\`mcp__opencode_proxy__question\\`.\n\n- When you need to ask the operator a question with options, call \\`mcp__opencode_proxy__question\\` with a \\`questions\\` array (each item has \\`question\\`, \\`header\\`, \\`options\\` of \\`{label, description}\\`, and optional \\`multiple\\`).\n- If that tool is not in your visible tool list it is deferred — load it with ToolSearch (\\`select:mcp__opencode_proxy__question\\`), then call it by its FULL name.\n- Do NOT call bare \\`question\\` — that is not a tool. Always use the full \\`mcp__opencode_proxy__question\\` name when invoking it.\n- Claude Code's built-in \\`AskUserQuestion\\` is disabled in this environment; the proxy is the only way to ask structured questions.`\n\n/**\n * Prepended to every appended system prompt so Claude knows which\n * context-management tools exist in the Claude CLI runtime versus a\n * direct API provider. DCP and similar plugins forward compress/distill/\n * prune instructions via system.transform; those reach us through\n * extractSystemMessages, but the tools themselves are not available in\n * the CLI environment. Without this note Claude wastes thinking cycles\n * searching for tools that don't exist.\n */\nconst CLAUDE_CLI_CONTEXT_NOTE = `## Runtime environment: Claude Code CLI\n\nYou are running via the Claude Code CLI (not a direct API call). This affects context management:\n\n- The \\`compress\\` tool is NOT available. Do not attempt to call it.\n- The \\`distill\\`, \\`prune\\`, and \\`extract\\` tools are NOT available.\n- Context window management is handled automatically by Claude CLI's own session history.\n- Ignore any system instructions that tell you to call \\`compress\\` — they are intended for direct API providers, not this environment.\n- DCP context injections (AGENTS.md, dynamic state) arrive via the system prompt and are already applied.`\n\n/**\n * Extract text content from all `system`-role messages in the prompt.\n * Standard API providers forward these as the `system` parameter; for\n * Claude CLI, the only equivalent path is --append-system-prompt-file.\n * Plugins like opencode-dcp inject AGENTS.md and other context via\n * system-role messages and would otherwise be silently dropped.\n */\nfunction extractSystemMessages(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n): string[] {\n const out: string[] = []\n for (const msg of prompt) {\n if (msg.role !== \"system\") continue\n if (typeof msg.content === \"string\") {\n if (msg.content.trim()) out.push(msg.content.trim())\n } else if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (\n part?.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text.trim()\n ) {\n out.push(part.text.trim())\n }\n }\n }\n }\n return out\n}\n\nexport function buildAppendedSystemPrompt(\n cwd: string,\n includeMultiStepHint = true,\n extraSystemContent: string[] = [],\n): string | undefined {\n const parts: string[] = []\n parts.push(CLAUDE_CLI_CONTEXT_NOTE)\n for (const s of extraSystemContent) {\n if (s.trim()) parts.push(s.trim())\n }\n const configRoot =\n process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\")\n const globalAgents = readPromptFileIfPresent(join(configRoot, \"opencode\", \"AGENTS.md\"))\n const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd)\n\n if (globalAgents) parts.push(globalAgents)\n if (workspaceAgents && workspaceAgents !== globalAgents) parts.push(workspaceAgents)\n if (globalAgents || workspaceAgents) parts.push(AGENTS_MAINTENANCE_HINT)\n if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT)\n\n const content = parts.join(\"\\n\\n\")\n if (!content) return undefined\n\n const path = join(tmpdir(), `opencode-cc-sys-${randomUUID()}.md`)\n try {\n writeFileSync(path, content, \"utf8\")\n return path\n } catch (err) {\n log.warn(\"failed to write system prompt file\", { error: String(err) })\n return undefined\n }\n}\n\nexport class ClaudeCodeLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\"\n readonly modelId: string\n private readonly config: ClaudeCodeConfig\n\n constructor(modelId: string, config: ClaudeCodeConfig) {\n this.modelId = modelId\n this.config = config\n }\n\n readonly supportedUrls: Record<string, RegExp[]> = {}\n\n get provider(): string {\n return this.config.provider\n }\n\n private toUsage(rawUsage?: ClaudeStreamMessage[\"usage\"]): LanguageModelV3Usage {\n // Prefer the last iteration's counters over cumulative totals.\n // CLI usage is the sum across all internal tool-use iterations;\n // using it directly inflates context size and triggers premature compaction.\n const iter = rawUsage?.iterations\n const effective = iter?.length ? iter[iter.length - 1] : rawUsage\n // Claude CLI reports input_tokens as non-cached input only.\n // OpenCode expects total = noCache + cacheRead + cacheWrite.\n const noCache = effective?.input_tokens ?? 0\n const cacheRead = effective?.cache_read_input_tokens ?? 0\n const cacheWrite = effective?.cache_creation_input_tokens ?? 0\n return {\n inputTokens: {\n total: noCache + cacheRead + cacheWrite,\n noCache,\n cacheRead: cacheRead || undefined,\n cacheWrite: cacheWrite || undefined,\n },\n outputTokens: {\n total: effective?.output_tokens,\n text: effective?.output_tokens,\n reasoning: undefined,\n },\n raw: rawUsage as any,\n }\n }\n\n private toFinishReason(\n reason: \"stop\" | \"tool-calls\" = \"stop\",\n ): LanguageModelV3FinishReason {\n return {\n unified: reason,\n raw: reason,\n }\n }\n\n private requestScope(options: { tools?: unknown }): \"tools\" | \"no-tools\" {\n const tools = options?.tools\n if (Array.isArray(tools)) return \"tools\"\n if (tools && typeof tools === \"object\") {\n return Object.keys(tools as Record<string, unknown>).length > 0\n ? \"tools\"\n : \"no-tools\"\n }\n return \"no-tools\"\n }\n\n /**\n * Build the combined `--mcp-config` list and return both the list and the\n * hash of the bridged opencode MCP block (or null when bridging is off /\n * yields nothing). The hash is used to detect mid-session config changes\n * and respawn the underlying claude process.\n *\n * `runtimeStatus` is a snapshot of opencode's `client.mcp.status()`. When\n * provided it overlays opencode's UI-toggled state on top of disk config\n * so `/mcps` toggles propagate without a config file write.\n */\n private effectiveMcpConfig(\n cwd: string,\n proxyConfigPath?: string,\n runtimeStatus?: RuntimeMcpStatus,\n excludeServers?: ReadonlySet<string>,\n ): {\n paths: string[]\n bridgedHash: string | null\n allEnabledServerNames: string[]\n } {\n const paths = Array.isArray(this.config.mcpConfig)\n ? this.config.mcpConfig.slice()\n : this.config.mcpConfig\n ? [this.config.mcpConfig]\n : []\n let bridgedHash: string | null = null\n let allEnabledServerNames: string[] = []\n if (this.config.bridgeOpencodeMcp !== false) {\n const bridged = bridgeOpencodeMcp(cwd, runtimeStatus, excludeServers)\n if (bridged) {\n if (bridged.path) paths.push(bridged.path)\n bridgedHash = bridged.hash\n allEnabledServerNames = bridged.allEnabledServerNames\n }\n }\n if (proxyConfigPath) paths.push(proxyConfigPath)\n return { paths, bridgedHash, allEnabledServerNames }\n }\n\n /** Resolve ProxyToolDef[] for the configured proxyTools names. */\n private resolvedProxyTools(): ProxyToolDef[] | null {\n const names = this.config.proxyTools\n if (!names || names.length === 0) return null\n const defsByName = new Map(\n DEFAULT_PROXY_TOOLS.map((t) => [t.name.toLowerCase(), t]),\n )\n const picked: ProxyToolDef[] = []\n for (const n of names) {\n const def = defsByName.get(String(n).toLowerCase())\n if (def) picked.push(def)\n }\n return picked.length > 0 ? picked : null\n }\n\n /**\n * Resolve ProxyToolDef[] for opencode's MCP-bridged tools so they go\n * through the in-process proxy instead of being bridged into Claude CLI's\n * `--mcp-config`. Direct bridging causes double execution because both\n * Claude CLI's own MCP child and opencode hold their own connection to\n * the same server; routing through the proxy keeps a single execution\n * site (opencode). Returns null when the feature is disabled, the SDK\n * client is unavailable, or no MCP servers are configured.\n */\n private async resolvedProxyMcpTools(\n allEnabledServerNames: string[],\n ): Promise<ProxyToolDef[] | null> {\n if (this.config.proxyOpencodeMcpTools === false) return null\n if (this.config.bridgeOpencodeMcp === false) return null\n if (allEnabledServerNames.length === 0) return null\n\n const items = await fetchOpencodeToolList(\n this.config.provider,\n this.modelId,\n this.config.cwd,\n )\n if (!items || items.length === 0) return null\n\n // opencode names MCP tools `<server>_<originalToolName>`. Match the\n // longest server name prefix first so e.g. `slack_intl_*` resolves to\n // server `slack_intl` not `slack`.\n const serversByLengthDesc = [...allEnabledServerNames].sort(\n (a, b) => b.length - a.length,\n )\n const out: ProxyToolDef[] = []\n const seen = new Set<string>()\n for (const item of items) {\n const matchedServer = serversByLengthDesc.find(\n (name) => item.id === name || item.id.startsWith(`${name}_`),\n )\n if (!matchedServer) continue\n if (seen.has(item.id)) continue\n seen.add(item.id)\n out.push({\n name: item.id,\n description: item.description ?? \"\",\n inputSchema:\n item.parameters && typeof item.parameters === \"object\"\n ? item.parameters\n : { type: \"object\", properties: {} },\n })\n }\n return out.length > 0 ? out : null\n }\n\n /**\n * Live tool info derived from a single `client.tool.list()` fetch:\n *\n * - `taskDescription`: opencode's `task` tool description exactly as the\n * registry renders it for native models, including the \"Available\n * agent types\" list. Overlaid onto the static `task` proxy def so\n * Claude sees the same subagent catalog native models see, instead\n * of hunting through config files.\n * - `questionDescription` / `hasQuestion`: opencode's `question` tool\n * description and whether the registry has the entry at all. Older\n * builds lack it, in which case a `mcp__opencode_proxy__question`\n * call resolves to `⚙ invalid`; the version gate drops the def.\n *\n * Returns undefined/false when the SDK client is unavailable (direct\n * AI-SDK use, tests) so the static defs stand. `resolved` distinguishes\n * \"the registry answered and has no `question` entry\" from \"nobody\n * answered\": only the former is a real version-gate signal.\n */\n private async fetchLiveToolInfo(): Promise<LiveToolInfo> {\n const items = await fetchOpencodeToolList(\n this.config.provider,\n this.modelId,\n this.config.cwd,\n )\n const question = items?.find((item) => item.id === \"question\")\n return {\n resolved: items !== undefined,\n taskDescription: items?.find((item) => item.id === \"task\")?.description,\n questionDescription: question?.description,\n hasQuestion: !!question,\n }\n }\n\n /** Share one lazy registry request within a turn without making it stale. */\n private createLiveToolInfoLoader(): () => Promise<LiveToolInfo> {\n let pending: Promise<LiveToolInfo> | undefined\n return () => {\n pending ??= this.fetchLiveToolInfo()\n return pending\n }\n }\n\n /**\n * Whether the ExitPlanMode approval bridge is live for this turn: the\n * operator opted in AND opencode's registry actually has the `question`\n * tool. Without the registry entry the emitted tool-call would render as\n * `⚙ invalid` and wedge the turn, so the plugin keeps the text path.\n */\n private async resolvePlanModeQuestion(\n compactionMode: boolean,\n loadLiveToolInfo = () => this.fetchLiveToolInfo(),\n ): Promise<boolean> {\n if (compactionMode || this.config.planModeQuestion !== true) return false\n const info = await loadLiveToolInfo()\n const active = isPlanModeQuestionActive({\n configured: this.config.planModeQuestion,\n opencodeHasQuestion: info.hasQuestion,\n compactionMode,\n })\n if (!active) {\n // Same reasoning as the question proxy's version-gate log: a silent\n // fallback to the text path looks from the outside like the setting\n // was ignored.\n log.info(\"plan-mode question gate\", {\n opencodeHasQuestion: info.hasQuestion,\n registryResolved: info.resolved,\n active,\n })\n }\n return active\n }\n\n /**\n * Create a proxy MCP server for a single active Claude process/session.\n * The process lifecycle owns the server lifecycle via session-manager.\n */\n private async ensureProxyServer(\n tools: ProxyToolDef[],\n sessionKeyForCalls: string,\n ): Promise<ProxyMcpServer> {\n const timeoutOverrides = this.config.proxyToolTimeoutMs\n const srv = await createProxyMcpServer(tools, timeoutOverrides)\n srv.calls.on(\"call\", (call: ProxyToolCall) => {\n queuePendingProxyCall(sessionKeyForCalls, call, timeoutOverrides)\n })\n return srv\n }\n\n private extractPendingProxyResult(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n toolCallId: string,\n ): ProxyToolResult | null {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role !== \"tool\" || !Array.isArray(msg.content)) continue\n\n for (const part of msg.content) {\n if (part.type !== \"tool-result\" || part.toolCallId !== toolCallId) continue\n\n const output = part.output as any\n if (!output || typeof output !== \"object\") {\n return {\n kind: \"text\",\n text: String(output ?? \"\"),\n }\n }\n\n if (output.type === \"text\") {\n return {\n kind: \"text\",\n text: String(output.value ?? \"\"),\n }\n }\n\n if (output.type === \"json\") {\n return {\n kind: \"text\",\n text: JSON.stringify(output.value),\n }\n }\n\n if (output.type === \"content\" && Array.isArray(output.value)) {\n const text = output.value\n .filter((v: any) => v?.type === \"text\" && typeof v.text === \"string\")\n .map((v: any) => v.text)\n .join(\"\\n\")\n return {\n kind: \"text\",\n text,\n }\n }\n\n return {\n kind: \"text\",\n text: JSON.stringify(output),\n }\n }\n }\n\n return null\n }\n\n /**\n * Resolve the session affinity token for this LLM call. Delegates to the\n * exported `resolveSessionAffinity` helper so the logic is unit-testable.\n * Priority:\n * 1. `x-session-affinity` request header (primary).\n * 2. `opencodeSessionID` in providerOptions (chat.params hook fallback —\n * covers provider switches mid-session and title synthesis paths\n * where the header is absent).\n * 3. `\"default\"`.\n */\n private sessionAffinity(\n options: LanguageModelV3CallOptions,\n ): string {\n const headers = (options as any)?.headers as\n | Record<string, string | undefined>\n | undefined\n return resolveSessionAffinity(\n headers,\n options.providerOptions as Record<string, unknown> | undefined,\n this.config.provider,\n )\n }\n\n private controlRequestBehaviorForTool(toolName: string): ControlRequestBehavior {\n const configured = this.config.controlRequestToolBehaviors\n if (configured && toolName) {\n const direct = configured[toolName] ?? configured[toolName.toLowerCase()]\n if (direct === \"allow\" || direct === \"deny\") return direct\n\n const lower = toolName.toLowerCase()\n for (const [key, behavior] of Object.entries(configured)) {\n if (key.toLowerCase() === lower && (behavior === \"allow\" || behavior === \"deny\")) {\n return behavior\n }\n }\n }\n\n // AskUserQuestion must never be auto-allowed. Allowing it lets the\n // Claude CLI resolve its own question internally — in headless mode\n // there is no TTY, so the CLI fabricates/empties the answer and the\n // model proceeds on a guess. Deny so the CLI cannot self-answer; the\n // tool_use is still streamed and rendered to the opencode user by\n // formatAskUserQuestion, and the turn stops for a real reply. An\n // explicit controlRequestToolBehaviors entry above can still override.\n if (isAskUserQuestionTool(toolName)) return \"deny\"\n\n return this.config.controlRequestBehavior ?? \"allow\"\n }\n\n private writeControlResponse(\n proc: import(\"child_process\").ChildProcess,\n requestId: string,\n response?: Record<string, unknown>,\n ): void {\n const payload = {\n type: \"control_response\",\n response: {\n subtype: \"success\",\n request_id: requestId,\n response,\n },\n }\n\n try {\n proc.stdin?.write(JSON.stringify(payload) + \"\\n\")\n } catch (error) {\n log.warn(\"failed to write control response\", {\n requestId,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n /**\n * Handle Claude stream-json control requests (`can_use_tool`, etc.) and\n * respond via stdin with a matching `control_response`.\n */\n private handleControlRequest(\n msg: ClaudeStreamMessage,\n proc: import(\"child_process\").ChildProcess,\n ): boolean {\n if (msg.type !== \"control_request\") return false\n const requestId = msg.request_id\n const request = msg.request\n if (!requestId || !request?.subtype) return false\n\n if (request.subtype === \"can_use_tool\") {\n const toolName = request.tool_name ?? \"unknown\"\n const behavior = this.controlRequestBehaviorForTool(toolName)\n\n if (behavior === \"allow\") {\n this.writeControlResponse(proc, requestId, {\n behavior: \"allow\",\n updatedInput: request.input ?? {},\n toolUseID: request.tool_use_id,\n })\n log.info(\"control request auto-allowed\", {\n requestId,\n toolName,\n })\n } else {\n const denyMessage = denyMessageForTool(\n toolName,\n this.config.controlRequestDenyMessage,\n )\n this.writeControlResponse(proc, requestId, {\n behavior: \"deny\",\n message: denyMessage,\n toolUseID: request.tool_use_id,\n })\n log.info(\"control request auto-denied\", {\n requestId,\n toolName,\n })\n }\n\n return true\n }\n\n // For control request subtypes we don't actively handle yet, acknowledge\n // with an empty success so the CLI stream does not stall.\n this.writeControlResponse(proc, requestId, {})\n log.debug(\"control request acknowledged\", {\n requestId,\n subtype: request.subtype,\n })\n return true\n }\n\n private getReasoningEffort(\n providerOptions?: LanguageModelV3CallOptions[\"providerOptions\"],\n ): ReasoningEffort | undefined {\n if (!providerOptions) return undefined\n const ownKey = this.config.provider\n const bag =\n (providerOptions as any)[ownKey] ??\n (providerOptions as any)[\"claude-code\"]\n const effort = bag?.reasoningEffort\n const valid: ReasoningEffort[] = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n ]\n return valid.includes(effort) ? effort : undefined\n }\n\n private getOpencodeAgent(\n providerOptions?: LanguageModelV3CallOptions[\"providerOptions\"],\n ): string | undefined {\n if (!providerOptions) return undefined\n const ownKey = this.config.provider\n const bag =\n (providerOptions as any)[ownKey] ??\n (providerOptions as any)[\"claude-code\"]\n const agent = bag?.opencodeAgent\n return typeof agent === \"string\" ? agent : undefined\n }\n\n private isCompactionCall(\n options: LanguageModelV3CallOptions,\n ): boolean {\n return this.getOpencodeAgent(options.providerOptions) === \"compaction\"\n }\n\n /**\n * Pick the model used to handle /compact. Precedence:\n * 1. `CLAUDE_CODE_COMPACTION_MODEL` env var (per-process override)\n * 2. `compactionModel` provider setting (opencode.json / .jsonc)\n * 3. Built-in default (claude-haiku-4-5)\n */\n private resolveCompactionModel(): string {\n return resolveCompactionModel(this.config.compactionModel)\n }\n\n private thinkingCliOptions(): {\n thinking?: \"enabled\"\n thinkingDisplay?: \"summarized\"\n } {\n if (isClaudeThinkingDisabled()) return {}\n\n return {\n thinking: \"enabled\",\n thinkingDisplay:\n process.env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES === undefined\n ? \"summarized\"\n : undefined,\n }\n }\n\n private latestUserText(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n ): string {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role !== \"user\") continue\n\n if (typeof msg.content === \"string\") {\n return String(msg.content).trim()\n }\n\n if (Array.isArray(msg.content)) {\n const text = (msg.content as any[])\n .filter((part) => part.type === \"text\" && typeof part.text === \"string\")\n .map((part: any) => String(part.text).trim())\n .filter(Boolean)\n .join(\" \")\n if (text) return text\n }\n }\n\n return \"\"\n }\n\n private synthesizeTitle(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n ): string {\n const source = this.latestUserText(prompt)\n .replace(/\\s+/g, \" \")\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, \" \")\n .trim()\n\n if (!source) return \"New Session\"\n\n const stop = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"or\",\n \"but\",\n \"to\",\n \"for\",\n \"of\",\n \"in\",\n \"on\",\n \"at\",\n \"with\",\n \"can\",\n \"could\",\n \"would\",\n \"should\",\n \"please\",\n \"hi\",\n \"hello\",\n \"hey\",\n \"there\",\n \"you\",\n \"your\",\n \"this\",\n \"that\",\n \"is\",\n \"are\",\n \"was\",\n \"were\",\n \"be\",\n \"do\",\n \"does\",\n \"did\",\n \"summarize\",\n \"summary\",\n \"project\",\n ])\n\n const words = source\n .split(\" \")\n .map((word) => word.trim())\n .filter(Boolean)\n .filter((word) => !stop.has(word.toLowerCase()))\n\n const picked = (words.length > 0 ? words : source.split(\" \").filter(Boolean))\n .slice(0, 6)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \")\n\n return picked || \"New Session\"\n }\n\n private async doGenerateViaStream(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n const result = await this.doStream(options)\n const reader = result.stream.getReader()\n\n let text = \"\"\n let reasoning = \"\"\n const toolCalls: LanguageModelV3Content[] = []\n let finishReason = this.toFinishReason(\"stop\")\n let usage: LanguageModelV3Usage = this.toUsage()\n let providerMetadata: any\n\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n\n switch ((value as any).type) {\n case \"text-delta\":\n text += (value as any).delta ?? \"\"\n break\n case \"reasoning-delta\":\n reasoning += (value as any).delta ?? \"\"\n break\n case \"tool-call\":\n toolCalls.push({\n type: \"tool-call\",\n toolCallId: (value as any).toolCallId,\n toolName: (value as any).toolName,\n input: (value as any).input,\n providerExecuted: (value as any).providerExecuted,\n } as any)\n break\n case \"finish\":\n finishReason = (value as any).finishReason ?? finishReason\n usage = (value as any).usage ?? usage\n providerMetadata = (value as any).providerMetadata ?? providerMetadata\n break\n }\n }\n\n const content: LanguageModelV3Content[] = []\n if (reasoning) {\n content.push({ type: \"reasoning\", text: reasoning } as any)\n }\n if (text) {\n content.push({ type: \"text\", text, providerMetadata } as any)\n }\n content.push(...toolCalls)\n\n return {\n content,\n finishReason,\n usage,\n request: result.request,\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata,\n warnings: [],\n }\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n const warnings: SharedV3Warning[] = []\n const cwd = resolveSpawnCwd(this.config.cwd)\n const scope = this.requestScope(options as any)\n const affinity = this.sessionAffinity(options)\n const sk = sessionKey(cwd, `${this.modelId}::${scope}::${affinity}`)\n\n // When selective proxying is enabled, doGenerate must not bypass the\n // proxy path. Reuse doStream and aggregate its events so proxied tools\n // still route through opencode permissions/execution. Same for\n // opencode MCP proxying — doStream is the only path that wires up the\n // proxy server with the dynamically-discovered MCP tool defs.\n const compactionMode = this.isCompactionCall(options)\n\n if (\n scope === \"tools\" &&\n (this.resolvedProxyTools() ||\n (this.config.proxyOpencodeMcpTools !== false &&\n this.config.bridgeOpencodeMcp !== false))\n ) {\n return this.doGenerateViaStream(options)\n }\n\n // Route compaction through doStream so it gets the lean spawn path,\n // model override, and rich transcript handling. Aggregating a stream\n // for doGenerate matches what doGenerateViaStream already does for\n // proxy tools.\n if (compactionMode) {\n return this.doGenerateViaStream(options)\n }\n\n if (scope === \"no-tools\") {\n log.info(\"doGenerate no-tools title stub\", {\n compactionMode,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n const text = this.synthesizeTitle(options.prompt)\n return {\n content: [{ type: \"text\", text }] as any,\n finishReason: this.toFinishReason(\"stop\"),\n usage: this.toUsage({ input_tokens: 0, output_tokens: 0 }),\n request: { body: { text: \"\" } },\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": {\n synthetic: true,\n path: \"no-tools\",\n },\n },\n warnings,\n }\n }\n\n // Short-circuit when opencode iterates the agent loop one more time\n // after a turn already finished. The prompt ends with an assistant\n // message and has no fresh user input — spawning Claude here would\n // just produce a stub like \"No input received. Standing by\".\n if (!hasNewUserContent(options.prompt)) {\n log.info(\"doGenerate short-circuit: no new user content\")\n return {\n content: [],\n finishReason: this.toFinishReason(\"stop\"),\n usage: this.toUsage({ input_tokens: 0, output_tokens: 0 }),\n request: { body: { text: \"\" } },\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": { synthetic: true, path: \"no-new-user-content\" },\n },\n warnings,\n }\n }\n\n const hasPriorConversation =\n options.prompt.filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .length > 1\n\n // New session — clear any stale state from a previous session\n if (!hasPriorConversation) {\n deleteClaudeSessionId(sk)\n deleteActiveProcess(sk)\n }\n\n const hasExistingSession = !!getClaudeSessionId(sk)\n const includeHistoryContext = !hasExistingSession && hasPriorConversation\n\n const reasoningEffort = this.getReasoningEffort(options.providerOptions)\n const userMsg =\n consumeExitPlanModeQuestionResult(sk, options.prompt as any) ??\n getClaudeUserMessage(options.prompt, includeHistoryContext, reasoningEffort)\n\n // doGenerate always spawns a fresh process, never reuse session ID.\n // Pre-fetch opencode's MCP runtime status so the bridge overlays\n // UI-toggled state on top of disk config.\n const [runtimeStatus, cliVersion, planModeQuestionActive] = await Promise.all([\n getRuntimeMcpStatus(),\n detectCliVersion(this.config.cliPath),\n this.resolvePlanModeQuestion(compactionMode),\n ])\n const systemPromptFile = buildAppendedSystemPrompt(\n cwd,\n this.config.multiStepContinuation !== false,\n extractSystemMessages(options.prompt),\n )\n const cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions: this.config.skipPermissions !== false,\n includeSessionId: false,\n model: this.modelId,\n permissionMode: this.config.permissionMode,\n mcpConfig: this.effectiveMcpConfig(cwd, undefined, runtimeStatus).paths,\n strictMcpConfig: this.config.strictMcpConfig,\n disallowedTools:\n this.config.webSearch === \"disabled\" ? [\"WebSearch\"] : undefined,\n appendSystemPromptFile: systemPromptFile,\n ...this.thinkingCliOptions(),\n cliVersion,\n })\n\n log.info(\"doGenerate starting\", {\n cwd,\n model: this.modelId,\n textLength: userMsg.length,\n includeHistoryContext,\n })\n\n const { spawn } = await import(\"node:child_process\")\n const { createInterface } = await import(\"node:readline\")\n\n const proc = spawn(this.config.cliPath, cliArgs, {\n cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: claudeSpawnEnv({\n ignoreAnthropicApiKey: this.config.ignoreAnthropicApiKey,\n }),\n shell: process.platform === \"win32\",\n })\n\n if (systemPromptFile) {\n proc.on(\"exit\", () => {\n void unlink(systemPromptFile).catch(() => {})\n })\n }\n\n const rl = createInterface({ input: proc.stdout! })\n\n let responseText = \"\"\n let thinkingText = \"\"\n let resultMeta: {\n sessionId?: string\n costUsd?: number\n durationMs?: number\n usage?: ClaudeStreamMessage[\"usage\"]\n } = {}\n const toolCalls: Array<{ id: string; name: string; args: unknown }> = []\n // Streaming tool_use entries keyed by content-block index. We accumulate\n // partial_json chunks here instead of trying to JSON.parse each chunk\n // independently, and flush to `toolCalls` at content_block_stop. The\n // previous code indexed `toolCalls` by `msg.index` directly, which is\n // wrong whenever non-tool blocks (text, thinking) precede a tool_use.\n const toolCallStreams = new Map<\n number,\n { id: string; name: string; inputJson: string }\n >()\n\n // Set true once we observe a `stream_event` envelope. When on, the\n // top-level `assistant` message is a duplicate of content already\n // accumulated via the inner content_block_* events — skip it.\n let gotPartialEvents = false\n\n const result = await new Promise<\n typeof resultMeta & {\n text: string\n thinking: string\n toolCalls: typeof toolCalls\n }\n >((resolve, reject) => {\n const cleanup = () => {\n try {\n if (!proc.killed && proc.exitCode === null) proc.kill()\n } catch {}\n }\n\n rl.on(\"line\", (line) => {\n if (!line.trim()) return\n try {\n const outer: ClaudeStreamMessage = JSON.parse(line)\n\n // Unwrap stream_event envelope (--include-partial-messages).\n // Inner event uses the same content_block_* / message_* shape.\n const msg: ClaudeStreamMessage =\n outer.type === \"stream_event\" && outer.event\n ? { ...outer.event, session_id: outer.session_id }\n : outer\n\n if (outer.type === \"stream_event\") {\n gotPartialEvents = true\n }\n\n if (this.handleControlRequest(msg, proc)) {\n return\n }\n\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n }\n\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n !gotPartialEvents\n ) {\n for (const block of msg.message.content) {\n if (block.type === \"text\" && block.text) {\n responseText += block.text\n }\n if (block.type === \"thinking\" && block.thinking) {\n thinkingText += block.thinking\n }\n if (block.type === \"tool_use\" && block.id && block.name) {\n if (isAskUserQuestionTool(block.name)) {\n // Render the full question + options as visible text so\n // the user can actually see and answer it.\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n responseText += formatAskUserQuestion(parsedInput)\n continue\n }\n\n if (block.name === \"ExitPlanMode\") {\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n const plan = (parsedInput?.plan as string) || \"\"\n if (planModeQuestionActive) {\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n block.id,\n plan,\n )\n responseText += questionCall.text\n toolCalls.push({\n id: questionCall.toolCallId,\n name: questionCall.toolName,\n args: questionCall.input,\n })\n continue\n }\n responseText += `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`\n continue\n }\n\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: block.input ?? {},\n })\n }\n }\n }\n\n if (\n msg.type === \"content_block_start\" &&\n msg.content_block &&\n msg.index !== undefined\n ) {\n if (\n msg.content_block.type === \"tool_use\" &&\n msg.content_block.id &&\n msg.content_block.name\n ) {\n toolCallStreams.set(msg.index, {\n id: msg.content_block.id,\n name: msg.content_block.name,\n inputJson: \"\",\n })\n }\n }\n\n if (\n msg.type === \"content_block_delta\" &&\n msg.delta &&\n msg.index !== undefined\n ) {\n if (msg.delta.type === \"text_delta\" && msg.delta.text) {\n responseText += msg.delta.text\n }\n if (msg.delta.type === \"thinking_delta\" && msg.delta.thinking) {\n thinkingText += msg.delta.thinking\n }\n if (\n msg.delta.type === \"input_json_delta\" &&\n msg.delta.partial_json\n ) {\n const tc = toolCallStreams.get(msg.index)\n if (tc) tc.inputJson += msg.delta.partial_json\n }\n }\n\n if (msg.type === \"content_block_stop\" && msg.index !== undefined) {\n const tc = toolCallStreams.get(msg.index)\n if (tc) {\n let args: unknown = {}\n try {\n args = tc.inputJson ? JSON.parse(tc.inputJson) : {}\n } catch (err) {\n log.warn(\"tool input JSON parse failed\", {\n name: tc.name,\n error: String(err),\n })\n }\n if (tc.name === \"ExitPlanMode\" && planModeQuestionActive) {\n const parsedInput = args as Record<string, unknown>\n const plan = (parsedInput?.plan as string) || \"\"\n const questionCall = createExitPlanModeQuestionCall(sk, tc.id, plan)\n responseText += questionCall.text\n toolCalls.push({\n id: questionCall.toolCallId,\n name: questionCall.toolName,\n args: questionCall.input,\n })\n } else {\n toolCalls.push({ id: tc.id, name: tc.name, args })\n }\n toolCallStreams.delete(msg.index)\n }\n }\n\n if (msg.type === \"result\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n\n // Some CLI failures only surface user-readable text on the final\n // `result` message (without prior assistant text blocks). Preserve\n // that so callers don't receive an empty response.\n if (\n !responseText &&\n msg.is_error &&\n typeof msg.result === \"string\" &&\n msg.result.trim().length > 0\n ) {\n responseText = msg.result\n }\n\n resultMeta = {\n sessionId: msg.session_id,\n costUsd: msg.total_cost_usd,\n durationMs: msg.duration_ms,\n usage: msg.usage,\n }\n cleanup()\n resolve({\n ...resultMeta,\n text: responseText,\n thinking: thinkingText,\n toolCalls,\n })\n }\n } catch {\n // Ignore non-JSON lines\n }\n })\n\n rl.on(\"close\", () => {\n cleanup()\n resolve({\n ...resultMeta,\n text: responseText,\n thinking: thinkingText,\n toolCalls,\n })\n })\n\n proc.on(\"error\", (err) => {\n log.error(\"process error\", { error: err.message })\n cleanup()\n reject(err)\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n log.debug(\"stderr\", { data: data.toString().slice(0, 200) })\n })\n\n proc.stdin?.write(userMsg + \"\\n\")\n })\n\n const content: LanguageModelV3Content[] = []\n\n if (result.thinking) {\n content.push({\n type: \"reasoning\",\n text: result.thinking,\n } as any)\n }\n\n if (result.text) {\n content.push({\n type: \"text\",\n text: result.text,\n providerMetadata: {\n \"claude-code\": {\n sessionId: result.sessionId ?? null,\n costUsd: result.costUsd ?? null,\n durationMs: result.durationMs ?? null,\n },\n ...(typeof result.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n result.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n })\n }\n\n for (const tc of result.toolCalls) {\n if (tc.name === QUESTION_TOOL_NAME) {\n content.push({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: tc.name,\n input: JSON.stringify(tc.args),\n providerExecuted: false,\n } as any)\n continue\n }\n\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(tc.name, tc.args, {\n webSearch: this.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: tc.id,\n })\n if (skip) continue\n content.push({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n\n const usage = this.toUsage(result.usage)\n\n return {\n content,\n // Claude CLI's `result` message normally signals a fully-completed turn:\n // tools have already been executed internally and final assistant text\n // has been produced. ExitPlanMode is the exception: we surface it as\n // opencode's native question tool so the outer loop must run that tool.\n finishReason: this.toFinishReason(\n result.toolCalls.some((tc) => tc.name === QUESTION_TOOL_NAME)\n ? \"tool-calls\"\n : \"stop\",\n ),\n usage,\n request: { body: { text: userMsg } },\n response: {\n id: result.sessionId ?? generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": {\n sessionId: result.sessionId ?? null,\n costUsd: result.costUsd ?? null,\n durationMs: result.durationMs ?? null,\n },\n ...(typeof result.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n result.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n warnings,\n }\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n const warnings: SharedV3Warning[] = []\n const cwd = resolveSpawnCwd(this.config.cwd)\n const cliPath = this.config.cliPath\n const skipPermissions = this.config.skipPermissions !== false\n const scope = this.requestScope(options as any)\n const affinity = this.sessionAffinity(options)\n const compactionMode = this.isCompactionCall(options)\n // Use a separate session key for compaction so its short-lived spawn\n // never collides with the main conversation's claude process.\n const effectiveModelId = compactionMode\n ? this.resolveCompactionModel()\n : this.modelId\n const sk = compactionMode\n ? sessionKey(cwd, `${effectiveModelId}::compaction::${affinity}`)\n : sessionKey(cwd, `${this.modelId}::${scope}::${affinity}`)\n const toUsage = this.toUsage.bind(this)\n const toFinishReason = this.toFinishReason.bind(this)\n const handleControlRequest = this.handleControlRequest.bind(this)\n const flagOn = (v: string | undefined) =>\n v !== undefined &&\n ![\"\", \"0\", \"false\", \"no\", \"off\"].includes(v.trim().toLowerCase())\n // Interactive (subscription) transport: drive the claude TUI over Bun's\n // native ConPTY + JSONL tail instead of headless `--print` stream-json.\n // Prefer the provider option (config-driven, reliable in the GUI app where\n // process env vars are not inherited); fall back to the env var. Self-healing:\n // if Bun.Terminal is unavailable (e.g. not under Bun), use the headless path.\n const interactivePref =\n this.config.interactive ??\n flagOn(process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT)\n const useInteractive =\n interactivePref && typeof (globalThis as any).Bun?.Terminal === \"function\"\n const interactiveBypassRequested =\n this.config.interactiveBypass ??\n flagOn(process.env.CLAUDE_CODE_INTERACTIVE_BYPASS)\n\n if (scope === \"no-tools\" && !compactionMode) {\n log.info(\"doStream no-tools title stub\", {\n compactionMode,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n const text = this.synthesizeTitle(options.prompt)\n const textId = generateId()\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n controller.enqueue({ type: \"stream-start\", warnings })\n controller.enqueue({ type: \"text-start\", id: textId } as any)\n controller.enqueue({\n type: \"text-delta\",\n id: textId,\n delta: text,\n })\n controller.enqueue({ type: \"text-end\", id: textId })\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage({ input_tokens: 0, output_tokens: 0 }),\n providerMetadata: {\n \"claude-code\": {\n synthetic: true,\n path: \"no-tools\",\n },\n },\n })\n controller.close()\n },\n })\n\n return {\n stream,\n request: { body: { text: \"\" } },\n }\n }\n\n // Short-circuit when opencode iterates the agent loop one more time\n // after a turn already finished. The prompt ends with an assistant\n // message and has no fresh user input — spawning Claude here would\n // just produce a stub like \"No input received. Standing by\".\n if (!hasNewUserContent(options.prompt)) {\n log.info(\"doStream short-circuit: no new user content\")\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n controller.enqueue({ type: \"stream-start\", warnings })\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage({ input_tokens: 0, output_tokens: 0 }),\n providerMetadata: {\n \"claude-code\": { synthetic: true, path: \"no-new-user-content\" },\n },\n })\n controller.close()\n },\n })\n return { stream, request: { body: { text: \"\" } } }\n }\n\n const hasPriorConversation =\n options.prompt.filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .length > 1\n\n // New session — clear any stale state from a previous session\n if (!hasPriorConversation) {\n deleteClaudeSessionId(sk)\n deleteActiveProcess(sk)\n }\n\n const hasExistingSession = !!getClaudeSessionId(sk)\n const hasActiveProcess = !!getActiveProcess(sk)\n const includeHistoryContext =\n !hasExistingSession && !hasActiveProcess && hasPriorConversation\n\n const reasoningEffort = this.getReasoningEffort(options.providerOptions)\n const exitPlanModeQuestionResult = compactionMode\n ? null\n : consumeExitPlanModeQuestionResult(sk, options.prompt as any)\n if (exitPlanModeQuestionResult) {\n // The whole user message for this turn is the `tool_result` for the\n // pending ExitPlanMode call, so say so: an operator looking at a turn\n // that carries none of their typed text needs the reason in the log.\n log.info(\"sending plan approval decision to claude\", { sk })\n }\n const userMsg =\n exitPlanModeQuestionResult ??\n getClaudeUserMessage(options.prompt, includeHistoryContext, reasoningEffort, {\n compactionMode,\n })\n const resolvedProxy = compactionMode ? null : this.resolvedProxyTools()\n const loadLiveToolInfo = this.createLiveToolInfoLoader()\n // Resolved here, not inside the stream body: the ExitPlanMode branches\n // run in a synchronous line handler and a reused process never reaches\n // the spawn block where the registry snapshot is otherwise taken.\n const planModeQuestionActive = await this.resolvePlanModeQuestion(\n compactionMode,\n loadLiveToolInfo,\n )\n const self = this\n\n const previousPendingProxyCalls = compactionMode\n ? []\n : getPendingProxyCalls(sk)\n const previousPendingProxyMatches: Array<{\n call: PendingProxyCall\n result: ProxyToolResult | null\n }> = previousPendingProxyCalls.map((call) => ({\n call,\n result: this.extractPendingProxyResult(options.prompt, call.toolCallId),\n }))\n const hasMatchedPendingResults = previousPendingProxyMatches.some(\n (m) => m.result !== null,\n )\n\n // Pre-fetch opencode's MCP runtime status before constructing the\n // ReadableStream so the sync hot-reload check and async setup() see\n // the same overlay snapshot. One in-process call per turn — cheap;\n // the SDK client routes through `Server.app.fetch` (no socket).\n // Detect the Claude CLI version in parallel so the spawn can decide\n // which optional flags it supports without crashing older binaries.\n const [runtimeStatus, cliVersion] = await Promise.all([\n compactionMode ? Promise.resolve(undefined) : getRuntimeMcpStatus(),\n detectCliVersion(this.config.cliPath),\n ])\n\n log.info(\"doStream starting\", {\n cwd,\n model: effectiveModelId,\n textLength: userMsg.length,\n includeHistoryContext,\n hasActiveProcess,\n reasoningEffort,\n proxyTools: resolvedProxy?.map((t) => t.name) ?? null,\n compactionMode,\n scope,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n // Compaction is a one-shot call. Don't reuse any cached process\n // from a prior compaction — each /compact gets a fresh spawn so\n // the new transcript isn't appended to a stale claude session.\n if (compactionMode) {\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n }\n\n let activeProcess = getActiveProcess(sk)\n let proc: import(\"child_process\").ChildProcess\n let lineEmitter: import(\"events\").EventEmitter\n let cliArgs: string[]\n let proxyServer: ProxyMcpServer | null = activeProcess?.proxyServer ?? null\n\n const setup = async () => {\n // Wait for the old owner to exit before resuming its session ID in\n // the replacement, so two processes never append to one transcript.\n if (\n !compactionMode &&\n activeProcess &&\n self.config.hotReloadMcp !== false &&\n self.config.bridgeOpencodeMcp !== false\n ) {\n const probe = self.effectiveMcpConfig(cwd, undefined, runtimeStatus!)\n const previousHash = activeProcess.mcpHash ?? null\n if (previousHash !== probe.bridgedHash) {\n if (previousPendingProxyCalls.length > 0) {\n log.info(\"deferring MCP hot reload until proxy calls resolve\", {\n sk,\n previousHash,\n currentHash: probe.bridgedHash,\n pendingCalls: previousPendingProxyCalls.length,\n })\n } else {\n log.info(\"opencode MCP config changed, respawning claude\", {\n sk,\n previousHash,\n currentHash: probe.bridgedHash,\n })\n await deleteActiveProcessAndWait(sk)\n activeProcess = undefined\n proxyServer = null\n }\n }\n }\n\n if (useInteractive && !compactionMode) {\n // Interactive Bun-ConPTY transport. Reuse the live session if one\n // exists for this key; else spawn a new interactive claude. The\n // wrapper conforms to ActiveProcess, so reuse/eviction/hot-reload\n // and the whole emission body below work unchanged.\n const mcp = self.effectiveMcpConfig(cwd, undefined, runtimeStatus!)\n if (activeProcess) {\n proc = activeProcess.proc\n lineEmitter = activeProcess.lineEmitter\n log.debug(\"reusing active interactive session\", { sk })\n } else {\n // MCP wildcards are always derived from the live bridge config;\n // the built-in tool list is overridable via interactiveAllowTools.\n const allow = [\n ...mcp.allEnabledServerNames.map((n) => `mcp__${n}__*`),\n \"mcp__opencode_proxy__*\",\n ...(self.config.interactiveAllowTools ?? [\n \"Bash\",\n \"Edit\",\n \"Write\",\n \"Read\",\n \"WebFetch\",\n ]),\n ]\n const systemPromptFile =\n self.config.interactiveSystemPrompt === false\n ? undefined\n : buildAppendedSystemPrompt(\n cwd,\n self.config.multiStepContinuation !== false,\n // Do not forward opencode's own system prompt into the\n // interactive TUI. Live subscription-account testing\n // showed that large forwarded payload can trigger Claude\n // Code's third-party-app usage gate, while our static\n // CLI/AGENTS/continuation prompt remains safe.\n )\n if (self.config.interactiveSystemPrompt === false) {\n log.warn(\n \"interactive system prompt disabled; opencode agent prompts will not be appended\",\n )\n }\n if (interactiveBypassRequested) {\n log.warn(\n \"interactiveBypass ignored: Claude Code prompts for bypassPermissions confirmation in the interactive TUI\",\n )\n }\n const ap = spawnInteractiveProcess({\n cwd,\n cliPath,\n configDir: self.config.configDir,\n model: effectiveModelId,\n mcpConfigPaths: mcp.paths,\n permissionsAllow: allow,\n systemPromptFile,\n ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey,\n })\n ap.mcpHash = mcp.bridgedHash\n setActiveProcess(sk, ap)\n proc = ap.proc\n lineEmitter = ap.lineEmitter\n activeProcess = ap\n log.info(\"spawned interactive claude session\", {\n sk,\n cliPath,\n configDir: self.config.configDir,\n model: effectiveModelId,\n })\n }\n } else {\n let spawnSystemPromptFile: string | undefined\n let spawnProxyServer: ProxyMcpServer | null = null\n let spawnMcpHash: string | null = null\n\n if (compactionMode) {\n // Compaction takes a lean spawn: no MCP servers, no proxy, no\n // appended system prompt, no disallowed-tools list. The model\n // is asked for text output only on a single turn — all the\n // normal tool wiring is pure overhead and adds latency.\n // Explicitly opt out of `--resume` so a stale id can never\n // resume into the lean spawn.\n cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions,\n includeSessionId: false,\n model: effectiveModelId,\n permissionMode: self.config.permissionMode,\n cliVersion,\n })\n } else {\n // First pass: discover which opencode MCP servers would be\n // bridged. We use this to decide which ones to re-route through\n // the proxy instead. No --mcp-config path is consumed here;\n // it's recomputed below with the exclusion set in place.\n const discovery = self.effectiveMcpConfig(\n cwd,\n undefined,\n runtimeStatus!,\n )\n\n // Fetch the proxy MCP tools (one ProxyToolDef per opencode\n // MCP-bridged tool). If discovery returns nothing or the SDK\n // is unreachable, this is null and we fall back to direct\n // bridging.\n const proxyMcpTools = await self.resolvedProxyMcpTools(\n discovery.allEnabledServerNames,\n )\n const excludeServers: ReadonlySet<string> | undefined = proxyMcpTools\n ? new Set(discovery.allEnabledServerNames)\n : undefined\n\n // Overlay opencode's live tool info onto the static proxy defs.\n // Both the `task` description (with the \"Available agent types\"\n // list, so the model sees which subagents exist instead of\n // grepping configs) and the `question` version gate (older\n // opencode builds lack the `question` registry entry; the def\n // must be dropped or a forwarded call renders `⚙ invalid`)\n // derive from a single tool-list fetch. Spawn-time only, like\n // the rest of this block; a reused process keeps its defs.\n const taskProxyEnabled =\n resolvedProxy?.some((t) => t.name === \"task\") ?? false\n const questionProxyEnabled =\n resolvedProxy?.some((t) => t.name === \"question\") ?? false\n const liveToolInfo =\n taskProxyEnabled || questionProxyEnabled\n ? await loadLiveToolInfo()\n : {\n resolved: false,\n taskDescription: undefined,\n questionDescription: undefined,\n hasQuestion: false,\n }\n let enrichedProxy = resolvedProxy\n if (enrichedProxy && taskProxyEnabled) {\n enrichedProxy = overlayTaskProxyDescription(\n enrichedProxy,\n liveToolInfo.taskDescription,\n )\n // Whether the model will see opencode's agent list is the\n // difference between a dispatch and an \"Unknown agent type\"\n // guess, so say so out loud.\n log.info(\"task proxy description overlay\", {\n applied: Boolean(liveToolInfo.taskDescription),\n liveDescriptionLength: liveToolInfo.taskDescription?.length ?? 0,\n listsAgentTypes: Boolean(\n liveToolInfo.taskDescription?.includes(\n \"Available agent types\",\n ),\n ),\n })\n }\n if (enrichedProxy && questionProxyEnabled) {\n // When the version gate is about to drop the def\n // (`hasQuestion === false`) the live description is moot,\n // so only overlay when the entry actually exists.\n enrichedProxy = overlayQuestionProxyDescription(\n enrichedProxy,\n liveToolInfo.hasQuestion\n ? liveToolInfo.questionDescription\n : undefined,\n )\n enrichedProxy = filterQuestionProxyByOpencodeSupport(\n enrichedProxy,\n liveToolInfo.hasQuestion,\n )\n // Same reasoning as the task overlay log: when the gate drops\n // the def the model silently falls back to the deny/markdown\n // path, which looks from the outside like the feature is off.\n log.info(\"question proxy version gate\", {\n opencodeHasQuestion: liveToolInfo.hasQuestion,\n kept: liveToolInfo.hasQuestion,\n })\n }\n\n // Combine the static proxy defs with any MCP-bridged proxy\n // tools. Guard against the empty case: a version gate can\n // drop every configured def (e.g. `proxyTools: [\"Question\"]`\n // on an opencode build that lacks the `question` registry\n // entry), and spinning up an MCP server with zero tools is\n // wasteful and wrong shape.\n const combinedList = [\n ...(enrichedProxy ?? []),\n ...(proxyMcpTools ?? []),\n ]\n const combinedProxyTools: ProxyToolDef[] | null =\n combinedList.length > 0 ? combinedList : null\n\n if (!proxyServer && combinedProxyTools) {\n proxyServer = await self.ensureProxyServer(combinedProxyTools, sk)\n }\n\n // Whether the question proxy actually survived the version\n // gate (post-filter). Used to decide whether to inject the\n // QUESTION_PROXY_HINT — if the gate dropped the def, the\n // model must fall back to AskUserQuestion (the deny/markdown\n // path) and must NOT be told to call a proxy tool that does\n // not exist.\n const questionProxyActive =\n enrichedProxy?.some((t) => t.name === \"question\") ?? false\n\n // Compute disallowed flags from the POST-FILTER proxy list\n // (enrichedProxy), not the pre-filter one (resolvedProxy).\n // When the version gate drops `question` on an older opencode\n // build, AskUserQuestion must NOT be added to\n // --disallowedTools — otherwise the native tool is disabled\n // while the proxy replacement is absent, leaving the model\n // with no way to ask questions at all (neither proxy nor the\n // deny/markdown fallback path fires).\n const proxyDisallowed = enrichedProxy\n ? disallowedToolFlags(enrichedProxy)\n : []\n const extraDisallowed: string[] = []\n if (self.config.webSearch === \"disabled\") extraDisallowed.push(\"WebSearch\")\n const allDisallowed = [...proxyDisallowed, ...extraDisallowed]\n const mcp = self.effectiveMcpConfig(\n cwd,\n proxyServer?.configPath(),\n runtimeStatus!,\n excludeServers,\n )\n const systemPromptFile = activeProcess\n ? undefined\n : buildAppendedSystemPrompt(\n cwd,\n self.config.multiStepContinuation !== false,\n [\n ...extractSystemMessages(options.prompt),\n ...(taskProxyEnabled ? [SUBAGENT_DISPATCH_HINT] : []),\n ...(questionProxyActive ? [QUESTION_PROXY_HINT] : []),\n ],\n )\n cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions,\n model: self.modelId,\n permissionMode: self.config.permissionMode,\n mcpConfig: mcp.paths,\n strictMcpConfig: self.config.strictMcpConfig,\n disallowedTools: allDisallowed.length > 0 ? allDisallowed : undefined,\n appendSystemPromptFile: systemPromptFile,\n ...self.thinkingCliOptions(),\n cliVersion,\n })\n spawnSystemPromptFile = systemPromptFile\n spawnProxyServer = proxyServer\n spawnMcpHash = mcp.bridgedHash\n }\n\n if (activeProcess && !compactionMode) {\n proc = activeProcess.proc\n lineEmitter = activeProcess.lineEmitter\n log.debug(\"reusing active process\", { sk })\n } else {\n const ap = spawnClaudeProcess(\n cliPath,\n cliArgs,\n cwd,\n sk,\n spawnProxyServer,\n spawnMcpHash,\n spawnSystemPromptFile,\n self.config.ignoreAnthropicApiKey,\n )\n proc = ap.proc\n lineEmitter = ap.lineEmitter\n activeProcess = ap\n }\n }\n\n controller.enqueue({ type: \"stream-start\", warnings })\n\n let currentTextId: string | null = null\n const textBlockIndices = new Set<number>()\n\n const startTextBlock = (): string => {\n if (currentTextId) {\n controller.enqueue({ type: \"text-end\", id: currentTextId })\n }\n const id = generateId()\n currentTextId = id\n controller.enqueue({ type: \"text-start\", id } as any)\n return id\n }\n\n const endTextBlock = (): void => {\n if (currentTextId) {\n controller.enqueue({ type: \"text-end\", id: currentTextId })\n currentTextId = null\n }\n }\n\n const reasoningIds = new Map<number, string>()\n const reasoningStarted = new Map<number, boolean>()\n let hadThinkingTextFromStream = false\n\n let turnCompleted = false\n let controllerClosed = false\n let pendingProxyUnsubscribe: (() => void) | null = null\n let resultFallbackTimer: ReturnType<typeof setTimeout> | null = null\n let pendingResultCompletion: (() => void) | null = null\n let hasReceivedContent = false\n let visibleTextSinceContinue = \"\"\n let lastVisibleTextSinceContinue = \"\"\n let hadReasoningSinceContinue = false\n let hadToolActivitySinceContinue = false\n let hadProxyActivitySinceContinue = false\n // v0.4.16: protocol-level stop signal captured from Claude CLI's\n // stream. Set by either the `message_delta` partial event or the\n // top-level `assistant` message, whichever arrives first.\n let lastStopReason: string | null = null\n const autoContinueState: AutoContinueState = {\n enabled: self.config.autoContinueIncompleteTurns,\n attempts: 0,\n startedAt: Date.now(),\n noProgressCount: 0,\n }\n\n const clearFallbackTimer = () => {\n if (resultFallbackTimer) {\n clearTimeout(resultFallbackTimer)\n resultFallbackTimer = null\n }\n }\n\n // Wire-inactivity watchdog. Resets on every line received from the\n // CLI; only fires if the CLI has emitted content and then gone\n // silent on stdout for `delayMs` without sending a `result`. The\n // previous design armed this on every text content_block_stop,\n // which killed legitimate mid-turn think pauses (most visibly\n // with sonnet between text-end and the next tool_use_start).\n const startResultFallback = (delayMs = 60_000) => {\n clearFallbackTimer()\n if (!hasReceivedContent || controllerClosed) return\n resultFallbackTimer = setTimeout(() => {\n if (controllerClosed) return\n log.warn(\"result fallback timer fired — closing stream without result event\", {\n delayMs,\n })\n closeHandler()\n }, delayMs)\n }\n\n // Start watchdog: complementary to the inactivity watchdog above.\n // That one only arms once content has arrived; this one covers the\n // gap the other explicitly skips — a reused process that produces\n // NO stdout at all after a fresh-turn envelope write. Seen after a\n // very long proxy-blocked tool call resumed successfully (the child\n // stays silent on stdout). On first fire we respawn the child with\n // --session-id to resume the conversation transparently; on a\n // second fire (respawn also silent) we end the turn cleanly so the\n // next opencode turn spawns fresh. Tunable via env for reproduces.\n const START_WATCHDOG_MS = (() => {\n const env = process.env.CLAUDE_CODE_START_WATCHDOG_MS\n const parsed = env ? Number.parseInt(env, 10) : NaN\n return Number.isFinite(parsed) && parsed > 0 ? parsed : 90_000\n })()\n let startWatchdog: ReturnType<typeof setTimeout> | null = null\n let respawnAttempted = false\n const clearStartWatchdog = () => {\n if (startWatchdog) {\n clearTimeout(startWatchdog)\n startWatchdog = null\n }\n }\n const onStartWatchdogFire = () => {\n startWatchdog = null\n if (controllerClosed || hasReceivedContent) return\n if (respawnAttempted) {\n log.error(\n \"claude process still silent after respawn; ending turn\",\n { sessionKey: sk },\n )\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({\n type: \"error\",\n error: new Error(\n \"Claude process produced no output after the envelope write (start watchdog timeout).\",\n ),\n })\n try {\n controller.close()\n } catch {}\n return\n }\n respawnAttempted = true\n log.warn(\n \"no stdout after envelope write; respawning claude process to resume conversation\",\n { sessionKey: sk, startWatchdogMs: START_WATCHDOG_MS },\n )\n lineEmitter.off(\"line\", lineHandler)\n lineEmitter.off(\"close\", closeHandler)\n proc.off(\"error\", procErrorHandler)\n const newAp = respawnActiveProcess(\n sk,\n cliPath,\n cliArgs,\n cwd,\n self.config.ignoreAnthropicApiKey,\n )\n if (!newAp) {\n log.error(\n \"no active process to respawn (start watchdog); ending turn\",\n { sessionKey: sk },\n )\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({\n type: \"error\",\n error: new Error(\n \"No active claude process to respawn after start watchdog timeout.\",\n ),\n })\n try {\n controller.close()\n } catch {}\n return\n }\n proc = newAp.proc\n lineEmitter = newAp.lineEmitter\n activeProcess = newAp\n lineEmitter.on(\"line\", lineHandler)\n lineEmitter.on(\"close\", closeHandler)\n proc.on(\"error\", procErrorHandler)\n try {\n proc.stdin?.write(userMsg + \"\\n\")\n log.debug(\"re-sent user message after respawn\", {\n textLength: userMsg.length,\n })\n } catch (err) {\n log.error(\"failed to re-send envelope after respawn\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n startWatchdog = setTimeout(\n onStartWatchdogFire,\n START_WATCHDOG_MS,\n )\n }\n const armStartWatchdog = () => {\n clearStartWatchdog()\n if (controllerClosed) return\n startWatchdog = setTimeout(onStartWatchdogFire, START_WATCHDOG_MS)\n }\n\n const toolCallMap = new Map<\n number,\n { id: string; name: string; inputJson: string; started: boolean }\n >()\n // Tool calls the plugin reported as providerExecuted:false — opencode\n // will run these itself and emit its own tool-result, so we must NOT\n // forward Claude CLI's tool_result for them (would short-circuit\n // opencode's execute).\n const skipResultForIds = new Set<string>()\n const toolCallsById = new Map<\n string,\n { id: string; name: string; input: unknown }\n >()\n\n let resultMeta: {\n sessionId?: string\n costUsd?: number\n durationMs?: number\n usage?: ClaudeStreamMessage[\"usage\"]\n } = {}\n\n // Batched drain so claude CLI's parallel tool_use blocks (e.g. two\n // bash calls in one assistant message) end up in a single\n // tool-calls finish event. Without this, the broker would reject\n // every overlapping call and claude would see spurious tool errors.\n const drainBuffer: PendingProxyCall[] = []\n let drainTimer: ReturnType<typeof setTimeout> | null = null\n const DRAIN_QUIET_MS = 100\n\n const finishWithToolCalls = (calls: PendingProxyCall[]) => {\n if (controllerClosed) return\n if (calls.length === 0) return\n for (const call of calls) {\n controller.enqueue({\n type: \"tool-input-start\",\n id: call.toolCallId,\n toolName: call.toolName,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: JSON.stringify(call.input),\n providerExecuted: false,\n } as any)\n skipResultForIds.add(call.toolCallId)\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"tool-calls\"),\n usage: toUsage(resultMeta.usage),\n providerMetadata: {\n \"claude-code\": resultMeta,\n },\n })\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n }\n\n const finishWithExitPlanQuestion = (\n call: ReturnType<typeof createExitPlanModeQuestionCall>,\n ) => {\n if (controllerClosed) return\n endTextBlock()\n controller.enqueue({\n type: \"tool-input-start\",\n id: call.toolCallId,\n toolName: call.toolName,\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: JSON.stringify(call.input),\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"tool-calls\"),\n usage: toUsage(resultMeta.usage),\n providerMetadata: {\n \"claude-code\": resultMeta,\n },\n })\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n }\n\n const drainNow = () => {\n if (drainTimer) {\n clearTimeout(drainTimer)\n drainTimer = null\n }\n if (drainBuffer.length === 0) return\n if (controllerClosed) return\n const batch = drainBuffer.splice(0, drainBuffer.length)\n log.info(\"draining pending proxy calls into stream finish\", {\n sessionKey: sk,\n count: batch.length,\n toolCallIds: batch.map((c) => c.toolCallId),\n })\n finishWithToolCalls(batch)\n }\n\n const settleResultBoundary = () => {\n drainTimer = null\n const completeResult = pendingResultCompletion\n pendingResultCompletion = null\n if (!completeResult || controllerClosed) return\n if (drainBuffer.length > 0) {\n drainNow()\n return\n }\n completeResult()\n }\n\n const scheduleResultBoundary = (\n completeResult: () => void,\n delayMs: number,\n ) => {\n pendingResultCompletion = completeResult\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(settleResultBoundary, delayMs)\n }\n\n const noteResultBoundaryCall = (): boolean => {\n if (!pendingResultCompletion) return false\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(settleResultBoundary, DRAIN_QUIET_MS)\n return true\n }\n\n const noteVisibleText = (text: string) => {\n visibleTextSinceContinue += text\n lastVisibleTextSinceContinue += text\n }\n\n const resetLastVisibleTextBlock = () => {\n lastVisibleTextSinceContinue = \"\"\n }\n\n const noteReasoning = () => {\n hadReasoningSinceContinue = true\n }\n\n const noteToolActivity = () => {\n hadToolActivitySinceContinue = true\n }\n\n const noteProxyActivity = () => {\n hadProxyActivitySinceContinue = true\n }\n\n const resetAutoContinueWindow = () => {\n visibleTextSinceContinue = \"\"\n lastVisibleTextSinceContinue = \"\"\n hadReasoningSinceContinue = false\n hadToolActivitySinceContinue = false\n hadProxyActivitySinceContinue = false\n lastStopReason = null\n }\n\n const completeResult = (msg: ClaudeStreamMessage) => {\n if (controllerClosed) return\n if (drainBuffer.length > 0) {\n drainNow()\n return\n }\n\n const pendingSiblings = getPendingProxyCalls(sk)\n if (pendingSiblings.length > 0) {\n log.info(\"leaving parallel proxy calls pending at result boundary\", {\n sessionKey: sk,\n count: pendingSiblings.length,\n })\n }\n\n const autoDecision = shouldAutoContinueIncompleteTurn(\n autoContinueState,\n {\n text: visibleTextSinceContinue,\n lastVisibleText: lastVisibleTextSinceContinue,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n isError: msg.is_error,\n stopReason: lastStopReason,\n },\n )\n if (autoDecision.continue) {\n const signature = continuationSignature({\n text: visibleTextSinceContinue,\n lastVisibleText: lastVisibleTextSinceContinue,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n isError: msg.is_error,\n })\n autoContinueState.noProgressCount =\n signature === autoContinueState.lastSignature\n ? autoContinueState.noProgressCount + 1\n : 0\n autoContinueState.lastSignature = signature\n autoContinueState.attempts++\n log.notice(\"auto-continuing incomplete claude result\", {\n sessionKey: sk,\n reason: autoDecision.reason,\n attempts: autoContinueState.attempts,\n textLength: visibleTextSinceContinue.length,\n lastTextLength: lastVisibleTextSinceContinue.length,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n })\n turnCompleted = false\n resetAutoContinueWindow()\n proc.stdin?.write(makeAutoContinueMessage() + \"\\n\")\n return\n }\n log.notice(\"auto-continuation stopped\", {\n sessionKey: sk,\n reason: autoDecision.reason,\n stopReason: lastStopReason,\n attempts: autoContinueState.attempts,\n textLength: visibleTextSinceContinue.length,\n lastTextLength: lastVisibleTextSinceContinue.length,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n })\n\n for (const [idx, reasoningId] of reasoningIds) {\n if (reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-end\",\n id: reasoningId,\n } as any)\n }\n }\n\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage(msg.usage),\n providerMetadata: {\n \"claude-code\": {\n ...resultMeta,\n ...(compactionMode\n ? { compactionModel: effectiveModelId }\n : {}),\n },\n ...(typeof msg.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n msg.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n })\n\n controllerClosed = true\n cleanupTurn()\n\n try {\n controller.close()\n } catch {}\n }\n\n // Set true once we observe a `stream_event` envelope. When on, the\n // top-level `assistant` message is a duplicate of what we already\n // streamed via content_block_* deltas — skip its content.\n let gotPartialEvents = false\n\n const lineHandler = (line: string) => {\n if (!line.trim()) return\n if (controllerClosed) return\n\n // Any line from the CLI counts as activity — reset the inactivity\n // watchdog so mid-turn pauses between blocks don't get killed.\n startResultFallback()\n // First stdout line means the child is alive and responding —\n // disarm the start watchdog (covers the \"no output at all\" gap).\n clearStartWatchdog()\n\n try {\n const outer: ClaudeStreamMessage = JSON.parse(line)\n\n // Unwrap stream_event envelope (--include-partial-messages).\n // Inner event uses the same content_block_* / message_* shape.\n const msg: ClaudeStreamMessage =\n outer.type === \"stream_event\" && outer.event\n ? { ...outer.event, session_id: outer.session_id }\n : outer\n\n if (outer.type === \"stream_event\") {\n gotPartialEvents = true\n }\n\n if (handleControlRequest(msg, proc)) {\n return\n }\n\n log.debug(\"stream message\", {\n type: msg.type,\n subtype: msg.subtype,\n })\n\n // Handle system init\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n log.info(\"session initialized\", {\n claudeSessionId: msg.session_id,\n })\n }\n }\n\n // content_block_start\n if (\n msg.type === \"content_block_start\" &&\n msg.content_block &&\n msg.index !== undefined\n ) {\n const block = msg.content_block\n const idx = msg.index\n\n if (block.type === \"thinking\") {\n noteReasoning()\n const reasoningId = generateId()\n reasoningIds.set(idx, reasoningId)\n }\n\n if (block.type === \"text\") {\n textBlockIndices.add(idx)\n // New text block — clear last-block buffer so final-answer\n // detection only considers this block's contents, not earlier\n // mid-task narration.\n resetLastVisibleTextBlock()\n if (block.text) {\n if (!currentTextId) startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: currentTextId!,\n delta: block.text,\n })\n noteVisibleText(block.text)\n hasReceivedContent = true\n }\n }\n\n if (block.type === \"tool_use\" && block.id && block.name) {\n noteToolActivity()\n const entry = {\n id: block.id,\n name: block.name,\n inputJson: \"\",\n started: false,\n }\n toolCallMap.set(idx, entry)\n\n if (\n block.name !== \"AskUserQuestion\" &&\n block.name !== \"ask_user_question\" &&\n block.name !== \"ExitPlanMode\" &&\n !block.name.startsWith(PROXY_TOOL_PREFIX)\n ) {\n const { name: mappedName, skip, executed } = mapTool(\n block.name,\n undefined,\n {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: block.id,\n },\n )\n if (!skip) {\n entry.started = true\n controller.enqueue({\n type: \"tool-input-start\",\n id: block.id,\n toolName: mappedName,\n providerExecuted: executed,\n } as any)\n log.info(\"tool started\", {\n name: block.name,\n mappedName,\n id: block.id,\n })\n }\n }\n }\n }\n\n // content_block_delta\n if (\n msg.type === \"content_block_delta\" &&\n msg.delta &&\n msg.index !== undefined\n ) {\n const delta = msg.delta\n const idx = msg.index\n\n if (delta.type === \"thinking_delta\" && delta.thinking) {\n noteReasoning()\n hadThinkingTextFromStream = true\n const reasoningId = reasoningIds.get(idx)\n if (reasoningId) {\n if (!reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-start\",\n id: reasoningId,\n } as any)\n reasoningStarted.set(idx, true)\n }\n controller.enqueue({\n type: \"reasoning-delta\",\n id: reasoningId,\n delta: delta.thinking,\n } as any)\n }\n }\n\n if (delta.type === \"text_delta\" && delta.text) {\n if (!currentTextId) startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: currentTextId!,\n delta: delta.text,\n })\n noteVisibleText(delta.text)\n hasReceivedContent = true\n }\n\n if (delta.type === \"input_json_delta\" && delta.partial_json) {\n const tc = toolCallMap.get(idx)\n if (tc) {\n tc.inputJson += delta.partial_json\n // Only forward deltas for tool calls whose tool-input-start\n // was actually emitted. Skipped tools (CLAUDE_INTERNAL_TOOLS,\n // TaskCreate/TaskUpdate, CLI-internal WebSearch, AskUserQuestion,\n // ExitPlanMode, proxy tools) never get a named start part, so\n // forwarding their deltas makes opencode's AI SDK bridge fall\n // back to a nameless pending part rendered as `⚙ unknown`.\n if (tc.started) {\n controller.enqueue({\n type: \"tool-input-delta\",\n id: tc.id,\n delta: delta.partial_json,\n } as any)\n }\n }\n }\n\n if (!KNOWN_DELTA_TYPES.has(delta.type)) {\n log.debug(\"unrecognized content_block_delta type\", {\n type: delta.type,\n idx,\n keys: Object.keys(delta),\n })\n }\n }\n\n // content_block_stop\n if (\n msg.type === \"content_block_stop\" &&\n msg.index !== undefined\n ) {\n const idx = msg.index\n\n const reasoningId = reasoningIds.get(idx)\n if (reasoningId && reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-end\",\n id: reasoningId,\n } as any)\n reasoningStarted.delete(idx)\n }\n\n if (textBlockIndices.has(idx)) {\n endTextBlock()\n textBlockIndices.delete(idx)\n }\n\n const tc = toolCallMap.get(idx)\n if (tc) {\n let parsedInput: any = {}\n try {\n parsedInput = JSON.parse(tc.inputJson || \"{}\")\n } catch {}\n\n if (isAskUserQuestionTool(tc.name)) {\n // Latch: the model handed control to the operator. Block any\n // auto-continue nudge for the rest of the turn so it can't\n // proceed on its own before the operator replies.\n autoContinueState.sawAskUserQuestion = true\n const askId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: askId,\n delta: formatAskUserQuestion(parsedInput),\n })\n endTextBlock()\n } else if (tc.name === \"ExitPlanMode\") {\n const plan = (parsedInput?.plan as string) || \"\"\n\n if (planModeQuestionActive) {\n // Approval bridge: render the plan, then hand the\n // yes/no back to opencode's own `question` tool and end\n // the turn on \"tool-calls\" so the outer loop runs it.\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n tc.id,\n plan,\n )\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: questionCall.text,\n })\n finishWithExitPlanQuestion(questionCall)\n return\n }\n\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`,\n })\n endTextBlock()\n } else if (\n isWebSearchTool(tc.name) &&\n isWebSearchHandledByCli(self.config.webSearch)\n ) {\n // Claude CLI runs WebSearch internally. Forwarding the\n // \"WebSearch\" tool-call part would render an invalid tool\n // row in opencode (no registry entry), so show the query\n // as a text line instead. The result stays CLI-internal.\n const query =\n typeof parsedInput?.query === \"string\"\n ? parsedInput.query\n : JSON.stringify(parsedInput)\n const searchId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: searchId,\n delta: `\\n> **Web search:** ${query}\\n`,\n })\n endTextBlock()\n } else if (tc.name.startsWith(PROXY_TOOL_PREFIX)) {\n noteProxyActivity()\n log.debug(\"ignoring proxy tool_use block; broker handles it\", {\n name: tc.name,\n id: tc.id,\n })\n } else {\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(tc.name, parsedInput, {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: tc.id,\n })\n\n if (!skip) {\n toolCallsById.set(tc.id, {\n id: tc.id,\n name: tc.name,\n input: parsedInput,\n })\n if (!executed) skipResultForIds.add(tc.id)\n\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n log.info(\"tool call complete\", {\n name: tc.name,\n mappedName,\n id: tc.id,\n executed,\n })\n }\n }\n }\n\n // Capture protocol-level stop_reason from the streaming\n // `message_delta` event (sent right before the final\n // `message_stop`). Any non-empty value is the source-of-truth\n // for why the turn ended — used to bypass the keyword heuristic.\n if (\n gotPartialEvents &&\n msg.type === \"message_delta\" &&\n typeof (msg as any).delta?.stop_reason === \"string\"\n ) {\n lastStopReason = (msg as any).delta.stop_reason\n }\n\n // assistant message (complete, not streaming).\n // When --include-partial-messages is on, this is a duplicate of\n // what we already streamed via content_block_* events. Skip it\n // for content, but still capture stop_reason from it for the\n // non-partial path.\n if (\n msg.type === \"assistant\" &&\n msg.message &&\n typeof (msg.message as any).stop_reason === \"string\"\n ) {\n lastStopReason = (msg.message as any).stop_reason\n }\n // Fallback: extract thinking from the complete assistant\n // message. opus-4-7's CLI strips thinking_delta from stream\n // events but may include thinking in the final message.\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n gotPartialEvents\n ) {\n const thinkingBlocks = (msg.message.content as any[]).filter(\n (b) => b.type === \"thinking\",\n )\n if (thinkingBlocks.length > 0) {\n log.info(\"assistant message thinking blocks\", {\n count: thinkingBlocks.length,\n hasText: thinkingBlocks.some(\n (b) => typeof b.thinking === \"string\" && b.thinking.length > 0,\n ),\n hadStreamThinking: hadThinkingTextFromStream,\n })\n if (!hadThinkingTextFromStream) {\n for (const block of thinkingBlocks) {\n if (block.thinking && block.thinking.length > 0) {\n noteReasoning()\n hadThinkingTextFromStream = true\n const thinkingId = generateId()\n controller.enqueue({\n type: \"reasoning-start\",\n id: thinkingId,\n } as any)\n controller.enqueue({\n type: \"reasoning-delta\",\n id: thinkingId,\n delta: block.thinking,\n } as any)\n controller.enqueue({\n type: \"reasoning-end\",\n id: thinkingId,\n } as any)\n }\n }\n }\n }\n }\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n !gotPartialEvents\n ) {\n const hasText = msg.message.content.some(\n (b: any) => b.type === \"text\" && b.text,\n )\n const hasToolUse = msg.message.content.some(\n (b: any) => b.type === \"tool_use\",\n )\n\n if (hasText) {\n hasReceivedContent = true\n }\n\n if (hasText && !hasToolUse) {\n startResultFallback()\n }\n if (hasToolUse) {\n clearFallbackTimer()\n }\n\n for (const block of msg.message.content) {\n if (block.type === \"text\" && block.text) {\n // New text block — keep only this block's text in the\n // last-block buffer for final-answer detection.\n resetLastVisibleTextBlock()\n const blockId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: blockId,\n delta: block.text,\n })\n endTextBlock()\n noteVisibleText(block.text)\n hasReceivedContent = true\n }\n\n if (block.type === \"thinking\" && block.thinking) {\n noteReasoning()\n const thinkingId = generateId()\n controller.enqueue({\n type: \"reasoning-start\",\n id: thinkingId,\n } as any)\n controller.enqueue({\n type: \"reasoning-delta\",\n id: thinkingId,\n delta: block.thinking,\n } as any)\n controller.enqueue({\n type: \"reasoning-end\",\n id: thinkingId,\n } as any)\n }\n\n if (block.type === \"tool_use\" && block.id && block.name) {\n noteToolActivity()\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n\n if (isAskUserQuestionTool(block.name)) {\n const askId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: askId,\n delta: formatAskUserQuestion(parsedInput),\n })\n endTextBlock()\n } else if (block.name === \"ExitPlanMode\") {\n const plan = (parsedInput?.plan as string) || \"\"\n\n if (planModeQuestionActive) {\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n block.id,\n plan,\n )\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: questionCall.text,\n })\n finishWithExitPlanQuestion(questionCall)\n return\n }\n\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`,\n })\n endTextBlock()\n } else if (\n isWebSearchTool(block.name) &&\n isWebSearchHandledByCli(self.config.webSearch)\n ) {\n // CLI-internal WebSearch: render the query as text and\n // drop the call/result parts (no opencode registry entry\n // for \"WebSearch\" — would render as an invalid tool row).\n toolCallsById.delete(block.id)\n const query =\n typeof parsedInput?.query === \"string\"\n ? parsedInput.query\n : JSON.stringify(parsedInput)\n const searchId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: searchId,\n delta: `\\n> **Web search:** ${query}\\n`,\n })\n endTextBlock()\n } else if (block.name.startsWith(PROXY_TOOL_PREFIX)) {\n noteProxyActivity()\n log.debug(\"ignoring proxy tool_use from assistant message\", {\n name: block.name,\n id: block.id,\n })\n } else {\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(block.name, parsedInput, {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: block.id,\n })\n\n if (!skip) {\n toolCallsById.set(block.id, {\n id: block.id,\n name: block.name,\n input: parsedInput,\n })\n if (!executed) skipResultForIds.add(block.id)\n controller.enqueue({\n type: \"tool-input-start\",\n id: block.id,\n toolName: mappedName,\n providerExecuted: executed,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: block.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n log.info(\"tool_use from assistant message\", {\n name: block.name,\n mappedName,\n id: block.id,\n executed,\n })\n }\n }\n\n if (block.type === \"tool_result\") {\n log.debug(\"tool_result\", {\n toolUseId: block.tool_use_id,\n })\n }\n }\n }\n\n // user message (tool results from Claude CLI)\n if (msg.type === \"user\" && msg.message?.content) {\n for (const block of msg.message.content) {\n if (block.type === \"tool_result\" && block.tool_use_id) {\n if (skipResultForIds.has(block.tool_use_id)) {\n log.debug(\"skipping tool-result (opencode runs it)\", {\n toolUseId: block.tool_use_id,\n })\n continue\n }\n\n let resultText = \"\"\n if (typeof block.content === \"string\") {\n resultText = block.content\n } else if (Array.isArray(block.content)) {\n resultText = block.content\n .filter(\n (\n c,\n ): c is { type: string; text: string } =>\n c.type === \"text\" &&\n typeof c.text === \"string\",\n )\n .map((c) => c.text)\n .join(\"\\n\")\n }\n\n // Ledger hook: commit pending TaskCreate to opencode's todo\n // panel via a synthetic todowrite emission. Pass-through —\n // returns null for non-TaskCreate ids, so cheap and silent.\n const claudeSessionId = getClaudeSessionId(sk)\n if (claudeSessionId) {\n const list = applyTaskCreateToolResult(\n claudeSessionId,\n block.tool_use_id,\n resultText,\n )\n if (list) {\n const synthId = `todowrite_${block.tool_use_id}`\n controller.enqueue({\n type: \"tool-input-start\",\n id: synthId,\n toolName: \"todowrite\",\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: synthId,\n toolName: \"todowrite\",\n input: JSON.stringify({\n todos: list.map((t) => ({\n id: t.id,\n content: t.content,\n status: t.status,\n priority: \"medium\",\n })),\n }),\n providerExecuted: false,\n } as any)\n noteToolActivity()\n }\n }\n\n const toolCall = toolCallsById.get(block.tool_use_id)\n if (toolCall) {\n controller.enqueue({\n type: \"tool-result\",\n toolCallId: block.tool_use_id,\n toolName: toolCall.name,\n result: {\n output: resultText,\n title: toolCall.name,\n metadata: {},\n },\n providerExecuted: true,\n } as any)\n noteToolActivity()\n log.info(\"tool result emitted\", {\n toolUseId: block.tool_use_id,\n name: toolCall.name,\n })\n toolCallsById.delete(block.tool_use_id)\n }\n }\n }\n }\n\n // result - end of conversation turn\n if (msg.type === \"result\") {\n clearFallbackTimer()\n\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n\n // Some CLI failures only include user-readable text in\n // `result.result` (no prior assistant text blocks). Emit it so\n // opencode users don't see a blank turn.\n if (\n !currentTextId &&\n msg.is_error &&\n typeof msg.result === \"string\" &&\n msg.result.trim().length > 0\n ) {\n const errId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: errId,\n delta: msg.result,\n })\n }\n\n resultMeta = {\n sessionId: msg.session_id,\n costUsd: msg.total_cost_usd,\n durationMs: msg.duration_ms,\n usage: msg.usage,\n }\n\n log.info(\"conversation result\", {\n sessionId: msg.session_id,\n durationMs: msg.duration_ms,\n numTurns: msg.num_turns,\n isError: msg.is_error,\n })\n\n turnCompleted = true\n\n endTextBlock()\n\n const shouldDeferResult =\n !msg.is_error &&\n !autoContinueState.aborted &&\n !autoContinueState.sawAskUserQuestion\n\n if (drainBuffer.length > 0 && shouldDeferResult) {\n log.info(\n \"waiting for parallel proxy calls at turn-result boundary\",\n {\n sessionKey: sk,\n count: drainBuffer.length,\n },\n )\n scheduleResultBoundary(\n () => completeResult(msg),\n DRAIN_QUIET_MS,\n )\n return\n }\n\n if (\n drainBuffer.length === 0 &&\n hadProxyActivitySinceContinue &&\n shouldDeferResult\n ) {\n log.info(\n \"waiting for delayed proxy call at turn-result boundary\",\n {\n sessionKey: sk,\n graceMs: PROXY_RESULT_BOUNDARY_GRACE_MS,\n },\n )\n scheduleResultBoundary(\n () => completeResult(msg),\n PROXY_RESULT_BOUNDARY_GRACE_MS,\n )\n return\n }\n\n completeResult(msg)\n }\n } catch (e) {\n log.debug(\"failed to parse line\", {\n error:\n e instanceof Error ? e.message : String(e),\n })\n }\n }\n\n const closeHandler = () => {\n log.debug(\"readline closed\")\n if (controllerClosed) return\n // Claude CLI's stdio is gone. The proxy-mcp HTTP requests that\n // backed any pending tool calls have no one to answer them now —\n // reject so the handlers return errors rather than hang.\n if (drainBuffer.length > 0 || getPendingProxyCalls(sk).length > 0) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n \"Claude CLI subprocess closed before pending tool calls were resolved\",\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n endTextBlock()\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage(),\n providerMetadata: {\n \"claude-code\": {\n ...resultMeta,\n ...(compactionMode\n ? { compactionModel: effectiveModelId }\n : {}),\n },\n },\n })\n try {\n controller.close()\n } catch {}\n }\n\n // Centralised per-turn teardown. Every exit path funnels through here\n // so we don't accumulate listeners across turns on a reused process.\n let cleanedUp = false\n const cleanupTurn = () => {\n if (cleanedUp) return\n cleanedUp = true\n clearFallbackTimer()\n pendingResultCompletion = null\n clearStartWatchdog()\n if (drainTimer) {\n clearTimeout(drainTimer)\n drainTimer = null\n }\n lineEmitter.off(\"line\", lineHandler)\n lineEmitter.off(\"close\", closeHandler)\n pendingProxyUnsubscribe?.()\n pendingProxyUnsubscribe = null\n proc.off(\"error\", procErrorHandler)\n }\n\n const procErrorHandler = (err: Error) => {\n log.error(\"process error\", { error: err.message })\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n if (controllerClosed) return\n // Subprocess failure invalidates every pending HTTP-bound tool\n // call for this session. Reject them so proxy-mcp returns errors\n // to Claude rather than letting the sockets stall.\n if (drainBuffer.length > 0 || getPendingProxyCalls(sk).length > 0) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n `Claude CLI subprocess error: ${err.message}`,\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({ type: \"error\", error: err })\n try {\n controller.close()\n } catch {}\n }\n\n lineEmitter.on(\"line\", lineHandler)\n lineEmitter.on(\"close\", closeHandler)\n\n pendingProxyUnsubscribe = onPendingProxyCall(sk, (call) => {\n if (controllerClosed) {\n // Stream already closed (we already drained). Late arrival —\n // reject immediately so the proxy-mcp HTTP request returns\n // instead of hanging until its 10-min timeout.\n log.warn(\n \"pending proxy call arrived after stream close; rejecting\",\n {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n },\n )\n rejectPendingProxyCallById(\n call.toolCallId,\n new Error(\n `Pending proxy call '${call.toolName}' arrived after the stream was already closed`,\n ),\n )\n return\n }\n log.info(\"received pending proxy call for session\", {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n })\n noteProxyActivity()\n noteToolActivity()\n drainBuffer.push(call)\n if (noteResultBoundaryCall()) return\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(drainNow, DRAIN_QUIET_MS)\n })\n\n proc.on(\"error\", procErrorHandler)\n\n // On abort, keep process alive for next message\n if (options.abortSignal) {\n options.abortSignal.addEventListener(\"abort\", () => {\n autoContinueState.aborted = true\n if (turnCompleted || controllerClosed) return\n\n if (!hasReceivedContent) {\n log.info(\n \"abort signal received before content, closing stream immediately\",\n { cwd },\n )\n if (\n drainBuffer.length > 0 ||\n getPendingProxyCalls(sk).length > 0\n ) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n \"Provider stream was aborted before pending proxy calls were emitted\",\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n return\n }\n\n log.info(\n \"abort signal received mid-turn, starting grace period\",\n { cwd },\n )\n // Abort grace period — short, since the user already asked to stop.\n startResultFallback(5_000)\n })\n }\n\n if (hasMatchedPendingResults) {\n // Tool-result turn: the prompt carries opencode's results for the\n // proxy tool calls we drained on the previous turn. Resolve each\n // matched call (claude CLI's HTTP handlers wake up and continue).\n // Parallel tools may complete in separate opencode turns. Keep\n // unmatched siblings pending until their own result, an explicit\n // abort/new user turn, or the proxy deadline.\n for (const { call, result } of previousPendingProxyMatches) {\n if (result) {\n log.info(\"resolving pending proxy call from tool result prompt\", {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n })\n resolvePendingProxyCallById(call.toolCallId, result)\n } else {\n log.info(\n \"leaving unmatched parallel proxy call pending\",\n {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n },\n )\n }\n }\n return\n }\n\n // No pending calls had matching tool-results. If any pending calls\n // are still hanging around from a prior turn, reject them so the\n // HTTP handlers in proxy-mcp don't sit blocked forever while we\n // proceed with a brand new user message.\n if (previousPendingProxyCalls.length > 0) {\n for (const call of previousPendingProxyCalls) {\n rejectPendingProxyCallById(\n call.toolCallId,\n new Error(\n `Pending proxy call '${call.toolName}' (${call.toolCallId}) was orphaned by a new user turn; rejecting`,\n ),\n )\n }\n }\n\n // Send the user message for a fresh turn.\n proc.stdin?.write(userMsg + \"\\n\")\n log.debug(\"sent user message\", { textLength: userMsg.length })\n // Arm the start watchdog so a reused child that goes silent after\n // the envelope write (seen after a long proxy-blocked tool call)\n // is respawned with --session-id instead of hanging the turn.\n armStartWatchdog()\n }\n\n void setup().catch((err) => {\n log.error(\"failed to set up doStream\", {\n error: err instanceof Error ? err.message : String(err),\n })\n controller.enqueue({\n type: \"error\",\n error: err instanceof Error ? err : new Error(String(err)),\n })\n try {\n controller.close()\n } catch {}\n })\n },\n cancel() {\n // Consumer cancelled the stream\n },\n })\n\n return {\n stream,\n request: { body: { text: userMsg } },\n response: { headers: {} },\n }\n }\n}\n","import { appendFileSync, mkdirSync, renameSync, statSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, join } from \"node:path\"\n\nexport type LogLevel = \"debug\" | \"info\" | \"notice\" | \"warn\" | \"error\"\nexport type LogMode = \"silent\" | \"debug\"\n\nexport interface LoggerConfig {\n file: boolean\n dir: string | null\n mode: LogMode\n level: LogLevel\n}\n\nconst LEVEL_RANK: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n notice: 2,\n warn: 3,\n error: 4,\n}\n\nconst MAX_LOG_BYTES = 5 * 1024 * 1024 // 5 MB\nconst DEFAULT_DIR = join(homedir(), \".local\", \"share\", \"opencode-claude-code\")\n\nconst DEFAULT_CONFIG: LoggerConfig = {\n file: false,\n dir: null,\n mode: \"silent\",\n level: \"info\",\n}\n\nfunction parseBoolEnv(v: string | undefined): boolean | undefined {\n if (v == null) return undefined\n const s = v.toLowerCase().trim()\n if (s === \"\") return undefined\n if (s === \"0\" || s === \"false\" || s === \"no\" || s === \"off\") return false\n return true\n}\n\nfunction parseLevelEnv(v: string | undefined): LogLevel | undefined {\n if (v == null) return undefined\n const s = v.toLowerCase().trim()\n if (s === \"\") return undefined\n if (s === \"debug\" || s === \"info\" || s === \"notice\" || s === \"warn\" || s === \"error\") {\n return s\n }\n return undefined\n}\n\nfunction parseModeFromDebugEnv(v: string | undefined): LogMode | undefined {\n if (v == null || v === \"\") return undefined\n return v.includes(\"opencode-claude-code\") ? \"debug\" : undefined\n}\n\nfunction withEnvOverrides(base: LoggerConfig): LoggerConfig {\n const result: LoggerConfig = { ...base }\n const envFile = parseBoolEnv(process.env.OPENCODE_CLAUDE_CODE_LOG_FILE)\n if (envFile !== undefined) result.file = envFile\n const envDir = process.env.OPENCODE_CLAUDE_CODE_LOG_DIR\n if (envDir !== undefined && envDir !== \"\") result.dir = envDir\n const envMode = parseModeFromDebugEnv(process.env.DEBUG)\n if (envMode !== undefined) result.mode = envMode\n const envLevel = parseLevelEnv(process.env.OPENCODE_CLAUDE_CODE_LOG_LEVEL)\n if (envLevel !== undefined) result.level = envLevel\n return result\n}\n\nlet activeConfig: LoggerConfig = withEnvOverrides(DEFAULT_CONFIG)\nlet fileLoggingDisabled = false\n\n/**\n * Configure the logger from plugin settings. Env vars override the supplied\n * config when explicitly set, so a developer can flip behavior for a single\n * process without editing opencode.jsonc.\n *\n * `OPENCODE_CLAUDE_CODE_LOG_FILE` → `file` (1/true/on/yes vs 0/false/no/off)\n * `OPENCODE_CLAUDE_CODE_LOG_DIR` → `dir`\n * `DEBUG=opencode-claude-code` → `mode: \"debug\"`\n * `OPENCODE_CLAUDE_CODE_LOG_LEVEL` → `level` (debug | info | notice | warn | error)\n */\nexport function configureLogger(input: Partial<LoggerConfig>): void {\n const merged: LoggerConfig = { ...DEFAULT_CONFIG, ...input }\n activeConfig = withEnvOverrides(merged)\n fileLoggingDisabled = false\n}\n\nexport function getLoggerConfig(): LoggerConfig {\n return { ...activeConfig }\n}\n\n/** Test-only helper. Resets to defaults+env so tests are deterministic. */\nexport function _resetLoggerForTests(): void {\n activeConfig = withEnvOverrides(DEFAULT_CONFIG)\n fileLoggingDisabled = false\n}\n\nfunction resolvedLogFile(): string {\n return join(activeConfig.dir ?? DEFAULT_DIR, \"plugin.log\")\n}\n\nfunction rotateIfNeeded(logFile: string): void {\n try {\n const stat = statSync(logFile)\n if (stat.size > MAX_LOG_BYTES) {\n renameSync(logFile, `${logFile}.1`)\n }\n } catch {\n // file does not exist yet — nothing to rotate\n }\n}\n\nfunction writeToFile(line: string): void {\n if (!activeConfig.file) return\n if (fileLoggingDisabled) return\n try {\n const logFile = resolvedLogFile()\n mkdirSync(dirname(logFile), { recursive: true })\n rotateIfNeeded(logFile)\n appendFileSync(logFile, line + \"\\n\", \"utf8\")\n } catch {\n // Disable on first failure to avoid spamming errors on a read-only FS.\n fileLoggingDisabled = true\n }\n}\n\nfunction fmt(level: string, msg: string, data?: Record<string, unknown>): string {\n const ts = new Date().toISOString()\n const base = `[${ts}] [opencode-claude-code] ${level}: ${msg}`\n if (data && Object.keys(data).length > 0) {\n return `${base} ${JSON.stringify(data)}`\n }\n return base\n}\n\nfunction shouldEmit(level: LogLevel): boolean {\n return LEVEL_RANK[level] >= LEVEL_RANK[activeConfig.level]\n}\n\nfunction shouldTui(level: LogLevel): boolean {\n // warn/error are alwaysStderr: a developer who passes the level threshold\n // should still see real problems in the TUI regardless of mode. Below-\n // threshold entries are filtered earlier by shouldEmit().\n if (level === \"warn\" || level === \"error\") return true\n return activeConfig.mode === \"debug\"\n}\n\nfunction emit(level: LogLevel, msg: string, data?: Record<string, unknown>): void {\n if (!shouldEmit(level)) return\n const line = fmt(level.toUpperCase(), msg, data)\n if (shouldTui(level)) {\n console.error(line)\n }\n writeToFile(line)\n}\n\nexport const log = {\n debug(msg: string, data?: Record<string, unknown>) {\n emit(\"debug\", msg, data)\n },\n info(msg: string, data?: Record<string, unknown>) {\n emit(\"info\", msg, data)\n },\n notice(msg: string, data?: Record<string, unknown>) {\n emit(\"notice\", msg, data)\n },\n warn(msg: string, data?: Record<string, unknown>) {\n emit(\"warn\", msg, data)\n },\n error(msg: string, data?: Record<string, unknown>) {\n emit(\"error\", msg, data)\n },\n}\n","import { log } from \"./logger.js\"\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\"\n\nexport interface TodoEntry {\n id: string\n content: string\n status: TodoStatus\n}\n\ninterface PendingCreate {\n subject: string\n createdAt: number\n}\n\ninterface SessionLedger {\n todos: Map<string, TodoEntry>\n pendingCreates: Map<string, PendingCreate>\n}\n\nconst ledgers = new Map<string, SessionLedger>()\n\nconst PENDING_CREATE_TTL_MS = 60_000\nconst TASK_CREATED_PATTERN = /Task\\s*#?\\s*(\\d+)\\s+created/i\nconst VALID_STATUSES: ReadonlySet<TodoStatus> = new Set([\"pending\", \"in_progress\", \"completed\"])\n\nfunction getOrCreate(sessionId: string): SessionLedger {\n let ledger = ledgers.get(sessionId)\n if (!ledger) {\n ledger = { todos: new Map(), pendingCreates: new Map() }\n ledgers.set(sessionId, ledger)\n }\n return ledger\n}\n\nfunction prunePending(ledger: SessionLedger): void {\n const cutoff = Date.now() - PENDING_CREATE_TTL_MS\n for (const [id, pending] of ledger.pendingCreates) {\n if (pending.createdAt < cutoff) ledger.pendingCreates.delete(id)\n }\n}\n\nfunction materialize(ledger: SessionLedger): TodoEntry[] {\n return Array.from(ledger.todos.values())\n}\n\nfunction resolveSubject(input: { subject?: unknown; description?: unknown } | undefined): string {\n const subject = typeof input?.subject === \"string\" ? input.subject.trim() : \"\"\n if (subject) return subject\n const description = typeof input?.description === \"string\" ? input.description.trim() : \"\"\n if (description) return description\n return \"(no subject)\"\n}\n\nexport function applyTaskCreateToolUse(\n sessionId: string,\n toolUseId: string,\n input: { subject?: unknown; description?: unknown } | undefined,\n): void {\n if (!sessionId || !toolUseId) return\n const ledger = getOrCreate(sessionId)\n prunePending(ledger)\n ledger.pendingCreates.set(toolUseId, {\n subject: resolveSubject(input),\n createdAt: Date.now(),\n })\n}\n\nexport function applyTaskCreateToolResult(\n sessionId: string,\n toolUseId: string,\n resultText: string,\n): TodoEntry[] | null {\n if (!sessionId || !toolUseId) return null\n const ledger = ledgers.get(sessionId)\n if (!ledger) return null\n const pending = ledger.pendingCreates.get(toolUseId)\n if (!pending) return null\n ledger.pendingCreates.delete(toolUseId)\n const match = typeof resultText === \"string\" ? resultText.match(TASK_CREATED_PATTERN) : null\n if (!match) {\n log.debug(\"TaskCreate result did not match expected format\", { sessionId, toolUseId, resultText })\n return null\n }\n const claudeId = match[1]\n if (ledger.todos.has(claudeId)) {\n log.debug(\"TaskCreate result for already-known claude id; overwriting\", { sessionId, claudeId })\n }\n ledger.todos.set(claudeId, { id: claudeId, content: pending.subject, status: \"pending\" })\n return materialize(ledger)\n}\n\nexport function applyTaskUpdate(\n sessionId: string,\n input: { taskId?: unknown; subject?: unknown; status?: unknown } | undefined,\n): TodoEntry[] | null {\n if (!sessionId) return null\n const taskId = typeof input?.taskId === \"string\" ? input.taskId : null\n if (!taskId) return null\n const ledger = ledgers.get(sessionId)\n if (!ledger) return null\n const entry = ledger.todos.get(taskId)\n if (!entry) {\n log.debug(\"TaskUpdate for unknown task id\", { sessionId, taskId })\n return null\n }\n if (input?.status === \"deleted\") {\n ledger.todos.delete(taskId)\n return materialize(ledger)\n }\n if (typeof input?.status === \"string\" && VALID_STATUSES.has(input.status as TodoStatus)) {\n entry.status = input.status as TodoStatus\n }\n if (typeof input?.subject === \"string\" && input.subject.trim().length > 0) {\n entry.content = input.subject.trim()\n }\n return materialize(ledger)\n}\n\nexport function clearLedger(sessionId: string): void {\n if (!sessionId) return\n ledgers.delete(sessionId)\n}\n\nexport function getLedger(sessionId: string): TodoEntry[] {\n const ledger = ledgers.get(sessionId)\n if (!ledger) return []\n return materialize(ledger)\n}\n\nexport function _resetAllLedgersForTests(): void {\n ledgers.clear()\n}\n","import { log } from \"./logger.js\"\nimport { applyTaskCreateToolUse, applyTaskUpdate, type TodoEntry } from \"./todo-ledger.js\"\nimport type { WebSearchRouting } from \"./types.js\"\n\nexport interface MapToolOptions {\n webSearch?: WebSearchRouting\n sessionId?: string\n toolUseId?: string\n}\n\n/** Claude CLI's built-in web search tool (name varies by CLI version). */\nexport function isWebSearchTool(name: string): boolean {\n return name === \"WebSearch\" || name === \"web_search\"\n}\n\n/**\n * True when WebSearch runs inside Claude CLI (default) rather than being\n * forwarded to an opencode tool. In that case the tool-call part must not\n * reach opencode — \"WebSearch\" has no registry entry there and renders as\n * an invalid tool row. Callers show the query as a text line instead.\n */\nexport function isWebSearchHandledByCli(route?: WebSearchRouting): boolean {\n return !route || route === \"claude\" || route === \"disabled\"\n}\n\n/**\n * Map Claude CLI tool input (snake_case) to OpenCode tool input (camelCase)\n */\nfunction mapToolInput(name: string, input: any): any {\n if (!input) return input\n\n switch (name) {\n case \"Write\":\n return {\n filePath: input.file_path ?? input.filePath,\n content: input.content,\n }\n case \"Edit\":\n return {\n filePath: input.file_path ?? input.filePath,\n oldString: input.old_string ?? input.oldString,\n newString: input.new_string ?? input.newString,\n replaceAll: input.replace_all ?? input.replaceAll,\n }\n case \"Read\":\n return {\n filePath: input.file_path ?? input.filePath,\n offset: input.offset,\n limit: input.limit,\n }\n case \"Bash\":\n return {\n command: input.command,\n description:\n input.description ||\n `Execute: ${String(input.command || \"\").slice(0, 50)}${String(input.command || \"\").length > 50 ? \"...\" : \"\"}`,\n timeout: input.timeout,\n }\n case \"NotebookEdit\":\n return {\n notebookPath: input.notebook_path ?? input.notebookPath,\n cellNumber: input.cell_number ?? input.cellNumber,\n newSource: input.new_source ?? input.newSource,\n cellType: input.cell_type ?? input.cellType,\n editMode: input.edit_mode ?? input.editMode,\n }\n case \"Glob\":\n return {\n pattern: input.pattern,\n path: input.path,\n }\n case \"Grep\":\n return {\n pattern: input.pattern,\n path: input.path,\n include: input.include,\n }\n case \"TodoWrite\":\n if (Array.isArray(input.todos)) {\n const mappedTodos = input.todos.map((todo: any, index: number) => ({\n content: todo.content,\n status: todo.status || \"pending\",\n priority: todo.priority || \"medium\",\n id: todo.id || `todo_${Date.now()}_${index}`,\n }))\n return { todos: mappedTodos }\n }\n return input\n default:\n return input\n }\n}\n\n// Tools that Claude CLI executes internally but we report to opencode for UI display\nconst OPENCODE_HANDLED_TOOLS = new Set([\n \"Edit\",\n \"Write\",\n \"Bash\",\n \"NotebookEdit\",\n \"Read\",\n \"Glob\",\n \"Grep\",\n])\n\n// Claude CLI internal tools that should not be forwarded to opencode.\n// These are part of Claude Code's own system and have no opencode equivalent.\n// Tools the Claude CLI emits for its own internal bookkeeping (sub-agents,\n// task tracking, search). opencode has no matching tool registry entry, so\n// forwarding them surfaces as `⚙ invalid` rows in the UI. Skip them.\n// TaskOutput is intentionally NOT here — it has an explicit bash-echo mapping\n// below so the result stays visible.\nconst CLAUDE_INTERNAL_TOOLS = new Set([\n \"ToolSearch\",\n \"Agent\",\n \"AskFollowupQuestion\",\n \"TaskList\",\n \"TaskGet\",\n \"TaskStop\",\n])\n\nfunction emitTodoWrite(todos: TodoEntry[]) {\n return {\n name: \"todowrite\",\n input: {\n todos: todos.map((todo) => ({\n id: todo.id,\n content: todo.content,\n status: todo.status,\n priority: \"medium\",\n })),\n },\n executed: false,\n }\n}\n\nexport function mapTool(\n name: string,\n input?: any,\n opts?: MapToolOptions,\n): { name: string; input?: any; executed: boolean; skip?: boolean } {\n // Claude CLI internal tools — skip entirely\n if (CLAUDE_INTERNAL_TOOLS.has(name)) {\n log.debug(\"skipping Claude CLI internal tool\", { name })\n return { name, input, executed: true, skip: true }\n }\n\n // TaskCreate: stash subject keyed by tool_use_id; emission happens on tool_result.\n // Without sessionId+toolUseId we cannot maintain the ledger, so fall back to skip\n // (preserves old behavior for callers that haven't been threaded yet).\n if (name === \"TaskCreate\") {\n if (opts?.sessionId && opts?.toolUseId) {\n applyTaskCreateToolUse(opts.sessionId, opts.toolUseId, input)\n }\n return { name, input, executed: true, skip: true }\n }\n\n // TaskUpdate: mutate ledger and emit full list as opencode todowrite. Without\n // sessionId, fall back to skip. Unknown task ids return null from the ledger\n // and we drop the event.\n if (name === \"TaskUpdate\") {\n if (opts?.sessionId) {\n const list = applyTaskUpdate(opts.sessionId, input)\n if (list !== null) return emitTodoWrite(list)\n }\n return { name, input, executed: true, skip: true }\n }\n\n // Plan mode tools\n if (name === \"EnterPlanMode\") return { name: \"plan_enter\", input: {}, executed: false }\n if (name === \"ExitPlanMode\") return { name: \"plan_exit\", input, executed: false }\n\n // TodoWrite needs opencode to run it locally so Todo.Service (and the UI\n // widget backed by it) gets populated. Reporting as provider-executed would\n // short-circuit opencode's own execute and leave the todo panel empty.\n if (name === \"TodoWrite\") {\n const mappedInput = mapToolInput(name, input)\n return { name: \"todowrite\", input: mappedInput, executed: false }\n }\n\n // WebSearch — routing controlled by config.webSearch\n if (isWebSearchTool(name)) {\n const mappedInput = input?.query ? { query: input.query } : input\n const route = opts?.webSearch\n if (route && route !== \"claude\" && route !== \"disabled\") {\n log.debug(\"routing WebSearch to opencode tool\", { target: route, mappedInput })\n return { name: route, input: mappedInput, executed: false }\n }\n // Claude CLI runs WebSearch internally; \"WebSearch\" has no opencode\n // registry entry, so forwarding the tool-call part surfaces a\n // \"Model tried to call unavailable tool\" invalid row in opencode.\n // Skip the part — callers render the query as a text line instead.\n log.debug(\"WebSearch executed by Claude CLI\", { mappedInput })\n return { name: \"WebSearch\", input: mappedInput, executed: true, skip: true }\n }\n\n // TaskOutput -> bash echo\n if (name === \"TaskOutput\") {\n if (!input) return { name: \"bash\", executed: false }\n const output = input?.content || input?.output || JSON.stringify(input)\n return {\n name: \"bash\",\n input: {\n command: `echo \"TASK OUTPUT: ${String(output).replace(/\"/g, '\\\\\"')}\"`,\n description: \"Displaying task output\",\n },\n executed: false,\n }\n }\n\n // Third-party MCP tools: mcp__<server>__<tool> -> <server>_<tool>.\n // Marked provider-executed because Claude CLI runs these internally via\n // its own --mcp-config; the tool-result is already in the stream. If we\n // reported executed:false, opencode would look up the tool in its own\n // registry, fail to find it, and emit an `invalid` tool error that\n // shadows the real result.\n //\n // Our own proxy tools (`mcp__opencode_proxy__*`) are filtered out by\n // callers before reaching here, so this branch only ever sees user MCP\n // servers configured in Claude CLI's settings.\n if (name.startsWith(\"mcp__\")) {\n const parts = name.slice(5).split(\"__\")\n if (parts.length >= 2) {\n const serverName = parts[0]\n const toolName = parts.slice(1).join(\"_\")\n const openCodeName = `${serverName}_${toolName}`\n log.debug(\"mapping MCP tool\", { original: name, mapped: openCodeName })\n return { name: openCodeName, input, executed: true }\n }\n }\n\n // Tools executed by Claude CLI internally - map to lowercase for opencode\n if (OPENCODE_HANDLED_TOOLS.has(name)) {\n const mappedInput = mapToolInput(name, input)\n const openCodeName = name.toLowerCase()\n log.debug(\"mapping CLI-executed tool\", { name, openCodeName })\n return { name: openCodeName, input: mappedInput, executed: true }\n }\n\n // Unknown tools - treated as provider-executed\n return { name, input, executed: true }\n}\n","import type { LanguageModelV3 } from \"@ai-sdk/provider\"\nimport { log } from \"./logger.js\"\nimport type { ReasoningEffort } from \"./types.js\"\n\ntype Prompt = Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"prompt\"]\n\nconst THINKING_KEYWORDS: Record<ReasoningEffort, string | null> = {\n minimal: null,\n low: \"think\",\n medium: \"think hard\",\n high: \"think harder\",\n xhigh: \"megathink\",\n max: \"ultrathink\",\n}\n\nexport function reasoningKeyword(effort?: ReasoningEffort): string | null {\n if (!effort) return null\n return THINKING_KEYWORDS[effort] ?? null\n}\n\nconst SUPPORTED_IMAGE_TYPES = new Set([\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n])\n\nfunction toImageBlock(part: any): any | null {\n const raw: unknown = part.image ?? part.data ?? part.url ?? part.source?.data\n if (!raw) {\n log.warn(\"file part without data, skipping\")\n return null\n }\n\n let resolvedMediaType: string = part.mediaType || part.mimeType || part.mime || \"\"\n let base64: string | null = null\n\n if (typeof raw === \"string\") {\n if (raw.startsWith(\"data:\")) {\n const match = /^data:([^;,]+)(?:;[^,]*)*(?:;base64)?,(.*)$/s.exec(raw)\n if (!match) {\n log.warn(\"malformed data URI, skipping file part\")\n return null\n }\n resolvedMediaType = resolvedMediaType || match[1]\n base64 = match[2]\n } else if (/^https?:\\/\\//i.test(raw)) {\n log.warn(\"remote URL images are not supported by Claude CLI, skipping\")\n return null\n } else {\n base64 = raw\n }\n } else if (raw instanceof URL) {\n log.warn(\"remote URL images are not supported by Claude CLI, skipping\")\n return null\n } else if (raw instanceof Uint8Array || Buffer.isBuffer(raw)) {\n base64 = Buffer.from(raw as Uint8Array).toString(\"base64\")\n } else {\n log.warn(\"unsupported file part data type\", { dataType: typeof raw })\n return null\n }\n\n if (!resolvedMediaType || !SUPPORTED_IMAGE_TYPES.has(resolvedMediaType)) {\n log.warn(\"unsupported media type for Claude image block, skipping\", {\n mediaType: resolvedMediaType,\n })\n return null\n }\n\n return {\n type: \"image\",\n source: { type: \"base64\", media_type: resolvedMediaType, data: base64 },\n }\n}\n\nfunction getToolResultText(part: any): string {\n const value = part.output ?? part.result\n\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\") {\n return JSON.stringify(value)\n }\n\n switch (value.type) {\n case \"text\":\n case \"error-text\":\n return String(value.value)\n case \"json\":\n case \"error-json\":\n return JSON.stringify(value.value)\n case \"execution-denied\":\n return value.reason ? `Execution denied: ${value.reason}` : \"Execution denied\"\n case \"content\":\n return Array.isArray(value.value)\n ? value.value\n .map((item: any) => {\n if (item?.type === \"text\") return item.text\n return JSON.stringify(item)\n })\n .join(\"\\n\")\n : JSON.stringify(value.value)\n default:\n return JSON.stringify(value)\n }\n}\n\n// Compaction-mode caps. These are the only knobs that affect how much\n// transcript content reaches the model when opencode invokes /compact.\n// 180k chars ≈ 60k tokens worst-case — well under Haiku 4.5's 200k window\n// after accounting for system prompt + output budget.\nconst MAX_HISTORY_CHARS = 180_000\nconst MAX_TOOL_RESULT_CHARS = 10_000\nconst MAX_TOOL_INPUT_CHARS = 2_000\n\nfunction clipWithMarker(text: string, max: number): string {\n if (text.length <= max) return text\n return `${text.slice(0, max)}\\n…[truncated ${text.length - max} chars]`\n}\n\nfunction renderToolInput(input: unknown): string {\n let raw: string\n try {\n raw = typeof input === \"string\" ? input : JSON.stringify(input)\n } catch {\n raw = String(input)\n }\n return clipWithMarker(raw, MAX_TOOL_INPUT_CHARS)\n}\n\nfunction renderMessageContentForCompaction(\n msg: any,\n): { text: string; toolResultCount: number } {\n const lines: string[] = []\n let toolResultCount = 0\n\n if (typeof msg.content === \"string\") {\n return { text: msg.content, toolResultCount: 0 }\n }\n\n if (!Array.isArray(msg.content)) {\n return { text: \"\", toolResultCount: 0 }\n }\n\n for (const part of msg.content as any[]) {\n if (!part) continue\n switch (part.type) {\n case \"text\":\n if (part.text) lines.push(part.text)\n break\n case \"tool-call\":\n lines.push(\n `[tool_use:${part.toolName ?? \"unknown\"}(${renderToolInput(part.input)})]`,\n )\n break\n case \"tool-result\":\n toolResultCount++\n lines.push(\n `[tool_result:${part.toolName ?? part.toolCallId ?? \"unknown\"}]\\n${clipWithMarker(\n getToolResultText(part),\n MAX_TOOL_RESULT_CHARS,\n )}`,\n )\n break\n case \"image\":\n lines.push(\n `[image: ${part.mediaType ?? part.mimeType ?? \"unknown\"}]`,\n )\n break\n case \"file\":\n lines.push(\n `[file: ${part.mediaType ?? part.mimeType ?? \"unknown\"}]`,\n )\n break\n case \"reasoning\":\n // Skip reasoning blocks in compaction — they bloat input without\n // helping the summarizer.\n break\n }\n }\n\n return { text: lines.join(\"\\n\"), toolResultCount }\n}\n\n/**\n * Compact conversation history into a context summary.\n *\n * - mode \"fresh-session\" (default): legacy behavior. Filters to\n * user/assistant only, clips each message at 2000 chars, drops tool\n * payloads to placeholders. Used when starting a fresh CLI session\n * that lost its prior session id.\n * - mode \"compaction\": rich serializer for opencode /compact. Includes\n * tool roles, renders tool_use input and tool_result content (each\n * clipped at MAX_TOOL_RESULT_CHARS), and caps aggregate output at\n * MAX_HISTORY_CHARS by dropping oldest entries first.\n */\nexport function compactConversationHistory(\n prompt: Prompt,\n opts: { mode?: \"fresh-session\" | \"compaction\" } = {},\n): string | null {\n const mode = opts.mode ?? \"fresh-session\"\n\n if (mode === \"compaction\") {\n return buildCompactionHistory(prompt)\n }\n\n const conversationMessages = prompt.filter(\n (m) => m.role === \"user\" || m.role === \"assistant\",\n )\n\n if (conversationMessages.length <= 1) {\n return null\n }\n\n const historyParts: string[] = []\n\n for (let i = 0; i < conversationMessages.length - 1; i++) {\n const msg = conversationMessages[i]\n const role = msg.role === \"user\" ? \"User\" : \"Assistant\"\n\n let text = \"\"\n if (typeof msg.content === \"string\") {\n text = msg.content\n } else if (Array.isArray(msg.content)) {\n const textParts = (msg.content as any[])\n .filter((p) => p.type === \"text\" && p.text)\n .map((p) => p.text)\n text = textParts.join(\"\\n\")\n\n const toolCalls = (msg.content as any[]).filter(\n (p) => p.type === \"tool-call\",\n )\n const toolResults = (msg.content as any[]).filter(\n (p) => p.type === \"tool-result\",\n )\n\n if (toolCalls.length > 0) {\n text += `\\n[Called ${toolCalls.length} tool(s): ${toolCalls.map((t: any) => t.toolName).join(\", \")}]`\n }\n if (toolResults.length > 0) {\n text += `\\n[Received ${toolResults.length} tool result(s)]`\n }\n }\n\n if (text.trim()) {\n const truncated =\n text.length > 2000 ? text.slice(0, 2000) + \"...\" : text\n historyParts.push(`${role}: ${truncated}`)\n }\n }\n\n if (historyParts.length === 0) {\n return null\n }\n\n return historyParts.join(\"\\n\\n\")\n}\n\nfunction buildCompactionHistory(prompt: Prompt): string | null {\n // Iterate newest-first, accumulate up to MAX_HISTORY_CHARS, then reverse\n // to chronological order. Oldest messages get dropped when the budget\n // is exhausted — they are the least relevant for a summary of recent\n // work.\n const entries: string[] = []\n let total = 0\n let totalToolResults = 0\n let droppedOldest = 0\n\n // Skip the trailing user message: opencode's /compact appends the\n // synthesis instruction as the final user turn. The instruction itself\n // is added by getClaudeUserMessage after the transcript block, so we\n // don't want it duplicated inside the transcript.\n const end = prompt.length > 0 && prompt[prompt.length - 1].role === \"user\"\n ? prompt.length - 1\n : prompt.length\n\n for (let i = end - 1; i >= 0; i--) {\n const msg = prompt[i] as any\n const roleLabel =\n msg.role === \"user\"\n ? \"User\"\n : msg.role === \"assistant\"\n ? \"Assistant\"\n : msg.role === \"tool\"\n ? \"Tool\"\n : msg.role\n\n const { text, toolResultCount } = renderMessageContentForCompaction(msg)\n if (!text.trim()) continue\n\n const entry = `${roleLabel}: ${text}`\n if (total + entry.length > MAX_HISTORY_CHARS) {\n droppedOldest = i + 1\n break\n }\n entries.push(entry)\n total += entry.length + 2 // +2 for the \"\\n\\n\" join\n totalToolResults += toolResultCount\n }\n\n if (entries.length === 0) return null\n\n entries.reverse()\n log.info(\"built compaction history\", {\n entries: entries.length,\n chars: total,\n toolResults: totalToolResults,\n droppedOldestBefore: droppedOldest,\n })\n\n return entries.join(\"\\n\\n\")\n}\n\n/**\n * Convert AI SDK prompt into a Claude CLI stream-json user message.\n *\n * `compactionMode` switches behavior for opencode /compact: the prior\n * transcript is rendered with rich tool content (not placeholders), the\n * wrapper framing tells the model this is the authoritative thread, and\n * the reasoning keyword is suppressed so the full output budget goes\n * toward the summary.\n */\nexport function getClaudeUserMessage(\n prompt: Prompt,\n includeHistoryContext: boolean = false,\n reasoningEffort?: ReasoningEffort,\n opts: { compactionMode?: boolean } = {},\n): string {\n const compactionMode = opts.compactionMode === true\n const content: any[] = []\n\n if (compactionMode) {\n const transcript = compactConversationHistory(prompt, {\n mode: \"compaction\",\n })\n if (transcript) {\n log.info(\"including compaction transcript\", {\n historyLength: transcript.length,\n })\n content.push({\n type: \"text\",\n text: `<conversation_transcript>\n${transcript}\n</conversation_transcript>\n\nThe complete prior conversation appears above. The synthesis instructions follow below.\n\n`,\n })\n }\n } else if (includeHistoryContext) {\n const historyContext = compactConversationHistory(prompt)\n if (historyContext) {\n log.info(\"including conversation history context\", {\n historyLength: historyContext.length,\n })\n content.push({\n type: \"text\",\n text: `<conversation_history>\nThe following is a summary of our conversation so far (from a previous session that couldn't be resumed):\n\n${historyContext}\n\n</conversation_history>\n\nNow continuing with the current message:\n\n`,\n })\n }\n }\n\n // Find messages since last assistant message\n const messages: typeof prompt = []\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === \"assistant\") break\n messages.unshift(prompt[i])\n }\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n const str = msg.content as string\n if (str.trim()) {\n content.push({ type: \"text\", text: str })\n }\n } else if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (part.type === \"text\") {\n if (part.text && part.text.trim()) {\n content.push({ type: \"text\", text: part.text })\n }\n } else if (part.type === \"file\" || part.type === \"image\") {\n const block = toImageBlock(part)\n if (block) {\n content.push(block)\n } else {\n log.debug(\"skipped non-image file part\", {\n mediaType: part.mediaType,\n })\n }\n } else if (part.type === \"tool-result\") {\n const p = part as any\n content.push({\n type: \"tool_result\",\n tool_use_id: p.toolCallId,\n content: getToolResultText(p),\n })\n }\n }\n }\n } else if (msg.role === \"tool\") {\n // AI SDK V3 delivers tool results in `tool`-role messages, not `user`.\n // Without this branch we'd hit the empty-content sentinel path and\n // send \"(empty)\" to Claude CLI instead of the actual tool result —\n // forcing the user to press \"continue\" between proxy tool calls.\n if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (part?.type === \"tool-result\") {\n const p = part as any\n content.push({\n type: \"tool_result\",\n tool_use_id: p.toolCallId,\n content: getToolResultText(p),\n })\n }\n }\n }\n }\n }\n\n if (content.length === 0) {\n // CLI rejects a zero-block message with 400, and Anthropic rejects\n // whitespace-only text blocks — so we need a non-whitespace sentinel.\n // \"(empty)\" matches the parenthetical meta-note convention this file\n // already uses for reasoning keywords (\"(think)\", \"(megathink)\", etc.),\n // which the model reads as out-of-band metadata rather than a prompt to\n // continue its previous turn.\n log.warn(\"empty user content; sending sentinel to satisfy CLI\")\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: \"(empty)\" }],\n },\n })\n }\n\n // Reasoning keyword is a Claude CLI hint that triggers extended thinking.\n // For compaction we want the full output budget to go to the summary\n // itself, not internal reasoning — so skip injection.\n if (!compactionMode) {\n const keyword = reasoningKeyword(reasoningEffort)\n if (keyword) {\n const lastTextPart = [...content].reverse().find((p) => p.type === \"text\")\n if (lastTextPart) {\n lastTextPart.text = lastTextPart.text\n ? `${lastTextPart.text}\\n\\n(${keyword})`\n : `(${keyword})`\n } else {\n content.push({ type: \"text\", text: `(${keyword})` })\n }\n log.debug(\"injected reasoning keyword\", { effort: reasoningEffort, keyword })\n }\n }\n\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content,\n },\n })\n}\n","export const QUESTION_TOOL_NAME = \"question\"\n\nexport const APPROVED_EXIT_PLAN_MODE_MESSAGE =\n \"User has approved your plan. You can now start coding. Start with updating your todo list if applicable.\"\n\nconst REJECTED_EXIT_PLAN_MODE_PREFIX =\n \"The user doesn't want to proceed with this tool use. The tool use was rejected. To tell you how to proceed, the user said:\"\n\nconst PLAN_MODE_APPROVAL_QUESTION = \"Do you want to proceed with this plan?\"\nconst OPENCODE_QUESTION_RESULT_PREFIX =\n `User has answered your questions: \"${PLAN_MODE_APPROVAL_QUESTION}\"=\"`\nconst OPENCODE_QUESTION_RESULT_SUFFIX =\n `\". You can now continue with the user's answers in mind.`\n\nconst KEY_SEPARATOR = \"\\u0000\"\n\nexport interface ExitPlanModeQuestionCall {\n toolCallId: string\n toolName: typeof QUESTION_TOOL_NAME\n input: {\n questions: Array<{\n header: string\n question: string\n options: Array<{ label: string; description: string }>\n multiple: boolean\n custom: boolean\n }>\n }\n text: string\n}\n\n/**\n * Whether to bridge `ExitPlanMode` into opencode's native `question` tool\n * this turn.\n *\n * Opt-in (`planModeQuestion`) because opencode's question form does not\n * currently render (anomalyco/opencode#36604), so an enabled bridge hangs the\n * turn until the operator interrupts, where the text path still works.\n * Gated on the live registry because emitting a `question` tool-call on a\n * build without that entry renders `⚙ invalid` and wedges the turn just the\n * same. Never bridged during compaction: that turn is text-only and its\n * answer would have nowhere to go.\n */\nexport function isPlanModeQuestionActive(input: {\n configured: boolean | undefined\n opencodeHasQuestion: boolean\n compactionMode: boolean\n}): boolean {\n if (input.compactionMode) return false\n if (input.configured !== true) return false\n return input.opencodeHasQuestion\n}\n\nconst pendingQuestions = new Map<string, string>()\n\nfunction pendingKey(sessionKey: string, questionToolCallId: string): string {\n return `${sessionKey}${KEY_SEPARATOR}${questionToolCallId}`\n}\n\nexport function clearExitPlanModeQuestions(sessionKey: string): void {\n const prefix = `${sessionKey}${KEY_SEPARATOR}`\n for (const key of pendingQuestions.keys()) {\n if (key.startsWith(prefix)) pendingQuestions.delete(key)\n }\n}\n\nexport function createExitPlanModeQuestionCall(\n sessionKey: string,\n exitPlanModeToolUseId: string,\n plan: string,\n questionToolCallId = `exit_plan_question_${exitPlanModeToolUseId}`,\n): ExitPlanModeQuestionCall {\n pendingQuestions.set(pendingKey(sessionKey, questionToolCallId), exitPlanModeToolUseId)\n\n return {\n toolCallId: questionToolCallId,\n toolName: QUESTION_TOOL_NAME,\n input: {\n questions: [\n {\n header: \"Plan approval\",\n question: PLAN_MODE_APPROVAL_QUESTION,\n options: [\n { label: \"yes\", description: \"\" },\n { label: \"no\", description: \"\" },\n ],\n multiple: false,\n custom: true,\n },\n ],\n },\n text: plan ? `\\n\\n${plan}\\n` : \"\\n\\n\",\n }\n}\n\nfunction buildToolResultMessage(input: {\n toolUseId: string\n approved: boolean\n feedback: string\n}): string {\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n input.approved\n ? {\n type: \"tool_result\",\n tool_use_id: input.toolUseId,\n content: APPROVED_EXIT_PLAN_MODE_MESSAGE,\n }\n : {\n type: \"tool_result\",\n tool_use_id: input.toolUseId,\n content: `${REJECTED_EXIT_PLAN_MODE_PREFIX}\\n${input.feedback || \"no\"}`,\n is_error: true,\n },\n ],\n },\n })\n}\n\nfunction tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction unwrapToolOutput(part: any): unknown {\n const output = part?.output ?? part?.result\n if (typeof output === \"string\") return tryParseJson(output)\n if (!output || typeof output !== \"object\") return output\n\n switch (output.type) {\n case \"json\":\n case \"error-json\":\n return output.value\n case \"text\":\n case \"error-text\":\n return tryParseJson(String(output.value ?? \"\"))\n case \"execution-denied\":\n return {\n denied: true,\n reason: String(output.reason ?? \"question rejected\"),\n }\n case \"content\":\n return Array.isArray(output.value)\n ? output.value\n .map((item: any) => {\n if (item?.type === \"text\") return item.text\n return JSON.stringify(item)\n })\n .join(\"\\n\")\n : output.value\n default:\n return output\n }\n}\n\nfunction unwrapOpencodeQuestionResult(value: string): string {\n if (\n value.startsWith(OPENCODE_QUESTION_RESULT_PREFIX) &&\n value.endsWith(OPENCODE_QUESTION_RESULT_SUFFIX)\n ) {\n return value.slice(\n OPENCODE_QUESTION_RESULT_PREFIX.length,\n -OPENCODE_QUESTION_RESULT_SUFFIX.length,\n )\n }\n return value\n}\n\nfunction collectAnswerStrings(value: unknown): string[] {\n if (typeof value === \"string\") return [unwrapOpencodeQuestionResult(value)]\n if (Array.isArray(value)) return value.flatMap(collectAnswerStrings)\n if (!value || typeof value !== \"object\") return []\n\n const obj = value as Record<string, unknown>\n if (obj.denied === true) return [String(obj.reason ?? \"question rejected\")]\n\n for (const key of [\"answers\", \"answer\", \"selected\", \"selection\", \"value\"]) {\n if (key in obj) return collectAnswerStrings(obj[key])\n }\n\n return []\n}\n\nfunction classifyQuestionResult(part: any): { approved: boolean; feedback: string } {\n const output = unwrapToolOutput(part)\n const answers = collectAnswerStrings(output)\n .map((answer) => answer.trim())\n .filter(Boolean)\n\n if (answers.length === 1 && answers[0].toLowerCase() === \"yes\") {\n return { approved: true, feedback: \"\" }\n }\n\n return {\n approved: false,\n feedback: answers.length > 0 ? answers.join(\"\\n\") : \"no\",\n }\n}\n\nexport function consumeExitPlanModeQuestionResult(\n sessionKey: string,\n prompt: Array<{ role: string; content?: unknown }>,\n): string | null {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (!Array.isArray(msg.content)) continue\n\n for (const part of msg.content as any[]) {\n if (part?.type !== \"tool-result\" || typeof part.toolCallId !== \"string\") {\n continue\n }\n\n const key = pendingKey(sessionKey, part.toolCallId)\n const exitPlanModeToolUseId = pendingQuestions.get(key)\n if (!exitPlanModeToolUseId) continue\n\n pendingQuestions.delete(key)\n const result = classifyQuestionResult(part)\n return buildToolResultMessage({\n toolUseId: exitPlanModeToolUseId,\n approved: result.approved,\n feedback: result.feedback,\n })\n }\n }\n\n return null\n}\n","import * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport * as os from \"node:os\"\nimport * as crypto from \"node:crypto\"\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\"\nimport { log } from \"./logger.js\"\nimport { pluginTmpDir } from \"./tmp.js\"\n\n/**\n * Bridge opencode's `mcp` config block into a Claude CLI `--mcp-config` file.\n *\n * Opencode core schema (packages/opencode/src/config/mcp.ts):\n * {\n * \"mcp\": {\n * \"name\": {\n * \"type\": \"local\" | \"remote\",\n * \"command\"?: string[], // local\n * \"environment\"?: Record<string,string>,\n * \"url\"?: string, // remote\n * \"headers\"?: Record<string,string>,\n * \"oauth\"?: object | false, // remote — NOT bridged (Claude --mcp-config has no slot)\n * \"timeout\"?: number, // NOT bridged (Claude --mcp-config has no slot)\n * \"enabled\"?: boolean\n * }\n * }\n * }\n *\n * Claude CLI `--mcp-config` schema:\n * {\n * \"mcpServers\": {\n * \"name\": {\n * \"type\": \"stdio\" | \"http\",\n * \"command\"?: string, \"args\"?: string[], \"env\"?: Record<string,string>,\n * \"url\"?: string, \"headers\"?: Record<string,string>\n * }\n * }\n * }\n *\n * Discovery + merge are aligned with opencode core's `loadInstanceState`\n * (packages/opencode/src/config/config.ts). In merge order (last wins),\n * opencode loads:\n *\n * 1. Auth `.well-known` remote configs ← NOT bridged\n * 2. Global: ~/.config/opencode/{config.json,opencode.json,opencode.jsonc}\n * — all three deep-merged, jsonc highest priority\n * 3. OPENCODE_CONFIG env var (single file)\n * 4. Project walk-up: opencode.json[c] in each dir from cwd up to (not past)\n * worktree, both extensions per dir, parent-most first\n * 5. .opencode/ siblings: from cwd up + home dir + OPENCODE_CONFIG_DIR,\n * both extensions per dir, opencode-iteration order (cwd-most first\n * in walk-up — so parent-most `.opencode/` wins, matching upstream)\n * 6. OPENCODE_CONFIG_CONTENT env var (inline JSON) ← NOT bridged\n * 7. Active org remote config ← NOT bridged\n * 8. Managed config dir / macOS MDM ← NOT bridged\n *\n * Sources marked NOT bridged are niche and would require live opencode\n * runtime state (auth tokens, account context, MDM access). Document them\n * here so the gap is explicit; functionality of the common path is intact.\n *\n * Per-server merge is deep-merge (matching opencode's `mergeConfigConcatArrays`\n * → `mergeDeep`), so a project layer can override one field of a global server\n * spec — e.g. `{ \"linear\": { \"enabled\": true } }` lifts global linear's URL.\n */\n\nconst FILE_NAMES = [\"opencode.jsonc\", \"opencode.json\", \"config.json\"] as const\nconst PROJECT_FILE_NAMES = [\"opencode.json\", \"opencode.jsonc\"] as const\n\nfunction fileExists(p: string): boolean {\n try {\n return fs.statSync(p).isFile()\n } catch {\n return false\n }\n}\n\nfunction dirExists(p: string): boolean {\n try {\n return fs.statSync(p).isDirectory()\n } catch {\n return false\n }\n}\n\nfunction readAndParse(file: string): Record<string, unknown> | null {\n try {\n const raw = fs.readFileSync(file, \"utf8\")\n const errors: ParseError[] = []\n const parsed = parseJsonc(raw, errors, { allowTrailingComma: true })\n if (errors.length > 0) {\n const first = errors[0]\n throw new Error(\n `${printParseErrorCode(first.error)} at offset ${first.offset}`,\n )\n }\n return parsed as Record<string, unknown>\n } catch (e) {\n log.warn(\"failed to parse opencode config\", {\n file,\n error: e instanceof Error ? e.message : String(e),\n })\n return null\n }\n}\n\n/**\n * Deep merge two plain-object trees. Arrays and primitives are replaced\n * (not concatenated). Matches the effective behavior of opencode's\n * `mergeDeep` from `remeda` for the MCP block — opencode does not special\n * case array fields inside `mcp.<server>` (its only special case is\n * `instructions`, which is concat-deduped at the config root).\n */\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\n return typeof x === \"object\" && x !== null && !Array.isArray(x)\n}\n\nfunction deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...target }\n for (const [k, v] of Object.entries(source)) {\n if (v === undefined) continue\n const existing = out[k]\n if (isPlainObject(existing) && isPlainObject(v)) {\n out[k] = deepMerge(existing, v)\n } else {\n out[k] = v\n }\n }\n return out\n}\n\n/**\n * Walk up from `start` toward filesystem root (or `stop` if provided),\n * collecting paths where each `target` exists. Mirrors opencode core's\n * `FileSystem.up` (packages/core/src/filesystem.ts): cwd-most first,\n * parent-most last.\n */\nfunction walkUp(opts: {\n start: string\n stop?: string\n targets: readonly string[]\n predicate: (p: string) => boolean\n}): string[] {\n const out: string[] = []\n let current = path.resolve(opts.start)\n while (true) {\n for (const target of opts.targets) {\n const candidate = path.join(current, target)\n if (opts.predicate(candidate)) out.push(candidate)\n }\n if (opts.stop && current === path.resolve(opts.stop)) break\n const parent = path.dirname(current)\n if (parent === current) break\n current = parent\n }\n return out\n}\n\n/**\n * Find the worktree root by walking up from `cwd` looking for a `.git`\n * entry (file or directory — submodules use a file). If no `.git` is\n * found, walk to filesystem root. Honors OPENCODE_WORKTREE override.\n */\nfunction detectWorktree(cwd: string): string | undefined {\n const override = process.env.OPENCODE_WORKTREE\n if (override) return path.resolve(override)\n let current = path.resolve(cwd)\n while (true) {\n const gitPath = path.join(current, \".git\")\n try {\n if (fs.existsSync(gitPath)) return current\n } catch {\n // ignore\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\nfunction globalConfigDir(): string {\n const xdg = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), \".config\")\n return path.join(xdg, \"opencode\")\n}\n\n/**\n * Load the merged global config from `~/.config/opencode/`. Mirrors\n * opencode core's `loadGlobal`: deep-merges config.json → opencode.json\n * → opencode.jsonc in that order (jsonc wins).\n */\nfunction loadGlobalConfig(): Record<string, unknown> {\n const dir = globalConfigDir()\n let merged: Record<string, unknown> = {}\n for (const name of FILE_NAMES.slice().reverse()) {\n // FILE_NAMES is jsonc-first; reverse to get config.json-first order.\n const file = path.join(dir, name)\n if (!fileExists(file)) continue\n const parsed = readAndParse(file)\n if (parsed) merged = deepMerge(merged, parsed)\n }\n return merged\n}\n\n/** Load both `opencode.json` and `opencode.jsonc` in `dir`, deep-merged. */\nfunction loadProjectFilesInDir(dir: string): Record<string, unknown> {\n let merged: Record<string, unknown> = {}\n for (const name of PROJECT_FILE_NAMES) {\n const file = path.join(dir, name)\n if (!fileExists(file)) continue\n const parsed = readAndParse(file)\n if (parsed) merged = deepMerge(merged, parsed)\n }\n return merged\n}\n\n/**\n * Build the list of `.opencode/` directories to consider, in opencode core's\n * order (matching `ConfigPaths.directories`):\n * project walk-up (cwd-most first) → home-dir `.opencode/` → OPENCODE_CONFIG_DIR\n */\nfunction dotOpencodeDirs(cwd: string, worktree?: string): string[] {\n const dirs: string[] = []\n const seen = new Set<string>()\n const push = (p: string) => {\n const abs = path.resolve(p)\n if (!seen.has(abs) && dirExists(abs)) {\n seen.add(abs)\n dirs.push(abs)\n }\n }\n\n for (const dir of walkUp({\n start: cwd,\n stop: worktree,\n targets: [\".opencode\"],\n predicate: dirExists,\n })) {\n push(dir)\n }\n\n const home = os.homedir()\n if (home) {\n const homeDot = path.join(home, \".opencode\")\n if (dirExists(homeDot)) push(homeDot)\n }\n\n const envDir = process.env.OPENCODE_CONFIG_DIR\n if (envDir && dirExists(envDir)) push(envDir)\n\n return dirs\n}\n\ninterface OpencodeLocalServer {\n type?: \"local\"\n command?: string[]\n environment?: Record<string, string>\n enabled?: boolean\n}\n\ninterface OpencodeRemoteServer {\n type?: \"remote\"\n url?: string\n headers?: Record<string, string>\n enabled?: boolean\n}\n\ntype OpencodeServer = OpencodeLocalServer | OpencodeRemoteServer | { enabled?: boolean }\n\n/**\n * Substitute opencode's `{env:VAR}` interpolation in a string-keyed record\n * using values from `process.env`. Returns a new object. If the source is\n * not a flat string-valued record, returns it unchanged.\n *\n * Opencode performs this substitution itself when it spawns MCP servers\n * directly, but the spec we read from disk still contains the literal\n * placeholders. Without substituting them here, Claude CLI hands the\n * literal string `{env:FOO}` to the MCP subprocess as the env value, and\n * any server that validates credentials at startup (e.g. slack-mcp-server)\n * crashes before exposing tools. Servers that defer validation to\n * request time (e.g. github-mcp-server) appear to register but every API\n * call 401s.\n */\nfunction substituteEnvPlaceholders(\n source: Record<string, unknown>,\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(source)) {\n if (typeof v !== \"string\") continue\n out[k] = v.replace(/\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name) => {\n const resolved = process.env[name]\n return typeof resolved === \"string\" ? resolved : \"\"\n })\n }\n return out\n}\n\nfunction translateServer(\n name: string,\n spec: Record<string, unknown>,\n): Record<string, unknown> | null {\n if (spec.enabled === false) return null\n\n const type = spec.type\n if (type === \"local\") {\n const cmd = spec.command\n if (!Array.isArray(cmd) || cmd.length === 0) {\n log.warn(\"skipping local MCP server with no command\", { name })\n return null\n }\n const out: Record<string, unknown> = {\n type: \"stdio\",\n command: String(cmd[0]),\n }\n if (cmd.length > 1) out.args = cmd.slice(1).map((s) => String(s))\n if (spec.environment && typeof spec.environment === \"object\") {\n out.env = substituteEnvPlaceholders(\n spec.environment as Record<string, unknown>,\n )\n }\n return out\n }\n\n if (type === \"remote\") {\n if (typeof spec.url !== \"string\" || !spec.url) {\n log.warn(\"skipping remote MCP server with no url\", { name })\n return null\n }\n const out: Record<string, unknown> = {\n type: \"http\",\n url: spec.url,\n }\n if (spec.headers && typeof spec.headers === \"object\") {\n out.headers = substituteEnvPlaceholders(\n spec.headers as Record<string, unknown>,\n )\n }\n return out\n }\n\n log.warn(\"skipping MCP server with unknown type\", {\n name,\n type: type ?? null,\n })\n return null\n}\n\nfunction extractMcpBlock(\n config: Record<string, unknown>,\n): Record<string, OpencodeServer> {\n const mcp = config.mcp\n if (!mcp || typeof mcp !== \"object\" || Array.isArray(mcp)) return {}\n return mcp as Record<string, OpencodeServer>\n}\n\n/**\n * Deep-merge per-server specs from `source` into `target`. Mirrors opencode's\n * `mergeDeep` semantics for the `mcp` record: each server entry is recursively\n * merged so a partial layer (e.g. `{ \"linear\": { \"enabled\": true } }`) can\n * override one field without dropping the rest.\n */\nfunction mergeMcp(\n target: Record<string, OpencodeServer>,\n source: Record<string, OpencodeServer>,\n): Record<string, OpencodeServer> {\n const out: Record<string, OpencodeServer> = { ...target }\n for (const [name, spec] of Object.entries(source)) {\n if (!spec || typeof spec !== \"object\") continue\n const existing = out[name]\n if (existing && typeof existing === \"object\") {\n out[name] = deepMerge(\n existing as Record<string, unknown>,\n spec as Record<string, unknown>,\n ) as OpencodeServer\n } else {\n out[name] = spec\n }\n }\n return out\n}\n\nexport interface BridgedMcp {\n /** Path to the temp file containing the translated `--mcp-config`. */\n path: string\n /** Stable hash of the merged opencode mcp block (pre-translation). */\n hash: string\n /**\n * Names of opencode MCP servers that were bridged into Claude CLI's\n * `--mcp-config`. Excludes any servers passed in `excludeServers`.\n */\n serverNames: string[]\n /**\n * Names of every enabled opencode MCP server after merge + runtime\n * overlay, regardless of whether they ended up bridged or excluded.\n * Callers (e.g. the proxy-tool builder) use this to decide which\n * `<server>_<tool>` IDs in opencode's tool catalog are MCP-origin.\n */\n allEnabledServerNames: string[]\n}\n\n/** Result of merging opencode's MCP config layers + applying runtime overlay. */\nexport interface MergedMcp {\n /** Merged, overlay-applied server specs keyed by opencode server name. */\n servers: Record<string, OpencodeServer>\n /** Server names whose final spec is enabled (or implicitly enabled). */\n enabledServerNames: string[]\n /** Stable hash of the merged (pre-translation) MCP block. */\n hash: string\n}\n\n/**\n * Per-server runtime status from opencode's `client.mcp.status()`. Used as\n * an overlay on top of the on-disk merged config so opencode's UI-toggled\n * state — which lives only in-memory; `connect()`/`disconnect()` never\n * touch disk — propagates to the bridged claude subprocess.\n *\n * Treatment per server:\n * - \"connected\" → force `enabled: true` (mirror opencode)\n * - any other status → force `enabled: false` (don't ship a server\n * opencode can't run; user fixes it in opencode first)\n * - missing entry → leave disk value\n *\n * Omit the overlay and the bridge falls back to disk-only.\n */\nexport type RuntimeMcpStatus = Record<string, string>\n\n/**\n * Read opencode config layers, deep-merge their `mcp` blocks per opencode's\n * own semantics, optionally apply an opencode runtime-status overlay, then\n * translate each server to Claude CLI format, write a scratch file, and\n * return its path + a stable hash. Returns null when no enabled MCP servers\n * remain after the merge + overlay.\n */\nexport function bridgeOpencodeMcp(\n cwd: string,\n runtimeStatus?: RuntimeMcpStatus,\n excludeServers?: ReadonlySet<string>,\n): BridgedMcp | null {\n const {\n servers: merged,\n enabledServerNames: allEnabledServerNames,\n hash,\n } = mergeOpencodeMcp(cwd, runtimeStatus)\n\n // Translate every still-enabled server, skipping any caller has asked us\n // to exclude (because they're being routed through the proxy instead).\n const servers: Record<string, unknown> = {}\n const bridgedServerNames: string[] = []\n for (const [name, spec] of Object.entries(merged)) {\n if (!spec || typeof spec !== \"object\") continue\n if (excludeServers?.has(name)) continue\n const translated = translateServer(name, spec as Record<string, unknown>)\n if (translated) {\n servers[name] = translated\n bridgedServerNames.push(name)\n }\n }\n return finishBridge({\n servers,\n bridgedServerNames,\n allEnabledServerNames,\n hash,\n excludeServers,\n })\n}\n\n/**\n * Merge opencode's MCP config layers (global → `OPENCODE_CONFIG` → project\n * walk-up → `.opencode/` siblings), apply the opencode runtime-status\n * overlay, and hash the result. Split out of `bridgeOpencodeMcp` so\n * read-only callers (startup diagnostics) can inspect what would be bridged\n * without translating servers or writing a scratch config file.\n */\nexport function mergeOpencodeMcp(\n cwd: string,\n runtimeStatus?: RuntimeMcpStatus,\n): MergedMcp {\n const worktree = detectWorktree(cwd)\n\n // Layer 1: global merged\n let merged: Record<string, OpencodeServer> = {}\n merged = mergeMcp(merged, extractMcpBlock(loadGlobalConfig()))\n\n // Layer 2: OPENCODE_CONFIG (single file, applied before project walk-up)\n const explicitConfig = process.env.OPENCODE_CONFIG\n if (explicitConfig && fileExists(explicitConfig)) {\n const parsed = readAndParse(explicitConfig)\n if (parsed) merged = mergeMcp(merged, extractMcpBlock(parsed))\n }\n\n // Layer 3: project walk-up — opencode.json[c] in each dir from cwd to\n // (not past) worktree, both extensions per dir. walkUp returns cwd-most\n // first; collect distinct dirs in that order then reverse for merge so\n // cwd-most wins under last-merge-wins.\n const projectFiles = walkUp({\n start: cwd,\n stop: worktree,\n targets: PROJECT_FILE_NAMES,\n predicate: fileExists,\n })\n const projectDirs: string[] = []\n const seenProjectDirs = new Set<string>()\n for (const f of projectFiles) {\n const d = path.dirname(f)\n if (!seenProjectDirs.has(d)) {\n seenProjectDirs.add(d)\n projectDirs.push(d)\n }\n }\n for (const dir of projectDirs.slice().reverse()) {\n merged = mergeMcp(merged, extractMcpBlock(loadProjectFilesInDir(dir)))\n }\n\n // Layer 4: `.opencode/` siblings — project walk-up then home-dir then\n // OPENCODE_CONFIG_DIR, in that order. Iteration order matches opencode's\n // (cwd-most first within walk-up), so under deep-merge \"later wins\"\n // parent-most `.opencode/` overrides cwd-most. This is upstream's\n // behavior, surprising though it is.\n for (const dir of dotOpencodeDirs(cwd, worktree)) {\n merged = mergeMcp(merged, extractMcpBlock(loadProjectFilesInDir(dir)))\n }\n\n // Layer 5: opencode runtime overlay. opencode's `/mcps` UI toggle calls\n // `mcp.connect()` / `mcp.disconnect()` which only mutate in-memory state,\n // never the on-disk config. Without this overlay the bridge can't see\n // those toggles and claude misses servers the user just enabled.\n if (runtimeStatus) {\n for (const name of Object.keys(merged)) {\n const status = runtimeStatus[name]\n if (status === undefined) continue\n const existing = merged[name]\n const base =\n existing && typeof existing === \"object\"\n ? (existing as Record<string, unknown>)\n : {}\n merged[name] = { ...base, enabled: status === \"connected\" } as OpencodeServer\n }\n }\n\n // Compute the set of enabled server names BEFORE exclusion so callers can\n // tell whether a tool ID like `slack_conversations_add_message` came from\n // an opencode MCP server (vs a built-in tool that happens to contain `_`).\n const enabledServerNames: string[] = []\n for (const [name, spec] of Object.entries(merged)) {\n if (!spec || typeof spec !== \"object\") continue\n const enabled = (spec as { enabled?: unknown }).enabled\n if (enabled === false) continue\n enabledServerNames.push(name)\n }\n\n // Hash the pre-exclusion merged block so the hot-reload detector picks up\n // upstream config changes even when every server is excluded.\n const mergedBody = JSON.stringify({ mcpServers: merged }, null, 2)\n const hash = crypto\n .createHash(\"sha256\")\n .update(mergedBody)\n .digest(\"hex\")\n .slice(0, 12)\n\n return { servers: merged, enabledServerNames, hash }\n}\n\n/** Write the translated config (if any) and shape `bridgeOpencodeMcp`'s result. */\nfunction finishBridge(input: {\n servers: Record<string, unknown>\n bridgedServerNames: string[]\n allEnabledServerNames: string[]\n hash: string\n excludeServers?: ReadonlySet<string>\n}): BridgedMcp | null {\n const { servers, bridgedServerNames, allEnabledServerNames, hash, excludeServers } =\n input\n\n if (Object.keys(servers).length === 0) {\n const allEnabledServersExcluded =\n excludeServers &&\n allEnabledServerNames.length > 0 &&\n allEnabledServerNames.every((name) => excludeServers.has(name))\n\n if (!allEnabledServersExcluded) return null\n\n return {\n path: \"\",\n hash,\n serverNames: [],\n allEnabledServerNames,\n }\n }\n\n const body = JSON.stringify({ mcpServers: servers }, null, 2)\n const outPath = path.join(\n pluginTmpDir(),\n `mcp-${hash}.json`,\n )\n try {\n if (!fileExists(outPath)) {\n fs.writeFileSync(outPath, body, { encoding: \"utf8\", mode: 0o600 })\n }\n } catch (e) {\n log.warn(\"failed to write bridged MCP config\", {\n error: e instanceof Error ? e.message : String(e),\n })\n return null\n }\n\n log.info(\"bridged opencode MCP config\", {\n target: outPath,\n hash,\n servers: bridgedServerNames,\n excluded: excludeServers ? Array.from(excludeServers) : [],\n })\n return {\n path: outPath,\n hash,\n serverNames: bridgedServerNames,\n allEnabledServerNames,\n }\n}\n\n// Internal helpers exported for tests only.\nexport const __test = {\n deepMerge,\n mergeMcp,\n translateServer,\n substituteEnvPlaceholders,\n detectWorktree,\n loadGlobalConfig,\n loadProjectFilesInDir,\n dotOpencodeDirs,\n}\n","import * as fs from \"node:fs\"\nimport * as os from \"node:os\"\nimport * as path from \"node:path\"\n\n/**\n * Per-process scratch directory for plugin tmp files (bridged MCP config,\n * proxy server config, etc.). Created lazily on first use and rm'd on\n * normal process exit so we don't leak across runs. PID-isolated so two\n * concurrent opencode processes don't race on the same files.\n *\n * Caveat: `process.on(\"exit\")` does not fire for SIGKILL or unhandled\n * external signals, so abnormal terminations still leak. OS-level tmpdir\n * cleanup (`systemd-tmpfiles`, macOS periodic) handles those eventually.\n */\nconst PLUGIN_TMP_DIR = path.join(\n os.tmpdir(),\n `opencode-claude-code-${process.pid}`,\n)\n\nlet registered = false\n\nexport function pluginTmpDir(): string {\n if (!fs.existsSync(PLUGIN_TMP_DIR)) {\n fs.mkdirSync(PLUGIN_TMP_DIR, { recursive: true })\n }\n if (!registered) {\n registered = true\n process.on(\"exit\", () => {\n try {\n fs.rmSync(PLUGIN_TMP_DIR, { recursive: true, force: true })\n } catch {}\n })\n }\n return PLUGIN_TMP_DIR\n}\n","import type { RuntimeMcpStatus } from \"./mcp-bridge.js\"\nimport { log } from \"./logger.js\"\n\n/**\n * Captured opencode runtime context (SDK client + project directory) from\n * `PluginInput`. Lives in its own module to break the cycle that would\n * otherwise form between `index.ts` and `claude-code-language-model.ts`.\n * Values are `null`/`undefined` until the plugin's `server` factory runs\n * (e.g. early provider lookups, direct AI-SDK use, tests).\n */\ntype OpencodeClient = {\n mcp?: {\n status?: () => Promise<{ data?: unknown; error?: unknown }>\n }\n tool?: {\n list?: (options: {\n query: { provider: string; model: string; directory?: string }\n }) => Promise<{ data?: unknown; error?: unknown }>\n }\n}\n\nlet opencodeClient: OpencodeClient | null = null\n\nexport function setOpencodeClient(client: unknown): void {\n if (client && typeof client === \"object\") {\n opencodeClient = client as OpencodeClient\n }\n}\n\n/**\n * Captured opencode project directory from `PluginInput.directory` (with\n * `worktree` as secondary signal). Used as a *fallback* at Claude CLI\n * spawn time only when `process.cwd()` is unusable (macOS GUI launches\n * where launchd hands the process `cwd=/`).\n *\n * IMPORTANT: never bake this into provider config (`mergedOptions.cwd`).\n * Doing so freezes the value at plugin init and breaks workspace\n * switching mid-session, because subsequent workspace changes in\n * opencode's UI never get reflected in `this.config.cwd`. See issue #4.\n */\nlet opencodeProjectDirectory: string | undefined\n\nexport function setOpencodeProjectDirectory(dir: string | undefined): void {\n opencodeProjectDirectory = dir\n}\n\nexport function getOpencodeProjectDirectory(): string | undefined {\n return opencodeProjectDirectory\n}\n\nexport function isUsableDirectory(d: unknown): d is string {\n return typeof d === \"string\" && d.length > 1 && d !== \"/\"\n}\n\n/**\n * Resolve the cwd for a Claude CLI subprocess spawn. Priority:\n *\n * 1. Explicit `configured` value (`options.cwd` from `opencode.json`).\n * Users who pinned a directory keep their override unconditionally.\n * 2. Live `process.cwd()` when it's a real directory. Restores the lazy\n * resolution that lets opencode's project-aware behavior (chdir on\n * workspace switch, project-per-shell on terminal launch) flow\n * through without restarting the plugin.\n * 3. Captured project directory from plugin init. Rescues macOS GUI\n * launches where `process.cwd()` is `/`.\n * 4. Final fallback to `process.cwd()` (returns `/` in the pathological\n * case where neither override nor capture is available).\n */\nexport function resolveSpawnCwd(configured: string | undefined): string {\n return resolveSpawnCwdFrom(\n configured,\n process.cwd(),\n opencodeProjectDirectory,\n )\n}\n\nexport function resolveSpawnCwdFrom(\n configured: string | undefined,\n live: string,\n captured: string | undefined,\n): string {\n if (configured) return configured\n if (isUsableDirectory(live)) return live\n return captured ?? live\n}\n\n/**\n * Snapshot opencode's current MCP runtime status so the bridge can overlay\n * UI-toggled state on top of disk config. Returns `undefined` on any\n * failure (no client captured, status call rejected, malformed response)\n * so the bridge falls back to disk-only.\n */\nexport async function getRuntimeMcpStatus(): Promise<\n RuntimeMcpStatus | undefined\n> {\n const client = opencodeClient\n if (!client?.mcp?.status) return undefined\n try {\n const res = await client.mcp.status()\n const data = (res as { data?: unknown }).data\n if (!data || typeof data !== \"object\") return undefined\n const out: RuntimeMcpStatus = {}\n for (const [name, entry] of Object.entries(data as Record<string, unknown>)) {\n if (entry && typeof entry === \"object\") {\n const status = (entry as { status?: unknown }).status\n if (typeof status === \"string\") out[name] = status\n }\n }\n return out\n } catch (err) {\n log.warn(\"failed to fetch opencode MCP runtime status\", {\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n}\n\nexport interface OpencodeToolListItem {\n id: string\n description: string\n parameters: Record<string, unknown>\n}\n\n/**\n * Fetch opencode's full tool catalog (built-ins + MCP-bridged) with JSON\n * Schema parameters via `client.tool.list()`. The provider/model query\n * narrows the schema variants opencode returns; in practice MCP-origin\n * tool schemas are model-agnostic, so any registered (provider, model)\n * works as the query target. Returns `undefined` on any failure so callers\n * can fall back to direct-bridge behavior.\n */\nexport async function fetchOpencodeToolList(\n provider: string,\n model: string,\n directory?: string,\n): Promise<OpencodeToolListItem[] | undefined> {\n const client = opencodeClient\n if (!client?.tool?.list) return undefined\n try {\n const res = await client.tool.list({\n query: { provider, model, ...(directory ? { directory } : {}) },\n })\n const data = (res as { data?: unknown }).data\n if (!Array.isArray(data)) return undefined\n const out: OpencodeToolListItem[] = []\n for (const entry of data as unknown[]) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const id = typeof e.id === \"string\" ? e.id : null\n const description =\n typeof e.description === \"string\" ? e.description : \"\"\n const parameters =\n e.parameters && typeof e.parameters === \"object\"\n ? (e.parameters as Record<string, unknown>)\n : {}\n if (!id) continue\n out.push({ id, description, parameters })\n }\n return out\n } catch (err) {\n log.warn(\"failed to fetch opencode tool list\", {\n provider,\n model,\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n}\n","import { spawn, type ChildProcess } from \"node:child_process\"\nimport { createInterface } from \"node:readline\"\nimport { EventEmitter } from \"node:events\"\nimport { unlink } from \"node:fs/promises\"\nimport { log } from \"./logger.js\"\nimport type { ProxyMcpServer } from \"./proxy-mcp.js\"\nimport { clearLedger } from \"./todo-ledger.js\"\nimport { clearExitPlanModeQuestions } from \"./plan-mode-question.js\"\nimport {\n cliSupportsThinking,\n cliSupportsThinkingDisplay,\n type CliVersion,\n} from \"./cli-version.js\"\n\nexport interface ActiveProcess {\n proc: ChildProcess\n lineEmitter: EventEmitter\n proxyServer?: ProxyMcpServer | null\n /**\n * Hash of the bridged opencode MCP config the process was spawned with.\n * `null` when the bridge produced nothing (no MCP servers). `undefined`\n * when the bridge was disabled. Used to detect mid-session config drift\n * and force a respawn.\n */\n mcpHash?: string | null\n /** Temp file holding `--append-system-prompt-file` content; unlinked on exit. */\n systemPromptFile?: string\n}\n\n// One active CLI process per session key. Keyed by a composite\n// (cwd + model + opencode session-affinity) so two chats don't race.\n// Iteration order is insertion order, which we refresh on access to\n// make this a poor-man's LRU; see `touch()` below.\nconst activeProcesses = new Map<string, ActiveProcess>()\nconst claudeSessions = new Map<string, string>()\n\n// Cap on live CLI subprocesses. Session-affinity-keyed entries accumulate\n// one-per-chat, so an unbounded map would leak processes as users open new\n// chats. This caps at a reasonable working-set and evicts the oldest.\nconst MAX_ACTIVE_PROCESSES = 16\nconst PROCESS_EXIT_TIMEOUT_MS = 1_500\nconst PROCESS_FORCE_EXIT_TIMEOUT_MS = 500\n\nfunction envFlagEnabled(value: string | undefined): boolean {\n if (value === undefined) return false\n const normalized = value.trim().toLowerCase()\n if (!normalized) return false\n return ![\"0\", \"false\", \"no\", \"off\"].includes(normalized)\n}\n\nexport function isClaudeThinkingDisabled(): boolean {\n return (\n envFlagEnabled(process.env.CLAUDE_CODE_DISABLE_THINKING) ||\n envFlagEnabled(process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING)\n )\n}\n\nexport function claudeSpawnEnv(opts?: {\n ignoreAnthropicApiKey?: boolean\n}): Record<string, string | undefined> {\n const env: Record<string, string | undefined> = {\n ...process.env,\n TERM: \"xterm-256color\",\n }\n\n // Force subscription auth: with an API key in the env, Claude Code bills\n // pay-as-you-go (Console) instead of the logged-in plan, bypassing the\n // Agent SDK credit. Opt-in via `ignoreAnthropicApiKey`.\n if (opts?.ignoreAnthropicApiKey) {\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_AUTH_TOKEN\n }\n\n // Default-on thinking summaries for opus-4-7 (which omits thinking by\n // default on the CLI side). Any var the user has explicitly set in their\n // shell is passed through untouched; the plugin only fills in the default.\n if (\n !isClaudeThinkingDisabled() &&\n process.env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES === undefined\n ) {\n env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES = \"1\"\n }\n\n return env\n}\n\nfunction touch(key: string): void {\n const existing = activeProcesses.get(key)\n if (existing) {\n activeProcesses.delete(key)\n activeProcesses.set(key, existing)\n }\n}\n\nfunction evictIfNeeded(): void {\n while (activeProcesses.size >= MAX_ACTIVE_PROCESSES) {\n const oldestKey = activeProcesses.keys().next().value\n if (!oldestKey) break\n log.info(\"evicting LRU claude process\", { sessionKey: oldestKey })\n deleteActiveProcess(oldestKey)\n }\n}\n\nexport function getActiveProcess(key: string): ActiveProcess | undefined {\n const ap = activeProcesses.get(key)\n if (ap) touch(key)\n return ap\n}\n\nexport function setActiveProcess(key: string, ap: ActiveProcess): void {\n activeProcesses.set(key, ap)\n}\n\nfunction detachActiveProcess(key: string): ActiveProcess | undefined {\n const ap = activeProcesses.get(key)\n if (!ap) return undefined\n activeProcesses.delete(key)\n void ap.proxyServer?.close()\n return ap\n}\n\nexport function deleteActiveProcess(key: string): void {\n const ap = detachActiveProcess(key)\n ap?.proc.kill()\n}\n\nfunction hasProcessExited(proc: ChildProcess): boolean {\n return proc.exitCode !== null || proc.signalCode !== null\n}\n\nfunction waitForProcessExit(\n proc: ChildProcess,\n timeoutMs: number,\n): Promise<boolean> {\n if (hasProcessExited(proc)) return Promise.resolve(true)\n\n return new Promise((resolve) => {\n const onExit = () => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n proc.off(\"exit\", onExit)\n resolve(hasProcessExited(proc))\n }, timeoutMs)\n proc.once(\"exit\", onExit)\n })\n}\n\nexport async function deleteActiveProcessAndWait(\n key: string,\n options: {\n exitTimeoutMs?: number\n forceExitTimeoutMs?: number\n } = {},\n): Promise<boolean> {\n const ap = detachActiveProcess(key)\n if (!ap || hasProcessExited(ap.proc)) return true\n\n const gracefulExit = waitForProcessExit(\n ap.proc,\n options.exitTimeoutMs ?? PROCESS_EXIT_TIMEOUT_MS,\n )\n ap.proc.kill()\n if (await gracefulExit) return true\n\n const forcedExit = waitForProcessExit(\n ap.proc,\n options.forceExitTimeoutMs ?? PROCESS_FORCE_EXIT_TIMEOUT_MS,\n )\n ap.proc.kill(\"SIGKILL\")\n if (await forcedExit) return true\n\n log.warn(\"claude process did not exit; starting a fresh session\", {\n sessionKey: key,\n })\n deleteClaudeSessionId(key)\n return false\n}\n\nexport function getClaudeSessionId(key: string): string | undefined {\n return claudeSessions.get(key)\n}\n\nexport function setClaudeSessionId(key: string, sessionId: string): void {\n claudeSessions.set(key, sessionId)\n}\n\nexport function deleteClaudeSessionId(key: string): void {\n clearExitPlanModeQuestions(key)\n const claudeSessionId = claudeSessions.get(key)\n if (claudeSessionId) clearLedger(claudeSessionId)\n claudeSessions.delete(key)\n}\n\nexport function spawnClaudeProcess(\n cliPath: string,\n cliArgs: string[],\n cwd: string,\n sessionKey: string,\n proxyServer?: ProxyMcpServer | null,\n mcpHash?: string | null,\n systemPromptFile?: string,\n ignoreAnthropicApiKey?: boolean,\n): ActiveProcess {\n evictIfNeeded()\n log.info(\"spawning new claude process\", { cliPath, cliArgs, cwd, sessionKey })\n\n const proc = spawn(cliPath, cliArgs, {\n cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: claudeSpawnEnv({ ignoreAnthropicApiKey }),\n shell: process.platform === \"win32\",\n })\n\n const lineEmitter = new EventEmitter()\n\n const rl = createInterface({ input: proc.stdout! })\n rl.on(\"line\", (line: string) => {\n lineEmitter.emit(\"line\", line)\n })\n rl.on(\"close\", () => {\n lineEmitter.emit(\"close\")\n })\n\n const ap: ActiveProcess = {\n proc,\n lineEmitter,\n proxyServer: proxyServer ?? null,\n mcpHash,\n systemPromptFile,\n }\n activeProcesses.set(sessionKey, ap)\n\n // Baseline 'error' listener so Node doesn't throw when the process emits\n // an error between stream turns (no per-stream listener attached then).\n proc.on(\"error\", (err) => {\n log.error(\"claude process error\", { sessionKey, error: err.message })\n })\n\n proc.on(\"exit\", (code, signal) => {\n log.info(\"claude process exited\", { code, signal, sessionKey })\n void proxyServer?.close()\n if (systemPromptFile) {\n void unlink(systemPromptFile).catch(() => {})\n }\n const ownsSessionKey = activeProcesses.get(sessionKey) === ap\n if (ownsSessionKey) activeProcesses.delete(sessionKey)\n if (ownsSessionKey && code !== 0 && code !== null) {\n log.info(\"process exited with error, clearing session\", {\n code,\n sessionKey,\n })\n claudeSessions.delete(sessionKey)\n }\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n const stderr = data.toString()\n log.debug(\"stderr\", { data: stderr.slice(0, 200) })\n\n // \"No conversation found with session ID: <uuid>\" is what `--resume`\n // prints for a purged transcript — note the lowercase \"session ID\",\n // which the capitalized match below does not catch.\n if (\n stderr.includes(\"No conversation found\") ||\n (stderr.includes(\"Session ID\") &&\n (stderr.includes(\"already in use\") ||\n stderr.includes(\"not found\") ||\n stderr.includes(\"invalid\")))\n ) {\n if (activeProcesses.get(sessionKey) === ap) {\n log.warn(\"claude session ID error, clearing session\", {\n sessionKey,\n error: stderr.slice(0, 200),\n })\n claudeSessions.delete(sessionKey)\n } else {\n log.debug(\"ignoring session ID error from stale claude process\", {\n sessionKey,\n })\n }\n }\n })\n\n return ap\n}\n\n/**\n * Append `--resume <id>` to an already-built args vector when a Claude\n * conversation id is known for the session and the args don't already carry\n * a session flag. Used by `respawnActiveProcess` to resume the conversation\n * in a fresh child without rebuilding the whole (version-gated) args vector.\n * `--resume`, not `--session-id`: the latter means \"create a NEW session\n * with this UUID\" and the CLI rejects it with \"Session ID ... is already in\n * use\" whenever a transcript exists on disk — which is exactly the state a\n * mid-conversation respawn is in. If the wedged child died before writing\n * any transcript, `--resume` fails with \"No conversation found with session\n * ID\", which the stderr recovery matcher already catches (fresh-session\n * fallback).\n */\nexport function appendResumeIfNeeded(\n sessionKey: string,\n cliArgs: string[],\n): string[] {\n if (cliArgs.includes(\"--resume\") || cliArgs.includes(\"--session-id\")) {\n return cliArgs\n }\n const sid = claudeSessions.get(sessionKey)\n if (!sid) return cliArgs\n return [...cliArgs, \"--resume\", sid]\n}\n\n/**\n * Replace a wedged reused process with a fresh one, resuming the same\n * Claude conversation. Used by the doStream start-watchdog when a reused\n * process produces no stdout within a grace window after a fresh-turn\n * envelope write — observed after a very long proxy-blocked tool call\n * (e.g. a multi-minute `task` subagent). Before the per-tool proxy timeout\n * fix this was masked because the flat 10-minute ceiling ended the turn\n * first; now that the task proxy blocks and returns successfully, resuming\n * a reused child after such a long wait can leave it silent on stdout.\n *\n * Reuses the existing proxy server, system-prompt file, and MCP hash (their\n * handles are already baked into `cliArgs`' `--mcp-config`/append-prompt\n * paths), so this only swaps the child process. The old child's exit\n * handler is silenced before kill so it doesn't close the proxy server we\n * are reusing; the new child gets its own exit handler from\n * `spawnClaudeProcess`. `claudeSessions` is left intact so the respawn can\n * add `--resume` (see `appendResumeIfNeeded`).\n *\n * Returns the new `ActiveProcess`, or `undefined` if there was no active\n * process for the key (caller should treat that as \"nothing to respawn\").\n */\nexport function respawnActiveProcess(\n sessionKey: string,\n cliPath: string,\n cliArgs: string[],\n cwd: string,\n ignoreAnthropicApiKey?: boolean,\n): ActiveProcess | undefined {\n const old = activeProcesses.get(sessionKey)\n if (!old) return undefined\n activeProcesses.delete(sessionKey)\n // Silence the old exit handler so it doesn't close the proxy server,\n // unlink the system-prompt file, or touch claudeSessions on its way out\n // — those handles are reused by the new child. spawnClaudeProcess wires\n // a fresh exit handler for the respawned child.\n old.proc.removeAllListeners(\"exit\")\n try {\n old.proc.kill()\n } catch {}\n return spawnClaudeProcess(\n cliPath,\n appendResumeIfNeeded(sessionKey, cliArgs),\n cwd,\n sessionKey,\n old.proxyServer,\n old.mcpHash,\n old.systemPromptFile,\n ignoreAnthropicApiKey,\n )\n}\n\nexport function buildCliArgs(opts: {\n sessionKey: string\n skipPermissions: boolean\n includeSessionId?: boolean\n model?: string\n permissionMode?: string\n mcpConfig?: string | string[]\n strictMcpConfig?: boolean\n disallowedTools?: string[]\n appendSystemPromptFile?: string\n thinking?: \"enabled\" | \"disabled\"\n thinkingDisplay?: \"summarized\" | \"omitted\"\n cliVersion?: CliVersion | null\n}): string[] {\n const {\n sessionKey,\n skipPermissions,\n includeSessionId = true,\n model,\n permissionMode,\n mcpConfig,\n strictMcpConfig,\n disallowedTools,\n appendSystemPromptFile,\n thinking,\n thinkingDisplay,\n cliVersion,\n } = opts\n const args = [\n \"--print\",\n \"--output-format\",\n \"stream-json\",\n \"--input-format\",\n \"stream-json\",\n \"--include-partial-messages\",\n \"--verbose\",\n ]\n\n if (model) {\n args.push(\"--model\", model)\n }\n\n if (permissionMode) {\n args.push(\"--permission-mode\", permissionMode)\n }\n\n // `--session-id` means \"create a NEW session with this UUID\" and the CLI\n // exits with \"Session ID ... is already in use\" whenever a transcript for\n // that ID already exists on disk. Continuing an existing session requires\n // `--resume` (which keeps the same session ID in print mode).\n if (includeSessionId) {\n const sessionId = claudeSessions.get(sessionKey)\n if (sessionId && !activeProcesses.has(sessionKey)) {\n args.push(\"--resume\", sessionId)\n }\n }\n\n if (mcpConfig) {\n const configs = Array.isArray(mcpConfig) ? mcpConfig : [mcpConfig]\n const filtered = configs.filter((c) => typeof c === \"string\" && c.length > 0)\n if (filtered.length > 0) {\n args.push(\"--mcp-config\", ...filtered)\n }\n }\n\n if (strictMcpConfig) {\n args.push(\"--strict-mcp-config\")\n }\n\n if (disallowedTools && disallowedTools.length > 0) {\n args.push(\"--disallowedTools\", ...disallowedTools)\n }\n\n // `--thinking` is only present from Claude Code 2.x onward; gate so\n // pre-2.x binaries don't crash with a parse error. Unknown version →\n // skip (the spawn still works, the user just doesn't get extended\n // thinking until they upgrade).\n if (thinking && cliSupportsThinking(cliVersion ?? null)) {\n args.push(\"--thinking\", thinking)\n }\n\n // `--thinking-display` was added in Claude Code 2.1.142. Older CLIs\n // reject it with a parse error, so gate on detected version. When\n // version is unknown (detection failed), be conservative and skip.\n if (thinkingDisplay && cliSupportsThinkingDisplay(cliVersion ?? null)) {\n args.push(\"--thinking-display\", thinkingDisplay)\n }\n\n if (appendSystemPromptFile) {\n args.push(\"--append-system-prompt-file\", appendSystemPromptFile)\n }\n\n if (skipPermissions) {\n args.push(\"--dangerously-skip-permissions\")\n }\n\n return args\n}\n\n/**\n * Build a session key that includes both cwd and model,\n * so different models get separate processes.\n */\nexport function sessionKey(cwd: string, modelId: string): string {\n return `${cwd}::${modelId}`\n}\n","import { execFile } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { log } from \"./logger.js\"\n\nconst execFileAsync = promisify(execFile)\n\nexport interface CliVersion {\n major: number\n minor: number\n patch: number\n raw: string\n}\n\nconst cache = new Map<string, Promise<CliVersion | null>>()\n\n/**\n * Run `claude --version` once per cliPath and parse the leading semver.\n * Returns null on any failure (binary missing, unparseable output, etc.)\n * so callers can fall back to the most conservative flag set.\n */\nexport function detectCliVersion(cliPath: string): Promise<CliVersion | null> {\n const cached = cache.get(cliPath)\n if (cached) return cached\n const promise = (async (): Promise<CliVersion | null> => {\n try {\n const { stdout } = await execFileAsync(cliPath, [\"--version\"], {\n timeout: 5000,\n })\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)/.exec(stdout.trim())\n if (!match) {\n log.warn(\"claude --version output unparseable\", { stdout: stdout.trim() })\n return null\n }\n const v: CliVersion = {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n raw: stdout.trim(),\n }\n log.info(\"detected claude cli version\", { cliPath, version: v.raw })\n if (!cliSupportsThinkingDisplay(v)) {\n log.notice(\n \"claude cli < 2.1.142 detected; Opus 4.7 thinking summaries unavailable. Run `npm i -g @anthropic-ai/claude-code` to upgrade.\",\n { version: v.raw },\n )\n }\n return v\n } catch (err) {\n log.warn(\"failed to detect claude cli version\", {\n cliPath,\n error: err instanceof Error ? err.message : String(err),\n })\n return null\n }\n })()\n cache.set(cliPath, promise)\n return promise\n}\n\nfunction gte(v: CliVersion, target: { major: number; minor: number; patch: number }): boolean {\n if (v.major !== target.major) return v.major > target.major\n if (v.minor !== target.minor) return v.minor > target.minor\n return v.patch >= target.patch\n}\n\n/**\n * `--thinking-display` was introduced in Claude Code 2.1.142 alongside\n * Opus 4.7's \"omitted by default\" thinking behavior. Older CLIs reject\n * the flag with a parse error, so we gate it. Unknown version → return\n * false so we don't risk crashing the spawn.\n */\nexport function cliSupportsThinkingDisplay(v: CliVersion | null): boolean {\n if (!v) return false\n return gte(v, { major: 2, minor: 1, patch: 142 })\n}\n\n/**\n * `--thinking` has been part of Claude Code's CLI since the 2.x line.\n * We require a detected 2.0.0+ before passing it; unknown version → skip\n * to avoid crashing a pre-flag binary. Anyone on the 1.x line should\n * upgrade.\n */\nexport function cliSupportsThinking(v: CliVersion | null): boolean {\n if (!v) return false\n return gte(v, { major: 2, minor: 0, patch: 0 })\n}\n\n/** For tests. */\nexport function _clearCache(): void {\n cache.clear()\n}\n","import { EventEmitter } from \"node:events\"\nimport { unlink } from \"node:fs/promises\"\nimport { ClaudeSession } from \"./claude-session-bun.js\"\nimport type { ActiveProcess } from \"./session-manager.js\"\nimport { log } from \"./logger.js\"\n\nexport interface InteractiveSpawnOptions {\n cwd: string\n /** Claude CLI executable or account wrapper path. */\n cliPath?: string\n /** Claude config root used for JSONL transcripts. */\n configDir?: string\n model?: string\n /** Bridged Claude `--mcp-config` file paths (from effectiveMcpConfig). */\n mcpConfigPaths?: string[]\n /** permissions.allow rules (e.g. mcp__server__*, Bash, Edit). */\n permissionsAllow?: string[]\n /** Optional permission mode. `bypassPermissions` is ignored for interactive\n * sessions because Claude Code shows a safety confirmation screen first. */\n permissionMode?: string\n /** Temp file for --append-system-prompt-file (parity with the headless\n * spawn; unlinked when the session is killed). */\n systemPromptFile?: string\n /** \"\" = skip CLAUDE.md + ambient settings (fast e2e); null/undefined =\n * normal settings (default — parity with the headless transport). */\n settingSources?: string | null\n /** Strip ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN from the spawn env so the\n * CLI uses subscription auth instead of pay-as-you-go API billing. */\n ignoreAnthropicApiKey?: boolean\n}\n\n/**\n * doStream writes stream-json user envelopes to stdin\n * (`{\"type\":\"user\",\"message\":{content:[...]}}`). The interactive TUI expects\n * plain typed text, so decode the envelope: extract the text blocks and drop\n * anything that can't be typed into a terminal (an image block would paste\n * megabytes of base64 into the chat). Tool results are rendered as labeled\n * text so the model still sees the outcome. Non-envelope input (already plain\n * text) passes through verbatim.\n */\nexport function decodeUserEnvelope(chunk: string): string {\n let parsed: any\n try {\n parsed = JSON.parse(chunk)\n } catch {\n return chunk\n }\n if (!parsed || parsed.type !== \"user\" || !parsed.message) return chunk\n const content = parsed.message.content\n if (typeof content === \"string\") return content\n if (!Array.isArray(content)) return chunk\n\n const parts: string[] = []\n let dropped = 0\n for (const block of content) {\n if (block?.type === \"text\" && typeof block.text === \"string\") {\n parts.push(block.text)\n } else if (block?.type === \"tool_result\") {\n const v = block.content\n const text =\n typeof v === \"string\"\n ? v\n : Array.isArray(v)\n ? v\n .map((i: any) => (i?.type === \"text\" ? i.text : \"\"))\n .filter(Boolean)\n .join(\"\\n\")\n : \"\"\n parts.push(\n `[Tool result${block.tool_use_id ? ` ${block.tool_use_id}` : \"\"}]\\n${text}`,\n )\n } else {\n dropped++\n }\n }\n if (dropped > 0) {\n log.warn(\"interactive transport dropped non-text content blocks\", {\n dropped,\n })\n }\n return parts.join(\"\\n\\n\")\n}\n\n/**\n * Adapt a ClaudeSession (interactive Bun ConPTY transport) to the ActiveProcess\n * contract the doStream line handler depends on. The shim's `proc.stdin.write`\n * injects a turn into the live interactive `claude` and re-emits each new JSONL\n * transcript record on `lineEmitter` as a 'line' event, plus a synthetic\n * `{type:'result'}` line on a terminal stop_reason so the existing finish branch\n * (usage + providerMetadata + controller.close) fires unchanged.\n *\n * No node-pty, no node sidecar: runs in-process under opencode's Bun (which\n * bundles a Bun version with native ConPTY). Interactive = subscription billing.\n */\nexport function spawnInteractiveProcess(\n opts: InteractiveSpawnOptions,\n): ActiveProcess {\n const extraArgs: string[] = []\n if (opts.mcpConfigPaths && opts.mcpConfigPaths.length > 0) {\n extraArgs.push(\n \"--mcp-config\",\n ...opts.mcpConfigPaths,\n \"--strict-mcp-config\",\n )\n }\n if (opts.permissionsAllow && opts.permissionsAllow.length > 0) {\n extraArgs.push(\n \"--settings\",\n JSON.stringify({ permissions: { allow: opts.permissionsAllow } }),\n )\n }\n if (opts.permissionMode === \"bypassPermissions\") {\n log.warn(\n \"interactive permissionMode bypassPermissions ignored: Claude Code prompts for confirmation in the TUI\",\n )\n } else if (opts.permissionMode) {\n extraArgs.push(\"--permission-mode\", opts.permissionMode)\n }\n if (opts.systemPromptFile) {\n extraArgs.push(\"--append-system-prompt-file\", opts.systemPromptFile)\n }\n\n const session = new ClaudeSession({\n cwd: opts.cwd,\n cliPath: opts.cliPath,\n configDir: opts.configDir,\n model: opts.model,\n // Default null = normal CLAUDE.md + settings load, matching what the\n // headless spawn does. \"\" (skip everything) is for fast e2e runs only.\n settingSources:\n opts.settingSources === undefined ? null : opts.settingSources,\n extraArgs,\n ignoreAnthropicApiKey: opts.ignoreAnthropicApiKey,\n })\n log.info(\"prepared interactive claude session\", {\n cwd: opts.cwd,\n cliPath: opts.cliPath ?? \"claude\",\n configDir: session.configDir,\n model: opts.model,\n sessionId: session.sessionId,\n jsonlPath: session.jsonlPath,\n })\n\n const lineEmitter = new EventEmitter()\n const errorHandlers = new Set<(err: Error) => void>()\n let startPromise: Promise<void> | null = null\n\n const ensureStarted = (): Promise<void> => {\n if (!startPromise) startPromise = session.start()\n return startPromise\n }\n\n const emitResult = (\n subtype: string,\n isError: boolean,\n result?: string,\n usage?: unknown,\n ): void => {\n lineEmitter.emit(\n \"line\",\n JSON.stringify({\n type: \"result\",\n subtype,\n is_error: isError,\n result,\n session_id: session.sessionId,\n usage: usage ?? {},\n total_cost_usd: null,\n duration_ms: 0,\n }),\n )\n }\n\n const runTurn = (userMsg: string): void => {\n void (async () => {\n try {\n await ensureStarted()\n const { stopReason, usage } = await session.tailTurn(userMsg, (raw) => {\n lineEmitter.emit(\"line\", raw)\n })\n // Synthesize the `result` line the headless transport would have\n // emitted, so doStream's existing finish branch runs verbatim. A turn\n // with no terminal stop_reason (timeout / session exit mid-turn) is\n // reported HONESTLY as an error result — not a clean end_turn — so\n // truncation is visible to the user and to auto-continue.\n const timedOut = !stopReason\n emitResult(\n timedOut ? \"error_during_execution\" : stopReason,\n timedOut,\n timedOut\n ? \"Interactive transport: the turn ended without a terminal stop_reason (turn timeout or claude exit). Output above may be incomplete.\"\n : undefined,\n usage,\n )\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err))\n log.error(\"interactive turn failed\", { error: e.message })\n emitResult(\n \"error_during_execution\",\n true,\n `Interactive transport failed: ${e.message}`,\n )\n if (errorHandlers.size > 0) {\n for (const h of errorHandlers) h(e)\n } else {\n lineEmitter.emit(\"close\")\n }\n }\n })()\n }\n\n // Minimal ChildProcess-shaped shim: only the members doStream/session-manager\n // actually touch (stdin.write, on/off 'error', kill).\n const proc: any = {\n stdin: {\n write(chunk: string): boolean {\n const raw =\n typeof chunk === \"string\" && chunk.endsWith(\"\\n\")\n ? chunk.slice(0, -1)\n : chunk\n // doStream writes stream-json envelopes; the TUI needs plain text.\n runTurn(decodeUserEnvelope(raw))\n return true\n },\n end(): void {},\n },\n stdout: null,\n stderr: null,\n pid: -1,\n killed: false,\n on(event: string, fn: (err: Error) => void): unknown {\n if (event === \"error\") errorHandlers.add(fn)\n return proc\n },\n once(): unknown {\n return proc\n },\n off(event: string, fn: (err: Error) => void): unknown {\n if (event === \"error\") errorHandlers.delete(fn)\n return proc\n },\n kill(): boolean {\n try {\n session.dispose()\n } catch {}\n if (opts.systemPromptFile) {\n void unlink(opts.systemPromptFile).catch(() => {})\n }\n proc.killed = true\n return true\n },\n }\n\n return {\n proc: proc as unknown as ActiveProcess[\"proc\"],\n lineEmitter,\n proxyServer: null,\n mcpHash: undefined,\n systemPromptFile: opts.systemPromptFile,\n }\n}\n","import * as os from \"node:os\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport { execFileSync } from \"node:child_process\"\nimport { randomUUID } from \"node:crypto\"\n\n/**\n * Persistent interactive Claude Code session driven over Bun's NATIVE PTY\n * (Bun.spawn `terminal` option = openpty on POSIX, ConPTY on Windows). This is\n * the in-process Bun port of claude-tui-bridge/src/claudeSession.ts: same\n * design, node-pty swapped for Bun's own ConPTY so it runs inside opencode's\n * Bun runtime with NO node sidecar and NO node-pty dependency.\n *\n * - ONE long-lived interactive `claude` process per session (multi-turn),\n * - turns injected by writing into the terminal (bracketed paste + Enter),\n * - replies captured by tailing the session JSONL transcript\n * (<CLAUDE_CONFIG_DIR>/projects/<encoded-cwd>/<session-id>.jsonl) and\n * parsing the assistant records; completion detected by a terminal\n * `stop_reason`.\n *\n * Driving the INTERACTIVE TUI (real TTY) keeps model calls on the subscription\n * billing path (not `claude -p` / Agent SDK, which meter after 2026-06-15).\n */\n\nfunction resolveClaude(cmd = \"claude\"): string {\n if (path.isAbsolute(cmd) && fs.existsSync(cmd)) return cmd\n const viaBun = Bun.which(cmd)\n if (viaBun) return viaBun\n const isWin = os.platform() === \"win32\"\n try {\n const out = execFileSync(isWin ? \"where\" : \"which\", [cmd], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n const first = out\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean)\n .find((p) => fs.existsSync(p))\n if (first) return first\n } catch {}\n throw new Error(`Could not resolve command on PATH: ${cmd}`)\n}\n\n/** Claude encodes the absolute cwd into the transcript dir name by replacing\n * EVERY non-alphanumeric char with `-` (no collapsing of runs). Verified on\n * Windows against ~/.claude/projects, e.g.:\n * C:\\code\\my-app -> C--code-my-app\n * C:\\dev\\My Project -> C--dev-My-Project (the space also becomes `-`). */\nexport function encodeCwd(cwd: string): string {\n return path.resolve(cwd).replace(/[^a-zA-Z0-9]/g, \"-\")\n}\n\nexport interface TurnResult {\n text: string\n stopReason: string | null\n usage: any | null\n cacheReadTokens: number\n cacheCreationTokens: number\n ephemeral1hTokens: number\n ephemeral5mTokens: number\n inputTokens: number\n outputTokens: number\n elapsedMs: number\n}\n\nexport interface ClaudeSessionOptions {\n cwd?: string\n /** Claude CLI executable or account wrapper path. */\n cliPath?: string\n /** Claude config root used for JSONL transcripts (defaults to ~/.claude). */\n configDir?: string\n model?: string\n /** '' bypasses CLAUDE.md + user/project/local settings load (fast tests).\n * null/undefined omits the flag entirely (normal settings). */\n settingSources?: string | null\n extraArgs?: string[]\n /** Strip ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN from the spawn env so the\n * CLI uses subscription auth instead of pay-as-you-go API billing. */\n ignoreAnthropicApiKey?: boolean\n cols?: number\n rows?: number\n bootMinMs?: number\n bootQuietMs?: number\n bootMaxMs?: number\n pollMs?: number\n turnTimeoutMs?: number\n /** false = plain write(prompt)+Enter; true = wrap in bracketed-paste so\n * multi-line prompts don't submit early. Default true. */\n bracketedPaste?: boolean\n /** Submitting a turn: a large/multi-line bracketed paste collapses into a\n * \"[Pasted text]\" placeholder, and an Enter sent while claude is still\n * ingesting the paste is silently DROPPED — so a single fixed-delay Enter is\n * unreliable and the turn can hang until turnTimeoutMs. Instead: wait\n * submitMinMs, send Enter, then confirm the turn was accepted (a new\n * transcript record appears) within submitConfirmMs; if not, resend Enter,\n * up to submitMaxRetries times. */\n submitMinMs?: number\n submitConfirmMs?: number\n submitMaxRetries?: number\n /** Abort the call (during boot or an in-flight turn): kills the process and\n * rejects with an \"aborted\" error. */\n signal?: AbortSignal\n debug?: boolean\n}\n\nconst TERMINAL_STOP = new Set([\"end_turn\", \"stop_sequence\", \"max_tokens\"])\nconst delay = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))\n\nfunction resolveConfigDir(configDir: string | undefined): string {\n const value = configDir ?? process.env.CLAUDE_CONFIG_DIR\n if (!value) return path.join(os.homedir(), \".claude\")\n if (value === \"~\") return os.homedir()\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return path.join(os.homedir(), value.slice(2))\n }\n return path.resolve(value)\n}\n\nexport class ClaudeSession {\n readonly sessionId: string\n readonly cwd: string\n readonly configDir: string\n readonly jsonlPath: string\n raw = \"\"\n\n private proc: BunSubprocess | null = null\n private cursor = 0 // index into transcript split('\\n')\n private lastDataAt = 0\n private exited = false\n private exitCode: number | null = null\n private aborted = false\n private readonly signal?: AbortSignal\n private readonly o: Required<\n Omit<\n ClaudeSessionOptions,\n | \"cliPath\"\n | \"configDir\"\n | \"model\"\n | \"settingSources\"\n | \"extraArgs\"\n | \"signal\"\n | \"ignoreAnthropicApiKey\"\n >\n > &\n Pick<\n ClaudeSessionOptions,\n | \"cliPath\"\n | \"configDir\"\n | \"model\"\n | \"settingSources\"\n | \"extraArgs\"\n | \"ignoreAnthropicApiKey\"\n >\n\n constructor(opts: ClaudeSessionOptions = {}) {\n this.cwd = path.resolve(opts.cwd ?? process.cwd())\n this.configDir = resolveConfigDir(opts.configDir)\n this.signal = opts.signal\n this.sessionId = randomUUID()\n this.jsonlPath = path.join(\n this.configDir,\n \"projects\",\n encodeCwd(this.cwd),\n `${this.sessionId}.jsonl`,\n )\n this.o = {\n cwd: this.cwd,\n cliPath: opts.cliPath,\n configDir: this.configDir,\n model: opts.model,\n settingSources: opts.settingSources,\n extraArgs: opts.extraArgs ?? [],\n ignoreAnthropicApiKey: opts.ignoreAnthropicApiKey,\n cols: opts.cols ?? 200,\n rows: opts.rows ?? 50,\n bootMinMs: opts.bootMinMs ?? 3000,\n bootQuietMs: opts.bootQuietMs ?? 1500,\n bootMaxMs: opts.bootMaxMs ?? 25000,\n pollMs: opts.pollMs ?? 250,\n // Agentic turns (tool loops) routinely run for many minutes; a short\n // cap would surface as a mid-task error result. 30 min mirrors the\n // proxy-tool ceiling rather than a chat-reply expectation.\n turnTimeoutMs: opts.turnTimeoutMs ?? 1_800_000,\n bracketedPaste: opts.bracketedPaste ?? true,\n submitMinMs: opts.submitMinMs ?? 200,\n submitConfirmMs: opts.submitConfirmMs ?? 1500,\n submitMaxRetries: opts.submitMaxRetries ?? 8,\n debug: opts.debug ?? false,\n }\n }\n\n async start(): Promise<void> {\n if (this.signal?.aborted) throw new Error(\"aborted before start\")\n this.signal?.addEventListener(\n \"abort\",\n () => {\n this.aborted = true\n this.dispose()\n },\n { once: true },\n )\n const claude = resolveClaude(this.o.cliPath ?? \"claude\")\n const args: string[] = [\"--session-id\", this.sessionId]\n if (this.o.model) args.push(\"--model\", this.o.model)\n if (this.o.settingSources !== null && this.o.settingSources !== undefined) {\n args.push(\"--setting-sources\", this.o.settingSources)\n }\n if (this.o.extraArgs && this.o.extraArgs.length) args.push(...this.o.extraArgs)\n\n if (this.o.debug)\n process.stderr.write(`[session] spawn: ${claude} ${args.join(\" \")}\\n`)\n\n this.lastDataAt = Date.now()\n this.proc = Bun.spawn([claude, ...args], {\n cwd: this.cwd,\n env: {\n ...process.env,\n CLAUDE_CONFIG_DIR: this.o.configDir,\n TERM: \"xterm-256color\",\n ...(this.o.ignoreAnthropicApiKey\n ? { ANTHROPIC_API_KEY: undefined, ANTHROPIC_AUTH_TOKEN: undefined }\n : {}),\n },\n terminal: {\n cols: this.o.cols,\n rows: this.o.rows,\n data: (_term, d) => {\n this.lastDataAt = Date.now()\n const chunk = Buffer.from(d).toString(\"utf8\")\n this.raw += chunk\n if (this.o.debug) process.stdout.write(chunk)\n },\n },\n })\n this.proc.exited\n .then((code) => {\n this.exitCode = typeof code === \"number\" ? code : null\n this.exited = true\n this.proc = null\n })\n .catch(() => {\n this.exited = true\n this.proc = null\n })\n\n await this.waitForBoot()\n this.cursor = this.lineCount()\n }\n\n /** Wait until the TUI has been quiet for bootQuietMs (Ink ready), bounded by\n * bootMinMs..bootMaxMs. */\n private async waitForBoot(): Promise<void> {\n const start = Date.now()\n while (Date.now() - start < this.o.bootMaxMs) {\n await delay(150)\n if (this.aborted) throw new Error(\"aborted during boot\")\n if (this.exited) {\n throw new Error(this.failureMessage(\"claude exited during boot\", true))\n }\n const elapsed = Date.now() - start\n const sinceData = Date.now() - this.lastDataAt\n if (elapsed >= this.o.bootMinMs && sinceData >= this.o.bootQuietMs) return\n }\n }\n\n /** Submit the freshly-injected prompt and confirm the turn was actually\n * accepted. A large bracketed paste collapses into a \"[Pasted text]\"\n * placeholder; an Enter sent while claude is still ingesting the paste is\n * silently dropped, so a single fixed-delay Enter races the paste and can\n * leave the prompt sitting unsubmitted (→ hang until turnTimeoutMs). Send\n * Enter, then poll for transcript growth past the cursor (the turn's records\n * are written on acceptance); resend Enter until accepted or the retry\n * budget is spent. Polling growth (not a blind delay) also stops us from\n * sending a stray Enter once the turn is in flight. */\n private async submitTurn(): Promise<void> {\n await delay(this.o.submitMinMs)\n for (let attempt = 0; attempt < this.o.submitMaxRetries; attempt++) {\n if (this.aborted || this.exited || !this.proc) return\n this.proc.terminal.write(\"\\r\")\n const until = Date.now() + this.o.submitConfirmMs\n while (Date.now() < until) {\n await delay(80)\n if (this.aborted || this.exited) return\n if (this.lineCount() > this.cursor) return // turn accepted\n }\n }\n }\n\n private readRawLines(): string[] {\n try {\n return fs.readFileSync(this.jsonlPath, \"utf8\").split(\"\\n\")\n } catch {\n return []\n }\n }\n\n /** Count of complete lines (split('\\n') minus the trailing/partial element). */\n private lineCount(): number {\n const lines = this.readRawLines()\n return lines.length > 0 ? lines.length - 1 : 0\n }\n\n private rawTail(max = 600): string {\n const clean = this.raw\n // Strip ANSI escape/control sequences before including terminal output in diagnostics.\n .replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n return clean.length > max ? clean.slice(-max) : clean\n }\n\n private failureMessage(reason: string, includeRaw = false): string {\n const parts = [\n `${reason} (sessionId=${this.sessionId}, jsonlPath=${this.jsonlPath}, exitCode=${this.exitCode ?? \"unknown\"})`,\n ]\n if (includeRaw) {\n const tail = this.rawTail()\n if (tail) parts.push(`terminalTail=${JSON.stringify(tail)}`)\n }\n return parts.join(\"; \")\n }\n\n /**\n * Inject a turn into the live session and return the assistant reply once a\n * terminal stop_reason is observed in the transcript.\n */\n async ask(prompt: string, perTurnTimeoutMs?: number): Promise<TurnResult> {\n if (this.aborted) throw new Error(\"aborted\")\n if (!this.proc || this.exited)\n throw new Error(\"session not started or already exited\")\n const timeout = perTurnTimeoutMs ?? this.o.turnTimeoutMs\n const t0 = Date.now()\n\n // Inject. Bracketed paste keeps multi-line prompts from submitting early;\n // submitTurn() then presses Enter and confirms the turn was accepted,\n // resending Enter if the (collapsed) paste swallowed the first one.\n if (this.o.bracketedPaste) {\n this.proc.terminal.write(\"\\x1b[200~\" + prompt + \"\\x1b[201~\")\n } else {\n this.proc.terminal.write(prompt)\n }\n await this.submitTurn()\n\n const collected: string[] = []\n let lastUsage: any = null\n let stopReason: string | null = null\n const deadline = Date.now() + timeout\n\n while (Date.now() < deadline) {\n await delay(this.o.pollMs)\n if (this.aborted) throw new Error(\"aborted mid-turn\")\n const lines = this.readRawLines()\n const lastComplete = lines.length - 1 // exclusive bound; trailing/partial line skipped\n if (lastComplete <= this.cursor) {\n // Drain the transcript before reacting to exit: a final assistant record\n // can be flushed in the same tick the process exits.\n if (this.exited) throw new Error(this.failureMessage(\"claude exited mid-turn\", true))\n continue\n }\n\n for (let i = this.cursor; i < lastComplete; i++) {\n const s = lines[i]\n if (!s || !s.trim()) continue\n let rec: any\n try {\n rec = JSON.parse(s)\n } catch {\n continue\n }\n if (rec.type === \"assistant\" && rec.message) {\n for (const b of rec.message.content ?? []) {\n if (b?.type === \"text\" && typeof b.text === \"string\")\n collected.push(b.text)\n }\n if (rec.message.usage) lastUsage = rec.message.usage\n if (\n rec.message.stop_reason &&\n TERMINAL_STOP.has(rec.message.stop_reason)\n ) {\n stopReason = rec.message.stop_reason\n }\n }\n }\n this.cursor = lastComplete\n if (stopReason) break\n }\n\n if (!stopReason) {\n throw new Error(\n this.failureMessage(\n `turn timed out after ${timeout}ms (no terminal assistant record; collected ${collected.length} text block(s))`,\n ),\n )\n }\n\n const u = lastUsage ?? {}\n return {\n text: collected.join(\"\\n\").trim(),\n stopReason,\n usage: lastUsage,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n cacheCreationTokens: u.cache_creation_input_tokens ?? 0,\n ephemeral1hTokens: u.cache_creation?.ephemeral_1h_input_tokens ?? 0,\n ephemeral5mTokens: u.cache_creation?.ephemeral_5m_input_tokens ?? 0,\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n elapsedMs: Date.now() - t0,\n }\n }\n\n /**\n * Like ask(), but instead of collecting the reply text it re-emits each NEW\n * raw JSONL transcript line via onLine (verbatim) until a terminal\n * stop_reason. Returns the terminal stop_reason + the last assistant usage.\n * Used by the opencode plugin transport shim, which feeds these raw lines\n * into the existing stream-json line handler unchanged.\n */\n async tailTurn(\n prompt: string,\n onLine: (rawLine: string) => void,\n perTurnTimeoutMs?: number\n ): Promise<{ stopReason: string | null; usage: any | null }> {\n if (this.aborted) throw new Error(\"aborted\")\n if (!this.proc || this.exited)\n throw new Error(\"session not started or already exited\")\n const timeout = perTurnTimeoutMs ?? this.o.turnTimeoutMs\n\n if (this.o.bracketedPaste) {\n this.proc.terminal.write(\"\\x1b[200~\" + prompt + \"\\x1b[201~\")\n } else {\n this.proc.terminal.write(prompt)\n }\n await this.submitTurn()\n\n let lastUsage: any = null\n let totalOutput = 0\n let stopReason: string | null = null\n const deadline = Date.now() + timeout\n\n while (Date.now() < deadline) {\n await delay(this.o.pollMs)\n if (this.aborted) throw new Error(\"aborted mid-turn\")\n const lines = this.readRawLines()\n const lastComplete = lines.length - 1\n if (lastComplete <= this.cursor) {\n // Drain the transcript before reacting to exit: the terminal assistant\n // record can land in the same tick the process exits.\n if (this.exited) {\n throw new Error(this.failureMessage(\"claude exited mid-turn\", true))\n }\n continue\n }\n for (let i = this.cursor; i < lastComplete; i++) {\n const s = lines[i]\n if (!s || !s.trim()) continue\n onLine(s)\n let rec: any\n try {\n rec = JSON.parse(s)\n } catch {\n continue\n }\n if (rec.type === \"assistant\" && rec.message) {\n if (rec.message.usage) {\n lastUsage = rec.message.usage\n totalOutput += rec.message.usage.output_tokens ?? 0\n }\n if (\n rec.message.stop_reason &&\n TERMINAL_STOP.has(rec.message.stop_reason)\n ) {\n stopReason = rec.message.stop_reason\n }\n }\n }\n this.cursor = lastComplete\n if (stopReason) break\n }\n\n // Context (input/cache) = the LAST record's full conversation state; output\n // = SUM across all assistant records this turn (each generation), else\n // multi-record tool turns undercount output. toUsage() prefers\n // iterations[last], so patch that entry's output too.\n let usage: any = lastUsage\n if (lastUsage) {\n usage = { ...lastUsage, output_tokens: totalOutput }\n if (Array.isArray(lastUsage.iterations) && lastUsage.iterations.length > 0) {\n const iters = lastUsage.iterations.map((it: any) => ({ ...it }))\n iters[iters.length - 1] = {\n ...iters[iters.length - 1],\n output_tokens: totalOutput,\n }\n usage.iterations = iters\n }\n }\n if (!stopReason) {\n throw new Error(\n this.failureMessage(\n `turn timed out after ${timeout}ms (no terminal assistant record)`,\n ),\n )\n }\n\n return { stopReason, usage }\n }\n\n dispose(): void {\n if (this.proc) {\n try {\n this.proc.terminal.write(\"\\x03\")\n } catch {}\n try {\n this.proc.kill()\n } catch {}\n try {\n this.proc.terminal.close()\n } catch {}\n }\n this.proc = null\n }\n}\n\n/** One-shot convenience (drop-in for `claude -p`): start, ask, dispose. */\nexport async function askOnce(\n prompt: string,\n opts: ClaudeSessionOptions = {},\n): Promise<TurnResult> {\n const s = new ClaudeSession(opts)\n await s.start()\n try {\n return await s.ask(prompt)\n } finally {\n s.dispose()\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport * as crypto from \"node:crypto\"\nimport { EventEmitter } from \"node:events\"\nimport { log } from \"./logger.js\"\nimport { pluginTmpDir } from \"./tmp.js\"\n\n/**\n * Minimal MCP HTTP server embedded in-process. Exposes a set of \"proxy\"\n * tools (Bash, Edit, Write, etc.) that Claude CLI calls when its built-in\n * equivalents are disabled via --disallowedTools. Our handler blocks until\n * an external broker resolves the call, then responds to Claude.\n *\n * Wire protocol: JSON-RPC 2.0 over plain HTTP POST to `/mcp`. MCP spec\n * also supports SSE streaming, but Claude's HTTP transport accepts single\n * JSON responses for short-lived tool calls, so we keep it simple.\n */\n\nexport interface ProxyMcpServer {\n url: string\n serverName: string\n tools: ProxyToolDef[]\n /** Fires when Claude invokes one of our proxy tools. The handler resolves\n * the returned pending call once a result is available. */\n calls: EventEmitter\n /** Write `--mcp-config <path>`-compatible scratch file and return its path. */\n configPath(): string\n close(): Promise<void>\n}\n\nexport interface ProxyToolDef {\n /** Raw name as seen by Claude once proxied: the MCP exposed tool name. */\n name: string\n description: string\n inputSchema: Record<string, unknown>\n}\n\nexport interface ProxyToolCall {\n id: string\n toolName: string\n input: Record<string, unknown>\n resolve: (result: ProxyToolResult) => void\n reject: (err: Error) => void\n}\n\nexport type ProxyToolResult =\n | { kind: \"text\"; text: string; isError?: boolean }\n | { kind: \"error\"; message: string }\n\nexport const SERVER_CLOSED_MESSAGE = \"proxy MCP server closed\"\n\n/** Rejections that fire on normal lifecycle transitions: AFK-permission\n * timeouts, orphan rejections at turn boundaries, stream aborts, and server\n * close while its owning Claude process exits or is replaced. None are\n * user-actionable — file-log them at NOTICE. Anything else stays WARN so\n * genuine bugs remain visible in the TUI. */\nexport function isExpectedCleanupError(message: string): boolean {\n return (\n (message.includes(\"timed out after\") &&\n message.includes(\"waiting for opencode to resolve\")) ||\n message.includes(\"rejecting as orphaned\") ||\n message.includes(\"was orphaned by a new user turn\") ||\n message.includes(\"stream was aborted\") ||\n message.includes(SERVER_CLOSED_MESSAGE)\n )\n}\n\nconst PROTOCOL_VERSION = \"2024-11-05\"\nconst SERVER_NAME = \"opencode_proxy\"\nexport const PROXY_TOOL_PREFIX = `mcp__${SERVER_NAME}__`\n\n// Flat fallback cap on how long a proxy tool call may wait for opencode to\n// resolve it. Matches Claude CLI's hard upper bound for Bash (10 min). The\n// effective deadline is resolved per tool — see `resolveProxyCallTimeoutMs`.\nexport const PROXY_DEFAULT_TIMEOUT_MS = 10 * 60 * 1000\n\n// Per-tool default deadlines, keyed by lowercase proxy tool name. `task`\n// dispatches an opencode subagent that routinely runs 20-40 min; the old\n// flat ceiling fired mid-subagent, made Claude believe its dispatch had\n// failed, and (because the proxy had already returned a timeout error) the\n// late subagent result was dropped on the floor -- the operator had to\n// nudge \"please check now, it seems the task succeeded\" (@jknlsn, live\n// session ses_0cfc0da6, 2026-07-05).\n//\n// `question` blocks on a human reading a TUI form, so the flat ceiling is\n// the wrong unit entirely: a question posed just before the operator steps\n// away would be rejected mid-answer. 30 min is jknlsn's original figure and\n// matches the \"prefer fewer, high-signal questions\" guidance in the def.\nexport const PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS: Record<string, number> = {\n task: 60 * 60 * 1000, // 60 min\n question: 30 * 60 * 1000, // 30 min\n}\n\n// Node's setTimeout delay is a signed 32-bit int; values above 2^31-1 ms\n// (~24.85 days) trigger TimeoutOverflowWarning and fire at ~1ms instead.\n// Clamp absurd overrides / input.timeouts so a misconfigured deadline\n// can't collapse to \"fires immediately\".\nexport const MAX_PROXY_TIMEOUT_MS = 2 ** 31 - 1\n\n/**\n * Resolve the proxy deadline for a tool call. Layers, most-specific last:\n * 1. flat default (`PROXY_DEFAULT_TIMEOUT_MS`, 10 min)\n * 2. per-tool default (`PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS`)\n * 3. user override via `proxyToolTimeoutMs` config (case-insensitive key)\n * 4. for `bash`, the call's own `input.timeout` -- the proxy must never\n * undercut a build the caller explicitly asked to run long. The bash\n * proxy def advertises a `timeout` field; before this fix the proxy\n * ignored it and killed the call at the flat ceiling anyway.\n * Finally clamped to `MAX_PROXY_TIMEOUT_MS` to stay within Node's timer range.\n */\nexport function resolveProxyCallTimeoutMs(\n toolName: string,\n input: Record<string, unknown> | undefined,\n overrides: Record<string, number> | undefined,\n): number {\n const key = toolName.toLowerCase()\n let ms = PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS[key] ?? PROXY_DEFAULT_TIMEOUT_MS\n if (overrides) {\n const ov = lookupCaseInsensitive(overrides, key)\n if (typeof ov === \"number\" && ov > 0) ms = ov\n }\n if (key === \"bash\") {\n const requested = input?.timeout\n if (typeof requested === \"number\" && requested > ms) ms = requested\n }\n return Math.min(ms, MAX_PROXY_TIMEOUT_MS)\n}\n\nfunction lookupCaseInsensitive(\n map: Record<string, number>,\n key: string,\n): number | undefined {\n if (Object.prototype.hasOwnProperty.call(map, key)) return map[key]\n for (const k of Object.keys(map)) {\n if (k.toLowerCase() === key) return map[k]\n }\n return undefined\n}\n\n/**\n * Client-side abort ceiling written into Claude's `--mcp-config` entry for\n * the proxy server. Without a `timeout` there, Claude CLI's remote-HTTP MCP\n * client aborts each call at its 60-second default even while an opencode\n * subagent is still running (@broskees, PR #18). It must be >= the largest\n * server-side deadline or the client gives up before the broker does, so it\n * tracks the max of the flat default, per-tool defaults, and user overrides.\n * (A bash call raising its own `input.timeout` above this ceiling is a known\n * edge; Claude CLI caps bash at 10 min anyway.)\n */\nexport function resolveProxyClientCeilingMs(\n overrides: Record<string, number> | undefined,\n): number {\n let ms = PROXY_DEFAULT_TIMEOUT_MS\n for (const v of Object.values(PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS)) {\n if (v > ms) ms = v\n }\n if (overrides) {\n for (const v of Object.values(overrides)) {\n if (typeof v === \"number\" && v > ms) ms = v\n }\n }\n return Math.min(ms, MAX_PROXY_TIMEOUT_MS)\n}\n\n/**\n * Build the timeout error surfaced to Claude. Keeps the substrings\n * `\"timed out after\"` and `\"waiting for opencode to resolve\"` that the\n * proxy-mcp catch block classifies as expected cleanup (notice, not warn).\n * For `task` we append guidance: a Task timeout means the subagent may\n * still be running but its result is now unreachable, and the model must\n * neither declare the dispatch failed nor \"schedule a wake-up\" -- that is a\n * Claude Code affordance which cannot fire in this headless/proxy context,\n * so deferring silently drops the work.\n */\nexport function buildProxyTimeoutError(toolName: string, ms: number): Error {\n const key = toolName.toLowerCase()\n const base = `Proxy tool '${toolName}' timed out after ${ms}ms waiting for opencode to resolve the call`\n if (key === \"task\") {\n return new Error(\n base +\n \" (the subagent). The subagent may still be running but its result\" +\n \" is no longer reachable in this session. Do not declare the dispatch\" +\n \" failed, and do not 'schedule a wake-up' or defer -- that mechanism\" +\n \" does not apply here. If the result is required, re-dispatch or\" +\n \" verify it directly now.\",\n )\n }\n return new Error(base)\n}\n\n/**\n * Disambiguation appended to the `task` proxy def (both the static\n * fallback and the live overlay). Models routinely resolve opencode's\n * \"call the task tool with subagent: X\" mention hint to Claude Code's\n * native TaskCreate (a todo tool) — creating a todo, dispatching nothing,\n * and then narrating a successful dispatch. Others burn turns grepping\n * config files to verify a subagent exists before daring to call it.\n * Both failure modes are addressed here, at the tool the model reads.\n */\nexport const TASK_PROXY_NOTE =\n \"This is the ONLY tool that dispatches opencode subagents (including\" +\n \" user @-mentions). Claude Code's built-in TaskCreate/TaskUpdate manage\" +\n \" a local todo list and cannot dispatch subagents. Do not search config\" +\n \" files to verify a subagent type exists — invalid types fail fast with\" +\n \" a clear error. Foreground calls block until the subagent finishes; set\" +\n \" `background` to request opencode's background execution mode. Task calls\" +\n \" get a 60-minute proxy deadline by default (configurable via\" +\n \" proxyToolTimeoutMs).\"\n\nconst AGENT_TYPES_HEADING = \"Available agent types\"\n\n/** Longest per-agent blurb we keep; enough to choose, short enough to survive. */\nconst AGENT_BLURB_LIMIT = 140\n\n/**\n * Disambiguation appended to the `question` proxy def. Claude Code ships\n * a built-in `AskUserQuestion` that, when proxied, is disabled via\n * `--disallowedTools`; without an explicit hand-off note models keep\n * reaching for the disabled built-in or fall back to plain text. This\n * states that the proxy is the structured-questions path and summarises\n * the answer shape so the model can act on the result without a second\n * round-trip.\n */\nexport const QUESTION_PROXY_NOTE =\n \"This routes structured questions through opencode's native `question`\" +\n \" tool, which renders a TUI form with the options you provide and\" +\n \" blocks until the operator answers. Claude Code's built-in\" +\n \" AskUserQuestion is disabled in this environment; this proxy is the\" +\n \" ONLY way to ask the operator for a decision or clarification.\" +\n \" Answers come back as arrays of selected labels (set `multiple: true`\" +\n \" to allow more than one). If the operator dismisses the form the call\" +\n \" returns an error — treat that as 'no answer' and stop, do not guess.\" +\n \" Question calls get a 30-minute proxy deadline by default (configurable\" +\n \" via proxyToolTimeoutMs); for long-AFK scenarios prefer fewer,\" +\n \" high-signal questions.\"\n\n/**\n * Pull *only* the agent-type list out of opencode's live `task` description.\n *\n * jknlsn's original overlaid the whole live description (2.8 KB here) in front\n * of the static def. Live check 2026-07-26 showed that backfires: Claude Code\n * truncates long MCP tool descriptions, and opencode puts the agent list at\n * the *end* (char 2306 of 2858), so the one part the model needs is exactly\n * what gets cut — haiku then guessed `general-purpose`, `default`, and\n * `code-reviewer` (Claude Code's own agent names) and every dispatch failed\n * with \"Unknown agent type\". So: keep the list, drop opencode's preamble\n * (generic delegation advice the model already has), trim each blurb, and let\n * the caller put it first.\n *\n * Returns undefined when the description carries no parsable list, so callers\n * leave the static def alone.\n */\nexport function extractAgentTypeList(\n liveDescription: string | undefined,\n): string | undefined {\n const live = liveDescription?.trim()\n if (!live) return undefined\n const start = live.indexOf(AGENT_TYPES_HEADING)\n if (start === -1) return undefined\n const entries: string[] = []\n for (const raw of live.slice(start).split(\"\\n\")) {\n const match = /^-\\s*([^:]+):\\s*(.+)$/.exec(raw.trim())\n if (!match) continue\n const name = match[1].trim()\n const blurb = match[2].trim()\n entries.push(\n `- ${name}: ${\n blurb.length > AGENT_BLURB_LIMIT\n ? `${blurb.slice(0, AGENT_BLURB_LIMIT).trimEnd()}…`\n : blurb\n }`,\n )\n }\n if (entries.length === 0) return undefined\n return `Valid subagent_type values, from opencode's live registry — anything else fails:\\n${entries.join(\"\\n\")}`\n}\n\n/**\n * Front-load opencode's live agent-type list onto the static `task` proxy def\n * so the model picks a real `subagent_type` instead of guessing a Claude Code\n * name. First, not last: see `extractAgentTypeList` for why position matters.\n * No-op when no list can be extracted (SDK client missing, older opencode) or\n * the `task` def is not among the tools.\n */\nexport function overlayTaskProxyDescription(\n tools: ProxyToolDef[],\n liveDescription: string | undefined,\n): ProxyToolDef[] {\n const agentTypes = extractAgentTypeList(liveDescription)\n if (!agentTypes) return tools\n return tools.map((t) =>\n t.name === \"task\"\n ? { ...t, description: `${agentTypes}\\n\\n${t.description}` }\n : t,\n )\n}\n\n/**\n * Overlay opencode's live `question` tool description onto the static\n * proxy def, then append the disambiguation note. No-op when the live\n * description is unavailable (older opencode, SDK client missing) — the\n * static def + note stands. Mirrors `overlayTaskProxyDescription`.\n */\nexport function overlayQuestionProxyDescription(\n tools: ProxyToolDef[],\n liveDescription: string | undefined,\n): ProxyToolDef[] {\n const live = liveDescription?.trim()\n if (!live) return tools\n return tools.map((t) =>\n t.name === \"question\"\n ? { ...t, description: `${live}\\n\\n${QUESTION_PROXY_NOTE}` }\n : t,\n )\n}\n\n/**\n * Version gate for the `question` proxy. opencode added a built-in\n * `question` tool (registry id `question`) — on older builds that entry\n * is absent and a forwarded `mcp__opencode_proxy__question` call would\n * resolve to `⚙ invalid` in opencode. Drop the def silently when the\n * live registry does not contain it so the model never sees a dead tool.\n */\nexport function filterQuestionProxyByOpencodeSupport(\n tools: ProxyToolDef[],\n opencodeHasQuestion: boolean,\n): ProxyToolDef[] {\n if (opencodeHasQuestion) return tools\n return tools.filter((t) => t.name !== \"question\")\n}\n\nexport const DEFAULT_PROXY_TOOLS: ProxyToolDef[] = [\n {\n name: \"bash\",\n description:\n \"Execute a shell command. Routed through opencode's bash tool so\" +\n \" permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: \"The shell command to execute.\",\n },\n description: {\n type: \"string\",\n description: \"Short human-readable description of what the command does.\",\n },\n timeout: {\n type: \"number\",\n description: \"Optional timeout in milliseconds.\",\n },\n },\n required: [\"command\"],\n },\n },\n {\n name: \"write\",\n description:\n \"Write a file. Routed through opencode's write tool so permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \"The file to write. Absolute paths are preferred.\",\n },\n content: {\n type: \"string\",\n description: \"The full content to write to the file.\",\n },\n },\n required: [\"filePath\", \"content\"],\n },\n },\n {\n name: \"edit\",\n description:\n \"Replace text in an existing file. Routed through opencode's edit tool so permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \"The file to edit. Absolute paths are preferred.\",\n },\n oldString: {\n type: \"string\",\n description: \"The exact text to replace.\",\n },\n newString: {\n type: \"string\",\n description: \"The replacement text.\",\n },\n replaceAll: {\n type: \"boolean\",\n description: \"Replace all occurrences instead of just the first one.\",\n },\n },\n required: [\"filePath\", \"oldString\", \"newString\"],\n },\n },\n {\n name: \"webfetch\",\n description:\n \"Fetch content from a URL. Routed through opencode's webfetch tool so\" +\n \" permission prompts flow through opencode's UI. Returns the page\" +\n \" content in the requested format.\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: {\n type: \"string\",\n description: \"The URL to fetch content from. Must start with http:// or https://.\",\n },\n format: {\n type: \"string\",\n enum: [\"text\", \"markdown\", \"html\"],\n description:\n \"The format to return the content in. Defaults to markdown.\",\n },\n timeout: {\n type: \"number\",\n description: \"Optional timeout in seconds (max 120).\",\n },\n },\n required: [\"url\"],\n },\n },\n {\n name: \"task\",\n description:\n \"Launch an opencode subagent to handle a complex multi-step task\" +\n \" autonomously. Routed through opencode's task tool so subagent\" +\n \" orchestration, permission, and lifecycle are handled by opencode.\" +\n \" Use `subagent_type` to pick which configured subagent runs (e.g.\" +\n \" `build`, `general`, `explore`, or any custom subagent declared in\" +\n \" opencode.json). \" +\n TASK_PROXY_NOTE,\n inputSchema: {\n type: \"object\",\n properties: {\n description: {\n type: \"string\",\n description: \"A short (3-5 words) description of the task\",\n },\n prompt: {\n type: \"string\",\n description: \"The task for the agent to perform\",\n },\n subagent_type: {\n type: \"string\",\n description: \"The type of specialized agent to use for this task\",\n },\n task_id: {\n type: \"string\",\n description:\n \"Set this only if you mean to resume a previous task — pass the\" +\n \" prior task_id to continue the same subagent session instead of\" +\n \" creating a fresh one.\",\n },\n command: {\n type: \"string\",\n description: \"The command that triggered this task\",\n },\n background: {\n type: \"boolean\",\n description:\n \"Run the task in the background when supported by opencode\",\n },\n },\n required: [\"description\", \"prompt\", \"subagent_type\"],\n },\n },\n {\n name: \"question\",\n description:\n \"Ask the operator structured questions with options and receive\" +\n \" their answers back. Routed through opencode's native `question`\" +\n \" tool so the prompt renders as a real TUI form (with options and a\" +\n \" custom-answer field) instead of a plain text turn. Use this when\" +\n \" you need a decision, clarification, or preference from the\" +\n \" operator mid-task. \" +\n QUESTION_PROXY_NOTE,\n inputSchema: {\n type: \"object\",\n properties: {\n questions: {\n type: \"array\",\n description: \"Questions to ask.\",\n items: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"Complete question.\",\n },\n header: {\n type: \"string\",\n description: \"Very short label (max 30 chars).\",\n },\n options: {\n type: \"array\",\n description: \"Available choices.\",\n items: {\n type: \"object\",\n properties: {\n label: {\n type: \"string\",\n description: \"Display text (1-5 words, concise).\",\n },\n description: {\n type: \"string\",\n description: \"Explanation of choice.\",\n },\n },\n required: [\"label\", \"description\"],\n },\n },\n multiple: {\n type: \"boolean\",\n description:\n \"Allow selecting multiple choices. Defaults to false.\",\n },\n },\n required: [\"question\", \"header\", \"options\"],\n },\n },\n },\n required: [\"questions\"],\n },\n },\n]\n\nexport async function createProxyMcpServer(\n tools: ProxyToolDef[] = DEFAULT_PROXY_TOOLS,\n timeoutOverrides?: Record<string, number>,\n): Promise<ProxyMcpServer> {\n const calls = new EventEmitter()\n const pending = new Map<string, ProxyToolCall>()\n\n const server = createServer(async (req, res) => {\n if (req.method !== \"POST\" || !req.url?.startsWith(\"/mcp\")) {\n res.statusCode = 404\n res.end()\n return\n }\n // Hoist the request id and method so the catch block can echo them\n // in error responses. Without this, a broker rejection (timeout /\n // orphan) on a tools/call lands in the catch with no visible id, and\n // the response goes back with `id: null` which Claude CLI cannot\n // match to the original request. The method is also needed because\n // tools/call errors must be returned as MCP results with isError\n // (not JSON-RPC errors) or Claude CLI rejects them as a \"malformed\n // result that failed schema validation\" (seen live 2026-07-04).\n let requestId: number | string | null = null\n let requestMethod: string | null = null\n try {\n const body = await readBody(req)\n const request = JSON.parse(body) as {\n jsonrpc?: string\n id?: number | string | null\n method?: string\n params?: Record<string, unknown>\n }\n requestId = request?.id ?? null\n requestMethod = typeof request?.method === \"string\" ? request.method : null\n\n if (request?.jsonrpc !== \"2.0\" || typeof request.method !== \"string\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32600, message: \"Invalid request\" },\n })\n return\n }\n\n log.debug(\"proxy-mcp request\", {\n method: request.method,\n id: request.id,\n })\n\n if (request.method === \"initialize\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: {\n name: SERVER_NAME,\n version: \"0.1.0\",\n },\n },\n })\n return\n }\n\n if (request.method === \"notifications/initialized\") {\n res.statusCode = 204\n res.end()\n return\n }\n\n if (request.method === \"tools/list\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n tools: tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n },\n })\n return\n }\n\n if (request.method === \"tools/call\") {\n const params = request.params ?? {}\n const toolName = String(params.name ?? \"\")\n const input = (params.arguments ?? {}) as Record<string, unknown>\n\n if (!tools.some((t) => t.name === toolName)) {\n // tools/call failures MUST be MCP results with isError, never\n // JSON-RPC error envelopes: Claude CLI validates every tools/call\n // response against the MCP result schema and rejects JSON-RPC\n // errors as malformed (@jknlsn, seen live 2026-07-04).\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n content: [{ type: \"text\", text: `Unknown proxy tool: ${toolName}` }],\n isError: true,\n },\n })\n return\n }\n\n const callId = crypto.randomUUID()\n log.info(\"proxy-mcp tool call received\", {\n callId,\n toolName,\n hasInput: input != null,\n })\n\n let timer: ReturnType<typeof setTimeout> | null = null\n const result = await new Promise<ProxyToolResult>(\n (resolve, reject) => {\n const entry: ProxyToolCall = {\n id: callId,\n toolName,\n input,\n resolve,\n reject,\n }\n pending.set(callId, entry)\n const deadlineMs = resolveProxyCallTimeoutMs(\n toolName,\n input,\n timeoutOverrides,\n )\n timer = setTimeout(() => {\n if (!pending.has(callId)) return\n pending.delete(callId)\n // v0.4.13: demoted from warn to notice. Timeouts are usually\n // permission-pending while the user is AFK — surfacing each as\n // a yellow UI bubble produces a wall of noise on return. The\n // file log still captures the event for diagnostics.\n log.notice(\"proxy-mcp tool call timed out\", {\n callId,\n toolName,\n deadlineMs,\n })\n reject(buildProxyTimeoutError(toolName, deadlineMs))\n }, deadlineMs)\n calls.emit(\"call\", entry)\n },\n ).finally(() => {\n if (timer) clearTimeout(timer)\n pending.delete(callId)\n })\n\n // Unify success and error results into one MCP result envelope.\n // A JSON-RPC error for `kind: \"error\"` was rejected by Claude\n // CLI as a \"malformed result that failed schema validation\"\n // because tools/call responses are validated as MCP results, so\n // tool-execution errors must surface as `isError: true` instead.\n const text = result.kind === \"error\" ? result.message : result.text\n const isError = result.kind === \"error\" || result.isError === true\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n content: [{ type: \"text\", text }],\n isError,\n },\n })\n return\n }\n\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32601, message: `Unknown method: ${request.method}` },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n const logFn = isExpectedCleanupError(errorMessage) ? log.notice : log.warn\n logFn(\"proxy-mcp error handling request\", {\n error: errorMessage,\n })\n // Broker rejections (timeouts, orphans, server close) surface here for\n // tools/call requests. Same rule as above: respond with an MCP result\n // carrying isError, never a JSON-RPC error envelope, or Claude CLI\n // rejects the response as schema-invalid.\n if (requestMethod === \"tools/call\") {\n try {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n content: [{ type: \"text\", text: errorMessage }],\n isError: true,\n },\n })\n } catch {\n try {\n res.statusCode = 500\n res.end()\n } catch {}\n }\n return\n }\n try {\n // tools/call already returned above with an MCP result; anything\n // reaching here is a protocol-level method (initialize, tools/list)\n // where a JSON-RPC error is the correct shape.\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: {\n code: -32603,\n message: error instanceof Error ? error.message : \"Internal error\",\n },\n })\n } catch {\n try {\n res.statusCode = 500\n res.end()\n } catch {}\n }\n }\n })\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n\n const addr = server.address() as AddressInfo | null\n if (!addr) {\n server.close()\n throw new Error(\"Failed to bind proxy MCP server\")\n }\n\n const url = `http://127.0.0.1:${addr.port}/mcp`\n\n log.info(\"proxy-mcp server started\", {\n url,\n tools: tools.map((t) => t.name),\n })\n\n let configFilePath: string | null = null\n\n const api: ProxyMcpServer = {\n url,\n serverName: SERVER_NAME,\n tools,\n calls,\n configPath() {\n if (configFilePath) return configFilePath\n const body = JSON.stringify(\n {\n mcpServers: {\n [SERVER_NAME]: {\n type: \"http\",\n url,\n timeout: resolveProxyClientCeilingMs(timeoutOverrides),\n },\n },\n },\n null,\n 2,\n )\n const hash = crypto\n .createHash(\"sha256\")\n .update(body)\n .digest(\"hex\")\n .slice(0, 12)\n const outPath = path.join(\n pluginTmpDir(),\n `proxy-${hash}.json`,\n )\n fs.writeFileSync(outPath, body, { encoding: \"utf8\", mode: 0o600 })\n configFilePath = outPath\n return outPath\n },\n async close() {\n for (const entry of pending.values()) {\n entry.reject(new Error(SERVER_CLOSED_MESSAGE))\n }\n pending.clear()\n await new Promise<void>((resolve) => {\n server.close(() => resolve())\n })\n if (configFilePath) {\n try {\n fs.unlinkSync(configFilePath)\n } catch {}\n configFilePath = null\n }\n },\n }\n\n return api\n}\n\n/** CLI-ready list of Claude tool names to disable, for each proxied tool. */\nexport function disallowedToolFlags(tools: ProxyToolDef[]): string[] {\n // Map our lowercase MCP tool names to the Claude tool name(s) they replace.\n // `edit` covers both `Edit` and `MultiEdit` because opencode has no\n // MultiEdit equivalent; without disabling MultiEdit, Claude can batch\n // file changes through it and bypass opencode's permission UI.\n // `task` disables Claude CLI's `Agent` tool (its built-in subagent\n // dispatcher) so subagent calls flow through opencode's `task` tool\n // instead — which lets opencode's configured subagent set (`build`,\n // `general`, custom subagents in opencode.json) execute the work\n // under opencode's permission/lifecycle, rather than Claude's\n // internal-only general-purpose / Explore / Plan options.\n const nameMap: Record<string, string[]> = {\n bash: [\"Bash\"],\n read: [\"Read\"],\n write: [\"Write\"],\n edit: [\"Edit\", \"MultiEdit\"],\n glob: [\"Glob\"],\n grep: [\"Grep\"],\n webfetch: [\"WebFetch\"],\n task: [\"Agent\"],\n // `question` disables Claude Code's built-in `AskUserQuestion` so the\n // structured-questions path flows through opencode's native `question`\n // tool instead — same UI/permission/audit benefits as the other\n // proxies. Without this, the model can call both and the two paths\n // diverge (opencode's form vs the headless deny-and-render fallback).\n question: [\"AskUserQuestion\"],\n }\n const out: string[] = []\n const seen = new Set<string>()\n for (const t of tools) {\n const mapped = nameMap[t.name.toLowerCase()]\n if (!mapped) continue\n for (const claudeTool of mapped) {\n if (seen.has(claudeTool)) continue\n seen.add(claudeTool)\n out.push(claudeTool)\n }\n }\n return out\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk))\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")))\n req.on(\"error\", reject)\n })\n}\n\nfunction writeJson(res: ServerResponse, body: unknown): void {\n const payload = JSON.stringify(body)\n res.statusCode = 200\n res.setHeader(\"Content-Type\", \"application/json\")\n res.setHeader(\"Content-Length\", Buffer.byteLength(payload).toString())\n res.end(payload)\n}\n","import { EventEmitter } from \"node:events\"\nimport {\n buildProxyTimeoutError,\n resolveProxyCallTimeoutMs,\n type ProxyToolCall,\n type ProxyToolResult,\n} from \"./proxy-mcp.js\"\nimport { log } from \"./logger.js\"\n\nexport interface PendingProxyCall {\n sessionKey: string\n toolCallId: string\n toolName: string\n input: Record<string, unknown>\n}\n\ntype InternalPending = PendingProxyCall & {\n createdAt: number\n timer: ReturnType<typeof setTimeout>\n resolve(result: ProxyToolResult): void\n reject(error: Error): void\n}\n\n// Primary index: callId -> pending. Tool call IDs are UUIDs produced by\n// proxy-mcp, so they are globally unique across sessions.\nconst pendingByCallId = new Map<string, InternalPending>()\n// Reverse index: sessionKey -> set of callIds, so the language model can\n// drain or reject every pending call for one Claude subprocess at once.\nconst callIdsBySession = new Map<string, Set<string>>()\n\nconst emitter = new EventEmitter()\n\nfunction eventName(sessionKey: string) {\n return `pending:${sessionKey}`\n}\n\nfunction indexAdd(sessionKey: string, callId: string) {\n let s = callIdsBySession.get(sessionKey)\n if (!s) {\n s = new Set()\n callIdsBySession.set(sessionKey, s)\n }\n s.add(callId)\n}\n\nfunction indexRemove(sessionKey: string, callId: string) {\n const s = callIdsBySession.get(sessionKey)\n if (!s) return\n s.delete(callId)\n if (s.size === 0) callIdsBySession.delete(sessionKey)\n}\n\nexport function onPendingProxyCall(\n sessionKey: string,\n handler: (call: PendingProxyCall) => void,\n): () => void {\n const name = eventName(sessionKey)\n emitter.on(name, handler)\n return () => emitter.off(name, handler)\n}\n\nexport function queuePendingProxyCall(\n sessionKey: string,\n call: ProxyToolCall,\n timeoutOverrides?: Record<string, number>,\n): PendingProxyCall {\n // Defensive: if this exact callId is somehow already pending (UUID\n // collision or retry storm), replace it cleanly so we never leak two\n // entries for the same id.\n const previous = pendingByCallId.get(call.id)\n if (previous) {\n clearTimeout(previous.timer)\n previous.reject(\n new Error(`Replaced pending proxy call ${call.id} with a fresh one`),\n )\n pendingByCallId.delete(call.id)\n indexRemove(previous.sessionKey, call.id)\n }\n\n const deadlineMs = resolveProxyCallTimeoutMs(\n call.toolName,\n call.input,\n timeoutOverrides,\n )\n\n const timer = setTimeout(() => {\n const current = pendingByCallId.get(call.id)\n if (!current) return\n pendingByCallId.delete(call.id)\n indexRemove(current.sessionKey, call.id)\n current.reject(buildProxyTimeoutError(call.toolName, deadlineMs))\n // v0.4.13: demoted from warn to notice. AFK-permission-pending\n // sessions can stack many of these; demoting keeps the UI quiet on\n // return while preserving the audit trail in plugin.log.\n log.notice(\"timed out pending proxy call\", {\n sessionKey: current.sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n deadlineMs,\n })\n }, deadlineMs)\n\n const pending: InternalPending = {\n sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n input: call.input,\n createdAt: Date.now(),\n timer,\n resolve: call.resolve,\n reject: call.reject,\n }\n pendingByCallId.set(call.id, pending)\n indexAdd(sessionKey, call.id)\n emitter.emit(eventName(sessionKey), pending)\n log.info(\"queued pending proxy call\", {\n sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n })\n return pending\n}\n\nexport function getPendingProxyCalls(sessionKey: string): PendingProxyCall[] {\n const s = callIdsBySession.get(sessionKey)\n if (!s || s.size === 0) return []\n const out: PendingProxyCall[] = []\n for (const id of s) {\n const p = pendingByCallId.get(id)\n if (p) out.push(p)\n }\n return out\n}\n\nexport function resolvePendingProxyCallById(\n toolCallId: string,\n result: ProxyToolResult,\n): boolean {\n const pending = pendingByCallId.get(toolCallId)\n if (!pending) return false\n pendingByCallId.delete(toolCallId)\n indexRemove(pending.sessionKey, toolCallId)\n clearTimeout(pending.timer)\n pending.resolve(result)\n log.info(\"resolved pending proxy call\", {\n sessionKey: pending.sessionKey,\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n })\n return true\n}\n\nexport function rejectPendingProxyCallById(\n toolCallId: string,\n error: Error,\n): boolean {\n const pending = pendingByCallId.get(toolCallId)\n if (!pending) return false\n pendingByCallId.delete(toolCallId)\n indexRemove(pending.sessionKey, toolCallId)\n clearTimeout(pending.timer)\n pending.reject(error)\n // Rejection is the broker's cleanup mechanism — fires on timeouts, orphans,\n // stream closes, etc. None are user-actionable. File-log them at NOTICE so\n // the audit trail is intact; rely on caller sites to decide TUI visibility.\n log.notice(\"rejected pending proxy call\", {\n sessionKey: pending.sessionKey,\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n error: error.message,\n })\n return true\n}\n\nexport function rejectAllPendingProxyCallsForSession(\n sessionKey: string,\n error: Error,\n): number {\n const s = callIdsBySession.get(sessionKey)\n if (!s) return 0\n const ids = [...s]\n let count = 0\n for (const id of ids) {\n if (rejectPendingProxyCallById(id, error)) count++\n }\n return count\n}\n","import type { OpenCodeModel } from \"./opencode-types.js\"\n\nconst PROVIDER_ID = \"claude-code\"\nconst NPM = \"@khalilgharbaoui/opencode-claude-code-plugin\"\n\nconst reasoningVariants: Record<string, Record<string, unknown>> = {\n low: { reasoningEffort: \"low\" },\n medium: { reasoningEffort: \"medium\" },\n high: { reasoningEffort: \"high\" },\n xhigh: { reasoningEffort: \"xhigh\" },\n max: { reasoningEffort: \"max\" },\n}\n\nconst baseCapabilities = {\n temperature: false,\n attachment: true,\n toolcall: true,\n input: { text: true, audio: false, image: true, video: false, pdf: false },\n output: { text: true, audio: false, image: false, video: false, pdf: false },\n interleaved: false as const,\n}\n\nfunction defineModel(opts: {\n id: string\n name: string\n family: string\n reasoning: boolean\n context: number\n output: number\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number }\n releaseDate: string\n // List-price multiplier relative to Haiku (the cheapest model). Derived\n // exactly from published per-token pricing: input AND output ratios both come\n // out to haiku 1, sonnet 3, opus 5, fable/mythos 10. Sonnet 5 is temporarily\n // 2x during its launch-price period through August 31, 2026. Rendered as an\n // `(N×)` suffix so it surfaces in opencode's model picker, which has no\n // dedicated multiplier field.\n // Display-only: model resolution keys off `id`.\n multiplier: number\n status?: OpenCodeModel[\"status\"]\n}): OpenCodeModel {\n return {\n id: opts.id,\n providerID: PROVIDER_ID,\n api: { id: opts.id, url: \"\", npm: NPM },\n name: `${opts.name} (${opts.multiplier}×)`,\n family: opts.family,\n capabilities: { ...baseCapabilities, reasoning: opts.reasoning },\n cost: {\n input: opts.cost.input,\n output: opts.cost.output,\n cache: { read: opts.cost.cacheRead, write: opts.cost.cacheWrite },\n },\n limit: { context: opts.context, output: opts.output },\n status: opts.status ?? \"active\",\n options: {},\n headers: {},\n release_date: opts.releaseDate,\n variants: opts.reasoning ? reasoningVariants : undefined,\n }\n}\n\n// Per-token costs derived from Anthropic per-million-token pricing.\n//\n// There is no long-context premium to model. Anthropic's pricing page states\n// that Claude 4.6 and later ship the full 1M-token context window at standard\n// pricing (\"a 900k-token request is billed at the same per-token rate as a\n// 9k-token request\"), and caching/batch discounts apply unchanged across it.\n// opencode 1.18.5 added optional `cost.tiers` / `cost.experimentalOver200K`\n// fields for above-200K pricing; they stay unset here deliberately, because a\n// tier would misreport the real price. Re-check only if Anthropic introduces\n// one. Verified against the pricing docs 2026-07-26.\nconst haikuCost = { input: 1e-6, output: 5e-6, cacheRead: 1e-7, cacheWrite: 1.25e-6 }\nconst sonnetCost = { input: 3e-6, output: 15e-6, cacheRead: 3e-7, cacheWrite: 3.75e-6 }\n// Introductory pricing through August 31, 2026. Standard pricing from September\n// 1 is the same $3/M input and $15/M output as the other Sonnet models.\nconst sonnet5Cost = { input: 2e-6, output: 10e-6, cacheRead: 2e-7, cacheWrite: 2.5e-6 }\n// Opus 4.5+ standard pricing is $5/M in, $25/M out (the price cut at 4.5; held\n// through 4.6/4.7/4.8/5). Cache read 0.1x input, cache write 1.25x input.\nconst opusCost = { input: 5e-6, output: 25e-6, cacheRead: 0.5e-6, cacheWrite: 6.25e-6 }\n// Fable 5 and Mythos 5 are the Mythos-class tier above Opus and share pricing\n// ($10/M in, $50/M out). Cache read/write follow Anthropic's standard 0.1x / 1.25x\n// input ratios (not separately published).\nconst fableCost = { input: 10e-6, output: 50e-6, cacheRead: 1e-6, cacheWrite: 12.5e-6 }\n\n/**\n * Convert an OpenCodeModel to the flat config schema that OpenCode's\n * provider.ts config parser expects (model.temperature, model.reasoning,\n * model.cost.cache_read, model.modalities, etc.).\n */\nexport function toConfigModel(model: OpenCodeModel): Record<string, unknown> {\n const inputMods: string[] = []\n const outputMods: string[] = []\n for (const [k, v] of Object.entries(model.capabilities.input)) {\n if (v) inputMods.push(k)\n }\n for (const [k, v] of Object.entries(model.capabilities.output)) {\n if (v) outputMods.push(k)\n }\n\n return {\n id: model.api.id,\n name: model.name,\n status: model.status,\n family: model.family ?? \"\",\n release_date: model.release_date,\n\n temperature: model.capabilities.temperature,\n reasoning: model.capabilities.reasoning,\n attachment: model.capabilities.attachment,\n tool_call: model.capabilities.toolcall,\n modalities: { input: inputMods, output: outputMods },\n\n cost: {\n input: model.cost.input,\n output: model.cost.output,\n cache_read: model.cost.cache.read,\n cache_write: model.cost.cache.write,\n },\n\n limit: model.limit,\n options: model.options,\n headers: model.headers,\n variants: model.variants,\n }\n}\n\nexport const defaultModels: Record<string, OpenCodeModel> = {\n \"claude-haiku-4-5\": defineModel({\n id: \"claude-haiku-4-5\",\n name: \"Claude Haiku 4.5\",\n family: \"haiku\",\n reasoning: false,\n context: 200_000,\n output: 64_000,\n cost: haikuCost,\n multiplier: 1,\n releaseDate: \"2025-10-01\",\n }),\n \"claude-sonnet-4-5\": defineModel({\n id: \"claude-sonnet-4-5\",\n name: \"Claude Sonnet 4.5\",\n family: \"sonnet\",\n reasoning: true,\n context: 200_000,\n output: 64_000,\n cost: sonnetCost,\n multiplier: 3,\n releaseDate: \"2025-09-29\",\n }),\n \"claude-sonnet-4-6\": defineModel({\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n family: \"sonnet\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: sonnetCost,\n multiplier: 3,\n releaseDate: \"2025-06-19\",\n }),\n \"claude-sonnet-5\": defineModel({\n id: \"claude-sonnet-5\",\n name: \"Claude Sonnet 5\",\n family: \"sonnet\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: sonnet5Cost,\n multiplier: 2,\n releaseDate: \"2026-06-30\",\n }),\n \"claude-opus-4-5\": defineModel({\n id: \"claude-opus-4-5\",\n name: \"Claude Opus 4.5\",\n family: \"opus\",\n reasoning: true,\n context: 200_000,\n output: 64_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-11-01\",\n }),\n \"claude-opus-4-6\": defineModel({\n id: \"claude-opus-4-6\",\n name: \"Claude Opus 4.6\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-06-19\",\n }),\n \"claude-opus-4-7\": defineModel({\n id: \"claude-opus-4-7\",\n name: \"Claude Opus 4.7\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-07-16\",\n }),\n \"claude-opus-4-8\": defineModel({\n id: \"claude-opus-4-8\",\n name: \"Claude Opus 4.8\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2026-05-28\",\n }),\n \"claude-opus-5\": defineModel({\n id: \"claude-opus-5\",\n name: \"Claude Opus 5\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2026-07-24\",\n }),\n \"claude-fable-5\": defineModel({\n id: \"claude-fable-5\",\n name: \"Claude Fable 5\",\n family: \"fable\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: fableCost,\n multiplier: 10,\n releaseDate: \"2026-06-09\",\n }),\n // Mythos 5 shares Fable 5's capabilities and pricing without the safety\n // classifiers; limited availability via Project Glasswing. `claude --model\n // claude-mythos-5` simply errors for accounts without access, so it's safe to\n // register unconditionally.\n \"claude-mythos-5\": defineModel({\n id: \"claude-mythos-5\",\n name: \"Claude Mythos 5\",\n family: \"mythos\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: fableCost,\n multiplier: 10,\n releaseDate: \"2026-06-09\",\n }),\n}\n","import { chmod, lstat, mkdir, readlink, symlink, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { log } from \"./logger.js\"\n\nexport const BASE_PROVIDER_ID = \"claude-code\"\nexport const DEFAULT_ACCOUNT = \"default\"\n\nconst SHARED_CAPABILITY_ITEMS = [\n \"CLAUDE.md\",\n \"settings.json\",\n \"skills\",\n \"agents\",\n \"commands\",\n \"plugins\",\n]\n\nexport function normalizeAccountName(account: string): string {\n return account\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n}\n\nexport function resolveAccounts(value: unknown): string[] | null {\n if (!Array.isArray(value)) return null\n\n const accounts = value\n .map((account) => normalizeAccountName(String(account)))\n .filter(Boolean)\n\n return Array.from(new Set([DEFAULT_ACCOUNT, ...accounts]))\n}\n\nexport function accountProviderId(account: string): string {\n return `${BASE_PROVIDER_ID}-${normalizeAccountName(account)}`\n}\n\nexport function accountDisplayName(account: string): string {\n return `Claude Code (${titleizeAccount(account)})`\n}\n\nexport function accountModelSuffix(account: string): string | undefined {\n const normalized = normalizeAccountName(account)\n return normalized === DEFAULT_ACCOUNT ? undefined : normalized\n}\n\nexport function accountConfigDir(account: string): string | undefined {\n const normalized = normalizeAccountName(account)\n\n if (!normalized || normalized === DEFAULT_ACCOUNT) return undefined\n\n return `~/.claude-${normalized}`\n}\n\nexport function expandHome(value: string): string {\n const home = process.env.HOME ?? process.env.USERPROFILE\n\n if (value === \"~\") return home ?? value\n\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return home ? path.join(home, value.slice(2)) : value\n }\n\n return value\n}\n\nexport async function ensureAccountRuntime(\n account: string,\n baseCliPath: string,\n): Promise<{ cliPath: string; configDir?: string }> {\n const configDir = accountConfigDir(account)\n\n if (!configDir) return { cliPath: baseCliPath }\n\n const expandedConfigDir = expandHome(configDir)\n await mkdir(expandedConfigDir, { recursive: true })\n\n try {\n await ensureSharedCapabilities(expandedConfigDir)\n } catch (err) {\n log.warn(\"failed to symlink shared capabilities; continuing anyway\", {\n account,\n configDir: expandedConfigDir,\n error: String(err),\n })\n }\n\n const cliPath = await writeAccountWrapper(\n normalizeAccountName(account),\n baseCliPath,\n expandedConfigDir,\n )\n\n return { cliPath, configDir: expandedConfigDir }\n}\n\nasync function ensureSharedCapabilities(targetRoot: string): Promise<void> {\n const sourceRoot = expandHome(\"~/.claude\")\n\n for (const item of SHARED_CAPABILITY_ITEMS) {\n await ensureSharedCapabilityItem(sourceRoot, targetRoot, item)\n }\n}\n\nasync function ensureSharedCapabilityItem(\n sourceRoot: string,\n targetRoot: string,\n item: string,\n): Promise<void> {\n const source = path.join(sourceRoot, item)\n const target = path.join(targetRoot, item)\n\n let sourceStat\n try {\n sourceStat = await lstat(source)\n } catch {\n return\n }\n\n try {\n const targetStat = await lstat(target)\n\n if (targetStat.isSymbolicLink()) {\n const current = await readlink(target)\n const resolvedCurrent = path.resolve(path.dirname(target), current)\n const resolvedSource = path.resolve(source)\n\n if (resolvedCurrent === resolvedSource) return\n }\n\n log.warn(\"shared Claude capability already exists; leaving untouched\", {\n item,\n target,\n source,\n })\n\n return\n } catch {\n // Missing target is expected.\n }\n\n const type = sourceStat.isDirectory()\n ? process.platform === \"win32\"\n ? \"junction\"\n : \"dir\"\n : \"file\"\n\n await symlink(source, target, type)\n}\n\nasync function writeAccountWrapper(\n account: string,\n baseCliPath: string,\n configDir: string,\n): Promise<string> {\n const cacheRoot = path.join(\n process.env.XDG_CACHE_HOME ?? expandHome(\"~/.cache\"),\n \"opencode-claude-code-plugin\",\n )\n const wrapperPath = path.join(cacheRoot, `claude-${account}`)\n const suffix = `@${account}`\n\n await mkdir(cacheRoot, { recursive: true })\n\n const script = `#!/usr/bin/env bash\nset -euo pipefail\n\nargs=()\nwhile [[ $# -gt 0 ]]; do\n if [[ \"$1\" == \"--model\" && $# -ge 2 ]]; then\n model=\"$2\"\n if [[ \"$model\" == *${shellDoubleQuote(suffix)} ]]; then\n model=\"\\${model%${shellDoubleQuote(suffix)}}\"\n fi\n args+=(\"$1\" \"$model\")\n shift 2\n else\n args+=(\"$1\")\n shift\n fi\ndone\n\nexport CLAUDE_CONFIG_DIR=${shellSingleQuote(configDir)}\nexec ${shellSingleQuote(baseCliPath)} \"\\${args[@]}\"\n`\n\n await writeFile(wrapperPath, script, \"utf8\")\n await chmod(wrapperPath, 0o755)\n\n return wrapperPath\n}\n\nfunction shellSingleQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n\nfunction shellDoubleQuote(value: string): string {\n return value.replace(/[$`\"\\\\]/g, \"\\\\$&\")\n}\n\nfunction titleizeAccount(account: string): string {\n return normalizeAccountName(account)\n .split(\"-\")\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \")\n}\n","// Removes a stale unscoped `opencode-claude-code-plugin` install left in\n// opencode's plugin cache by older configs. The unscoped name is a different\n// artifact than this scoped plugin and shadows it when both coexist.\n// Disable with OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP=1.\n\nimport {\n existsSync,\n readFileSync,\n realpathSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { log } from \"./logger.js\"\n\nconst STALE_PACKAGE_NAME = \"opencode-claude-code-plugin\"\nconst SUSPECT_DESCRIPTION_TOKEN = \"Claude Code\"\n\nlet alreadyRan = false\n\nfunction candidateCacheRoots(): string[] {\n const xdg = process.env.XDG_CACHE_HOME\n return [\n xdg ? join(xdg, \"opencode\") : null,\n join(homedir(), \".cache\", \"opencode\"),\n join(homedir(), \"Library\", \"Caches\", \"opencode\"),\n ].filter((p): p is string => Boolean(p))\n}\n\nfunction userOpencodeJsonPath(): string {\n const xdgConfig = process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\")\n return join(xdgConfig, \"opencode\", \"opencode.json\")\n}\n\nfunction userIntendsToUseUnscoped(): boolean {\n const cfg = userOpencodeJsonPath()\n if (!existsSync(cfg)) return false\n try {\n const json = JSON.parse(readFileSync(cfg, \"utf8\"))\n const plugins: unknown = json.plugin\n if (!Array.isArray(plugins)) return false\n return plugins.some(\n (entry) =>\n typeof entry === \"string\" &&\n /^opencode-claude-code-plugin(@[^/]+)?$/.test(entry),\n )\n } catch {\n return false\n }\n}\n\nfunction ourLoadedDir(): string | null {\n try {\n const filePath = fileURLToPath(import.meta.url)\n return realpathSync(resolve(filePath, \"..\", \"..\"))\n } catch {\n return null\n }\n}\n\nexport function cleanupStaleUnscopedInstall(): void {\n if (alreadyRan) return\n alreadyRan = true\n\n if (process.env.OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP === \"1\") return\n if (userIntendsToUseUnscoped()) return\n\n const ourDir = ourLoadedDir()\n\n for (const cacheRoot of candidateCacheRoots()) {\n try {\n cleanupOne(cacheRoot, ourDir)\n } catch (err) {\n log.warn(\"cleanup-stale: error processing cache root\", {\n cacheRoot,\n error: String(err),\n })\n }\n }\n}\n\nfunction cleanupOne(cacheRoot: string, ourDir: string | null): void {\n if (!existsSync(cacheRoot)) return\n\n const stalePath = join(cacheRoot, \"node_modules\", STALE_PACKAGE_NAME)\n if (!existsSync(stalePath)) return\n\n // Don't self-delete if we are the unscoped install.\n let realStalePath = stalePath\n try {\n realStalePath = realpathSync(stalePath)\n } catch {\n // ignore\n }\n if (ourDir && realStalePath === ourDir) return\n\n // Verify identity before removing.\n const pkgJsonPath = join(stalePath, \"package.json\")\n if (!existsSync(pkgJsonPath)) return\n let pkg: { name?: string; description?: string } = {}\n try {\n pkg = JSON.parse(readFileSync(pkgJsonPath, \"utf8\"))\n } catch {\n return\n }\n if (pkg.name !== STALE_PACKAGE_NAME) return\n if (!pkg.description?.includes(SUSPECT_DESCRIPTION_TOKEN)) return\n\n log.info(\"cleanup-stale: removing unscoped install\", { stalePath })\n try {\n rmSync(stalePath, { recursive: true, force: true })\n } catch (err) {\n log.warn(\"cleanup-stale: rmSync failed\", {\n stalePath,\n error: String(err),\n })\n return\n }\n\n // Drop the dep from the cache root's package.json so opencode's installer\n // doesn't reinstate it on its next pass. Lockfile is left alone; bun\n // reconciles against package.json on the next install.\n const cachePkgJson = join(cacheRoot, \"package.json\")\n if (!existsSync(cachePkgJson)) return\n try {\n const cfg = JSON.parse(readFileSync(cachePkgJson, \"utf8\"))\n if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {\n delete cfg.dependencies[STALE_PACKAGE_NAME]\n writeFileSync(cachePkgJson, JSON.stringify(cfg, null, 2) + \"\\n\")\n log.info(\"cleanup-stale: pruned dep from cache package.json\")\n }\n } catch (err) {\n log.warn(\"cleanup-stale: cache package.json update failed\", {\n error: String(err),\n })\n }\n}\n","import { execFile } from \"node:child_process\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { detectCliVersion } from \"./cli-version.js\"\nimport { log } from \"./logger.js\"\nimport { mergeOpencodeMcp } from \"./mcp-bridge.js\"\nimport { getOpencodeProjectDirectory, isUsableDirectory } from \"./runtime-status.js\"\n\n/**\n * One compact status block logged once per process, right after providers are\n * registered. Every field here answers a question that previously cost a live\n * debugging session: which plugin build is loaded, whether the Claude CLI is\n * even reachable, which cwd the spawn will use and why, what is proxied, and\n * how many MCP servers the bridge sees. Keep it cheap and never let it throw:\n * diagnostics must not be able to break provider registration.\n */\nexport interface StartupDiagnostics {\n plugin: string\n opencode: string\n claudeCli: { path: string; version: string }\n cwd: { resolved: string; source: CwdSource }\n providers: string[]\n accounts: string[]\n proxyTools: string[]\n mcpServers: string[]\n interactiveTransport: boolean\n /** ExitPlanMode approval routed through opencode's `question` tool. */\n planModeQuestion: boolean\n anthropicApiKeyInEnv: boolean\n}\n\n/** Which branch of `resolveSpawnCwd` a Claude CLI spawn would take right now. */\nexport type CwdSource = \"configured\" | \"process\" | \"captured\" | \"unresolved\"\n\nexport interface DiagnosticsProviderEntry {\n name?: string\n options?: Record<string, unknown>\n}\n\nlet cachedPluginVersion: string | undefined\n\n/** Version of this plugin, read from the package manifest one level up. */\nexport function pluginVersion(): string {\n if (cachedPluginVersion) return cachedPluginVersion\n try {\n const here = path.dirname(fileURLToPath(import.meta.url))\n const raw = fs.readFileSync(path.join(here, \"..\", \"package.json\"), \"utf8\")\n const version = (JSON.parse(raw) as { version?: unknown }).version\n cachedPluginVersion = typeof version === \"string\" ? version : \"unknown\"\n } catch {\n cachedPluginVersion = \"unknown\"\n }\n return cachedPluginVersion\n}\n\n/**\n * Best-effort opencode version from the plugin input. Re-verified on opencode\n * 1.18.5: nothing on the plugin surface carries it. `PluginInput` has no\n * version field, the SDK client's `app` namespace exposes only `log`/`agents`,\n * and the server has no `/version` route. So this probes a couple of plausible\n * shapes for future opencode releases and otherwise returns undefined, leaving\n * the binary probe (`detectOpencodeVersion`) as the fallback. Do not replace it\n * with a `client.app.get()` call — that method does not exist.\n */\nexport function pickOpencodeVersion(input: unknown): string | undefined {\n if (!input || typeof input !== \"object\") return undefined\n const app = (input as { app?: unknown }).app\n if (app && typeof app === \"object\") {\n const version = (app as { version?: unknown }).version\n if (typeof version === \"string\" && version.length > 0) return version\n }\n const direct = (input as { version?: unknown }).version\n if (typeof direct === \"string\" && direct.length > 0) return direct\n return undefined\n}\n\nconst execFileAsync = promisify(execFile)\n\nlet opencodeVersionProbe: Promise<string | undefined> | undefined\n\n/**\n * The plugin runs *inside* opencode's process, so `process.execPath` is the\n * opencode binary itself — asking it for `--version` is the only reliable way\n * to name the version, since the plugin API exposes it nowhere (see\n * `pickOpencodeVersion`). Guarded on the basename: when opencode is run from\n * source (`bun run packages/opencode/src/index.ts`) execPath is the Bun binary,\n * and reporting Bun's version as opencode's would be worse than \"unknown\".\n * Cached, 5s timeout, never throws.\n */\nexport function detectOpencodeVersion(\n execPath: string = process.execPath,\n): Promise<string | undefined> {\n if (opencodeVersionProbe) return opencodeVersionProbe\n opencodeVersionProbe = (async (): Promise<string | undefined> => {\n if (!path.basename(execPath).toLowerCase().includes(\"opencode\")) {\n log.debug(\"skipping opencode version probe: execPath is not opencode\", { execPath })\n return undefined\n }\n try {\n const { stdout } = await execFileAsync(execPath, [\"--version\"], { timeout: 5000 })\n const match = /\\d+\\.\\d+\\.\\d+\\S*/.exec(stdout.trim())\n return match ? match[0] : undefined\n } catch (err) {\n log.debug(\"opencode version probe failed\", {\n execPath,\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n })()\n return opencodeVersionProbe\n}\n\n/** Test seam: drop the cached probe so a fresh execPath is honored. */\nexport function resetOpencodeVersionProbe(): void {\n opencodeVersionProbe = undefined\n}\n\n/**\n * Mirror of `resolveSpawnCwd`'s priority order, but reporting *which* branch\n * won. `configured` means `options.cwd` pinned it, `process` is the normal\n * lazy path, `captured` means `process.cwd()` was unusable (macOS GUI launch\n * at `/`) and the captured project directory rescued it — that one is the\n * fingerprint of issue #4.\n */\nexport function describeSpawnCwd(\n configured: unknown,\n live: string = process.cwd(),\n captured: string | undefined = getOpencodeProjectDirectory(),\n): { resolved: string; source: CwdSource } {\n if (typeof configured === \"string\" && configured.length > 0) {\n return { resolved: configured, source: \"configured\" }\n }\n if (isUsableDirectory(live)) return { resolved: live, source: \"process\" }\n if (isUsableDirectory(captured)) return { resolved: captured, source: \"captured\" }\n return { resolved: live, source: \"unresolved\" }\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value.filter((entry): entry is string => typeof entry === \"string\")\n}\n\nfunction firstOption(\n providers: Record<string, DiagnosticsProviderEntry>,\n key: string,\n): unknown {\n for (const entry of Object.values(providers)) {\n const value = entry?.options?.[key]\n if (value !== undefined) return value\n }\n return undefined\n}\n\nexport function collectStartupDiagnostics(\n providers: Record<string, DiagnosticsProviderEntry>,\n opencodeVersion?: string,\n): Omit<StartupDiagnostics, \"claudeCli\"> & { claudeCliPath: string } {\n const accounts: string[] = []\n for (const entry of Object.values(providers)) {\n const account = entry?.options?.account\n if (typeof account === \"string\" && account.length > 0) accounts.push(account)\n }\n\n const cwd = describeSpawnCwd(firstOption(providers, \"cwd\"))\n\n let mcpServers: string[] = []\n try {\n // Disk-only view: opencode's runtime MCP status isn't settled at plugin\n // init (servers are still connecting), so the per-turn overlay is not\n // applied here. This is what the bridge would ship on a cold start.\n mcpServers = mergeOpencodeMcp(cwd.resolved).enabledServerNames\n } catch (err) {\n log.debug(\"startup diagnostics could not read MCP config\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n\n return {\n plugin: pluginVersion(),\n opencode: opencodeVersion ?? process.env.OPENCODE_VERSION ?? \"unknown\",\n claudeCliPath: String(firstOption(providers, \"cliPath\") ?? \"claude\"),\n cwd,\n providers: Object.keys(providers),\n accounts,\n proxyTools: stringList(firstOption(providers, \"proxyTools\")),\n mcpServers,\n interactiveTransport:\n firstOption(providers, \"interactive\") === true ||\n process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT === \"1\",\n planModeQuestion: firstOption(providers, \"planModeQuestion\") === true,\n anthropicApiKeyInEnv: Boolean(\n process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN,\n ),\n }\n}\n\nlet logged = false\n\n/**\n * Emit the startup block once per process. Fire-and-forget: the Claude CLI\n * version probe is async (`claude --version`, 5s timeout, cached), and a slow\n * or missing binary must never delay provider registration.\n */\nexport function logStartupDiagnostics(\n providers: Record<string, DiagnosticsProviderEntry>,\n opencodeVersion?: string,\n): void {\n if (logged) return\n logged = true\n void (async () => {\n try {\n // Probe the binary only when the plugin input and env gave us nothing,\n // so a future opencode that reports its version costs no spawn.\n const version =\n opencodeVersion ?? process.env.OPENCODE_VERSION ?? (await detectOpencodeVersion())\n const { claudeCliPath, ...rest } = collectStartupDiagnostics(providers, version)\n const cli = await detectCliVersion(claudeCliPath)\n const diagnostics: StartupDiagnostics = {\n ...rest,\n claudeCli: { path: claudeCliPath, version: cli?.raw ?? \"not detected\" },\n }\n log.notice(\"claude-code plugin ready\", { ...diagnostics })\n } catch (err) {\n log.debug(\"startup diagnostics failed\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n })()\n}\n\n/** For tests. */\nexport function _resetStartupDiagnostics(): void {\n logged = false\n}\n","import type { LanguageModelV3 } from \"@ai-sdk/provider\"\nimport { ClaudeCodeLanguageModel } from \"./claude-code-language-model.js\"\nimport { defaultModels, toConfigModel } from \"./models.js\"\nimport type { OpenCodeModel, OpenCodePlugin, OpenCodeProvider } from \"./opencode-types.js\"\nimport type { ClaudeCodeProviderSettings } from \"./types.js\"\nimport {\n BASE_PROVIDER_ID,\n accountDisplayName,\n accountModelSuffix,\n accountProviderId,\n ensureAccountRuntime,\n resolveAccounts,\n} from \"./accounts.js\"\nimport { cleanupStaleUnscopedInstall } from \"./cleanup-stale.js\"\nimport { configureLogger, log } from \"./logger.js\"\nimport {\n isUsableDirectory,\n setOpencodeClient,\n setOpencodeProjectDirectory,\n} from \"./runtime-status.js\"\nimport {\n logStartupDiagnostics,\n pickOpencodeVersion,\n type DiagnosticsProviderEntry,\n} from \"./startup-diagnostics.js\"\n\nexport interface ClaudeCodeProvider {\n specificationVersion: \"v3\"\n (modelId: string): LanguageModelV3\n languageModel(modelId: string): LanguageModelV3\n}\n\n// Picks the best directory from opencode's plugin context (`directory` /\n// `worktree`). Result is handed to runtime-status so it's available as a\n// *fallback* at spawn time only when `process.cwd()` is unusable (macOS\n// GUI launches at `/`). Never baked into provider config — see #4.\nfunction pickOpencodeDirectory(input: unknown): string | undefined {\n if (!input || typeof input !== \"object\") return undefined\n const ctx = input as { directory?: unknown; worktree?: unknown }\n if (isUsableDirectory(ctx.directory)) return ctx.directory\n if (isUsableDirectory(ctx.worktree)) return ctx.worktree\n return undefined\n}\n\nlet warnedAnthropicApiKey = false\n\n// `Question` is deliberately absent: enabling it disables Claude Code's\n// built-in AskUserQuestion (via --disallowedTools) and replaces the\n// stop-and-wait deny/markdown path with an in-turn blocking form. That is a\n// behavior trade against the issue-#8 guarantee, so it stays opt-in until it\n// has the same live mileage Task had before v0.10.0 flipped it on. Users opt\n// in by listing it in `proxyTools`; see README \"Question proxy tool\".\nconst DEFAULT_PROXY_TOOL_NAMES = [\n \"Bash\",\n \"Edit\",\n \"Write\",\n \"WebFetch\",\n \"Task\",\n]\n\n// One-time heads-up: an API key in the environment makes Claude Code bill\n// pay-as-you-go (Console) instead of the logged-in Pro/Max subscription, which\n// silently bypasses the Agent SDK plan credit. Surfaced once per process.\nfunction warnIfAnthropicApiKey(ignore: boolean | undefined): void {\n if (warnedAnthropicApiKey) return\n if (!process.env.ANTHROPIC_API_KEY && !process.env.ANTHROPIC_AUTH_TOKEN) return\n warnedAnthropicApiKey = true\n if (ignore) {\n log.warn(\n \"ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN detected; stripping it from claude spawns (ignoreAnthropicApiKey) so requests use your subscription auth, not pay-as-you-go API billing.\",\n )\n } else {\n log.warn(\n \"ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN detected; claude may bill as pay-as-you-go API usage instead of your subscription / Agent SDK credit. Set provider option `ignoreAnthropicApiKey: true` to force subscription auth.\",\n )\n }\n}\n\nexport function createClaudeCode(\n settings: ClaudeCodeProviderSettings = {},\n): ClaudeCodeProvider {\n if (settings.logging) {\n configureLogger({\n file: settings.logging.file ?? false,\n dir: settings.logging.dir ?? null,\n mode: settings.logging.mode ?? \"silent\",\n level: settings.logging.level ?? \"info\",\n })\n }\n warnIfAnthropicApiKey(settings.ignoreAnthropicApiKey)\n const cliPath =\n settings.cliPath ?? process.env.CLAUDE_CLI_PATH ?? \"claude\"\n const providerName = settings.providerID ?? settings.name ?? \"claude-code\"\n const proxyTools = settings.proxyTools ?? [...DEFAULT_PROXY_TOOL_NAMES]\n\n const createModel = (modelId: string): LanguageModelV3 => {\n return new ClaudeCodeLanguageModel(modelId, {\n provider: providerName,\n cliPath,\n cwd: settings.cwd,\n account: settings.account,\n configDir: settings.configDir,\n providerID: settings.providerID,\n skipPermissions: settings.skipPermissions ?? true,\n permissionMode: settings.permissionMode,\n mcpConfig: settings.mcpConfig,\n strictMcpConfig: settings.strictMcpConfig,\n bridgeOpencodeMcp: settings.bridgeOpencodeMcp ?? true,\n controlRequestBehavior: settings.controlRequestBehavior ?? \"allow\",\n controlRequestToolBehaviors: settings.controlRequestToolBehaviors,\n controlRequestDenyMessage: settings.controlRequestDenyMessage,\n proxyTools,\n proxyToolTimeoutMs: settings.proxyToolTimeoutMs,\n planModeQuestion: settings.planModeQuestion ?? false,\n webSearch: settings.webSearch,\n hotReloadMcp: settings.hotReloadMcp ?? true,\n proxyOpencodeMcpTools: settings.proxyOpencodeMcpTools ?? true,\n multiStepContinuation: settings.multiStepContinuation ?? true,\n autoContinueIncompleteTurns:\n settings.autoContinueIncompleteTurns ?? \"smart\",\n compactionModel: settings.compactionModel,\n ignoreAnthropicApiKey: settings.ignoreAnthropicApiKey,\n interactive: settings.interactive,\n interactiveBypass: settings.interactiveBypass,\n interactiveAllowTools: settings.interactiveAllowTools,\n interactiveSystemPrompt: settings.interactiveSystemPrompt,\n })\n }\n\n const provider = function (modelId: string) {\n return createModel(modelId)\n } as ClaudeCodeProvider\n\n provider.specificationVersion = \"v3\"\n provider.languageModel = createModel\n\n return provider\n}\n\n// ---------------------------------------------------------------------------\n// OpenCode plugin interface\n// ---------------------------------------------------------------------------\n\nconst PROVIDER_ID = BASE_PROVIDER_ID\nconst PACKAGE_NPM = \"@khalilgharbaoui/opencode-claude-code-plugin\"\n\nfunction pluginEntrypoint(): string {\n return import.meta.url.startsWith(\"file:\") ? import.meta.url : PACKAGE_NPM\n}\n\nfunction cleanProviderOptions(\n options: Record<string, unknown> = {},\n): Record<string, unknown> {\n const result = { ...options }\n delete result.accounts\n return result\n}\n\nfunction defaultModelsForProvider(\n providerModels: OpenCodeProvider[\"models\"],\n providerID = PROVIDER_ID,\n modelSuffix?: string,\n) {\n const models = Object.fromEntries(\n Object.entries(defaultModels).map(([id, model]) => {\n const modelId = modelSuffix ? `${id}@${modelSuffix}` : id\n const existing = providerModels[id] ?? providerModels[modelId]\n return [\n modelId,\n {\n ...model,\n id: modelId,\n providerID,\n api: {\n ...model.api,\n id: modelId,\n npm: existing?.api?.npm ?? model.api.npm,\n url: existing?.api?.url ?? model.api.url,\n },\n },\n ]\n }),\n )\n\n for (const [id, model] of Object.entries(providerModels)) {\n if (!(id in models)) {\n models[id] = {\n ...model,\n providerID,\n }\n }\n }\n\n return models\n}\n\n/**\n * Build models in OpenCode's config schema format (flat properties like\n * `temperature`, `reasoning`, `cost.cache_read`, `modalities`, etc.)\n * so the config-path provider loader parses them correctly.\n */\nexport function configModelsForProvider(\n providerModels: OpenCodeProvider[\"models\"],\n providerID: string,\n modelSuffix?: string,\n): Record<string, Record<string, unknown>> {\n const models: Record<string, Record<string, unknown>> = {}\n\n for (const [id, model] of Object.entries(defaultModels)) {\n const modelId = modelSuffix ? `${id}@${modelSuffix}` : id\n const existing = providerModels[id] ?? providerModels[modelId]\n const existingVariants =\n existing && typeof (existing as { variants?: unknown }).variants === \"object\"\n ? ((existing as { variants?: Record<string, Record<string, unknown>> }).variants ?? {})\n : {}\n const full: OpenCodeModel = {\n ...model,\n id: modelId,\n providerID,\n api: {\n ...model.api,\n id: modelId,\n npm: existing?.api?.npm ?? model.api.npm,\n url: existing?.api?.url ?? model.api.url,\n },\n variants: {\n ...(model.variants ?? {}),\n ...existingVariants,\n },\n }\n models[modelId] = toConfigModel(full)\n }\n\n for (const [id, model] of Object.entries(providerModels)) {\n if (!(id in models)) {\n models[id] = toConfigModel({ ...model, providerID } as OpenCodeModel)\n }\n }\n\n return models\n}\n\nasync function providerConfig(\n existing: {\n name?: string\n npm?: string\n options?: Record<string, unknown>\n models?: Record<string, unknown>\n } | undefined,\n providerID = PROVIDER_ID,\n optionDefaults: Record<string, unknown> = {},\n displayName?: string,\n) {\n const mergedOptions: Record<string, unknown> = {\n cliPath: \"claude\",\n proxyTools: [...DEFAULT_PROXY_TOOL_NAMES],\n ...optionDefaults,\n ...cleanProviderOptions(existing?.options),\n providerID,\n }\n\n const cliPath = String(mergedOptions.cliPath ?? \"claude\")\n const account =\n typeof mergedOptions.account === \"string\" ? mergedOptions.account : undefined\n const runtime = account\n ? await ensureAccountRuntime(account, cliPath)\n : { cliPath }\n\n return {\n name: displayName ?? existing?.name,\n npm: existing?.npm ?? pluginEntrypoint(),\n options: {\n ...mergedOptions,\n ...runtime,\n },\n // models is intentionally omitted: both callers overwrite it with\n // configModelsForProvider(), which emits the flat config schema\n // opencode's config-path loader parses (and merges user variants).\n }\n}\n\n/**\n * Narrow opencode's full provider map down to the ones this plugin owns\n * (`claude-code` plus every `claude-code-<account>` expansion) so startup\n * diagnostics never report another provider's options.\n */\nexport function claudeCodeProviders(\n providers: Record<string, DiagnosticsProviderEntry> | undefined,\n): Record<string, DiagnosticsProviderEntry> {\n const out: Record<string, DiagnosticsProviderEntry> = {}\n for (const [id, entry] of Object.entries(providers ?? {})) {\n if (id === PROVIDER_ID || id.startsWith(`${PROVIDER_ID}-`)) out[id] = entry\n }\n return out\n}\n\nasync function expandAccountProviders(config: {\n provider?: Record<\n string,\n {\n name?: string\n npm?: string\n options?: Record<string, unknown>\n models?: Record<string, unknown>\n }\n >\n}): Promise<boolean> {\n const seed = config.provider?.[PROVIDER_ID]\n const accounts = resolveAccounts(seed?.options?.accounts)\n\n if (!accounts) return false\n\n config.provider ??= {}\n\n const seedOptions = cleanProviderOptions(seed?.options)\n let expandedCount = 0\n\n for (const account of accounts) {\n const providerID = accountProviderId(account)\n try {\n const existing = config.provider[providerID]\n const modelSuffix = accountModelSuffix(account)\n\n config.provider[providerID] = {\n ...existing,\n ...(await providerConfig(\n existing,\n providerID,\n {\n ...seedOptions,\n account,\n },\n accountDisplayName(account),\n )),\n models: configModelsForProvider(\n (existing?.models ?? seed?.models ?? {}) as OpenCodeProvider[\"models\"],\n providerID,\n modelSuffix,\n ),\n }\n expandedCount++\n } catch (err) {\n log.error(\"failed to expand account provider\", {\n account,\n providerID,\n error: String(err),\n })\n }\n }\n\n if (expandedCount > 0) {\n delete config.provider[PROVIDER_ID]\n }\n\n return expandedCount > 0\n}\n\nconst server: OpenCodePlugin = async (input) => {\n cleanupStaleUnscopedInstall()\n\n const opencodeVersion = pickOpencodeVersion(input)\n\n // Capture the SDK client so the language model can query opencode's\n // in-memory MCP state per-turn for the runtime overlay. `input` is\n // `unknown` here (kept loose since opencode adds fields over time);\n // narrow defensively.\n if (input && typeof input === \"object\" && \"client\" in input) {\n setOpencodeClient((input as { client?: unknown }).client)\n }\n\n // Capture opencode's project-aware directory as a *fallback* used at\n // Claude CLI spawn time only when `process.cwd()` is unusable. Rescues\n // macOS GUI launches at `/` without freezing the value into provider\n // config, so opencode workspace switches mid-session still take effect.\n // See `resolveSpawnCwd` in runtime-status.ts and issue #4.\n setOpencodeProjectDirectory(pickOpencodeDirectory(input))\n\n return {\n config: async (config) => {\n config.provider ??= {}\n\n const expanded = await expandAccountProviders(config)\n if (expanded) {\n logStartupDiagnostics(\n claudeCodeProviders(config.provider),\n opencodeVersion,\n )\n return\n }\n\n const existing = config.provider[PROVIDER_ID]\n config.provider[PROVIDER_ID] = {\n ...existing,\n ...(await providerConfig(existing)),\n models: configModelsForProvider(\n (existing?.models ?? {}) as OpenCodeProvider[\"models\"],\n PROVIDER_ID,\n ),\n }\n logStartupDiagnostics(\n claudeCodeProviders(config.provider),\n opencodeVersion,\n )\n },\n // No `event` hook: MCP config drift is detected at turn start by the\n // hot-reload check in `claude-code-language-model.ts`, which respawns\n // claude safely between turns. Eviction on `global.disposed` would kill\n // an in-flight stream and abort the user's current turn.\n provider: {\n id: PROVIDER_ID,\n models: async (provider) => defaultModelsForProvider(provider.models),\n },\n // Inject opencode's agent name into providerOptions so the language\n // model can distinguish /compact (and title) calls from normal turns.\n // Without this, every no-tools call looks like a title request and\n // gets short-circuited to a synthetic stub.\n \"chat.params\": async (input, output) => {\n const providerID = input.model?.providerID ?? input.provider?.info?.id\n // The hook fires for every provider opencode is configured with, not\n // just ours — keep this at debug to avoid log spam on non-claude-code\n // calls.\n log.debug(\"chat.params hook fired\", {\n agent: input.agent,\n providerID,\n sessionID: input.sessionID,\n })\n if (typeof providerID !== \"string\") return\n if (providerID !== PROVIDER_ID && !providerID.startsWith(`${PROVIDER_ID}-`)) return\n\n // Inject sessionID BEFORE the agent guard so session isolation works\n // even when input.agent is absent (older opencode, provider-switch\n // edge paths). resolveSessionAffinity reads this as a fallback when\n // the x-session-affinity header is missing.\n if (typeof input.sessionID === \"string\" && input.sessionID.length > 0) {\n output.options ??= {}\n ;(output.options as Record<string, unknown>).opencodeSessionID = input.sessionID\n }\n\n if (!input.agent) return\n // opencode wraps the entire `output.options` bag under the providerID\n // via ProviderTransform.providerOptions(model, options) → { [providerID]: options }\n // before handing it to the language model as `providerOptions`. So we\n // write fields at the TOP LEVEL of output.options, not nested under\n // providerID — otherwise the model sees providerOptions[id][id].opencodeAgent.\n output.options ??= {}\n ;(output.options as Record<string, unknown>).opencodeAgent = input.agent\n log.debug(\"chat.params tagged providerOptions\", {\n agent: input.agent,\n sessionID: input.sessionID,\n providerID,\n })\n },\n }\n}\n\nexport default {\n id: \"@khalilgharbaoui/opencode-claude-code-plugin\",\n server,\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { ClaudeCodeLanguageModel } from \"./claude-code-language-model.js\"\nexport { bridgeOpencodeMcp } from \"./mcp-bridge.js\"\nexport { defaultModels } from \"./models.js\"\nexport type {\n ClaudeCodeConfig,\n ClaudeCodeProviderSettings,\n ClaudeStreamMessage,\n} from \"./types.js\"\nexport type { OpenCodeHooks, OpenCodeModel, OpenCodePlugin } from \"./opencode-types.js\"\n"],"mappings":";AASA,SAAS,kBAAkB;;;ACT3B,SAAS,gBAAgB,WAAW,YAAY,gBAAgB;AAChE,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAY9B,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AACT;AAEA,IAAM,gBAAgB,IAAI,OAAO;AACjC,IAAM,cAAc,KAAK,QAAQ,GAAG,UAAU,SAAS,sBAAsB;AAE7E,IAAM,iBAA+B;AAAA,EACnC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACT;AAEA,SAAS,aAAa,GAA4C;AAChE,MAAI,KAAK,KAAM,QAAO;AACtB,QAAM,IAAI,EAAE,YAAY,EAAE,KAAK;AAC/B,MAAI,MAAM,GAAI,QAAO;AACrB,MAAI,MAAM,OAAO,MAAM,WAAW,MAAM,QAAQ,MAAM,MAAO,QAAO;AACpE,SAAO;AACT;AAEA,SAAS,cAAc,GAA6C;AAClE,MAAI,KAAK,KAAM,QAAO;AACtB,QAAM,IAAI,EAAE,YAAY,EAAE,KAAK;AAC/B,MAAI,MAAM,GAAI,QAAO;AACrB,MAAI,MAAM,WAAW,MAAM,UAAU,MAAM,YAAY,MAAM,UAAU,MAAM,SAAS;AACpF,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,GAA4C;AACzE,MAAI,KAAK,QAAQ,MAAM,GAAI,QAAO;AAClC,SAAO,EAAE,SAAS,sBAAsB,IAAI,UAAU;AACxD;AAEA,SAAS,iBAAiB,MAAkC;AAC1D,QAAM,SAAuB,EAAE,GAAG,KAAK;AACvC,QAAM,UAAU,aAAa,QAAQ,IAAI,6BAA6B;AACtE,MAAI,YAAY,OAAW,QAAO,OAAO;AACzC,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,WAAW,UAAa,WAAW,GAAI,QAAO,MAAM;AACxD,QAAM,UAAU,sBAAsB,QAAQ,IAAI,KAAK;AACvD,MAAI,YAAY,OAAW,QAAO,OAAO;AACzC,QAAM,WAAW,cAAc,QAAQ,IAAI,8BAA8B;AACzE,MAAI,aAAa,OAAW,QAAO,QAAQ;AAC3C,SAAO;AACT;AAEA,IAAI,eAA6B,iBAAiB,cAAc;AAChE,IAAI,sBAAsB;AAYnB,SAAS,gBAAgB,OAAoC;AAClE,QAAM,SAAuB,EAAE,GAAG,gBAAgB,GAAG,MAAM;AAC3D,iBAAe,iBAAiB,MAAM;AACtC,wBAAsB;AACxB;AAYA,SAAS,kBAA0B;AACjC,SAAO,KAAK,aAAa,OAAO,aAAa,YAAY;AAC3D;AAEA,SAAS,eAAe,SAAuB;AAC7C,MAAI;AACF,UAAM,OAAO,SAAS,OAAO;AAC7B,QAAI,KAAK,OAAO,eAAe;AAC7B,iBAAW,SAAS,GAAG,OAAO,IAAI;AAAA,IACpC;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,YAAY,MAAoB;AACvC,MAAI,CAAC,aAAa,KAAM;AACxB,MAAI,oBAAqB;AACzB,MAAI;AACF,UAAM,UAAU,gBAAgB;AAChC,cAAU,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C,mBAAe,OAAO;AACtB,mBAAe,SAAS,OAAO,MAAM,MAAM;AAAA,EAC7C,QAAQ;AAEN,0BAAsB;AAAA,EACxB;AACF;AAEA,SAAS,IAAI,OAAe,KAAa,MAAwC;AAC/E,QAAM,MAAK,oBAAI,KAAK,GAAE,YAAY;AAClC,QAAM,OAAO,IAAI,EAAE,4BAA4B,KAAK,KAAK,GAAG;AAC5D,MAAI,QAAQ,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AACxC,WAAO,GAAG,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAA0B;AAC5C,SAAO,WAAW,KAAK,KAAK,WAAW,aAAa,KAAK;AAC3D;AAEA,SAAS,UAAU,OAA0B;AAI3C,MAAI,UAAU,UAAU,UAAU,QAAS,QAAO;AAClD,SAAO,aAAa,SAAS;AAC/B;AAEA,SAAS,KAAK,OAAiB,KAAa,MAAsC;AAChF,MAAI,CAAC,WAAW,KAAK,EAAG;AACxB,QAAM,OAAO,IAAI,MAAM,YAAY,GAAG,KAAK,IAAI;AAC/C,MAAI,UAAU,KAAK,GAAG;AACpB,YAAQ,MAAM,IAAI;AAAA,EACpB;AACA,cAAY,IAAI;AAClB;AAEO,IAAM,MAAM;AAAA,EACjB,MAAM,KAAa,MAAgC;AACjD,SAAK,SAAS,KAAK,IAAI;AAAA,EACzB;AAAA,EACA,KAAK,KAAa,MAAgC;AAChD,SAAK,QAAQ,KAAK,IAAI;AAAA,EACxB;AAAA,EACA,OAAO,KAAa,MAAgC;AAClD,SAAK,UAAU,KAAK,IAAI;AAAA,EAC1B;AAAA,EACA,KAAK,KAAa,MAAgC;AAChD,SAAK,QAAQ,KAAK,IAAI;AAAA,EACxB;AAAA,EACA,MAAM,KAAa,MAAgC;AACjD,SAAK,SAAS,KAAK,IAAI;AAAA,EACzB;AACF;;;ACxJA,IAAM,UAAU,oBAAI,IAA2B;AAE/C,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,iBAA0C,oBAAI,IAAI,CAAC,WAAW,eAAe,WAAW,CAAC;AAE/F,SAAS,YAAY,WAAkC;AACrD,MAAI,SAAS,QAAQ,IAAI,SAAS;AAClC,MAAI,CAAC,QAAQ;AACX,aAAS,EAAE,OAAO,oBAAI,IAAI,GAAG,gBAAgB,oBAAI,IAAI,EAAE;AACvD,YAAQ,IAAI,WAAW,MAAM;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,aAAa,QAA6B;AACjD,QAAM,SAAS,KAAK,IAAI,IAAI;AAC5B,aAAW,CAAC,IAAI,OAAO,KAAK,OAAO,gBAAgB;AACjD,QAAI,QAAQ,YAAY,OAAQ,QAAO,eAAe,OAAO,EAAE;AAAA,EACjE;AACF;AAEA,SAAS,YAAY,QAAoC;AACvD,SAAO,MAAM,KAAK,OAAO,MAAM,OAAO,CAAC;AACzC;AAEA,SAAS,eAAe,OAAyE;AAC/F,QAAM,UAAU,OAAO,OAAO,YAAY,WAAW,MAAM,QAAQ,KAAK,IAAI;AAC5E,MAAI,QAAS,QAAO;AACpB,QAAM,cAAc,OAAO,OAAO,gBAAgB,WAAW,MAAM,YAAY,KAAK,IAAI;AACxF,MAAI,YAAa,QAAO;AACxB,SAAO;AACT;AAEO,SAAS,uBACd,WACA,WACA,OACM;AACN,MAAI,CAAC,aAAa,CAAC,UAAW;AAC9B,QAAM,SAAS,YAAY,SAAS;AACpC,eAAa,MAAM;AACnB,SAAO,eAAe,IAAI,WAAW;AAAA,IACnC,SAAS,eAAe,KAAK;AAAA,IAC7B,WAAW,KAAK,IAAI;AAAA,EACtB,CAAC;AACH;AAEO,SAAS,0BACd,WACA,WACA,YACoB;AACpB,MAAI,CAAC,aAAa,CAAC,UAAW,QAAO;AACrC,QAAM,SAAS,QAAQ,IAAI,SAAS;AACpC,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,UAAU,OAAO,eAAe,IAAI,SAAS;AACnD,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,eAAe,OAAO,SAAS;AACtC,QAAM,QAAQ,OAAO,eAAe,WAAW,WAAW,MAAM,oBAAoB,IAAI;AACxF,MAAI,CAAC,OAAO;AACV,QAAI,MAAM,mDAAmD,EAAE,WAAW,WAAW,WAAW,CAAC;AACjG,WAAO;AAAA,EACT;AACA,QAAM,WAAW,MAAM,CAAC;AACxB,MAAI,OAAO,MAAM,IAAI,QAAQ,GAAG;AAC9B,QAAI,MAAM,8DAA8D,EAAE,WAAW,SAAS,CAAC;AAAA,EACjG;AACA,SAAO,MAAM,IAAI,UAAU,EAAE,IAAI,UAAU,SAAS,QAAQ,SAAS,QAAQ,UAAU,CAAC;AACxF,SAAO,YAAY,MAAM;AAC3B;AAEO,SAAS,gBACd,WACA,OACoB;AACpB,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS,OAAO,OAAO,WAAW,WAAW,MAAM,SAAS;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,SAAS,QAAQ,IAAI,SAAS;AACpC,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,MAAM,IAAI,MAAM;AACrC,MAAI,CAAC,OAAO;AACV,QAAI,MAAM,kCAAkC,EAAE,WAAW,OAAO,CAAC;AACjE,WAAO;AAAA,EACT;AACA,MAAI,OAAO,WAAW,WAAW;AAC/B,WAAO,MAAM,OAAO,MAAM;AAC1B,WAAO,YAAY,MAAM;AAAA,EAC3B;AACA,MAAI,OAAO,OAAO,WAAW,YAAY,eAAe,IAAI,MAAM,MAAoB,GAAG;AACvF,UAAM,SAAS,MAAM;AAAA,EACvB;AACA,MAAI,OAAO,OAAO,YAAY,YAAY,MAAM,QAAQ,KAAK,EAAE,SAAS,GAAG;AACzE,UAAM,UAAU,MAAM,QAAQ,KAAK;AAAA,EACrC;AACA,SAAO,YAAY,MAAM;AAC3B;AAEO,SAAS,YAAY,WAAyB;AACnD,MAAI,CAAC,UAAW;AAChB,UAAQ,OAAO,SAAS;AAC1B;;;AC/GO,SAAS,gBAAgB,MAAuB;AACrD,SAAO,SAAS,eAAe,SAAS;AAC1C;AAQO,SAAS,wBAAwB,OAAmC;AACzE,SAAO,CAAC,SAAS,UAAU,YAAY,UAAU;AACnD;AAKA,SAAS,aAAa,MAAc,OAAiB;AACnD,MAAI,CAAC,MAAO,QAAO;AAEnB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,QACL,UAAU,MAAM,aAAa,MAAM;AAAA,QACnC,SAAS,MAAM;AAAA,MACjB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,UAAU,MAAM,aAAa,MAAM;AAAA,QACnC,WAAW,MAAM,cAAc,MAAM;AAAA,QACrC,WAAW,MAAM,cAAc,MAAM;AAAA,QACrC,YAAY,MAAM,eAAe,MAAM;AAAA,MACzC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,UAAU,MAAM,aAAa,MAAM;AAAA,QACnC,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM;AAAA,MACf;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,SAAS,MAAM;AAAA,QACf,aACE,MAAM,eACN,YAAY,OAAO,MAAM,WAAW,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,OAAO,MAAM,WAAW,EAAE,EAAE,SAAS,KAAK,QAAQ,EAAE;AAAA,QAC7G,SAAS,MAAM;AAAA,MACjB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,cAAc,MAAM,iBAAiB,MAAM;AAAA,QAC3C,YAAY,MAAM,eAAe,MAAM;AAAA,QACvC,WAAW,MAAM,cAAc,MAAM;AAAA,QACrC,UAAU,MAAM,aAAa,MAAM;AAAA,QACnC,UAAU,MAAM,aAAa,MAAM;AAAA,MACrC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA,MACd;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,MACjB;AAAA,IACF,KAAK;AACH,UAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC9B,cAAM,cAAc,MAAM,MAAM,IAAI,CAAC,MAAW,WAAmB;AAAA,UACjE,SAAS,KAAK;AAAA,UACd,QAAQ,KAAK,UAAU;AAAA,UACvB,UAAU,KAAK,YAAY;AAAA,UAC3B,IAAI,KAAK,MAAM,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK;AAAA,QAC5C,EAAE;AACF,eAAO,EAAE,OAAO,YAAY;AAAA,MAC9B;AACA,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAGA,IAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASD,IAAM,wBAAwB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,cAAc,OAAoB;AACzC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,OAAO,MAAM,IAAI,CAAC,UAAU;AAAA,QAC1B,IAAI,KAAK;AAAA,QACT,SAAS,KAAK;AAAA,QACd,QAAQ,KAAK;AAAA,QACb,UAAU;AAAA,MACZ,EAAE;AAAA,IACJ;AAAA,IACA,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,QACd,MACA,OACA,MACkE;AAElE,MAAI,sBAAsB,IAAI,IAAI,GAAG;AACnC,QAAI,MAAM,qCAAqC,EAAE,KAAK,CAAC;AACvD,WAAO,EAAE,MAAM,OAAO,UAAU,MAAM,MAAM,KAAK;AAAA,EACnD;AAKA,MAAI,SAAS,cAAc;AACzB,QAAI,MAAM,aAAa,MAAM,WAAW;AACtC,6BAAuB,KAAK,WAAW,KAAK,WAAW,KAAK;AAAA,IAC9D;AACA,WAAO,EAAE,MAAM,OAAO,UAAU,MAAM,MAAM,KAAK;AAAA,EACnD;AAKA,MAAI,SAAS,cAAc;AACzB,QAAI,MAAM,WAAW;AACnB,YAAM,OAAO,gBAAgB,KAAK,WAAW,KAAK;AAClD,UAAI,SAAS,KAAM,QAAO,cAAc,IAAI;AAAA,IAC9C;AACA,WAAO,EAAE,MAAM,OAAO,UAAU,MAAM,MAAM,KAAK;AAAA,EACnD;AAGA,MAAI,SAAS,gBAAiB,QAAO,EAAE,MAAM,cAAc,OAAO,CAAC,GAAG,UAAU,MAAM;AACtF,MAAI,SAAS,eAAgB,QAAO,EAAE,MAAM,aAAa,OAAO,UAAU,MAAM;AAKhF,MAAI,SAAS,aAAa;AACxB,UAAM,cAAc,aAAa,MAAM,KAAK;AAC5C,WAAO,EAAE,MAAM,aAAa,OAAO,aAAa,UAAU,MAAM;AAAA,EAClE;AAGA,MAAI,gBAAgB,IAAI,GAAG;AACzB,UAAM,cAAc,OAAO,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI;AAC5D,UAAM,QAAQ,MAAM;AACpB,QAAI,SAAS,UAAU,YAAY,UAAU,YAAY;AACvD,UAAI,MAAM,sCAAsC,EAAE,QAAQ,OAAO,YAAY,CAAC;AAC9E,aAAO,EAAE,MAAM,OAAO,OAAO,aAAa,UAAU,MAAM;AAAA,IAC5D;AAKA,QAAI,MAAM,oCAAoC,EAAE,YAAY,CAAC;AAC7D,WAAO,EAAE,MAAM,aAAa,OAAO,aAAa,UAAU,MAAM,MAAM,KAAK;AAAA,EAC7E;AAGA,MAAI,SAAS,cAAc;AACzB,QAAI,CAAC,MAAO,QAAO,EAAE,MAAM,QAAQ,UAAU,MAAM;AACnD,UAAM,SAAS,OAAO,WAAW,OAAO,UAAU,KAAK,UAAU,KAAK;AACtE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,QACL,SAAS,sBAAsB,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,CAAC;AAAA,QAClE,aAAa;AAAA,MACf;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAYA,MAAI,KAAK,WAAW,OAAO,GAAG;AAC5B,UAAM,QAAQ,KAAK,MAAM,CAAC,EAAE,MAAM,IAAI;AACtC,QAAI,MAAM,UAAU,GAAG;AACrB,YAAM,aAAa,MAAM,CAAC;AAC1B,YAAM,WAAW,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AACxC,YAAM,eAAe,GAAG,UAAU,IAAI,QAAQ;AAC9C,UAAI,MAAM,oBAAoB,EAAE,UAAU,MAAM,QAAQ,aAAa,CAAC;AACtE,aAAO,EAAE,MAAM,cAAc,OAAO,UAAU,KAAK;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,uBAAuB,IAAI,IAAI,GAAG;AACpC,UAAM,cAAc,aAAa,MAAM,KAAK;AAC5C,UAAM,eAAe,KAAK,YAAY;AACtC,QAAI,MAAM,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC7D,WAAO,EAAE,MAAM,cAAc,OAAO,aAAa,UAAU,KAAK;AAAA,EAClE;AAGA,SAAO,EAAE,MAAM,OAAO,UAAU,KAAK;AACvC;;;AC1OA,IAAM,oBAA4D;AAAA,EAChE,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AACP;AAEO,SAAS,iBAAiB,QAAyC;AACxE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,kBAAkB,MAAM,KAAK;AACtC;AAEA,IAAM,wBAAwB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,aAAa,MAAuB;AAC3C,QAAM,MAAe,KAAK,SAAS,KAAK,QAAQ,KAAK,OAAO,KAAK,QAAQ;AACzE,MAAI,CAAC,KAAK;AACR,QAAI,KAAK,kCAAkC;AAC3C,WAAO;AAAA,EACT;AAEA,MAAI,oBAA4B,KAAK,aAAa,KAAK,YAAY,KAAK,QAAQ;AAChF,MAAI,SAAwB;AAE5B,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI,IAAI,WAAW,OAAO,GAAG;AAC3B,YAAM,QAAQ,+CAA+C,KAAK,GAAG;AACrE,UAAI,CAAC,OAAO;AACV,YAAI,KAAK,wCAAwC;AACjD,eAAO;AAAA,MACT;AACA,0BAAoB,qBAAqB,MAAM,CAAC;AAChD,eAAS,MAAM,CAAC;AAAA,IAClB,WAAW,gBAAgB,KAAK,GAAG,GAAG;AACpC,UAAI,KAAK,6DAA6D;AACtE,aAAO;AAAA,IACT,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF,WAAW,eAAe,KAAK;AAC7B,QAAI,KAAK,6DAA6D;AACtE,WAAO;AAAA,EACT,WAAW,eAAe,cAAc,OAAO,SAAS,GAAG,GAAG;AAC5D,aAAS,OAAO,KAAK,GAAiB,EAAE,SAAS,QAAQ;AAAA,EAC3D,OAAO;AACL,QAAI,KAAK,mCAAmC,EAAE,UAAU,OAAO,IAAI,CAAC;AACpE,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,qBAAqB,CAAC,sBAAsB,IAAI,iBAAiB,GAAG;AACvE,QAAI,KAAK,2DAA2D;AAAA,MAClE,WAAW;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,EAAE,MAAM,UAAU,YAAY,mBAAmB,MAAM,OAAO;AAAA,EACxE;AACF;AAEA,SAAS,kBAAkB,MAAmB;AAC5C,QAAM,QAAQ,KAAK,UAAU,KAAK;AAElC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,MAAM,KAAK;AAAA,IAC3B,KAAK;AAAA,IACL,KAAK;AACH,aAAO,KAAK,UAAU,MAAM,KAAK;AAAA,IACnC,KAAK;AACH,aAAO,MAAM,SAAS,qBAAqB,MAAM,MAAM,KAAK;AAAA,IAC9D,KAAK;AACH,aAAO,MAAM,QAAQ,MAAM,KAAK,IAC5B,MAAM,MACH,IAAI,CAAC,SAAc;AAClB,YAAI,MAAM,SAAS,OAAQ,QAAO,KAAK;AACvC,eAAO,KAAK,UAAU,IAAI;AAAA,MAC5B,CAAC,EACA,KAAK,IAAI,IACZ,KAAK,UAAU,MAAM,KAAK;AAAA,IAChC;AACE,aAAO,KAAK,UAAU,KAAK;AAAA,EAC/B;AACF;AAMA,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAE7B,SAAS,eAAe,MAAc,KAAqB;AACzD,MAAI,KAAK,UAAU,IAAK,QAAO;AAC/B,SAAO,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC;AAAA,mBAAiB,KAAK,SAAS,GAAG;AAChE;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI;AACJ,MAAI;AACF,UAAM,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AAAA,EAChE,QAAQ;AACN,UAAM,OAAO,KAAK;AAAA,EACpB;AACA,SAAO,eAAe,KAAK,oBAAoB;AACjD;AAEA,SAAS,kCACP,KAC2C;AAC3C,QAAM,QAAkB,CAAC;AACzB,MAAI,kBAAkB;AAEtB,MAAI,OAAO,IAAI,YAAY,UAAU;AACnC,WAAO,EAAE,MAAM,IAAI,SAAS,iBAAiB,EAAE;AAAA,EACjD;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC/B,WAAO,EAAE,MAAM,IAAI,iBAAiB,EAAE;AAAA,EACxC;AAEA,aAAW,QAAQ,IAAI,SAAkB;AACvC,QAAI,CAAC,KAAM;AACX,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,YAAI,KAAK,KAAM,OAAM,KAAK,KAAK,IAAI;AACnC;AAAA,MACF,KAAK;AACH,cAAM;AAAA,UACJ,aAAa,KAAK,YAAY,SAAS,IAAI,gBAAgB,KAAK,KAAK,CAAC;AAAA,QACxE;AACA;AAAA,MACF,KAAK;AACH;AACA,cAAM;AAAA,UACJ,gBAAgB,KAAK,YAAY,KAAK,cAAc,SAAS;AAAA,EAAM;AAAA,YACjE,kBAAkB,IAAI;AAAA,YACtB;AAAA,UACF,CAAC;AAAA,QACH;AACA;AAAA,MACF,KAAK;AACH,cAAM;AAAA,UACJ,WAAW,KAAK,aAAa,KAAK,YAAY,SAAS;AAAA,QACzD;AACA;AAAA,MACF,KAAK;AACH,cAAM;AAAA,UACJ,UAAU,KAAK,aAAa,KAAK,YAAY,SAAS;AAAA,QACxD;AACA;AAAA,MACF,KAAK;AAGH;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,MAAM,KAAK,IAAI,GAAG,gBAAgB;AACnD;AAcO,SAAS,2BACd,QACA,OAAkD,CAAC,GACpC;AACf,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,SAAS,cAAc;AACzB,WAAO,uBAAuB,MAAM;AAAA,EACtC;AAEA,QAAM,uBAAuB,OAAO;AAAA,IAClC,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS;AAAA,EACzC;AAEA,MAAI,qBAAqB,UAAU,GAAG;AACpC,WAAO;AAAA,EACT;AAEA,QAAM,eAAyB,CAAC;AAEhC,WAAS,IAAI,GAAG,IAAI,qBAAqB,SAAS,GAAG,KAAK;AACxD,UAAM,MAAM,qBAAqB,CAAC;AAClC,UAAM,OAAO,IAAI,SAAS,SAAS,SAAS;AAE5C,QAAI,OAAO;AACX,QAAI,OAAO,IAAI,YAAY,UAAU;AACnC,aAAO,IAAI;AAAA,IACb,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AACrC,YAAM,YAAa,IAAI,QACpB,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,IAAI,EACzC,IAAI,CAAC,MAAM,EAAE,IAAI;AACpB,aAAO,UAAU,KAAK,IAAI;AAE1B,YAAM,YAAa,IAAI,QAAkB;AAAA,QACvC,CAAC,MAAM,EAAE,SAAS;AAAA,MACpB;AACA,YAAM,cAAe,IAAI,QAAkB;AAAA,QACzC,CAAC,MAAM,EAAE,SAAS;AAAA,MACpB;AAEA,UAAI,UAAU,SAAS,GAAG;AACxB,gBAAQ;AAAA,UAAa,UAAU,MAAM,aAAa,UAAU,IAAI,CAAC,MAAW,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;AAAA,MACpG;AACA,UAAI,YAAY,SAAS,GAAG;AAC1B,gBAAQ;AAAA,YAAe,YAAY,MAAM;AAAA,MAC3C;AAAA,IACF;AAEA,QAAI,KAAK,KAAK,GAAG;AACf,YAAM,YACJ,KAAK,SAAS,MAAO,KAAK,MAAM,GAAG,GAAI,IAAI,QAAQ;AACrD,mBAAa,KAAK,GAAG,IAAI,KAAK,SAAS,EAAE;AAAA,IAC3C;AAAA,EACF;AAEA,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,aAAa,KAAK,MAAM;AACjC;AAEA,SAAS,uBAAuB,QAA+B;AAK7D,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACZ,MAAI,mBAAmB;AACvB,MAAI,gBAAgB;AAMpB,QAAM,MAAM,OAAO,SAAS,KAAK,OAAO,OAAO,SAAS,CAAC,EAAE,SAAS,SAChE,OAAO,SAAS,IAChB,OAAO;AAEX,WAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,UAAM,MAAM,OAAO,CAAC;AACpB,UAAM,YACJ,IAAI,SAAS,SACT,SACA,IAAI,SAAS,cACX,cACA,IAAI,SAAS,SACX,SACA,IAAI;AAEd,UAAM,EAAE,MAAM,gBAAgB,IAAI,kCAAkC,GAAG;AACvE,QAAI,CAAC,KAAK,KAAK,EAAG;AAElB,UAAM,QAAQ,GAAG,SAAS,KAAK,IAAI;AACnC,QAAI,QAAQ,MAAM,SAAS,mBAAmB;AAC5C,sBAAgB,IAAI;AACpB;AAAA,IACF;AACA,YAAQ,KAAK,KAAK;AAClB,aAAS,MAAM,SAAS;AACxB,wBAAoB;AAAA,EACtB;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,UAAQ,QAAQ;AAChB,MAAI,KAAK,4BAA4B;AAAA,IACnC,SAAS,QAAQ;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,qBAAqB;AAAA,EACvB,CAAC;AAED,SAAO,QAAQ,KAAK,MAAM;AAC5B;AAWO,SAAS,qBACd,QACA,wBAAiC,OACjC,iBACA,OAAqC,CAAC,GAC9B;AACR,QAAM,iBAAiB,KAAK,mBAAmB;AAC/C,QAAM,UAAiB,CAAC;AAExB,MAAI,gBAAgB;AAClB,UAAM,aAAa,2BAA2B,QAAQ;AAAA,MACpD,MAAM;AAAA,IACR,CAAC;AACD,QAAI,YAAY;AACd,UAAI,KAAK,mCAAmC;AAAA,QAC1C,eAAe,WAAW;AAAA,MAC5B,CAAC;AACD,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM;AAAA,EACZ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMN,CAAC;AAAA,IACH;AAAA,EACF,WAAW,uBAAuB;AAChC,UAAM,iBAAiB,2BAA2B,MAAM;AACxD,QAAI,gBAAgB;AAClB,UAAI,KAAK,0CAA0C;AAAA,QACjD,eAAe,eAAe;AAAA,MAChC,CAAC;AACD,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM;AAAA;AAAA;AAAA,EAGZ,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOV,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,WAA0B,CAAC;AACjC,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,QAAI,OAAO,CAAC,EAAE,SAAS,YAAa;AACpC,aAAS,QAAQ,OAAO,CAAC,CAAC;AAAA,EAC5B;AAEA,aAAW,OAAO,UAAU;AAC1B,QAAI,IAAI,SAAS,QAAQ;AACvB,UAAI,OAAO,IAAI,YAAY,UAAU;AACnC,cAAM,MAAM,IAAI;AAChB,YAAI,IAAI,KAAK,GAAG;AACd,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,QAC1C;AAAA,MACF,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AACrC,mBAAW,QAAQ,IAAI,SAAkB;AACvC,cAAI,KAAK,SAAS,QAAQ;AACxB,gBAAI,KAAK,QAAQ,KAAK,KAAK,KAAK,GAAG;AACjC,sBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,YAChD;AAAA,UACF,WAAW,KAAK,SAAS,UAAU,KAAK,SAAS,SAAS;AACxD,kBAAM,QAAQ,aAAa,IAAI;AAC/B,gBAAI,OAAO;AACT,sBAAQ,KAAK,KAAK;AAAA,YACpB,OAAO;AACL,kBAAI,MAAM,+BAA+B;AAAA,gBACvC,WAAW,KAAK;AAAA,cAClB,CAAC;AAAA,YACH;AAAA,UACF,WAAW,KAAK,SAAS,eAAe;AACtC,kBAAM,IAAI;AACV,oBAAQ,KAAK;AAAA,cACX,MAAM;AAAA,cACN,aAAa,EAAE;AAAA,cACf,SAAS,kBAAkB,CAAC;AAAA,YAC9B,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,IAAI,SAAS,QAAQ;AAK9B,UAAI,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC9B,mBAAW,QAAQ,IAAI,SAAkB;AACvC,cAAI,MAAM,SAAS,eAAe;AAChC,kBAAM,IAAI;AACV,oBAAQ,KAAK;AAAA,cACX,MAAM;AAAA,cACN,aAAa,EAAE;AAAA,cACf,SAAS,kBAAkB,CAAC;AAAA,YAC9B,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AAOxB,QAAI,KAAK,qDAAqD;AAC9D,WAAO,KAAK,UAAU;AAAA,MACpB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,MAAM;AAAA,QACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,UAAU,CAAC;AAAA,MAC7C;AAAA,IACF,CAAC;AAAA,EACH;AAKA,MAAI,CAAC,gBAAgB;AACnB,UAAM,UAAU,iBAAiB,eAAe;AAChD,QAAI,SAAS;AACX,YAAM,eAAe,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACzE,UAAI,cAAc;AAChB,qBAAa,OAAO,aAAa,OAC7B,GAAG,aAAa,IAAI;AAAA;AAAA,GAAQ,OAAO,MACnC,IAAI,OAAO;AAAA,MACjB,OAAO;AACL,gBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,CAAC;AAAA,MACrD;AACA,UAAI,MAAM,8BAA8B,EAAE,QAAQ,iBAAiB,QAAQ,CAAC;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO,KAAK,UAAU;AAAA,IACpB,MAAM;AAAA,IACN,SAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AC3dO,IAAM,qBAAqB;AAE3B,IAAM,kCACX;AAEF,IAAM,iCACJ;AAEF,IAAM,8BAA8B;AACpC,IAAM,kCACJ,sCAAsC,2BAA2B;AACnE,IAAM,kCACJ;AAEF,IAAM,gBAAgB;AA6Bf,SAAS,yBAAyB,OAI7B;AACV,MAAI,MAAM,eAAgB,QAAO;AACjC,MAAI,MAAM,eAAe,KAAM,QAAO;AACtC,SAAO,MAAM;AACf;AAEA,IAAM,mBAAmB,oBAAI,IAAoB;AAEjD,SAAS,WAAWA,aAAoB,oBAAoC;AAC1E,SAAO,GAAGA,WAAU,GAAG,aAAa,GAAG,kBAAkB;AAC3D;AAEO,SAAS,2BAA2BA,aAA0B;AACnE,QAAM,SAAS,GAAGA,WAAU,GAAG,aAAa;AAC5C,aAAW,OAAO,iBAAiB,KAAK,GAAG;AACzC,QAAI,IAAI,WAAW,MAAM,EAAG,kBAAiB,OAAO,GAAG;AAAA,EACzD;AACF;AAEO,SAAS,+BACdA,aACA,uBACA,MACA,qBAAqB,sBAAsB,qBAAqB,IACtC;AAC1B,mBAAiB,IAAI,WAAWA,aAAY,kBAAkB,GAAG,qBAAqB;AAEtF,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,OAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,SAAS;AAAA,YACP,EAAE,OAAO,OAAO,aAAa,GAAG;AAAA,YAChC,EAAE,OAAO,MAAM,aAAa,GAAG;AAAA,UACjC;AAAA,UACA,UAAU;AAAA,UACV,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,OAAO;AAAA;AAAA,EAAO,IAAI;AAAA,IAAO;AAAA,EACjC;AACF;AAEA,SAAS,uBAAuB,OAIrB;AACT,SAAO,KAAK,UAAU;AAAA,IACpB,MAAM;AAAA,IACN,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,QACP,MAAM,WACF;AAAA,UACE,MAAM;AAAA,UACN,aAAa,MAAM;AAAA,UACnB,SAAS;AAAA,QACX,IACA;AAAA,UACE,MAAM;AAAA,UACN,aAAa,MAAM;AAAA,UACnB,SAAS,GAAG,8BAA8B;AAAA,EAAK,MAAM,YAAY,IAAI;AAAA,UACrE,UAAU;AAAA,QACZ;AAAA,MACN;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,aAAa,MAAuB;AAC3C,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,MAAoB;AAC5C,QAAM,SAAS,MAAM,UAAU,MAAM;AACrC,MAAI,OAAO,WAAW,SAAU,QAAO,aAAa,MAAM;AAC1D,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAElD,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,aAAa,OAAO,OAAO,SAAS,EAAE,CAAC;AAAA,IAChD,KAAK;AACH,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ,OAAO,OAAO,UAAU,mBAAmB;AAAA,MACrD;AAAA,IACF,KAAK;AACH,aAAO,MAAM,QAAQ,OAAO,KAAK,IAC7B,OAAO,MACJ,IAAI,CAAC,SAAc;AAClB,YAAI,MAAM,SAAS,OAAQ,QAAO,KAAK;AACvC,eAAO,KAAK,UAAU,IAAI;AAAA,MAC5B,CAAC,EACA,KAAK,IAAI,IACZ,OAAO;AAAA,IACb;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,6BAA6B,OAAuB;AAC3D,MACE,MAAM,WAAW,+BAA+B,KAChD,MAAM,SAAS,+BAA+B,GAC9C;AACA,WAAO,MAAM;AAAA,MACX,gCAAgC;AAAA,MAChC,CAAC,gCAAgC;AAAA,IACnC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAA0B;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO,CAAC,6BAA6B,KAAK,CAAC;AAC1E,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,QAAQ,oBAAoB;AACnE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO,CAAC;AAEjD,QAAM,MAAM;AACZ,MAAI,IAAI,WAAW,KAAM,QAAO,CAAC,OAAO,IAAI,UAAU,mBAAmB,CAAC;AAE1E,aAAW,OAAO,CAAC,WAAW,UAAU,YAAY,aAAa,OAAO,GAAG;AACzE,QAAI,OAAO,IAAK,QAAO,qBAAqB,IAAI,GAAG,CAAC;AAAA,EACtD;AAEA,SAAO,CAAC;AACV;AAEA,SAAS,uBAAuB,MAAoD;AAClF,QAAM,SAAS,iBAAiB,IAAI;AACpC,QAAM,UAAU,qBAAqB,MAAM,EACxC,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,EAC7B,OAAO,OAAO;AAEjB,MAAI,QAAQ,WAAW,KAAK,QAAQ,CAAC,EAAE,YAAY,MAAM,OAAO;AAC9D,WAAO,EAAE,UAAU,MAAM,UAAU,GAAG;AAAA,EACxC;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,UAAU,QAAQ,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI;AAAA,EACtD;AACF;AAEO,SAAS,kCACdA,aACA,QACe;AACf,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,MAAM,OAAO,CAAC;AACpB,QAAI,CAAC,MAAM,QAAQ,IAAI,OAAO,EAAG;AAEjC,eAAW,QAAQ,IAAI,SAAkB;AACvC,UAAI,MAAM,SAAS,iBAAiB,OAAO,KAAK,eAAe,UAAU;AACvE;AAAA,MACF;AAEA,YAAM,MAAM,WAAWA,aAAY,KAAK,UAAU;AAClD,YAAM,wBAAwB,iBAAiB,IAAI,GAAG;AACtD,UAAI,CAAC,sBAAuB;AAE5B,uBAAiB,OAAO,GAAG;AAC3B,YAAM,SAAS,uBAAuB,IAAI;AAC1C,aAAO,uBAAuB;AAAA,QAC5B,WAAW;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;ACzOA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,SAAQ;AACpB,YAAY,YAAY;AACxB;AAAA,EACE,SAAS;AAAA,EACT;AAAA,OAEK;;;ACRP,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,YAAY,UAAU;AAYtB,IAAM,iBAAsB;AAAA,EACvB,UAAO;AAAA,EACV,wBAAwB,QAAQ,GAAG;AACrC;AAEA,IAAI,aAAa;AAEV,SAAS,eAAuB;AACrC,MAAI,CAAI,cAAW,cAAc,GAAG;AAClC,IAAG,aAAU,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAAA,EAClD;AACA,MAAI,CAAC,YAAY;AACf,iBAAa;AACb,YAAQ,GAAG,QAAQ,MAAM;AACvB,UAAI;AACF,QAAG,UAAO,gBAAgB,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAC5D,QAAQ;AAAA,MAAC;AAAA,IACX,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;ADkCA,IAAM,aAAa,CAAC,kBAAkB,iBAAiB,aAAa;AACpE,IAAM,qBAAqB,CAAC,iBAAiB,gBAAgB;AAE7D,SAAS,WAAW,GAAoB;AACtC,MAAI;AACF,WAAU,aAAS,CAAC,EAAE,OAAO;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,GAAoB;AACrC,MAAI;AACF,WAAU,aAAS,CAAC,EAAE,YAAY;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,MAA8C;AAClE,MAAI;AACF,UAAM,MAAS,iBAAa,MAAM,MAAM;AACxC,UAAM,SAAuB,CAAC;AAC9B,UAAM,SAAS,WAAW,KAAK,QAAQ,EAAE,oBAAoB,KAAK,CAAC;AACnE,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,QAAQ,OAAO,CAAC;AACtB,YAAM,IAAI;AAAA,QACR,GAAG,oBAAoB,MAAM,KAAK,CAAC,cAAc,MAAM,MAAM;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,KAAK,mCAAmC;AAAA,MAC1C;AAAA,MACA,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,IAClD,CAAC;AACD,WAAO;AAAA,EACT;AACF;AASA,SAAS,cAAc,GAA0C;AAC/D,SAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAChE;AAEA,SAAS,UACP,QACA,QACyB;AACzB,QAAM,MAA+B,EAAE,GAAG,OAAO;AACjD,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,QAAI,MAAM,OAAW;AACrB,UAAM,WAAW,IAAI,CAAC;AACtB,QAAI,cAAc,QAAQ,KAAK,cAAc,CAAC,GAAG;AAC/C,UAAI,CAAC,IAAI,UAAU,UAAU,CAAC;AAAA,IAChC,OAAO;AACL,UAAI,CAAC,IAAI;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,OAAO,MAKH;AACX,QAAM,MAAgB,CAAC;AACvB,MAAI,UAAe,cAAQ,KAAK,KAAK;AACrC,SAAO,MAAM;AACX,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,YAAiB,WAAK,SAAS,MAAM;AAC3C,UAAI,KAAK,UAAU,SAAS,EAAG,KAAI,KAAK,SAAS;AAAA,IACnD;AACA,QAAI,KAAK,QAAQ,YAAiB,cAAQ,KAAK,IAAI,EAAG;AACtD,UAAM,SAAc,cAAQ,OAAO;AACnC,QAAI,WAAW,QAAS;AACxB,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAOA,SAAS,eAAe,KAAiC;AACvD,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAY,cAAQ,QAAQ;AAC1C,MAAI,UAAe,cAAQ,GAAG;AAC9B,SAAO,MAAM;AACX,UAAM,UAAe,WAAK,SAAS,MAAM;AACzC,QAAI;AACF,UAAO,eAAW,OAAO,EAAG,QAAO;AAAA,IACrC,QAAQ;AAAA,IAER;AACA,UAAM,SAAc,cAAQ,OAAO;AACnC,QAAI,WAAW,QAAS,QAAO;AAC/B,cAAU;AAAA,EACZ;AACF;AAEA,SAAS,kBAA0B;AACjC,QAAM,MAAM,QAAQ,IAAI,mBAAwB,WAAQ,YAAQ,GAAG,SAAS;AAC5E,SAAY,WAAK,KAAK,UAAU;AAClC;AAOA,SAAS,mBAA4C;AACnD,QAAM,MAAM,gBAAgB;AAC5B,MAAI,SAAkC,CAAC;AACvC,aAAW,QAAQ,WAAW,MAAM,EAAE,QAAQ,GAAG;AAE/C,UAAM,OAAY,WAAK,KAAK,IAAI;AAChC,QAAI,CAAC,WAAW,IAAI,EAAG;AACvB,UAAM,SAAS,aAAa,IAAI;AAChC,QAAI,OAAQ,UAAS,UAAU,QAAQ,MAAM;AAAA,EAC/C;AACA,SAAO;AACT;AAGA,SAAS,sBAAsB,KAAsC;AACnE,MAAI,SAAkC,CAAC;AACvC,aAAW,QAAQ,oBAAoB;AACrC,UAAM,OAAY,WAAK,KAAK,IAAI;AAChC,QAAI,CAAC,WAAW,IAAI,EAAG;AACvB,UAAM,SAAS,aAAa,IAAI;AAChC,QAAI,OAAQ,UAAS,UAAU,QAAQ,MAAM;AAAA,EAC/C;AACA,SAAO;AACT;AAOA,SAAS,gBAAgB,KAAa,UAA6B;AACjE,QAAM,OAAiB,CAAC;AACxB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,OAAO,CAAC,MAAc;AAC1B,UAAM,MAAW,cAAQ,CAAC;AAC1B,QAAI,CAAC,KAAK,IAAI,GAAG,KAAK,UAAU,GAAG,GAAG;AACpC,WAAK,IAAI,GAAG;AACZ,WAAK,KAAK,GAAG;AAAA,IACf;AAAA,EACF;AAEA,aAAW,OAAO,OAAO;AAAA,IACvB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS,CAAC,WAAW;AAAA,IACrB,WAAW;AAAA,EACb,CAAC,GAAG;AACF,SAAK,GAAG;AAAA,EACV;AAEA,QAAM,OAAU,YAAQ;AACxB,MAAI,MAAM;AACR,UAAM,UAAe,WAAK,MAAM,WAAW;AAC3C,QAAI,UAAU,OAAO,EAAG,MAAK,OAAO;AAAA,EACtC;AAEA,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,UAAU,UAAU,MAAM,EAAG,MAAK,MAAM;AAE5C,SAAO;AACT;AAgCA,SAAS,0BACP,QACwB;AACxB,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,QAAI,OAAO,MAAM,SAAU;AAC3B,QAAI,CAAC,IAAI,EAAE,QAAQ,qCAAqC,CAAC,QAAQ,SAAS;AACxE,YAAM,WAAW,QAAQ,IAAI,IAAI;AACjC,aAAO,OAAO,aAAa,WAAW,WAAW;AAAA,IACnD,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,gBACP,MACA,MACgC;AAChC,MAAI,KAAK,YAAY,MAAO,QAAO;AAEnC,QAAM,OAAO,KAAK;AAClB,MAAI,SAAS,SAAS;AACpB,UAAM,MAAM,KAAK;AACjB,QAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,GAAG;AAC3C,UAAI,KAAK,6CAA6C,EAAE,KAAK,CAAC;AAC9D,aAAO;AAAA,IACT;AACA,UAAM,MAA+B;AAAA,MACnC,MAAM;AAAA,MACN,SAAS,OAAO,IAAI,CAAC,CAAC;AAAA,IACxB;AACA,QAAI,IAAI,SAAS,EAAG,KAAI,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAChE,QAAI,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAC5D,UAAI,MAAM;AAAA,QACR,KAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,UAAU;AACrB,QAAI,OAAO,KAAK,QAAQ,YAAY,CAAC,KAAK,KAAK;AAC7C,UAAI,KAAK,0CAA0C,EAAE,KAAK,CAAC;AAC3D,aAAO;AAAA,IACT;AACA,UAAM,MAA+B;AAAA,MACnC,MAAM;AAAA,MACN,KAAK,KAAK;AAAA,IACZ;AACA,QAAI,KAAK,WAAW,OAAO,KAAK,YAAY,UAAU;AACpD,UAAI,UAAU;AAAA,QACZ,KAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,yCAAyC;AAAA,IAChD;AAAA,IACA,MAAM,QAAQ;AAAA,EAChB,CAAC;AACD,SAAO;AACT;AAEA,SAAS,gBACP,QACgC;AAChC,QAAM,MAAM,OAAO;AACnB,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AACnE,SAAO;AACT;AAQA,SAAS,SACP,QACA,QACgC;AAChC,QAAM,MAAsC,EAAE,GAAG,OAAO;AACxD,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,WAAW,IAAI,IAAI;AACzB,QAAI,YAAY,OAAO,aAAa,UAAU;AAC5C,UAAI,IAAI,IAAI;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,IAAI,IAAI;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;AAsDO,SAAS,kBACd,KACA,eACA,gBACmB;AACnB,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB;AAAA,EACF,IAAI,iBAAiB,KAAK,aAAa;AAIvC,QAAM,UAAmC,CAAC;AAC1C,QAAM,qBAA+B,CAAC;AACtC,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,QAAI,gBAAgB,IAAI,IAAI,EAAG;AAC/B,UAAM,aAAa,gBAAgB,MAAM,IAA+B;AACxE,QAAI,YAAY;AACd,cAAQ,IAAI,IAAI;AAChB,yBAAmB,KAAK,IAAI;AAAA,IAC9B;AAAA,EACF;AACA,SAAO,aAAa;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AASO,SAAS,iBACd,KACA,eACW;AACX,QAAM,WAAW,eAAe,GAAG;AAGnC,MAAI,SAAyC,CAAC;AAC9C,WAAS,SAAS,QAAQ,gBAAgB,iBAAiB,CAAC,CAAC;AAG7D,QAAM,iBAAiB,QAAQ,IAAI;AACnC,MAAI,kBAAkB,WAAW,cAAc,GAAG;AAChD,UAAM,SAAS,aAAa,cAAc;AAC1C,QAAI,OAAQ,UAAS,SAAS,QAAQ,gBAAgB,MAAM,CAAC;AAAA,EAC/D;AAMA,QAAM,eAAe,OAAO;AAAA,IAC1B,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,QAAM,cAAwB,CAAC;AAC/B,QAAM,kBAAkB,oBAAI,IAAY;AACxC,aAAW,KAAK,cAAc;AAC5B,UAAM,IAAS,cAAQ,CAAC;AACxB,QAAI,CAAC,gBAAgB,IAAI,CAAC,GAAG;AAC3B,sBAAgB,IAAI,CAAC;AACrB,kBAAY,KAAK,CAAC;AAAA,IACpB;AAAA,EACF;AACA,aAAW,OAAO,YAAY,MAAM,EAAE,QAAQ,GAAG;AAC/C,aAAS,SAAS,QAAQ,gBAAgB,sBAAsB,GAAG,CAAC,CAAC;AAAA,EACvE;AAOA,aAAW,OAAO,gBAAgB,KAAK,QAAQ,GAAG;AAChD,aAAS,SAAS,QAAQ,gBAAgB,sBAAsB,GAAG,CAAC,CAAC;AAAA,EACvE;AAMA,MAAI,eAAe;AACjB,eAAW,QAAQ,OAAO,KAAK,MAAM,GAAG;AACtC,YAAM,SAAS,cAAc,IAAI;AACjC,UAAI,WAAW,OAAW;AAC1B,YAAM,WAAW,OAAO,IAAI;AAC5B,YAAM,OACJ,YAAY,OAAO,aAAa,WAC3B,WACD,CAAC;AACP,aAAO,IAAI,IAAI,EAAE,GAAG,MAAM,SAAS,WAAW,YAAY;AAAA,IAC5D;AAAA,EACF;AAKA,QAAM,qBAA+B,CAAC;AACtC,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,UAAW,KAA+B;AAChD,QAAI,YAAY,MAAO;AACvB,uBAAmB,KAAK,IAAI;AAAA,EAC9B;AAIA,QAAM,aAAa,KAAK,UAAU,EAAE,YAAY,OAAO,GAAG,MAAM,CAAC;AACjE,QAAM,OACH,kBAAW,QAAQ,EACnB,OAAO,UAAU,EACjB,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAEd,SAAO,EAAE,SAAS,QAAQ,oBAAoB,KAAK;AACrD;AAGA,SAAS,aAAa,OAMA;AACpB,QAAM,EAAE,SAAS,oBAAoB,uBAAuB,MAAM,eAAe,IAC/E;AAEF,MAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;AACrC,UAAM,4BACJ,kBACA,sBAAsB,SAAS,KAC/B,sBAAsB,MAAM,CAAC,SAAS,eAAe,IAAI,IAAI,CAAC;AAEhE,QAAI,CAAC,0BAA2B,QAAO;AAEvC,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,aAAa,CAAC;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,KAAK,UAAU,EAAE,YAAY,QAAQ,GAAG,MAAM,CAAC;AAC5D,QAAM,UAAe;AAAA,IACnB,aAAa;AAAA,IACb,OAAO,IAAI;AAAA,EACb;AACA,MAAI;AACF,QAAI,CAAC,WAAW,OAAO,GAAG;AACxB,MAAG,kBAAc,SAAS,MAAM,EAAE,UAAU,QAAQ,MAAM,IAAM,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,GAAG;AACV,QAAI,KAAK,sCAAsC;AAAA,MAC7C,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,IAClD,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,+BAA+B;AAAA,IACtC,QAAQ;AAAA,IACR;AAAA,IACA,SAAS;AAAA,IACT,UAAU,iBAAiB,MAAM,KAAK,cAAc,IAAI,CAAC;AAAA,EAC3D,CAAC;AACD,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,aAAa;AAAA,IACb;AAAA,EACF;AACF;;;AExlBA,IAAI,iBAAwC;AAErC,SAAS,kBAAkB,QAAuB;AACvD,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,qBAAiB;AAAA,EACnB;AACF;AAaA,IAAI;AAEG,SAAS,4BAA4B,KAA+B;AACzE,6BAA2B;AAC7B;AAEO,SAAS,8BAAkD;AAChE,SAAO;AACT;AAEO,SAAS,kBAAkB,GAAyB;AACzD,SAAO,OAAO,MAAM,YAAY,EAAE,SAAS,KAAK,MAAM;AACxD;AAgBO,SAAS,gBAAgB,YAAwC;AACtE,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,IAAI;AAAA,IACZ;AAAA,EACF;AACF;AAEO,SAAS,oBACd,YACA,MACA,UACQ;AACR,MAAI,WAAY,QAAO;AACvB,MAAI,kBAAkB,IAAI,EAAG,QAAO;AACpC,SAAO,YAAY;AACrB;AAQA,eAAsB,sBAEpB;AACA,QAAM,SAAS;AACf,MAAI,CAAC,QAAQ,KAAK,OAAQ,QAAO;AACjC,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,IAAI,OAAO;AACpC,UAAM,OAAQ,IAA2B;AACzC,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,UAAM,MAAwB,CAAC;AAC/B,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAA+B,GAAG;AAC3E,UAAI,SAAS,OAAO,UAAU,UAAU;AACtC,cAAM,SAAU,MAA+B;AAC/C,YAAI,OAAO,WAAW,SAAU,KAAI,IAAI,IAAI;AAAA,MAC9C;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,KAAK,+CAA+C;AAAA,MACtD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD,CAAC;AACD,WAAO;AAAA,EACT;AACF;AAgBA,eAAsB,sBACpB,UACA,OACA,WAC6C;AAC7C,QAAM,SAAS;AACf,MAAI,CAAC,QAAQ,MAAM,KAAM,QAAO;AAChC,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA,MACjC,OAAO,EAAE,UAAU,OAAO,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AAAA,IAChE,CAAC;AACD,UAAM,OAAQ,IAA2B;AACzC,QAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO;AACjC,UAAM,MAA8B,CAAC;AACrC,eAAW,SAAS,MAAmB;AACrC,UAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,YAAM,IAAI;AACV,YAAM,KAAK,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC7C,YAAM,cACJ,OAAO,EAAE,gBAAgB,WAAW,EAAE,cAAc;AACtD,YAAM,aACJ,EAAE,cAAc,OAAO,EAAE,eAAe,WACnC,EAAE,aACH,CAAC;AACP,UAAI,CAAC,GAAI;AACT,UAAI,KAAK,EAAE,IAAI,aAAa,WAAW,CAAC;AAAA,IAC1C;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,KAAK,sCAAsC;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;ACvKA,SAAS,aAAgC;AACzC,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,cAAc;;;ACHvB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAG1B,IAAM,gBAAgB,UAAU,QAAQ;AASxC,IAAM,QAAQ,oBAAI,IAAwC;AAOnD,SAAS,iBAAiB,SAA6C;AAC5E,QAAM,SAAS,MAAM,IAAI,OAAO;AAChC,MAAI,OAAQ,QAAO;AACnB,QAAM,WAAW,YAAwC;AACvD,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM,cAAc,SAAS,CAAC,WAAW,GAAG;AAAA,QAC7D,SAAS;AAAA,MACX,CAAC;AACD,YAAM,QAAQ,sBAAsB,KAAK,OAAO,KAAK,CAAC;AACtD,UAAI,CAAC,OAAO;AACV,YAAI,KAAK,uCAAuC,EAAE,QAAQ,OAAO,KAAK,EAAE,CAAC;AACzE,eAAO;AAAA,MACT;AACA,YAAM,IAAgB;AAAA,QACpB,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,QACtB,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,QACtB,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,QACtB,KAAK,OAAO,KAAK;AAAA,MACnB;AACA,UAAI,KAAK,+BAA+B,EAAE,SAAS,SAAS,EAAE,IAAI,CAAC;AACnE,UAAI,CAAC,2BAA2B,CAAC,GAAG;AAClC,YAAI;AAAA,UACF;AAAA,UACA,EAAE,SAAS,EAAE,IAAI;AAAA,QACnB;AAAA,MACF;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,KAAK,uCAAuC;AAAA,QAC9C;AAAA,QACA,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AACH,QAAM,IAAI,SAAS,OAAO;AAC1B,SAAO;AACT;AAEA,SAAS,IAAI,GAAe,QAAkE;AAC5F,MAAI,EAAE,UAAU,OAAO,MAAO,QAAO,EAAE,QAAQ,OAAO;AACtD,MAAI,EAAE,UAAU,OAAO,MAAO,QAAO,EAAE,QAAQ,OAAO;AACtD,SAAO,EAAE,SAAS,OAAO;AAC3B;AAQO,SAAS,2BAA2B,GAA+B;AACxE,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,IAAI,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,CAAC;AAClD;AAQO,SAAS,oBAAoB,GAA+B;AACjE,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,IAAI,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE,CAAC;AAChD;;;ADpDA,IAAM,kBAAkB,oBAAI,IAA2B;AACvD,IAAM,iBAAiB,oBAAI,IAAoB;AAK/C,IAAM,uBAAuB;AAC7B,IAAM,0BAA0B;AAChC,IAAM,gCAAgC;AAEtC,SAAS,eAAe,OAAoC;AAC1D,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,CAAC,CAAC,KAAK,SAAS,MAAM,KAAK,EAAE,SAAS,UAAU;AACzD;AAEO,SAAS,2BAAoC;AAClD,SACE,eAAe,QAAQ,IAAI,4BAA4B,KACvD,eAAe,QAAQ,IAAI,qCAAqC;AAEpE;AAEO,SAAS,eAAe,MAEQ;AACrC,QAAM,MAA0C;AAAA,IAC9C,GAAG,QAAQ;AAAA,IACX,MAAM;AAAA,EACR;AAKA,MAAI,MAAM,uBAAuB;AAC/B,WAAO,IAAI;AACX,WAAO,IAAI;AAAA,EACb;AAKA,MACE,CAAC,yBAAyB,KAC1B,QAAQ,IAAI,wCAAwC,QACpD;AACA,QAAI,sCAAsC;AAAA,EAC5C;AAEA,SAAO;AACT;AAEA,SAAS,MAAM,KAAmB;AAChC,QAAM,WAAW,gBAAgB,IAAI,GAAG;AACxC,MAAI,UAAU;AACZ,oBAAgB,OAAO,GAAG;AAC1B,oBAAgB,IAAI,KAAK,QAAQ;AAAA,EACnC;AACF;AAEA,SAAS,gBAAsB;AAC7B,SAAO,gBAAgB,QAAQ,sBAAsB;AACnD,UAAM,YAAY,gBAAgB,KAAK,EAAE,KAAK,EAAE;AAChD,QAAI,CAAC,UAAW;AAChB,QAAI,KAAK,+BAA+B,EAAE,YAAY,UAAU,CAAC;AACjE,wBAAoB,SAAS;AAAA,EAC/B;AACF;AAEO,SAAS,iBAAiB,KAAwC;AACvE,QAAM,KAAK,gBAAgB,IAAI,GAAG;AAClC,MAAI,GAAI,OAAM,GAAG;AACjB,SAAO;AACT;AAEO,SAAS,iBAAiB,KAAa,IAAyB;AACrE,kBAAgB,IAAI,KAAK,EAAE;AAC7B;AAEA,SAAS,oBAAoB,KAAwC;AACnE,QAAM,KAAK,gBAAgB,IAAI,GAAG;AAClC,MAAI,CAAC,GAAI,QAAO;AAChB,kBAAgB,OAAO,GAAG;AAC1B,OAAK,GAAG,aAAa,MAAM;AAC3B,SAAO;AACT;AAEO,SAAS,oBAAoB,KAAmB;AACrD,QAAM,KAAK,oBAAoB,GAAG;AAClC,MAAI,KAAK,KAAK;AAChB;AAEA,SAAS,iBAAiB,MAA6B;AACrD,SAAO,KAAK,aAAa,QAAQ,KAAK,eAAe;AACvD;AAEA,SAAS,mBACP,MACA,WACkB;AAClB,MAAI,iBAAiB,IAAI,EAAG,QAAO,QAAQ,QAAQ,IAAI;AAEvD,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,SAAS,MAAM;AACnB,mBAAa,KAAK;AAClB,MAAAA,SAAQ,IAAI;AAAA,IACd;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,WAAK,IAAI,QAAQ,MAAM;AACvB,MAAAA,SAAQ,iBAAiB,IAAI,CAAC;AAAA,IAChC,GAAG,SAAS;AACZ,SAAK,KAAK,QAAQ,MAAM;AAAA,EAC1B,CAAC;AACH;AAEA,eAAsB,2BACpB,KACA,UAGI,CAAC,GACa;AAClB,QAAM,KAAK,oBAAoB,GAAG;AAClC,MAAI,CAAC,MAAM,iBAAiB,GAAG,IAAI,EAAG,QAAO;AAE7C,QAAM,eAAe;AAAA,IACnB,GAAG;AAAA,IACH,QAAQ,iBAAiB;AAAA,EAC3B;AACA,KAAG,KAAK,KAAK;AACb,MAAI,MAAM,aAAc,QAAO;AAE/B,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH,QAAQ,sBAAsB;AAAA,EAChC;AACA,KAAG,KAAK,KAAK,SAAS;AACtB,MAAI,MAAM,WAAY,QAAO;AAE7B,MAAI,KAAK,yDAAyD;AAAA,IAChE,YAAY;AAAA,EACd,CAAC;AACD,wBAAsB,GAAG;AACzB,SAAO;AACT;AAEO,SAAS,mBAAmB,KAAiC;AAClE,SAAO,eAAe,IAAI,GAAG;AAC/B;AAEO,SAAS,mBAAmB,KAAa,WAAyB;AACvE,iBAAe,IAAI,KAAK,SAAS;AACnC;AAEO,SAAS,sBAAsB,KAAmB;AACvD,6BAA2B,GAAG;AAC9B,QAAM,kBAAkB,eAAe,IAAI,GAAG;AAC9C,MAAI,gBAAiB,aAAY,eAAe;AAChD,iBAAe,OAAO,GAAG;AAC3B;AAEO,SAAS,mBACd,SACA,SACA,KACAC,aACA,aACA,SACA,kBACA,uBACe;AACf,gBAAc;AACd,MAAI,KAAK,+BAA+B,EAAE,SAAS,SAAS,KAAK,YAAAA,YAAW,CAAC;AAE7E,QAAM,OAAO,MAAM,SAAS,SAAS;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAC9B,KAAK,eAAe,EAAE,sBAAsB,CAAC;AAAA,IAC7C,OAAO,QAAQ,aAAa;AAAA,EAC9B,CAAC;AAED,QAAM,cAAc,IAAI,aAAa;AAErC,QAAM,KAAK,gBAAgB,EAAE,OAAO,KAAK,OAAQ,CAAC;AAClD,KAAG,GAAG,QAAQ,CAAC,SAAiB;AAC9B,gBAAY,KAAK,QAAQ,IAAI;AAAA,EAC/B,CAAC;AACD,KAAG,GAAG,SAAS,MAAM;AACnB,gBAAY,KAAK,OAAO;AAAA,EAC1B,CAAC;AAED,QAAM,KAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,aAAa,eAAe;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AACA,kBAAgB,IAAIA,aAAY,EAAE;AAIlC,OAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,QAAI,MAAM,wBAAwB,EAAE,YAAAA,aAAY,OAAO,IAAI,QAAQ,CAAC;AAAA,EACtE,CAAC;AAED,OAAK,GAAG,QAAQ,CAAC,MAAM,WAAW;AAChC,QAAI,KAAK,yBAAyB,EAAE,MAAM,QAAQ,YAAAA,YAAW,CAAC;AAC9D,SAAK,aAAa,MAAM;AACxB,QAAI,kBAAkB;AACpB,WAAK,OAAO,gBAAgB,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC9C;AACA,UAAM,iBAAiB,gBAAgB,IAAIA,WAAU,MAAM;AAC3D,QAAI,eAAgB,iBAAgB,OAAOA,WAAU;AACrD,QAAI,kBAAkB,SAAS,KAAK,SAAS,MAAM;AACjD,UAAI,KAAK,+CAA+C;AAAA,QACtD;AAAA,QACA,YAAAA;AAAA,MACF,CAAC;AACD,qBAAe,OAAOA,WAAU;AAAA,IAClC;AAAA,EACF,CAAC;AAED,OAAK,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACxC,UAAM,SAAS,KAAK,SAAS;AAC7B,QAAI,MAAM,UAAU,EAAE,MAAM,OAAO,MAAM,GAAG,GAAG,EAAE,CAAC;AAKlD,QACE,OAAO,SAAS,uBAAuB,KACtC,OAAO,SAAS,YAAY,MAC1B,OAAO,SAAS,gBAAgB,KAC/B,OAAO,SAAS,WAAW,KAC3B,OAAO,SAAS,SAAS,IAC7B;AACA,UAAI,gBAAgB,IAAIA,WAAU,MAAM,IAAI;AAC1C,YAAI,KAAK,6CAA6C;AAAA,UACpD,YAAAA;AAAA,UACA,OAAO,OAAO,MAAM,GAAG,GAAG;AAAA,QAC5B,CAAC;AACD,uBAAe,OAAOA,WAAU;AAAA,MAClC,OAAO;AACL,YAAI,MAAM,uDAAuD;AAAA,UAC/D,YAAAA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAeO,SAAS,qBACdA,aACA,SACU;AACV,MAAI,QAAQ,SAAS,UAAU,KAAK,QAAQ,SAAS,cAAc,GAAG;AACpE,WAAO;AAAA,EACT;AACA,QAAM,MAAM,eAAe,IAAIA,WAAU;AACzC,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,CAAC,GAAG,SAAS,YAAY,GAAG;AACrC;AAuBO,SAAS,qBACdA,aACA,SACA,SACA,KACA,uBAC2B;AAC3B,QAAM,MAAM,gBAAgB,IAAIA,WAAU;AAC1C,MAAI,CAAC,IAAK,QAAO;AACjB,kBAAgB,OAAOA,WAAU;AAKjC,MAAI,KAAK,mBAAmB,MAAM;AAClC,MAAI;AACF,QAAI,KAAK,KAAK;AAAA,EAChB,QAAQ;AAAA,EAAC;AACT,SAAO;AAAA,IACL;AAAA,IACA,qBAAqBA,aAAY,OAAO;AAAA,IACxC;AAAA,IACAA;AAAA,IACA,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ;AAAA,EACF;AACF;AAEO,SAAS,aAAa,MAahB;AACX,QAAM;AAAA,IACJ,YAAAA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,OAAO;AACT,SAAK,KAAK,WAAW,KAAK;AAAA,EAC5B;AAEA,MAAI,gBAAgB;AAClB,SAAK,KAAK,qBAAqB,cAAc;AAAA,EAC/C;AAMA,MAAI,kBAAkB;AACpB,UAAM,YAAY,eAAe,IAAIA,WAAU;AAC/C,QAAI,aAAa,CAAC,gBAAgB,IAAIA,WAAU,GAAG;AACjD,WAAK,KAAK,YAAY,SAAS;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,WAAW;AACb,UAAM,UAAU,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AACjE,UAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,SAAS,CAAC;AAC5E,QAAI,SAAS,SAAS,GAAG;AACvB,WAAK,KAAK,gBAAgB,GAAG,QAAQ;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,iBAAiB;AACnB,SAAK,KAAK,qBAAqB;AAAA,EACjC;AAEA,MAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,SAAK,KAAK,qBAAqB,GAAG,eAAe;AAAA,EACnD;AAMA,MAAI,YAAY,oBAAoB,cAAc,IAAI,GAAG;AACvD,SAAK,KAAK,cAAc,QAAQ;AAAA,EAClC;AAKA,MAAI,mBAAmB,2BAA2B,cAAc,IAAI,GAAG;AACrE,SAAK,KAAK,sBAAsB,eAAe;AAAA,EACjD;AAEA,MAAI,wBAAwB;AAC1B,SAAK,KAAK,+BAA+B,sBAAsB;AAAA,EACjE;AAEA,MAAI,iBAAiB;AACnB,SAAK,KAAK,gCAAgC;AAAA,EAC5C;AAEA,SAAO;AACT;AAMO,SAAS,WAAW,KAAa,SAAyB;AAC/D,SAAO,GAAG,GAAG,KAAK,OAAO;AAC3B;;;AErdA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,UAAAC,eAAc;;;ACDvB,YAAYC,SAAQ;AACpB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAoB3B,SAAS,cAAc,MAAM,UAAkB;AAC7C,MAAS,iBAAW,GAAG,KAAQ,eAAW,GAAG,EAAG,QAAO;AACvD,QAAM,SAAS,IAAI,MAAM,GAAG;AAC5B,MAAI,OAAQ,QAAO;AACnB,QAAM,QAAW,aAAS,MAAM;AAChC,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,UAAU,SAAS,CAAC,GAAG,GAAG;AAAA,MACzD,UAAU;AAAA,MACV,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,IACpC,CAAC;AACD,UAAM,QAAQ,IACX,MAAM,OAAO,EACb,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,KAAK,CAAC,MAAS,eAAW,CAAC,CAAC;AAC/B,QAAI,MAAO,QAAO;AAAA,EACpB,QAAQ;AAAA,EAAC;AACT,QAAM,IAAI,MAAM,sCAAsC,GAAG,EAAE;AAC7D;AAOO,SAAS,UAAU,KAAqB;AAC7C,SAAY,cAAQ,GAAG,EAAE,QAAQ,iBAAiB,GAAG;AACvD;AAuDA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,YAAY,iBAAiB,YAAY,CAAC;AACzE,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAc,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAExE,SAAS,iBAAiB,WAAuC;AAC/D,QAAM,QAAQ,aAAa,QAAQ,IAAI;AACvC,MAAI,CAAC,MAAO,QAAY,WAAQ,YAAQ,GAAG,SAAS;AACpD,MAAI,UAAU,IAAK,QAAU,YAAQ;AACrC,MAAI,MAAM,WAAW,IAAI,KAAK,MAAM,WAAW,KAAK,GAAG;AACrD,WAAY,WAAQ,YAAQ,GAAG,MAAM,MAAM,CAAC,CAAC;AAAA,EAC/C;AACA,SAAY,cAAQ,KAAK;AAC3B;AAEO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,MAAM;AAAA,EAEE,OAA6B;AAAA,EAC7B,SAAS;AAAA;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAA0B;AAAA,EAC1B,UAAU;AAAA,EACD;AAAA,EACA;AAAA,EAsBjB,YAAY,OAA6B,CAAC,GAAG;AAC3C,SAAK,MAAW,cAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AACjD,SAAK,YAAY,iBAAiB,KAAK,SAAS;AAChD,SAAK,SAAS,KAAK;AACnB,SAAK,YAAY,WAAW;AAC5B,SAAK,YAAiB;AAAA,MACpB,KAAK;AAAA,MACL;AAAA,MACA,UAAU,KAAK,GAAG;AAAA,MAClB,GAAG,KAAK,SAAS;AAAA,IACnB;AACA,SAAK,IAAI;AAAA,MACP,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,gBAAgB,KAAK;AAAA,MACrB,WAAW,KAAK,aAAa,CAAC;AAAA,MAC9B,uBAAuB,KAAK;AAAA,MAC5B,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,QAAQ;AAAA,MACnB,WAAW,KAAK,aAAa;AAAA,MAC7B,aAAa,KAAK,eAAe;AAAA,MACjC,WAAW,KAAK,aAAa;AAAA,MAC7B,QAAQ,KAAK,UAAU;AAAA;AAAA;AAAA;AAAA,MAIvB,eAAe,KAAK,iBAAiB;AAAA,MACrC,gBAAgB,KAAK,kBAAkB;AAAA,MACvC,aAAa,KAAK,eAAe;AAAA,MACjC,iBAAiB,KAAK,mBAAmB;AAAA,MACzC,kBAAkB,KAAK,oBAAoB;AAAA,MAC3C,OAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ,QAAS,OAAM,IAAI,MAAM,sBAAsB;AAChE,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,MAAM;AACJ,aAAK,UAAU;AACf,aAAK,QAAQ;AAAA,MACf;AAAA,MACA,EAAE,MAAM,KAAK;AAAA,IACf;AACA,UAAM,SAAS,cAAc,KAAK,EAAE,WAAW,QAAQ;AACvD,UAAM,OAAiB,CAAC,gBAAgB,KAAK,SAAS;AACtD,QAAI,KAAK,EAAE,MAAO,MAAK,KAAK,WAAW,KAAK,EAAE,KAAK;AACnD,QAAI,KAAK,EAAE,mBAAmB,QAAQ,KAAK,EAAE,mBAAmB,QAAW;AACzE,WAAK,KAAK,qBAAqB,KAAK,EAAE,cAAc;AAAA,IACtD;AACA,QAAI,KAAK,EAAE,aAAa,KAAK,EAAE,UAAU,OAAQ,MAAK,KAAK,GAAG,KAAK,EAAE,SAAS;AAE9E,QAAI,KAAK,EAAE;AACT,cAAQ,OAAO,MAAM,oBAAoB,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,CAAI;AAEvE,SAAK,aAAa,KAAK,IAAI;AAC3B,SAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG;AAAA,MACvC,KAAK,KAAK;AAAA,MACV,KAAK;AAAA,QACH,GAAG,QAAQ;AAAA,QACX,mBAAmB,KAAK,EAAE;AAAA,QAC1B,MAAM;AAAA,QACN,GAAI,KAAK,EAAE,wBACP,EAAE,mBAAmB,QAAW,sBAAsB,OAAU,IAChE,CAAC;AAAA,MACP;AAAA,MACA,UAAU;AAAA,QACR,MAAM,KAAK,EAAE;AAAA,QACb,MAAM,KAAK,EAAE;AAAA,QACb,MAAM,CAAC,OAAO,MAAM;AAClB,eAAK,aAAa,KAAK,IAAI;AAC3B,gBAAM,QAAQ,OAAO,KAAK,CAAC,EAAE,SAAS,MAAM;AAC5C,eAAK,OAAO;AACZ,cAAI,KAAK,EAAE,MAAO,SAAQ,OAAO,MAAM,KAAK;AAAA,QAC9C;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,KAAK,OACP,KAAK,CAAC,SAAS;AACd,WAAK,WAAW,OAAO,SAAS,WAAW,OAAO;AAClD,WAAK,SAAS;AACd,WAAK,OAAO;AAAA,IACd,CAAC,EACA,MAAM,MAAM;AACX,WAAK,SAAS;AACd,WAAK,OAAO;AAAA,IACd,CAAC;AAEH,UAAM,KAAK,YAAY;AACvB,SAAK,SAAS,KAAK,UAAU;AAAA,EAC/B;AAAA;AAAA;AAAA,EAIA,MAAc,cAA6B;AACzC,UAAM,QAAQ,KAAK,IAAI;AACvB,WAAO,KAAK,IAAI,IAAI,QAAQ,KAAK,EAAE,WAAW;AAC5C,YAAM,MAAM,GAAG;AACf,UAAI,KAAK,QAAS,OAAM,IAAI,MAAM,qBAAqB;AACvD,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,MAAM,KAAK,eAAe,6BAA6B,IAAI,CAAC;AAAA,MACxE;AACA,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,YAAM,YAAY,KAAK,IAAI,IAAI,KAAK;AACpC,UAAI,WAAW,KAAK,EAAE,aAAa,aAAa,KAAK,EAAE,YAAa;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,aAA4B;AACxC,UAAM,MAAM,KAAK,EAAE,WAAW;AAC9B,aAAS,UAAU,GAAG,UAAU,KAAK,EAAE,kBAAkB,WAAW;AAClE,UAAI,KAAK,WAAW,KAAK,UAAU,CAAC,KAAK,KAAM;AAC/C,WAAK,KAAK,SAAS,MAAM,IAAI;AAC7B,YAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,EAAE;AAClC,aAAO,KAAK,IAAI,IAAI,OAAO;AACzB,cAAM,MAAM,EAAE;AACd,YAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,YAAI,KAAK,UAAU,IAAI,KAAK,OAAQ;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAyB;AAC/B,QAAI;AACF,aAAU,iBAAa,KAAK,WAAW,MAAM,EAAE,MAAM,IAAI;AAAA,IAC3D,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGQ,YAAoB;AAC1B,UAAM,QAAQ,KAAK,aAAa;AAChC,WAAO,MAAM,SAAS,IAAI,MAAM,SAAS,IAAI;AAAA,EAC/C;AAAA,EAEQ,QAAQ,MAAM,KAAa;AACjC,UAAM,QAAQ,KAAK,IAEhB,QAAQ,0CAA0C,EAAE,EACpD,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACR,WAAO,MAAM,SAAS,MAAM,MAAM,MAAM,CAAC,GAAG,IAAI;AAAA,EAClD;AAAA,EAEQ,eAAe,QAAgB,aAAa,OAAe;AACjE,UAAM,QAAQ;AAAA,MACZ,GAAG,MAAM,eAAe,KAAK,SAAS,eAAe,KAAK,SAAS,cAAc,KAAK,YAAY,SAAS;AAAA,IAC7G;AACA,QAAI,YAAY;AACd,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,KAAM,OAAM,KAAK,gBAAgB,KAAK,UAAU,IAAI,CAAC,EAAE;AAAA,IAC7D;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAI,QAAgB,kBAAgD;AACxE,QAAI,KAAK,QAAS,OAAM,IAAI,MAAM,SAAS;AAC3C,QAAI,CAAC,KAAK,QAAQ,KAAK;AACrB,YAAM,IAAI,MAAM,uCAAuC;AACzD,UAAM,UAAU,oBAAoB,KAAK,EAAE;AAC3C,UAAM,KAAK,KAAK,IAAI;AAKpB,QAAI,KAAK,EAAE,gBAAgB;AACzB,WAAK,KAAK,SAAS,MAAM,cAAc,SAAS,WAAW;AAAA,IAC7D,OAAO;AACL,WAAK,KAAK,SAAS,MAAM,MAAM;AAAA,IACjC;AACA,UAAM,KAAK,WAAW;AAEtB,UAAM,YAAsB,CAAC;AAC7B,QAAI,YAAiB;AACrB,QAAI,aAA4B;AAChC,UAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,MAAM,KAAK,EAAE,MAAM;AACzB,UAAI,KAAK,QAAS,OAAM,IAAI,MAAM,kBAAkB;AACpD,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,eAAe,MAAM,SAAS;AACpC,UAAI,gBAAgB,KAAK,QAAQ;AAG/B,YAAI,KAAK,OAAQ,OAAM,IAAI,MAAM,KAAK,eAAe,0BAA0B,IAAI,CAAC;AACpF;AAAA,MACF;AAEA,eAAS,IAAI,KAAK,QAAQ,IAAI,cAAc,KAAK;AAC/C,cAAM,IAAI,MAAM,CAAC;AACjB,YAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAG;AACrB,YAAI;AACJ,YAAI;AACF,gBAAM,KAAK,MAAM,CAAC;AAAA,QACpB,QAAQ;AACN;AAAA,QACF;AACA,YAAI,IAAI,SAAS,eAAe,IAAI,SAAS;AAC3C,qBAAW,KAAK,IAAI,QAAQ,WAAW,CAAC,GAAG;AACzC,gBAAI,GAAG,SAAS,UAAU,OAAO,EAAE,SAAS;AAC1C,wBAAU,KAAK,EAAE,IAAI;AAAA,UACzB;AACA,cAAI,IAAI,QAAQ,MAAO,aAAY,IAAI,QAAQ;AAC/C,cACE,IAAI,QAAQ,eACZ,cAAc,IAAI,IAAI,QAAQ,WAAW,GACzC;AACA,yBAAa,IAAI,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AACA,WAAK,SAAS;AACd,UAAI,WAAY;AAAA,IAClB;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR,KAAK;AAAA,UACH,wBAAwB,OAAO,+CAA+C,UAAU,MAAM;AAAA,QAChG;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI,aAAa,CAAC;AACxB,WAAO;AAAA,MACL,MAAM,UAAU,KAAK,IAAI,EAAE,KAAK;AAAA,MAChC;AAAA,MACA,OAAO;AAAA,MACP,iBAAiB,EAAE,2BAA2B;AAAA,MAC9C,qBAAqB,EAAE,+BAA+B;AAAA,MACtD,mBAAmB,EAAE,gBAAgB,6BAA6B;AAAA,MAClE,mBAAmB,EAAE,gBAAgB,6BAA6B;AAAA,MAClE,aAAa,EAAE,gBAAgB;AAAA,MAC/B,cAAc,EAAE,iBAAiB;AAAA,MACjC,WAAW,KAAK,IAAI,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SACJ,QACA,QACA,kBAC2D;AAC3D,QAAI,KAAK,QAAS,OAAM,IAAI,MAAM,SAAS;AAC3C,QAAI,CAAC,KAAK,QAAQ,KAAK;AACrB,YAAM,IAAI,MAAM,uCAAuC;AACzD,UAAM,UAAU,oBAAoB,KAAK,EAAE;AAE3C,QAAI,KAAK,EAAE,gBAAgB;AACzB,WAAK,KAAK,SAAS,MAAM,cAAc,SAAS,WAAW;AAAA,IAC7D,OAAO;AACL,WAAK,KAAK,SAAS,MAAM,MAAM;AAAA,IACjC;AACA,UAAM,KAAK,WAAW;AAEtB,QAAI,YAAiB;AACrB,QAAI,cAAc;AAClB,QAAI,aAA4B;AAChC,UAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,MAAM,KAAK,EAAE,MAAM;AACzB,UAAI,KAAK,QAAS,OAAM,IAAI,MAAM,kBAAkB;AACpD,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,eAAe,MAAM,SAAS;AACpC,UAAI,gBAAgB,KAAK,QAAQ;AAG/B,YAAI,KAAK,QAAQ;AACf,gBAAM,IAAI,MAAM,KAAK,eAAe,0BAA0B,IAAI,CAAC;AAAA,QACrE;AACA;AAAA,MACF;AACA,eAAS,IAAI,KAAK,QAAQ,IAAI,cAAc,KAAK;AAC/C,cAAM,IAAI,MAAM,CAAC;AACjB,YAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAG;AACrB,eAAO,CAAC;AACR,YAAI;AACJ,YAAI;AACF,gBAAM,KAAK,MAAM,CAAC;AAAA,QACpB,QAAQ;AACN;AAAA,QACF;AACA,YAAI,IAAI,SAAS,eAAe,IAAI,SAAS;AAC3C,cAAI,IAAI,QAAQ,OAAO;AACrB,wBAAY,IAAI,QAAQ;AACxB,2BAAe,IAAI,QAAQ,MAAM,iBAAiB;AAAA,UACpD;AACA,cACE,IAAI,QAAQ,eACZ,cAAc,IAAI,IAAI,QAAQ,WAAW,GACzC;AACA,yBAAa,IAAI,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AACA,WAAK,SAAS;AACd,UAAI,WAAY;AAAA,IAClB;AAMA,QAAI,QAAa;AACjB,QAAI,WAAW;AACb,cAAQ,EAAE,GAAG,WAAW,eAAe,YAAY;AACnD,UAAI,MAAM,QAAQ,UAAU,UAAU,KAAK,UAAU,WAAW,SAAS,GAAG;AAC1E,cAAM,QAAQ,UAAU,WAAW,IAAI,CAAC,QAAa,EAAE,GAAG,GAAG,EAAE;AAC/D,cAAM,MAAM,SAAS,CAAC,IAAI;AAAA,UACxB,GAAG,MAAM,MAAM,SAAS,CAAC;AAAA,UACzB,eAAe;AAAA,QACjB;AACA,cAAM,aAAa;AAAA,MACrB;AAAA,IACF;AACA,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR,KAAK;AAAA,UACH,wBAAwB,OAAO;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,YAAY,MAAM;AAAA,EAC7B;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,MAAM;AACb,UAAI;AACF,aAAK,KAAK,SAAS,MAAM,GAAM;AAAA,MACjC,QAAQ;AAAA,MAAC;AACT,UAAI;AACF,aAAK,KAAK,KAAK;AAAA,MACjB,QAAQ;AAAA,MAAC;AACT,UAAI;AACF,aAAK,KAAK,SAAS,MAAM;AAAA,MAC3B,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ADjeO,SAAS,mBAAmB,OAAuB;AACxD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,KAAK;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,UAAU,OAAO,SAAS,UAAU,CAAC,OAAO,QAAS,QAAO;AACjE,QAAM,UAAU,OAAO,QAAQ;AAC/B,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AAEpC,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,aAAW,SAAS,SAAS;AAC3B,QAAI,OAAO,SAAS,UAAU,OAAO,MAAM,SAAS,UAAU;AAC5D,YAAM,KAAK,MAAM,IAAI;AAAA,IACvB,WAAW,OAAO,SAAS,eAAe;AACxC,YAAM,IAAI,MAAM;AAChB,YAAM,OACJ,OAAO,MAAM,WACT,IACA,MAAM,QAAQ,CAAC,IACb,EACG,IAAI,CAAC,MAAY,GAAG,SAAS,SAAS,EAAE,OAAO,EAAG,EAClD,OAAO,OAAO,EACd,KAAK,IAAI,IACZ;AACR,YAAM;AAAA,QACJ,eAAe,MAAM,cAAc,IAAI,MAAM,WAAW,KAAK,EAAE;AAAA,EAAM,IAAI;AAAA,MAC3E;AAAA,IACF,OAAO;AACL;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,GAAG;AACf,QAAI,KAAK,yDAAyD;AAAA,MAChE;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAaO,SAAS,wBACd,MACe;AACf,QAAM,YAAsB,CAAC;AAC7B,MAAI,KAAK,kBAAkB,KAAK,eAAe,SAAS,GAAG;AACzD,cAAU;AAAA,MACR;AAAA,MACA,GAAG,KAAK;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC7D,cAAU;AAAA,MACR;AAAA,MACA,KAAK,UAAU,EAAE,aAAa,EAAE,OAAO,KAAK,iBAAiB,EAAE,CAAC;AAAA,IAClE;AAAA,EACF;AACA,MAAI,KAAK,mBAAmB,qBAAqB;AAC/C,QAAI;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,KAAK,gBAAgB;AAC9B,cAAU,KAAK,qBAAqB,KAAK,cAAc;AAAA,EACzD;AACA,MAAI,KAAK,kBAAkB;AACzB,cAAU,KAAK,+BAA+B,KAAK,gBAAgB;AAAA,EACrE;AAEA,QAAM,UAAU,IAAI,cAAc;AAAA,IAChC,KAAK,KAAK;AAAA,IACV,SAAS,KAAK;AAAA,IACd,WAAW,KAAK;AAAA,IAChB,OAAO,KAAK;AAAA;AAAA;AAAA,IAGZ,gBACE,KAAK,mBAAmB,SAAY,OAAO,KAAK;AAAA,IAClD;AAAA,IACA,uBAAuB,KAAK;AAAA,EAC9B,CAAC;AACD,MAAI,KAAK,uCAAuC;AAAA,IAC9C,KAAK,KAAK;AAAA,IACV,SAAS,KAAK,WAAW;AAAA,IACzB,WAAW,QAAQ;AAAA,IACnB,OAAO,KAAK;AAAA,IACZ,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,EACrB,CAAC;AAED,QAAM,cAAc,IAAIC,cAAa;AACrC,QAAM,gBAAgB,oBAAI,IAA0B;AACpD,MAAI,eAAqC;AAEzC,QAAM,gBAAgB,MAAqB;AACzC,QAAI,CAAC,aAAc,gBAAe,QAAQ,MAAM;AAChD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,CACjB,SACA,SACA,QACA,UACS;AACT,gBAAY;AAAA,MACV;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,YAAY,QAAQ;AAAA,QACpB,OAAO,SAAS,CAAC;AAAA,QACjB,gBAAgB;AAAA,QAChB,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,YAA0B;AACzC,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,cAAc;AACpB,cAAM,EAAE,YAAY,MAAM,IAAI,MAAM,QAAQ,SAAS,SAAS,CAAC,QAAQ;AACrE,sBAAY,KAAK,QAAQ,GAAG;AAAA,QAC9B,CAAC;AAMD,cAAM,WAAW,CAAC;AAClB;AAAA,UACE,WAAW,2BAA2B;AAAA,UACtC;AAAA,UACA,WACI,wIACA;AAAA,UACJ;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,IAAI,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAC5D,YAAI,MAAM,2BAA2B,EAAE,OAAO,EAAE,QAAQ,CAAC;AACzD;AAAA,UACE;AAAA,UACA;AAAA,UACA,iCAAiC,EAAE,OAAO;AAAA,QAC5C;AACA,YAAI,cAAc,OAAO,GAAG;AAC1B,qBAAW,KAAK,cAAe,GAAE,CAAC;AAAA,QACpC,OAAO;AACL,sBAAY,KAAK,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,GAAG;AAAA,EACL;AAIA,QAAM,OAAY;AAAA,IAChB,OAAO;AAAA,MACL,MAAM,OAAwB;AAC5B,cAAM,MACJ,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,IAC5C,MAAM,MAAM,GAAG,EAAE,IACjB;AAEN,gBAAQ,mBAAmB,GAAG,CAAC;AAC/B,eAAO;AAAA,MACT;AAAA,MACA,MAAY;AAAA,MAAC;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,GAAG,OAAe,IAAmC;AACnD,UAAI,UAAU,QAAS,eAAc,IAAI,EAAE;AAC3C,aAAO;AAAA,IACT;AAAA,IACA,OAAgB;AACd,aAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAe,IAAmC;AACpD,UAAI,UAAU,QAAS,eAAc,OAAO,EAAE;AAC9C,aAAO;AAAA,IACT;AAAA,IACA,OAAgB;AACd,UAAI;AACF,gBAAQ,QAAQ;AAAA,MAClB,QAAQ;AAAA,MAAC;AACT,UAAI,KAAK,kBAAkB;AACzB,aAAKC,QAAO,KAAK,gBAAgB,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACnD;AACA,WAAK,SAAS;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,SAAS;AAAA,IACT,kBAAkB,KAAK;AAAA,EACzB;AACF;;;AEpQA,SAAS,oBAA+D;AAExE,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,aAAY;AACxB,SAAS,gBAAAC,qBAAoB;AA8CtB,IAAM,wBAAwB;AAO9B,SAAS,uBAAuB,SAA0B;AAC/D,SACG,QAAQ,SAAS,iBAAiB,KACjC,QAAQ,SAAS,iCAAiC,KACpD,QAAQ,SAAS,uBAAuB,KACxC,QAAQ,SAAS,iCAAiC,KAClD,QAAQ,SAAS,oBAAoB,KACrC,QAAQ,SAAS,qBAAqB;AAE1C;AAEA,IAAM,mBAAmB;AACzB,IAAM,cAAc;AACb,IAAM,oBAAoB,QAAQ,WAAW;AAK7C,IAAM,2BAA2B,KAAK,KAAK;AAc3C,IAAM,oCAA4D;AAAA,EACvE,MAAM,KAAK,KAAK;AAAA;AAAA,EAChB,UAAU,KAAK,KAAK;AAAA;AACtB;AAMO,IAAM,uBAAuB,KAAK,KAAK;AAavC,SAAS,0BACd,UACA,OACA,WACQ;AACR,QAAM,MAAM,SAAS,YAAY;AACjC,MAAI,KAAK,kCAAkC,GAAG,KAAK;AACnD,MAAI,WAAW;AACb,UAAM,KAAK,sBAAsB,WAAW,GAAG;AAC/C,QAAI,OAAO,OAAO,YAAY,KAAK,EAAG,MAAK;AAAA,EAC7C;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM,YAAY,OAAO;AACzB,QAAI,OAAO,cAAc,YAAY,YAAY,GAAI,MAAK;AAAA,EAC5D;AACA,SAAO,KAAK,IAAI,IAAI,oBAAoB;AAC1C;AAEA,SAAS,sBACP,KACA,KACoB;AACpB,MAAI,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG,EAAG,QAAO,IAAI,GAAG;AAClE,aAAW,KAAK,OAAO,KAAK,GAAG,GAAG;AAChC,QAAI,EAAE,YAAY,MAAM,IAAK,QAAO,IAAI,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAYO,SAAS,4BACd,WACQ;AACR,MAAI,KAAK;AACT,aAAW,KAAK,OAAO,OAAO,iCAAiC,GAAG;AAChE,QAAI,IAAI,GAAI,MAAK;AAAA,EACnB;AACA,MAAI,WAAW;AACb,eAAW,KAAK,OAAO,OAAO,SAAS,GAAG;AACxC,UAAI,OAAO,MAAM,YAAY,IAAI,GAAI,MAAK;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,KAAK,IAAI,IAAI,oBAAoB;AAC1C;AAYO,SAAS,uBAAuB,UAAkB,IAAmB;AAC1E,QAAM,MAAM,SAAS,YAAY;AACjC,QAAM,OAAO,eAAe,QAAQ,qBAAqB,EAAE;AAC3D,MAAI,QAAQ,QAAQ;AAClB,WAAO,IAAI;AAAA,MACT,OACE;AAAA,IAKJ;AAAA,EACF;AACA,SAAO,IAAI,MAAM,IAAI;AACvB;AAWO,IAAM,kBACX;AASF,IAAM,sBAAsB;AAG5B,IAAM,oBAAoB;AAWnB,IAAM,sBACX;AA4BK,SAAS,qBACd,iBACoB;AACpB,QAAM,OAAO,iBAAiB,KAAK;AACnC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,QAAQ,mBAAmB;AAC9C,MAAI,UAAU,GAAI,QAAO;AACzB,QAAM,UAAoB,CAAC;AAC3B,aAAW,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM,IAAI,GAAG;AAC/C,UAAM,QAAQ,wBAAwB,KAAK,IAAI,KAAK,CAAC;AACrD,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,UAAM,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC5B,YAAQ;AAAA,MACN,KAAK,IAAI,KACP,MAAM,SAAS,oBACX,GAAG,MAAM,MAAM,GAAG,iBAAiB,EAAE,QAAQ,CAAC,WAC9C,KACN;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO;AAAA,EAAqF,QAAQ,KAAK,IAAI,CAAC;AAChH;AASO,SAAS,4BACd,OACA,iBACgB;AAChB,QAAM,aAAa,qBAAqB,eAAe;AACvD,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,MAAM;AAAA,IAAI,CAAC,MAChB,EAAE,SAAS,SACP,EAAE,GAAG,GAAG,aAAa,GAAG,UAAU;AAAA;AAAA,EAAO,EAAE,WAAW,GAAG,IACzD;AAAA,EACN;AACF;AAQO,SAAS,gCACd,OACA,iBACgB;AAChB,QAAM,OAAO,iBAAiB,KAAK;AACnC,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,MAAM;AAAA,IAAI,CAAC,MAChB,EAAE,SAAS,aACP,EAAE,GAAG,GAAG,aAAa,GAAG,IAAI;AAAA;AAAA,EAAO,mBAAmB,GAAG,IACzD;AAAA,EACN;AACF;AASO,SAAS,qCACd,OACA,qBACgB;AAChB,MAAI,oBAAqB,QAAO;AAChC,SAAO,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU;AAClD;AAEO,IAAM,sBAAsC;AAAA,EACjD;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IAEF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,SAAS;AAAA,IACtB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,SAAS;AAAA,IAClC;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU;AAAA,UACR,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,WAAW;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,WAAW;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,aAAa,WAAW;AAAA,IACjD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IAGF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,KAAK;AAAA,UACH,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,CAAC,QAAQ,YAAY,MAAM;AAAA,UACjC,aACE;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE,wVAMA;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,aAAa;AAAA,UACX,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,eAAe;AAAA,UACb,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aACE;AAAA,QAGJ;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC,eAAe,UAAU,eAAe;AAAA,IACrD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE,qVAMA;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,WAAW;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,UACb,OAAO;AAAA,YACL,MAAM;AAAA,YACN,YAAY;AAAA,cACV,UAAU;AAAA,gBACR,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,cACA,QAAQ;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,cACf;AAAA,cACA,SAAS;AAAA,gBACP,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,OAAO;AAAA,kBACL,MAAM;AAAA,kBACN,YAAY;AAAA,oBACV,OAAO;AAAA,sBACL,MAAM;AAAA,sBACN,aAAa;AAAA,oBACf;AAAA,oBACA,aAAa;AAAA,sBACX,MAAM;AAAA,sBACN,aAAa;AAAA,oBACf;AAAA,kBACF;AAAA,kBACA,UAAU,CAAC,SAAS,aAAa;AAAA,gBACnC;AAAA,cACF;AAAA,cACA,UAAU;AAAA,gBACR,MAAM;AAAA,gBACN,aACE;AAAA,cACJ;AAAA,YACF;AAAA,YACA,UAAU,CAAC,YAAY,UAAU,SAAS;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU,CAAC,WAAW;AAAA,IACxB;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,QAAwB,qBACxB,kBACyB;AACzB,QAAM,QAAQ,IAAIC,cAAa;AAC/B,QAAM,UAAU,oBAAI,IAA2B;AAE/C,QAAMC,UAAS,aAAa,OAAO,KAAK,QAAQ;AAC9C,QAAI,IAAI,WAAW,UAAU,CAAC,IAAI,KAAK,WAAW,MAAM,GAAG;AACzD,UAAI,aAAa;AACjB,UAAI,IAAI;AACR;AAAA,IACF;AASA,QAAI,YAAoC;AACxC,QAAI,gBAA+B;AACnC,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,YAAM,UAAU,KAAK,MAAM,IAAI;AAM/B,kBAAY,SAAS,MAAM;AAC3B,sBAAgB,OAAO,SAAS,WAAW,WAAW,QAAQ,SAAS;AAEvE,UAAI,SAAS,YAAY,SAAS,OAAO,QAAQ,WAAW,UAAU;AACpE,kBAAU,KAAK;AAAA,UACb,SAAS;AAAA,UACT,IAAI;AAAA,UACJ,OAAO,EAAE,MAAM,QAAQ,SAAS,kBAAkB;AAAA,QACpD,CAAC;AACD;AAAA,MACF;AAEA,UAAI,MAAM,qBAAqB;AAAA,QAC7B,QAAQ,QAAQ;AAAA,QAChB,IAAI,QAAQ;AAAA,MACd,CAAC;AAED,UAAI,QAAQ,WAAW,cAAc;AACnC,kBAAU,KAAK;AAAA,UACb,SAAS;AAAA,UACT,IAAI;AAAA,UACJ,QAAQ;AAAA,YACN,iBAAiB;AAAA,YACjB,cAAc,EAAE,OAAO,CAAC,EAAE;AAAA,YAC1B,YAAY;AAAA,cACV,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,6BAA6B;AAClD,YAAI,aAAa;AACjB,YAAI,IAAI;AACR;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,cAAc;AACnC,kBAAU,KAAK;AAAA,UACb,SAAS;AAAA,UACT,IAAI;AAAA,UACJ,QAAQ;AAAA,YACN,OAAO,MAAM,IAAI,CAAC,OAAO;AAAA,cACvB,MAAM,EAAE;AAAA,cACR,aAAa,EAAE;AAAA,cACf,aAAa,EAAE;AAAA,YACjB,EAAE;AAAA,UACJ;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,cAAc;AACnC,cAAM,SAAS,QAAQ,UAAU,CAAC;AAClC,cAAM,WAAW,OAAO,OAAO,QAAQ,EAAE;AACzC,cAAM,QAAS,OAAO,aAAa,CAAC;AAEpC,YAAI,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,GAAG;AAK3C,oBAAU,KAAK;AAAA,YACb,SAAS;AAAA,YACT,IAAI;AAAA,YACJ,QAAQ;AAAA,cACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,uBAAuB,QAAQ,GAAG,CAAC;AAAA,cACnE,SAAS;AAAA,YACX;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAEA,cAAM,SAAgB,mBAAW;AACjC,YAAI,KAAK,gCAAgC;AAAA,UACvC;AAAA,UACA;AAAA,UACA,UAAU,SAAS;AAAA,QACrB,CAAC;AAED,YAAI,QAA8C;AAClD,cAAM,SAAS,MAAM,IAAI;AAAA,UACvB,CAACC,UAAS,WAAW;AACnB,kBAAM,QAAuB;AAAA,cAC3B,IAAI;AAAA,cACJ;AAAA,cACA;AAAA,cACA,SAAAA;AAAA,cACA;AAAA,YACF;AACA,oBAAQ,IAAI,QAAQ,KAAK;AACzB,kBAAM,aAAa;AAAA,cACjB;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,oBAAQ,WAAW,MAAM;AACvB,kBAAI,CAAC,QAAQ,IAAI,MAAM,EAAG;AAC1B,sBAAQ,OAAO,MAAM;AAKrB,kBAAI,OAAO,iCAAiC;AAAA,gBAC1C;AAAA,gBACA;AAAA,gBACA;AAAA,cACF,CAAC;AACD,qBAAO,uBAAuB,UAAU,UAAU,CAAC;AAAA,YACrD,GAAG,UAAU;AACb,kBAAM,KAAK,QAAQ,KAAK;AAAA,UAC1B;AAAA,QACF,EAAE,QAAQ,MAAM;AACd,cAAI,MAAO,cAAa,KAAK;AAC7B,kBAAQ,OAAO,MAAM;AAAA,QACvB,CAAC;AAOD,cAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,OAAO;AAC/D,cAAM,UAAU,OAAO,SAAS,WAAW,OAAO,YAAY;AAC9D,kBAAU,KAAK;AAAA,UACb,SAAS;AAAA,UACT,IAAI;AAAA,UACJ,QAAQ;AAAA,YACN,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,YAChC;AAAA,UACF;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,gBAAU,KAAK;AAAA,QACb,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,OAAO,EAAE,MAAM,QAAQ,SAAS,mBAAmB,QAAQ,MAAM,GAAG;AAAA,MACtE,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,YAAM,QAAQ,uBAAuB,YAAY,IAAI,IAAI,SAAS,IAAI;AACtE,YAAM,oCAAoC;AAAA,QACxC,OAAO;AAAA,MACT,CAAC;AAKD,UAAI,kBAAkB,cAAc;AAClC,YAAI;AACF,oBAAU,KAAK;AAAA,YACb,SAAS;AAAA,YACT,IAAI;AAAA,YACJ,QAAQ;AAAA,cACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,aAAa,CAAC;AAAA,cAC9C,SAAS;AAAA,YACX;AAAA,UACF,CAAC;AAAA,QACH,QAAQ;AACN,cAAI;AACF,gBAAI,aAAa;AACjB,gBAAI,IAAI;AAAA,UACV,QAAQ;AAAA,UAAC;AAAA,QACX;AACA;AAAA,MACF;AACA,UAAI;AAIF,kBAAU,KAAK;AAAA,UACb,SAAS;AAAA,UACT,IAAI;AAAA,UACJ,OAAO;AAAA,YACL,MAAM;AAAA,YACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UACpD;AAAA,QACF,CAAC;AAAA,MACH,QAAQ;AACN,YAAI;AACF,cAAI,aAAa;AACjB,cAAI,IAAI;AAAA,QACV,QAAQ;AAAA,QAAC;AAAA,MACX;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,IAAI,QAAc,CAACA,UAAS,WAAW;AAC3C,IAAAD,QAAO,KAAK,SAAS,MAAM;AAC3B,IAAAA,QAAO,OAAO,GAAG,aAAa,MAAM;AAClC,MAAAA,QAAO,IAAI,SAAS,MAAM;AAC1B,MAAAC,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAED,QAAM,OAAOD,QAAO,QAAQ;AAC5B,MAAI,CAAC,MAAM;AACT,IAAAA,QAAO,MAAM;AACb,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,QAAM,MAAM,oBAAoB,KAAK,IAAI;AAEzC,MAAI,KAAK,4BAA4B;AAAA,IACnC;AAAA,IACA,OAAO,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EAChC,CAAC;AAED,MAAI,iBAAgC;AAEpC,QAAM,MAAsB;AAAA,IAC1B;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,aAAa;AACX,UAAI,eAAgB,QAAO;AAC3B,YAAM,OAAO,KAAK;AAAA,QAChB;AAAA,UACE,YAAY;AAAA,YACV,CAAC,WAAW,GAAG;AAAA,cACb,MAAM;AAAA,cACN;AAAA,cACA,SAAS,4BAA4B,gBAAgB;AAAA,YACvD;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,OACH,mBAAW,QAAQ,EACnB,OAAO,IAAI,EACX,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AACd,YAAM,UAAe;AAAA,QACnB,aAAa;AAAA,QACb,SAAS,IAAI;AAAA,MACf;AACA,MAAG,kBAAc,SAAS,MAAM,EAAE,UAAU,QAAQ,MAAM,IAAM,CAAC;AACjE,uBAAiB;AACjB,aAAO;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AACZ,iBAAW,SAAS,QAAQ,OAAO,GAAG;AACpC,cAAM,OAAO,IAAI,MAAM,qBAAqB,CAAC;AAAA,MAC/C;AACA,cAAQ,MAAM;AACd,YAAM,IAAI,QAAc,CAACC,aAAY;AACnC,QAAAD,QAAO,MAAM,MAAMC,SAAQ,CAAC;AAAA,MAC9B,CAAC;AACD,UAAI,gBAAgB;AAClB,YAAI;AACF,UAAG,eAAW,cAAc;AAAA,QAC9B,QAAQ;AAAA,QAAC;AACT,yBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,oBAAoB,OAAiC;AAWnE,QAAM,UAAoC;AAAA,IACxC,MAAM,CAAC,MAAM;AAAA,IACb,MAAM,CAAC,MAAM;AAAA,IACb,OAAO,CAAC,OAAO;AAAA,IACf,MAAM,CAAC,QAAQ,WAAW;AAAA,IAC1B,MAAM,CAAC,MAAM;AAAA,IACb,MAAM,CAAC,MAAM;AAAA,IACb,UAAU,CAAC,UAAU;AAAA,IACrB,MAAM,CAAC,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMd,UAAU,CAAC,iBAAiB;AAAA,EAC9B;AACA,QAAM,MAAgB,CAAC;AACvB,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,OAAO;AACrB,UAAM,SAAS,QAAQ,EAAE,KAAK,YAAY,CAAC;AAC3C,QAAI,CAAC,OAAQ;AACb,eAAW,cAAc,QAAQ;AAC/B,UAAI,KAAK,IAAI,UAAU,EAAG;AAC1B,WAAK,IAAI,UAAU;AACnB,UAAI,KAAK,UAAU;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,KAAuC;AACvD,SAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,QAAI,GAAG,OAAO,MAAMA,SAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC,CAAC;AACnE,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEA,SAAS,UAAU,KAAqB,MAAqB;AAC3D,QAAM,UAAU,KAAK,UAAU,IAAI;AACnC,MAAI,aAAa;AACjB,MAAI,UAAU,gBAAgB,kBAAkB;AAChD,MAAI,UAAU,kBAAkB,OAAO,WAAW,OAAO,EAAE,SAAS,CAAC;AACrE,MAAI,IAAI,OAAO;AACjB;;;AC33BA,SAAS,gBAAAC,qBAAoB;AAyB7B,IAAM,kBAAkB,oBAAI,IAA6B;AAGzD,IAAM,mBAAmB,oBAAI,IAAyB;AAEtD,IAAM,UAAU,IAAIC,cAAa;AAEjC,SAAS,UAAUC,aAAoB;AACrC,SAAO,WAAWA,WAAU;AAC9B;AAEA,SAAS,SAASA,aAAoB,QAAgB;AACpD,MAAI,IAAI,iBAAiB,IAAIA,WAAU;AACvC,MAAI,CAAC,GAAG;AACN,QAAI,oBAAI,IAAI;AACZ,qBAAiB,IAAIA,aAAY,CAAC;AAAA,EACpC;AACA,IAAE,IAAI,MAAM;AACd;AAEA,SAAS,YAAYA,aAAoB,QAAgB;AACvD,QAAM,IAAI,iBAAiB,IAAIA,WAAU;AACzC,MAAI,CAAC,EAAG;AACR,IAAE,OAAO,MAAM;AACf,MAAI,EAAE,SAAS,EAAG,kBAAiB,OAAOA,WAAU;AACtD;AAEO,SAAS,mBACdA,aACA,SACY;AACZ,QAAM,OAAO,UAAUA,WAAU;AACjC,UAAQ,GAAG,MAAM,OAAO;AACxB,SAAO,MAAM,QAAQ,IAAI,MAAM,OAAO;AACxC;AAEO,SAAS,sBACdA,aACA,MACA,kBACkB;AAIlB,QAAM,WAAW,gBAAgB,IAAI,KAAK,EAAE;AAC5C,MAAI,UAAU;AACZ,iBAAa,SAAS,KAAK;AAC3B,aAAS;AAAA,MACP,IAAI,MAAM,+BAA+B,KAAK,EAAE,mBAAmB;AAAA,IACrE;AACA,oBAAgB,OAAO,KAAK,EAAE;AAC9B,gBAAY,SAAS,YAAY,KAAK,EAAE;AAAA,EAC1C;AAEA,QAAM,aAAa;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,EACF;AAEA,QAAM,QAAQ,WAAW,MAAM;AAC7B,UAAM,UAAU,gBAAgB,IAAI,KAAK,EAAE;AAC3C,QAAI,CAAC,QAAS;AACd,oBAAgB,OAAO,KAAK,EAAE;AAC9B,gBAAY,QAAQ,YAAY,KAAK,EAAE;AACvC,YAAQ,OAAO,uBAAuB,KAAK,UAAU,UAAU,CAAC;AAIhE,QAAI,OAAO,gCAAgC;AAAA,MACzC,YAAY,QAAQ;AAAA,MACpB,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH,GAAG,UAAU;AAEb,QAAM,UAA2B;AAAA,IAC/B,YAAAA;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,EACf;AACA,kBAAgB,IAAI,KAAK,IAAI,OAAO;AACpC,WAASA,aAAY,KAAK,EAAE;AAC5B,UAAQ,KAAK,UAAUA,WAAU,GAAG,OAAO;AAC3C,MAAI,KAAK,6BAA6B;AAAA,IACpC,YAAAA;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,UAAU,KAAK;AAAA,EACjB,CAAC;AACD,SAAO;AACT;AAEO,SAAS,qBAAqBA,aAAwC;AAC3E,QAAM,IAAI,iBAAiB,IAAIA,WAAU;AACzC,MAAI,CAAC,KAAK,EAAE,SAAS,EAAG,QAAO,CAAC;AAChC,QAAM,MAA0B,CAAC;AACjC,aAAW,MAAM,GAAG;AAClB,UAAM,IAAI,gBAAgB,IAAI,EAAE;AAChC,QAAI,EAAG,KAAI,KAAK,CAAC;AAAA,EACnB;AACA,SAAO;AACT;AAEO,SAAS,4BACd,YACA,QACS;AACT,QAAM,UAAU,gBAAgB,IAAI,UAAU;AAC9C,MAAI,CAAC,QAAS,QAAO;AACrB,kBAAgB,OAAO,UAAU;AACjC,cAAY,QAAQ,YAAY,UAAU;AAC1C,eAAa,QAAQ,KAAK;AAC1B,UAAQ,QAAQ,MAAM;AACtB,MAAI,KAAK,+BAA+B;AAAA,IACtC,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ;AAAA,EACpB,CAAC;AACD,SAAO;AACT;AAEO,SAAS,2BACd,YACA,OACS;AACT,QAAM,UAAU,gBAAgB,IAAI,UAAU;AAC9C,MAAI,CAAC,QAAS,QAAO;AACrB,kBAAgB,OAAO,UAAU;AACjC,cAAY,QAAQ,YAAY,UAAU;AAC1C,eAAa,QAAQ,KAAK;AAC1B,UAAQ,OAAO,KAAK;AAIpB,MAAI,OAAO,+BAA+B;AAAA,IACxC,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ;AAAA,IAClB,OAAO,MAAM;AAAA,EACf,CAAC;AACD,SAAO;AACT;AAEO,SAAS,qCACdA,aACA,OACQ;AACR,QAAM,IAAI,iBAAiB,IAAIA,WAAU;AACzC,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,MAAM,CAAC,GAAG,CAAC;AACjB,MAAI,QAAQ;AACZ,aAAW,MAAM,KAAK;AACpB,QAAI,2BAA2B,IAAI,KAAK,EAAG;AAAA,EAC7C;AACA,SAAO;AACT;;;AdnHA,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,UAAAC,eAAc;AACvB,SAAS,WAAAC,UAAS,UAAAC,eAAc;AAChC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AASvB,IAAM,2BAA2B;AAWjC,SAAS,uBAAuB,YAA6B;AAClE,QAAM,MAAM,QAAQ,IAAI,8BAA8B,KAAK;AAC3D,MAAI,IAAK,QAAO;AAChB,QAAM,UAAU,YAAY,KAAK;AACjC,MAAI,QAAS,QAAO;AACpB,SAAO;AACT;AAsBO,SAAS,uBACd,SACA,iBACA,aACQ;AACR,MAAI,SAAS;AACX,eAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACtC,UAAI,IAAI,YAAY,MAAM,sBAAsB;AAC9C,cAAM,IAAI,QAAQ,GAAG;AACrB,YAAI,OAAO,MAAM,YAAY,EAAE,SAAS,EAAG,QAAO;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,MAAI,iBAAiB;AACnB,UAAM,MACH,gBAAwB,WAAW,KACnC,gBAAwB,aAAa;AACxC,UAAM,MAAM,KAAK;AACjB,QAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,EAAG,QAAO;AAAA,EACxD;AACA,SAAO;AACT;AAQA,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWM,SAAS,kBACd,QACS;AACT,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,MAAM,OAAO,CAAC;AACpB,QAAI,IAAI,SAAS,YAAa,QAAO;AAMrC,QAAI,IAAI,SAAS,QAAQ;AACvB,YAAMC,WAAe,IAAI;AACzB,UAAI,MAAM,QAAQA,QAAO,GAAG;AAC1B,mBAAW,QAAQA,UAAkB;AACnC,cAAI,MAAM,SAAS,cAAe,QAAO;AAAA,QAC3C;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,IAAI,SAAS,OAAQ;AACzB,UAAM,UAAe,IAAI;AACzB,QAAI,OAAO,YAAY,UAAU;AAC/B,UAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,iBAAW,QAAQ,SAAkB;AACnC,YAAI,KAAK,SAAS,UAAU,KAAK,QAAQ,KAAK,KAAK,KAAK,EAAG,QAAO;AAClE,YAAI,KAAK,SAAS,cAAe,QAAO;AAGxC,YAAI,KAAK,SAAS,WAAW,KAAK,SAAS,OAAQ,QAAO;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,6BAA6B;AACnC,IAAM,+BAA+B,KAAK,KAAK;AAC/C,IAAM,kCAAkC;AACxC,IAAM,iCAAiC;AAEvC,IAAM,uBACJ;AA4DF,SAAS,qBAAqB,MAAsB;AAClD,SAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACxC;AAGO,SAAS,sBAAsB,MAAmC;AACvE,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,IAAI,KAAK,YAAY;AAC3B,SAAO,MAAM,qBAAqB,MAAM;AAC1C;AAeA,IAAM,iCACJ;AASK,SAAS,mBACd,UACA,uBACQ;AACR,MAAI,sBAAsB,QAAQ,EAAG,QAAO;AAC5C,SACE,yBACA,kDAAkD,QAAQ;AAE9D;AAgBA,SAAS,sBAAsB,OAAwC;AACrE,QAAM,WAAW;AACjB,QAAM,YAAmB,MAAM,QAAQ,UAAU,SAAS,IACtD,SAAS,YACT,CAAC;AAEL,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,SAAS,UAAU,YAAY,UAAU;AAC/C,UAAM,IACJ,OAAO,WAAW,YAAY,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI;AAChE,WAAO;AAAA;AAAA,IAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EACnB;AAEA,QAAM,MAAgB,CAAC,MAAM;AAC7B,QAAM,SAAS,UAAU,SAAS;AAClC,YAAU,QAAQ,CAAC,GAAG,MAAM;AAC1B,UAAM,OACH,OAAO,GAAG,aAAa,YAAY,EAAE,SAAS,KAAK,KACnD,OAAO,GAAG,SAAS,YAAY,EAAE,KAAK,KAAK,KAC5C;AACF,UAAM,SACJ,OAAO,GAAG,WAAW,YAAY,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,KAAK,IAAI;AACvE,QAAI,KAAK,KAAK,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI;AACnD,QAAI,OAAQ,KAAI,KAAK,MAAM,MAAM,IAAI;AACrC,QAAI,KAAK,MAAM;AAEf,UAAM,UAAiB,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,UAAU,CAAC;AAChE,YAAQ,QAAQ,CAAC,KAAK,MAAM;AAC1B,YAAM,QACH,OAAO,KAAK,UAAU,YAAY,IAAI,MAAM,KAAK,KACjD,OAAO,QAAQ,YAAY,IAAI,KAAK,KACrC,UAAU,IAAI,CAAC;AACjB,YAAM,OACJ,OAAO,KAAK,gBAAgB,YAAY,IAAI,YAAY,KAAK,IACzD,WAAM,IAAI,YAAY,KAAK,CAAC,KAC5B;AACN,UAAI,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI;AAAA,CAAI;AAAA,IAC5C,CAAC;AAED,QAAI;AAAA,MACF,GAAG,gBAAgB,OACf,wEACA;AAAA,IACN;AAAA,EACF,CAAC;AACD,SAAO,IAAI,KAAK,EAAE;AACpB;AAEA,SAAS,kBAAkB,MAAuB;AAChD,QAAM,aAAa,qBAAqB,IAAI,EAAE,YAAY;AAC1D,MAAI,CAAC,WAAY,QAAO;AAKxB,MAAI,WAAW,SAAS,GAAG,EAAG,QAAO;AAcrC,SAAO,wjBAAwjB,KAAK,UAAU;AAChlB;AAEA,SAAS,iBAAiB,MAAuB;AAC/C,QAAM,aAAa,qBAAqB,IAAI,EAAE,YAAY;AAC1D,MAAI,CAAC,WAAY,QAAO;AAGxB,SAAO,uOAAuO,KAAK,UAAU;AAC/P;AAEA,SAAS,qBAAqB,MAAuB;AACnD,QAAM,aAAa,qBAAqB,IAAI,EAAE,YAAY;AAC1D,MAAI,kBAAkB,UAAU,KAAK,iBAAiB,UAAU,EAAG,QAAO;AAI1E,MAAI,iDAAiD,KAAK,UAAU,GAAG;AACrE,WAAO;AAAA,EACT;AAIA,MAAI,WAAW,SAAS,GAAI,QAAO;AAKnC,SAAO,uIAAuI,KAAK,UAAU;AAAA;AAAA;AAAA,EAI3J,8CAA8C,KAAK,UAAU,KAC7D,0CAA0C,KAAK,UAAU;AAC7D;AAEA,SAAS,sBAAsB,UAAwC;AACrE,QAAM,OAAO,qBAAqB,SAAS,IAAI,EAAE,MAAM,IAAI;AAC3D,SAAO,KAAK,UAAU;AAAA,IACpB;AAAA,IACA,WAAW,SAAS;AAAA,IACpB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,EAClB,CAAC;AACH;AAEO,SAAS,iCACd,OACA,UACsB;AACtB,MAAI,MAAM,YAAY,MAAO,QAAO,EAAE,UAAU,OAAO,QAAQ,WAAW;AAC1E,MAAI,SAAS,QAAS,QAAO,EAAE,UAAU,OAAO,QAAQ,QAAQ;AAChE,MAAI,MAAM,QAAS,QAAO,EAAE,UAAU,OAAO,QAAQ,UAAU;AAI/D,MAAI,MAAM,mBAAoB,QAAO,EAAE,UAAU,OAAO,QAAQ,WAAW;AAO3E,MAAI,SAAS,YAAY;AACvB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,SAAS,WAAW,QAAQ,MAAM,GAAG;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,MAAM,YAAY,4BAA4B;AAChD,WAAO,EAAE,UAAU,OAAO,QAAQ,eAAe;AAAA,EACnD;AACA,QAAM,MAAM,SAAS,OAAO,KAAK,IAAI;AACrC,MAAI,MAAM,MAAM,YAAY,8BAA8B;AACxD,WAAO,EAAE,UAAU,OAAO,QAAQ,cAAc;AAAA,EAClD;AAEA,QAAM,OAAO,qBAAqB,SAAS,IAAI;AAC/C,QAAM,WAAW,qBAAqB,SAAS,eAAe;AAC9D,MAAI,kBAAkB,IAAI,EAAG,QAAO,EAAE,UAAU,OAAO,QAAQ,WAAW;AAC1E,MAAI,iBAAiB,IAAI,EAAG,QAAO,EAAE,UAAU,OAAO,QAAQ,UAAU;AAKxE,MAAI,qBAAqB,QAAQ,GAAG;AAClC,WAAO,EAAE,UAAU,OAAO,QAAQ,eAAe;AAAA,EACnD;AAEA,QAAM,cACJ,SAAS,gBAAgB,SAAS,mBAAmB,SAAS;AAChE,MAAI,CAAC,YAAa,QAAO,EAAE,UAAU,OAAO,QAAQ,cAAc;AAElE,QAAM,YAAY,sBAAsB,QAAQ;AAChD,QAAM,aAAa,cAAc,MAAM;AACvC,MAAI,cAAc,MAAM,kBAAkB,KAAK,iCAAiC;AAC9E,WAAO,EAAE,UAAU,OAAO,QAAQ,cAAc;AAAA,EAClD;AAEA,MAAI,CAAC,MAAM;AACT,WAAO,EAAE,UAAU,MAAM,QAAQ,kCAAkC;AAAA,EACrE;AAEA,SAAO,EAAE,UAAU,MAAM,QAAQ,qBAAqB;AACxD;AAEA,SAAS,0BAAkC;AACzC,SAAO,KAAK,UAAU;AAAA,IACpB,MAAM;AAAA,IACN,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,qBAAqB,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AACH;AAEA,SAAS,wBAAwBC,OAAkC;AACjE,MAAI;AACF,UAAM,UAAUT,cAAaS,OAAM,MAAM,EAAE,KAAK;AAChD,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,6BAA6B,KAAiC;AACrE,MAAI,MAAM;AACV,SAAO,MAAM;AACX,UAAM,UAAU,wBAAwBF,MAAK,KAAK,WAAW,CAAC;AAC9D,QAAI,QAAS,QAAO;AACpB,UAAM,SAASD,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAEA,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAMhC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBtB,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoB/B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBnC,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBhC,SAAS,sBACP,QACU;AACV,QAAM,MAAgB,CAAC;AACvB,aAAW,OAAO,QAAQ;AACxB,QAAI,IAAI,SAAS,SAAU;AAC3B,QAAI,OAAO,IAAI,YAAY,UAAU;AACnC,UAAI,IAAI,QAAQ,KAAK,EAAG,KAAI,KAAK,IAAI,QAAQ,KAAK,CAAC;AAAA,IACrD,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AACrC,iBAAW,QAAQ,IAAI,SAAkB;AACvC,YACE,MAAM,SAAS,UACf,OAAO,KAAK,SAAS,YACrB,KAAK,KAAK,KAAK,GACf;AACA,cAAI,KAAK,KAAK,KAAK,KAAK,CAAC;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,0BACd,KACA,uBAAuB,MACvB,qBAA+B,CAAC,GACZ;AACpB,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,uBAAuB;AAClC,aAAW,KAAK,oBAAoB;AAClC,QAAI,EAAE,KAAK,EAAG,OAAM,KAAK,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,aACJ,QAAQ,IAAI,mBAAmBC,MAAKJ,SAAQ,GAAG,SAAS;AAC1D,QAAM,eAAe,wBAAwBI,MAAK,YAAY,YAAY,WAAW,CAAC;AACtF,QAAM,kBAAkB,6BAA6B,GAAG;AAExD,MAAI,aAAc,OAAM,KAAK,YAAY;AACzC,MAAI,mBAAmB,oBAAoB,aAAc,OAAM,KAAK,eAAe;AACnF,MAAI,gBAAgB,gBAAiB,OAAM,KAAK,uBAAuB;AACvE,MAAI,qBAAsB,OAAM,KAAK,oBAAoB;AAEzD,QAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,CAAC,QAAS,QAAO;AAErB,QAAME,QAAOF,MAAKH,QAAO,GAAG,mBAAmBC,YAAW,CAAC,KAAK;AAChE,MAAI;AACF,IAAAJ,eAAcQ,OAAM,SAAS,MAAM;AACnC,WAAOA;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,KAAK,sCAAsC,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AACrE,WAAO;AAAA,EACT;AACF;AAEO,IAAM,0BAAN,MAAyD;AAAA,EACrD,uBAAuB;AAAA,EACvB;AAAA,EACQ;AAAA,EAEjB,YAAY,SAAiB,QAA0B;AACrD,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAChB;AAAA,EAES,gBAA0C,CAAC;AAAA,EAEpD,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEQ,QAAQ,UAA+D;AAI7E,UAAM,OAAO,UAAU;AACvB,UAAM,YAAY,MAAM,SAAS,KAAK,KAAK,SAAS,CAAC,IAAI;AAGzD,UAAM,UAAU,WAAW,gBAAgB;AAC3C,UAAM,YAAY,WAAW,2BAA2B;AACxD,UAAM,aAAa,WAAW,+BAA+B;AAC7D,WAAO;AAAA,MACL,aAAa;AAAA,QACX,OAAO,UAAU,YAAY;AAAA,QAC7B;AAAA,QACA,WAAW,aAAa;AAAA,QACxB,YAAY,cAAc;AAAA,MAC5B;AAAA,MACA,cAAc;AAAA,QACZ,OAAO,WAAW;AAAA,QAClB,MAAM,WAAW;AAAA,QACjB,WAAW;AAAA,MACb;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,eACN,SAAgC,QACH;AAC7B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,aAAa,SAAoD;AACvE,UAAM,QAAQ,SAAS;AACvB,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,aAAO,OAAO,KAAK,KAAgC,EAAE,SAAS,IAC1D,UACA;AAAA,IACN;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,mBACN,KACA,iBACA,eACA,gBAKA;AACA,UAAM,QAAQ,MAAM,QAAQ,KAAK,OAAO,SAAS,IAC7C,KAAK,OAAO,UAAU,MAAM,IAC5B,KAAK,OAAO,YACV,CAAC,KAAK,OAAO,SAAS,IACtB,CAAC;AACP,QAAI,cAA6B;AACjC,QAAI,wBAAkC,CAAC;AACvC,QAAI,KAAK,OAAO,sBAAsB,OAAO;AAC3C,YAAM,UAAU,kBAAkB,KAAK,eAAe,cAAc;AACpE,UAAI,SAAS;AACX,YAAI,QAAQ,KAAM,OAAM,KAAK,QAAQ,IAAI;AACzC,sBAAc,QAAQ;AACtB,gCAAwB,QAAQ;AAAA,MAClC;AAAA,IACF;AACA,QAAI,gBAAiB,OAAM,KAAK,eAAe;AAC/C,WAAO,EAAE,OAAO,aAAa,sBAAsB;AAAA,EACrD;AAAA;AAAA,EAGQ,qBAA4C;AAClD,UAAM,QAAQ,KAAK,OAAO;AAC1B,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,UAAM,aAAa,IAAI;AAAA,MACrB,oBAAoB,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,YAAY,GAAG,CAAC,CAAC;AAAA,IAC1D;AACA,UAAM,SAAyB,CAAC;AAChC,eAAW,KAAK,OAAO;AACrB,YAAM,MAAM,WAAW,IAAI,OAAO,CAAC,EAAE,YAAY,CAAC;AAClD,UAAI,IAAK,QAAO,KAAK,GAAG;AAAA,IAC1B;AACA,WAAO,OAAO,SAAS,IAAI,SAAS;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,sBACZ,uBACgC;AAChC,QAAI,KAAK,OAAO,0BAA0B,MAAO,QAAO;AACxD,QAAI,KAAK,OAAO,sBAAsB,MAAO,QAAO;AACpD,QAAI,sBAAsB,WAAW,EAAG,QAAO;AAE/C,UAAM,QAAQ,MAAM;AAAA,MAClB,KAAK,OAAO;AAAA,MACZ,KAAK;AAAA,MACL,KAAK,OAAO;AAAA,IACd;AACA,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AAKzC,UAAM,sBAAsB,CAAC,GAAG,qBAAqB,EAAE;AAAA,MACrD,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE;AAAA,IACzB;AACA,UAAM,MAAsB,CAAC;AAC7B,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,QAAQ,OAAO;AACxB,YAAM,gBAAgB,oBAAoB;AAAA,QACxC,CAAC,SAAS,KAAK,OAAO,QAAQ,KAAK,GAAG,WAAW,GAAG,IAAI,GAAG;AAAA,MAC7D;AACA,UAAI,CAAC,cAAe;AACpB,UAAI,KAAK,IAAI,KAAK,EAAE,EAAG;AACvB,WAAK,IAAI,KAAK,EAAE;AAChB,UAAI,KAAK;AAAA,QACP,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe;AAAA,QACjC,aACE,KAAK,cAAc,OAAO,KAAK,eAAe,WAC1C,KAAK,aACL,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,MACzC,CAAC;AAAA,IACH;AACA,WAAO,IAAI,SAAS,IAAI,MAAM;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAc,oBAA2C;AACvD,UAAM,QAAQ,MAAM;AAAA,MAClB,KAAK,OAAO;AAAA,MACZ,KAAK;AAAA,MACL,KAAK,OAAO;AAAA,IACd;AACA,UAAM,WAAW,OAAO,KAAK,CAAC,SAAS,KAAK,OAAO,UAAU;AAC7D,WAAO;AAAA,MACL,UAAU,UAAU;AAAA,MACpB,iBAAiB,OAAO,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM,GAAG;AAAA,MAC5D,qBAAqB,UAAU;AAAA,MAC/B,aAAa,CAAC,CAAC;AAAA,IACjB;AAAA,EACF;AAAA;AAAA,EAGQ,2BAAwD;AAC9D,QAAI;AACJ,WAAO,MAAM;AACX,kBAAY,KAAK,kBAAkB;AACnC,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,wBACZ,gBACA,mBAAmB,MAAM,KAAK,kBAAkB,GAC9B;AAClB,QAAI,kBAAkB,KAAK,OAAO,qBAAqB,KAAM,QAAO;AACpE,UAAM,OAAO,MAAM,iBAAiB;AACpC,UAAM,SAAS,yBAAyB;AAAA,MACtC,YAAY,KAAK,OAAO;AAAA,MACxB,qBAAqB,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,QAAI,CAAC,QAAQ;AAIX,UAAI,KAAK,2BAA2B;AAAA,QAClC,qBAAqB,KAAK;AAAA,QAC1B,kBAAkB,KAAK;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,kBACZ,OACA,oBACyB;AACzB,UAAM,mBAAmB,KAAK,OAAO;AACrC,UAAM,MAAM,MAAM,qBAAqB,OAAO,gBAAgB;AAC9D,QAAI,MAAM,GAAG,QAAQ,CAAC,SAAwB;AAC5C,4BAAsB,oBAAoB,MAAM,gBAAgB;AAAA,IAClE,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,0BACN,QACA,YACwB;AACxB,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,IAAI,SAAS,UAAU,CAAC,MAAM,QAAQ,IAAI,OAAO,EAAG;AAExD,iBAAW,QAAQ,IAAI,SAAS;AAC9B,YAAI,KAAK,SAAS,iBAAiB,KAAK,eAAe,WAAY;AAEnE,cAAM,SAAS,KAAK;AACpB,YAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,MAAM,OAAO,UAAU,EAAE;AAAA,UAC3B;AAAA,QACF;AAEA,YAAI,OAAO,SAAS,QAAQ;AAC1B,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,MAAM,OAAO,OAAO,SAAS,EAAE;AAAA,UACjC;AAAA,QACF;AAEA,YAAI,OAAO,SAAS,QAAQ;AAC1B,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,OAAO,KAAK;AAAA,UACnC;AAAA,QACF;AAEA,YAAI,OAAO,SAAS,aAAa,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC5D,gBAAM,OAAO,OAAO,MACjB,OAAO,CAAC,MAAW,GAAG,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EACnE,IAAI,CAAC,MAAW,EAAE,IAAI,EACtB,KAAK,IAAI;AACZ,iBAAO;AAAA,YACL,MAAM;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,KAAK,UAAU,MAAM;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,gBACN,SACQ;AACR,UAAM,UAAW,SAAiB;AAGlC,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,KAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,8BAA8B,UAA0C;AAC9E,UAAM,aAAa,KAAK,OAAO;AAC/B,QAAI,cAAc,UAAU;AAC1B,YAAM,SAAS,WAAW,QAAQ,KAAK,WAAW,SAAS,YAAY,CAAC;AACxE,UAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AAEpD,YAAM,QAAQ,SAAS,YAAY;AACnC,iBAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AACxD,YAAI,IAAI,YAAY,MAAM,UAAU,aAAa,WAAW,aAAa,SAAS;AAChF,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AASA,QAAI,sBAAsB,QAAQ,EAAG,QAAO;AAE5C,WAAO,KAAK,OAAO,0BAA0B;AAAA,EAC/C;AAAA,EAEQ,qBACN,MACA,WACA,UACM;AACN,UAAM,UAAU;AAAA,MACd,MAAM;AAAA,MACN,UAAU;AAAA,QACR,SAAS;AAAA,QACT,YAAY;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,WAAK,OAAO,MAAM,KAAK,UAAU,OAAO,IAAI,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,UAAI,KAAK,oCAAoC;AAAA,QAC3C;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBACN,KACA,MACS;AACT,QAAI,IAAI,SAAS,kBAAmB,QAAO;AAC3C,UAAM,YAAY,IAAI;AACtB,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,aAAa,CAAC,SAAS,QAAS,QAAO;AAE5C,QAAI,QAAQ,YAAY,gBAAgB;AACtC,YAAM,WAAW,QAAQ,aAAa;AACtC,YAAM,WAAW,KAAK,8BAA8B,QAAQ;AAE5D,UAAI,aAAa,SAAS;AACxB,aAAK,qBAAqB,MAAM,WAAW;AAAA,UACzC,UAAU;AAAA,UACV,cAAc,QAAQ,SAAS,CAAC;AAAA,UAChC,WAAW,QAAQ;AAAA,QACrB,CAAC;AACD,YAAI,KAAK,gCAAgC;AAAA,UACvC;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,cAAM,cAAc;AAAA,UAClB;AAAA,UACA,KAAK,OAAO;AAAA,QACd;AACA,aAAK,qBAAqB,MAAM,WAAW;AAAA,UACzC,UAAU;AAAA,UACV,SAAS;AAAA,UACT,WAAW,QAAQ;AAAA,QACrB,CAAC;AACD,YAAI,KAAK,+BAA+B;AAAA,UACtC;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAIA,SAAK,qBAAqB,MAAM,WAAW,CAAC,CAAC;AAC7C,QAAI,MAAM,gCAAgC;AAAA,MACxC;AAAA,MACA,SAAS,QAAQ;AAAA,IACnB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,mBACN,iBAC6B;AAC7B,QAAI,CAAC,gBAAiB,QAAO;AAC7B,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,MACH,gBAAwB,MAAM,KAC9B,gBAAwB,aAAa;AACxC,UAAM,SAAS,KAAK;AACpB,UAAM,QAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,MAAM,SAAS,MAAM,IAAI,SAAS;AAAA,EAC3C;AAAA,EAEQ,iBACN,iBACoB;AACpB,QAAI,CAAC,gBAAiB,QAAO;AAC7B,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,MACH,gBAAwB,MAAM,KAC9B,gBAAwB,aAAa;AACxC,UAAM,QAAQ,KAAK;AACnB,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C;AAAA,EAEQ,iBACN,SACS;AACT,WAAO,KAAK,iBAAiB,QAAQ,eAAe,MAAM;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,yBAAiC;AACvC,WAAO,uBAAuB,KAAK,OAAO,eAAe;AAAA,EAC3D;AAAA,EAEQ,qBAGN;AACA,QAAI,yBAAyB,EAAG,QAAO,CAAC;AAExC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,iBACE,QAAQ,IAAI,wCAAwC,SAChD,eACA;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,eACN,QACQ;AACR,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,IAAI,SAAS,OAAQ;AAEzB,UAAI,OAAO,IAAI,YAAY,UAAU;AACnC,eAAO,OAAO,IAAI,OAAO,EAAE,KAAK;AAAA,MAClC;AAEA,UAAI,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC9B,cAAM,OAAQ,IAAI,QACf,OAAO,CAAC,SAAS,KAAK,SAAS,UAAU,OAAO,KAAK,SAAS,QAAQ,EACtE,IAAI,CAAC,SAAc,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,EAC3C,OAAO,OAAO,EACd,KAAK,GAAG;AACX,YAAI,KAAM,QAAO;AAAA,MACnB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,gBACN,QACQ;AACR,UAAM,SAAS,KAAK,eAAe,MAAM,EACtC,QAAQ,QAAQ,GAAG,EACnB,QAAQ,sBAAsB,GAAG,EACjC,KAAK;AAER,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,OAAO,oBAAI,IAAI;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,QAAQ,OACX,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO,EACd,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,YAAY,CAAC,CAAC;AAEjD,UAAM,UAAU,MAAM,SAAS,IAAI,QAAQ,OAAO,MAAM,GAAG,EAAE,OAAO,OAAO,GACxE,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AAEX,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAc,oBACZ,SAC6D;AAC7D,UAAM,SAAS,MAAM,KAAK,SAAS,OAAO;AAC1C,UAAM,SAAS,OAAO,OAAO,UAAU;AAEvC,QAAI,OAAO;AACX,QAAI,YAAY;AAChB,UAAM,YAAsC,CAAC;AAC7C,QAAI,eAAe,KAAK,eAAe,MAAM;AAC7C,QAAI,QAA8B,KAAK,QAAQ;AAC/C,QAAI;AAEJ,WAAO,MAAM;AACX,YAAM,EAAE,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,cAAS,MAAc,MAAM;AAAA,QAC3B,KAAK;AACH,kBAAS,MAAc,SAAS;AAChC;AAAA,QACF,KAAK;AACH,uBAAc,MAAc,SAAS;AACrC;AAAA,QACF,KAAK;AACH,oBAAU,KAAK;AAAA,YACb,MAAM;AAAA,YACN,YAAa,MAAc;AAAA,YAC3B,UAAW,MAAc;AAAA,YACzB,OAAQ,MAAc;AAAA,YACtB,kBAAmB,MAAc;AAAA,UACnC,CAAQ;AACR;AAAA,QACF,KAAK;AACH,yBAAgB,MAAc,gBAAgB;AAC9C,kBAAS,MAAc,SAAS;AAChC,6BAAoB,MAAc,oBAAoB;AACtD;AAAA,MACJ;AAAA,IACF;AAEA,UAAM,UAAoC,CAAC;AAC3C,QAAI,WAAW;AACb,cAAQ,KAAK,EAAE,MAAM,aAAa,MAAM,UAAU,CAAQ;AAAA,IAC5D;AACA,QAAI,MAAM;AACR,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,iBAAiB,CAAQ;AAAA,IAC9D;AACA,YAAQ,KAAK,GAAG,SAAS;AAEzB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,UAAU;AAAA,QACR,IAAI,WAAW;AAAA,QACf,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,SAC6D;AAC7D,UAAM,WAA8B,CAAC;AACrC,UAAM,MAAM,gBAAgB,KAAK,OAAO,GAAG;AAC3C,UAAM,QAAQ,KAAK,aAAa,OAAc;AAC9C,UAAM,WAAW,KAAK,gBAAgB,OAAO;AAC7C,UAAM,KAAK,WAAW,KAAK,GAAG,KAAK,OAAO,KAAK,KAAK,KAAK,QAAQ,EAAE;AAOnE,UAAM,iBAAiB,KAAK,iBAAiB,OAAO;AAEpD,QACE,UAAU,YACT,KAAK,mBAAmB,KACtB,KAAK,OAAO,0BAA0B,SACrC,KAAK,OAAO,sBAAsB,QACtC;AACA,aAAO,KAAK,oBAAoB,OAAO;AAAA,IACzC;AAMA,QAAI,gBAAgB;AAClB,aAAO,KAAK,oBAAoB,OAAO;AAAA,IACzC;AAEA,QAAI,UAAU,YAAY;AACxB,UAAI,KAAK,kCAAkC;AAAA,QACzC;AAAA,QACA,eAAe,KAAK,iBAAiB,QAAQ,eAAe;AAAA,QAC5D,qBAAqB,QAAQ,kBACzB,OAAO,KAAK,QAAQ,eAAe,IACnC,CAAC;AAAA,MACP,CAAC;AACD,YAAM,OAAO,KAAK,gBAAgB,QAAQ,MAAM;AAChD,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,QAChC,cAAc,KAAK,eAAe,MAAM;AAAA,QACxC,OAAO,KAAK,QAAQ,EAAE,cAAc,GAAG,eAAe,EAAE,CAAC;AAAA,QACzD,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE;AAAA,QAC9B,UAAU;AAAA,UACR,IAAI,WAAW;AAAA,UACf,WAAW,oBAAI,KAAK;AAAA,UACpB,SAAS,KAAK;AAAA,QAChB;AAAA,QACA,kBAAkB;AAAA,UAChB,eAAe;AAAA,YACb,WAAW;AAAA,YACX,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAMA,QAAI,CAAC,kBAAkB,QAAQ,MAAM,GAAG;AACtC,UAAI,KAAK,+CAA+C;AACxD,aAAO;AAAA,QACL,SAAS,CAAC;AAAA,QACV,cAAc,KAAK,eAAe,MAAM;AAAA,QACxC,OAAO,KAAK,QAAQ,EAAE,cAAc,GAAG,eAAe,EAAE,CAAC;AAAA,QACzD,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE;AAAA,QAC9B,UAAU;AAAA,UACR,IAAI,WAAW;AAAA,UACf,WAAW,oBAAI,KAAK;AAAA,UACpB,SAAS,KAAK;AAAA,QAChB;AAAA,QACA,kBAAkB;AAAA,UAChB,eAAe,EAAE,WAAW,MAAM,MAAM,sBAAsB;AAAA,QAChE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,uBACJ,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,WAAW,EACrE,SAAS;AAGd,QAAI,CAAC,sBAAsB;AACzB,4BAAsB,EAAE;AACxB,0BAAoB,EAAE;AAAA,IACxB;AAEA,UAAM,qBAAqB,CAAC,CAAC,mBAAmB,EAAE;AAClD,UAAM,wBAAwB,CAAC,sBAAsB;AAErD,UAAM,kBAAkB,KAAK,mBAAmB,QAAQ,eAAe;AACvE,UAAM,UACJ,kCAAkC,IAAI,QAAQ,MAAa,KAC3D,qBAAqB,QAAQ,QAAQ,uBAAuB,eAAe;AAK7E,UAAM,CAAC,eAAe,YAAY,sBAAsB,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC5E,oBAAoB;AAAA,MACpB,iBAAiB,KAAK,OAAO,OAAO;AAAA,MACpC,KAAK,wBAAwB,cAAc;AAAA,IAC7C,CAAC;AACD,UAAM,mBAAmB;AAAA,MACvB;AAAA,MACA,KAAK,OAAO,0BAA0B;AAAA,MACtC,sBAAsB,QAAQ,MAAM;AAAA,IACtC;AACA,UAAM,UAAU,aAAa;AAAA,MAC3B,YAAY;AAAA,MACZ,iBAAiB,KAAK,OAAO,oBAAoB;AAAA,MACjD,kBAAkB;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,gBAAgB,KAAK,OAAO;AAAA,MAC5B,WAAW,KAAK,mBAAmB,KAAK,QAAW,aAAa,EAAE;AAAA,MAClE,iBAAiB,KAAK,OAAO;AAAA,MAC7B,iBACE,KAAK,OAAO,cAAc,aAAa,CAAC,WAAW,IAAI;AAAA,MACzD,wBAAwB;AAAA,MACxB,GAAG,KAAK,mBAAmB;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,QAAI,KAAK,uBAAuB;AAAA,MAC9B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,YAAY,QAAQ;AAAA,MACpB;AAAA,IACF,CAAC;AAED,UAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,eAAoB;AACnD,UAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM,OAAO,UAAe;AAExD,UAAM,OAAOD,OAAM,KAAK,OAAO,SAAS,SAAS;AAAA,MAC/C;AAAA,MACA,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC9B,KAAK,eAAe;AAAA,QAClB,uBAAuB,KAAK,OAAO;AAAA,MACrC,CAAC;AAAA,MACD,OAAO,QAAQ,aAAa;AAAA,IAC9B,CAAC;AAED,QAAI,kBAAkB;AACpB,WAAK,GAAG,QAAQ,MAAM;AACpB,aAAKR,QAAO,gBAAgB,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAEA,UAAM,KAAKS,iBAAgB,EAAE,OAAO,KAAK,OAAQ,CAAC;AAElD,QAAI,eAAe;AACnB,QAAI,eAAe;AACnB,QAAI,aAKA,CAAC;AACL,UAAM,YAAgE,CAAC;AAMvE,UAAM,kBAAkB,oBAAI,IAG1B;AAKF,QAAI,mBAAmB;AAEvB,UAAM,SAAS,MAAM,IAAI,QAMvB,CAACC,UAAS,WAAW;AACrB,YAAM,UAAU,MAAM;AACpB,YAAI;AACF,cAAI,CAAC,KAAK,UAAU,KAAK,aAAa,KAAM,MAAK,KAAK;AAAA,QACxD,QAAQ;AAAA,QAAC;AAAA,MACX;AAEA,SAAG,GAAG,QAAQ,CAAC,SAAS;AACtB,YAAI,CAAC,KAAK,KAAK,EAAG;AAClB,YAAI;AACF,gBAAM,QAA6B,KAAK,MAAM,IAAI;AAIlD,gBAAM,MACJ,MAAM,SAAS,kBAAkB,MAAM,QACnC,EAAE,GAAG,MAAM,OAAO,YAAY,MAAM,WAAW,IAC/C;AAEN,cAAI,MAAM,SAAS,gBAAgB;AACjC,+BAAmB;AAAA,UACrB;AAEA,cAAI,KAAK,qBAAqB,KAAK,IAAI,GAAG;AACxC;AAAA,UACF;AAEA,cAAI,IAAI,SAAS,YAAY,IAAI,YAAY,QAAQ;AACnD,gBAAI,IAAI,YAAY;AAClB,iCAAmB,IAAI,IAAI,UAAU;AAAA,YACvC;AAAA,UACF;AAEA,cACE,IAAI,SAAS,eACb,IAAI,SAAS,WACb,CAAC,kBACD;AACA,uBAAW,SAAS,IAAI,QAAQ,SAAS;AACvC,kBAAI,MAAM,SAAS,UAAU,MAAM,MAAM;AACvC,gCAAgB,MAAM;AAAA,cACxB;AACA,kBAAI,MAAM,SAAS,cAAc,MAAM,UAAU;AAC/C,gCAAgB,MAAM;AAAA,cACxB;AACA,kBAAI,MAAM,SAAS,cAAc,MAAM,MAAM,MAAM,MAAM;AACvD,oBAAI,sBAAsB,MAAM,IAAI,GAAG;AAGrC,wBAAM,cAAe,MAAM,SAAS,CAAC;AAIrC,kCAAgB,sBAAsB,WAAW;AACjD;AAAA,gBACF;AAEA,oBAAI,MAAM,SAAS,gBAAgB;AACjC,wBAAM,cAAe,MAAM,SAAS,CAAC;AAIrC,wBAAM,OAAQ,aAAa,QAAmB;AAC9C,sBAAI,wBAAwB;AAC1B,0BAAM,eAAe;AAAA,sBACnB;AAAA,sBACA,MAAM;AAAA,sBACN;AAAA,oBACF;AACA,oCAAgB,aAAa;AAC7B,8BAAU,KAAK;AAAA,sBACb,IAAI,aAAa;AAAA,sBACjB,MAAM,aAAa;AAAA,sBACnB,MAAM,aAAa;AAAA,oBACrB,CAAC;AACD;AAAA,kBACF;AACA,kCAAgB;AAAA;AAAA,EAAO,IAAI;AAAA;AAAA;AAAA;AAAA;AAC3B;AAAA,gBACF;AAEA,0BAAU,KAAK;AAAA,kBACb,IAAI,MAAM;AAAA,kBACV,MAAM,MAAM;AAAA,kBACZ,MAAM,MAAM,SAAS,CAAC;AAAA,gBACxB,CAAC;AAAA,cACH;AAAA,YACF;AAAA,UACF;AAEA,cACE,IAAI,SAAS,yBACb,IAAI,iBACJ,IAAI,UAAU,QACd;AACA,gBACE,IAAI,cAAc,SAAS,cAC3B,IAAI,cAAc,MAClB,IAAI,cAAc,MAClB;AACA,8BAAgB,IAAI,IAAI,OAAO;AAAA,gBAC7B,IAAI,IAAI,cAAc;AAAA,gBACtB,MAAM,IAAI,cAAc;AAAA,gBACxB,WAAW;AAAA,cACb,CAAC;AAAA,YACH;AAAA,UACF;AAEA,cACE,IAAI,SAAS,yBACb,IAAI,SACJ,IAAI,UAAU,QACd;AACA,gBAAI,IAAI,MAAM,SAAS,gBAAgB,IAAI,MAAM,MAAM;AACrD,8BAAgB,IAAI,MAAM;AAAA,YAC5B;AACA,gBAAI,IAAI,MAAM,SAAS,oBAAoB,IAAI,MAAM,UAAU;AAC7D,8BAAgB,IAAI,MAAM;AAAA,YAC5B;AACA,gBACE,IAAI,MAAM,SAAS,sBACnB,IAAI,MAAM,cACV;AACA,oBAAM,KAAK,gBAAgB,IAAI,IAAI,KAAK;AACxC,kBAAI,GAAI,IAAG,aAAa,IAAI,MAAM;AAAA,YACpC;AAAA,UACF;AAEA,cAAI,IAAI,SAAS,wBAAwB,IAAI,UAAU,QAAW;AAChE,kBAAM,KAAK,gBAAgB,IAAI,IAAI,KAAK;AACxC,gBAAI,IAAI;AACN,kBAAI,OAAgB,CAAC;AACrB,kBAAI;AACF,uBAAO,GAAG,YAAY,KAAK,MAAM,GAAG,SAAS,IAAI,CAAC;AAAA,cACpD,SAAS,KAAK;AACZ,oBAAI,KAAK,gCAAgC;AAAA,kBACvC,MAAM,GAAG;AAAA,kBACT,OAAO,OAAO,GAAG;AAAA,gBACnB,CAAC;AAAA,cACH;AACA,kBAAI,GAAG,SAAS,kBAAkB,wBAAwB;AACxD,sBAAM,cAAc;AACpB,sBAAM,OAAQ,aAAa,QAAmB;AAC9C,sBAAM,eAAe,+BAA+B,IAAI,GAAG,IAAI,IAAI;AACnE,gCAAgB,aAAa;AAC7B,0BAAU,KAAK;AAAA,kBACb,IAAI,aAAa;AAAA,kBACjB,MAAM,aAAa;AAAA,kBACnB,MAAM,aAAa;AAAA,gBACrB,CAAC;AAAA,cACH,OAAO;AACL,0BAAU,KAAK,EAAE,IAAI,GAAG,IAAI,MAAM,GAAG,MAAM,KAAK,CAAC;AAAA,cACnD;AACA,8BAAgB,OAAO,IAAI,KAAK;AAAA,YAClC;AAAA,UACF;AAEA,cAAI,IAAI,SAAS,UAAU;AACzB,gBAAI,IAAI,YAAY;AAClB,iCAAmB,IAAI,IAAI,UAAU;AAAA,YACvC;AAKA,gBACE,CAAC,gBACD,IAAI,YACJ,OAAO,IAAI,WAAW,YACtB,IAAI,OAAO,KAAK,EAAE,SAAS,GAC3B;AACA,6BAAe,IAAI;AAAA,YACrB;AAEA,yBAAa;AAAA,cACX,WAAW,IAAI;AAAA,cACf,SAAS,IAAI;AAAA,cACb,YAAY,IAAI;AAAA,cAChB,OAAO,IAAI;AAAA,YACb;AACA,oBAAQ;AACR,YAAAA,SAAQ;AAAA,cACN,GAAG;AAAA,cACH,MAAM;AAAA,cACN,UAAU;AAAA,cACV;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF,CAAC;AAED,SAAG,GAAG,SAAS,MAAM;AACnB,gBAAQ;AACR,QAAAA,SAAQ;AAAA,UACN,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,WAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,YAAI,MAAM,iBAAiB,EAAE,OAAO,IAAI,QAAQ,CAAC;AACjD,gBAAQ;AACR,eAAO,GAAG;AAAA,MACZ,CAAC;AAED,WAAK,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACxC,YAAI,MAAM,UAAU,EAAE,MAAM,KAAK,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,CAAC;AAAA,MAC7D,CAAC;AAED,WAAK,OAAO,MAAM,UAAU,IAAI;AAAA,IAClC,CAAC;AAED,UAAM,UAAoC,CAAC;AAE3C,QAAI,OAAO,UAAU;AACnB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,OAAO;AAAA,MACf,CAAQ;AAAA,IACV;AAEA,QAAI,OAAO,MAAM;AACf,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,OAAO;AAAA,QACb,kBAAkB;AAAA,UAChB,eAAe;AAAA,YACb,WAAW,OAAO,aAAa;AAAA,YAC/B,SAAS,OAAO,WAAW;AAAA,YAC3B,YAAY,OAAO,cAAc;AAAA,UACnC;AAAA,UACA,GAAI,OAAO,OAAO,OAAO,gCAAgC,WACrD;AAAA,YACE,WAAW;AAAA,cACT,0BACE,OAAO,MAAM;AAAA,YACjB;AAAA,UACF,IACA,CAAC;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH;AAEA,eAAW,MAAM,OAAO,WAAW;AACjC,UAAI,GAAG,SAAS,oBAAoB;AAClC,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,YAAY,GAAG;AAAA,UACf,UAAU,GAAG;AAAA,UACb,OAAO,KAAK,UAAU,GAAG,IAAI;AAAA,UAC7B,kBAAkB;AAAA,QACpB,CAAQ;AACR;AAAA,MACF;AAEA,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MACF,IAAI,QAAQ,GAAG,MAAM,GAAG,MAAM;AAAA,QAC5B,WAAW,KAAK,OAAO;AAAA,QACvB,WAAW,mBAAmB,EAAE;AAAA,QAChC,WAAW,GAAG;AAAA,MAChB,CAAC;AACD,UAAI,KAAM;AACV,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,YAAY,GAAG;AAAA,QACf,UAAU;AAAA,QACV,OAAO,KAAK,UAAU,WAAW;AAAA,QACjC,kBAAkB;AAAA,MACpB,CAAQ;AAAA,IACV;AAEA,UAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK;AAEvC,WAAO;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc,KAAK;AAAA,QACjB,OAAO,UAAU,KAAK,CAAC,OAAO,GAAG,SAAS,kBAAkB,IACxD,eACA;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE;AAAA,MACnC,UAAU;AAAA,QACR,IAAI,OAAO,aAAa,WAAW;AAAA,QACnC,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,MAChB;AAAA,MACA,kBAAkB;AAAA,QAChB,eAAe;AAAA,UACb,WAAW,OAAO,aAAa;AAAA,UAC/B,SAAS,OAAO,WAAW;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,QACnC;AAAA,QACA,GAAI,OAAO,OAAO,OAAO,gCAAgC,WACrD;AAAA,UACE,WAAW;AAAA,YACT,0BACE,OAAO,MAAM;AAAA,UACjB;AAAA,QACF,IACA,CAAC;AAAA,MACP;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,SAC2D;AAC3D,UAAM,WAA8B,CAAC;AACrC,UAAM,MAAM,gBAAgB,KAAK,OAAO,GAAG;AAC3C,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,kBAAkB,KAAK,OAAO,oBAAoB;AACxD,UAAM,QAAQ,KAAK,aAAa,OAAc;AAC9C,UAAM,WAAW,KAAK,gBAAgB,OAAO;AAC7C,UAAM,iBAAiB,KAAK,iBAAiB,OAAO;AAGpD,UAAM,mBAAmB,iBACrB,KAAK,uBAAuB,IAC5B,KAAK;AACT,UAAM,KAAK,iBACP,WAAW,KAAK,GAAG,gBAAgB,iBAAiB,QAAQ,EAAE,IAC9D,WAAW,KAAK,GAAG,KAAK,OAAO,KAAK,KAAK,KAAK,QAAQ,EAAE;AAC5D,UAAM,UAAU,KAAK,QAAQ,KAAK,IAAI;AACtC,UAAM,iBAAiB,KAAK,eAAe,KAAK,IAAI;AACpD,UAAM,uBAAuB,KAAK,qBAAqB,KAAK,IAAI;AAChE,UAAM,SAAS,CAAC,MACd,MAAM,UACN,CAAC,CAAC,IAAI,KAAK,SAAS,MAAM,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,CAAC;AAMlE,UAAM,kBACJ,KAAK,OAAO,eACZ,OAAO,QAAQ,IAAI,iCAAiC;AACtD,UAAM,iBACJ,mBAAmB,OAAQ,WAAmB,KAAK,aAAa;AAClE,UAAM,6BACJ,KAAK,OAAO,qBACZ,OAAO,QAAQ,IAAI,8BAA8B;AAEnD,QAAI,UAAU,cAAc,CAAC,gBAAgB;AAC3C,UAAI,KAAK,gCAAgC;AAAA,QACvC;AAAA,QACA,eAAe,KAAK,iBAAiB,QAAQ,eAAe;AAAA,QAC5D,qBAAqB,QAAQ,kBACzB,OAAO,KAAK,QAAQ,eAAe,IACnC,CAAC;AAAA,MACP,CAAC;AACD,YAAM,OAAO,KAAK,gBAAgB,QAAQ,MAAM;AAChD,YAAM,SAAS,WAAW;AAC1B,YAAMC,UAAS,IAAI,eAA0C;AAAA,QAC3D,MAAM,YAAY;AAChB,qBAAW,QAAQ,EAAE,MAAM,gBAAgB,SAAS,CAAC;AACrD,qBAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAQ;AAC5D,qBAAW,QAAQ;AAAA,YACjB,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,OAAO;AAAA,UACT,CAAC;AACD,qBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,OAAO,CAAC;AACnD,qBAAW,QAAQ;AAAA,YACjB,MAAM;AAAA,YACN,cAAc,eAAe,MAAM;AAAA,YACnC,OAAO,QAAQ,EAAE,cAAc,GAAG,eAAe,EAAE,CAAC;AAAA,YACpD,kBAAkB;AAAA,cAChB,eAAe;AAAA,gBACb,WAAW;AAAA,gBACX,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF,CAAC;AACD,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,QAAAA;AAAA,QACA,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE;AAAA,MAChC;AAAA,IACF;AAMA,QAAI,CAAC,kBAAkB,QAAQ,MAAM,GAAG;AACtC,UAAI,KAAK,6CAA6C;AACtD,YAAMA,UAAS,IAAI,eAA0C;AAAA,QAC3D,MAAM,YAAY;AAChB,qBAAW,QAAQ,EAAE,MAAM,gBAAgB,SAAS,CAAC;AACrD,qBAAW,QAAQ;AAAA,YACjB,MAAM;AAAA,YACN,cAAc,eAAe,MAAM;AAAA,YACnC,OAAO,QAAQ,EAAE,cAAc,GAAG,eAAe,EAAE,CAAC;AAAA,YACpD,kBAAkB;AAAA,cAChB,eAAe,EAAE,WAAW,MAAM,MAAM,sBAAsB;AAAA,YAChE;AAAA,UACF,CAAC;AACD,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AACD,aAAO,EAAE,QAAAA,SAAQ,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE;AAAA,IACnD;AAEA,UAAM,uBACJ,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,WAAW,EACrE,SAAS;AAGd,QAAI,CAAC,sBAAsB;AACzB,4BAAsB,EAAE;AACxB,0BAAoB,EAAE;AAAA,IACxB;AAEA,UAAM,qBAAqB,CAAC,CAAC,mBAAmB,EAAE;AAClD,UAAM,mBAAmB,CAAC,CAAC,iBAAiB,EAAE;AAC9C,UAAM,wBACJ,CAAC,sBAAsB,CAAC,oBAAoB;AAE9C,UAAM,kBAAkB,KAAK,mBAAmB,QAAQ,eAAe;AACvE,UAAM,6BAA6B,iBAC/B,OACA,kCAAkC,IAAI,QAAQ,MAAa;AAC/D,QAAI,4BAA4B;AAI9B,UAAI,KAAK,4CAA4C,EAAE,GAAG,CAAC;AAAA,IAC7D;AACA,UAAM,UACJ,8BACA,qBAAqB,QAAQ,QAAQ,uBAAuB,iBAAiB;AAAA,MAC3E;AAAA,IACF,CAAC;AACH,UAAM,gBAAgB,iBAAiB,OAAO,KAAK,mBAAmB;AACtE,UAAM,mBAAmB,KAAK,yBAAyB;AAIvD,UAAM,yBAAyB,MAAM,KAAK;AAAA,MACxC;AAAA,MACA;AAAA,IACF;AACA,UAAM,OAAO;AAEb,UAAM,4BAA4B,iBAC9B,CAAC,IACD,qBAAqB,EAAE;AAC3B,UAAM,8BAGD,0BAA0B,IAAI,CAAC,UAAU;AAAA,MAC5C;AAAA,MACA,QAAQ,KAAK,0BAA0B,QAAQ,QAAQ,KAAK,UAAU;AAAA,IACxE,EAAE;AACF,UAAM,2BAA2B,4BAA4B;AAAA,MAC3D,CAAC,MAAM,EAAE,WAAW;AAAA,IACtB;AAQA,UAAM,CAAC,eAAe,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,MACpD,iBAAiB,QAAQ,QAAQ,MAAS,IAAI,oBAAoB;AAAA,MAClE,iBAAiB,KAAK,OAAO,OAAO;AAAA,IACtC,CAAC;AAED,QAAI,KAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,OAAO;AAAA,MACP,YAAY,QAAQ;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK;AAAA,MACjD;AAAA,MACA;AAAA,MACA,eAAe,KAAK,iBAAiB,QAAQ,eAAe;AAAA,MAC5D,qBAAqB,QAAQ,kBACzB,OAAO,KAAK,QAAQ,eAAe,IACnC,CAAC;AAAA,IACP,CAAC;AAED,UAAM,SAAS,IAAI,eAA0C;AAAA,MAC3D,MAAM,YAAY;AAIhB,YAAI,gBAAgB;AAClB,8BAAoB,EAAE;AACtB,gCAAsB,EAAE;AAAA,QAC1B;AAEA,YAAI,gBAAgB,iBAAiB,EAAE;AACvC,YAAI;AACJ,YAAI;AACJ,YAAI;AACJ,YAAI,cAAqC,eAAe,eAAe;AAEvE,cAAM,QAAQ,YAAY;AAGxB,cACE,CAAC,kBACD,iBACA,KAAK,OAAO,iBAAiB,SAC7B,KAAK,OAAO,sBAAsB,OAClC;AACA,kBAAM,QAAQ,KAAK,mBAAmB,KAAK,QAAW,aAAc;AACpE,kBAAM,eAAe,cAAc,WAAW;AAC9C,gBAAI,iBAAiB,MAAM,aAAa;AACtC,kBAAI,0BAA0B,SAAS,GAAG;AACxC,oBAAI,KAAK,sDAAsD;AAAA,kBAC7D;AAAA,kBACA;AAAA,kBACA,aAAa,MAAM;AAAA,kBACnB,cAAc,0BAA0B;AAAA,gBAC1C,CAAC;AAAA,cACH,OAAO;AACL,oBAAI,KAAK,kDAAkD;AAAA,kBACzD;AAAA,kBACA;AAAA,kBACA,aAAa,MAAM;AAAA,gBACrB,CAAC;AACD,sBAAM,2BAA2B,EAAE;AACnC,gCAAgB;AAChB,8BAAc;AAAA,cAChB;AAAA,YACF;AAAA,UACF;AAEA,cAAI,kBAAkB,CAAC,gBAAgB;AAKrC,kBAAM,MAAM,KAAK,mBAAmB,KAAK,QAAW,aAAc;AAClE,gBAAI,eAAe;AACjB,qBAAO,cAAc;AACrB,4BAAc,cAAc;AAC5B,kBAAI,MAAM,sCAAsC,EAAE,GAAG,CAAC;AAAA,YACxD,OAAO;AAGL,oBAAM,QAAQ;AAAA,gBACZ,GAAG,IAAI,sBAAsB,IAAI,CAAC,MAAM,QAAQ,CAAC,KAAK;AAAA,gBACtD;AAAA,gBACA,GAAI,KAAK,OAAO,yBAAyB;AAAA,kBACvC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,cACF;AACA,oBAAM,mBACJ,KAAK,OAAO,4BAA4B,QACpC,SACA;AAAA,gBACE;AAAA,gBACA,KAAK,OAAO,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMxC;AACN,kBAAI,KAAK,OAAO,4BAA4B,OAAO;AACjD,oBAAI;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AACA,kBAAI,4BAA4B;AAC9B,oBAAI;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AACA,oBAAM,KAAK,wBAAwB;AAAA,gBACjC;AAAA,gBACA;AAAA,gBACA,WAAW,KAAK,OAAO;AAAA,gBACvB,OAAO;AAAA,gBACP,gBAAgB,IAAI;AAAA,gBACpB,kBAAkB;AAAA,gBAClB;AAAA,gBACA,uBAAuB,KAAK,OAAO;AAAA,cACrC,CAAC;AACD,iBAAG,UAAU,IAAI;AACjB,+BAAiB,IAAI,EAAE;AACvB,qBAAO,GAAG;AACV,4BAAc,GAAG;AACjB,8BAAgB;AAChB,kBAAI,KAAK,sCAAsC;AAAA,gBAC7C;AAAA,gBACA;AAAA,gBACA,WAAW,KAAK,OAAO;AAAA,gBACvB,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,UACF,OAAO;AACP,gBAAI;AACJ,gBAAI,mBAA0C;AAC9C,gBAAI,eAA8B;AAElC,gBAAI,gBAAgB;AAOlB,wBAAU,aAAa;AAAA,gBACrB,YAAY;AAAA,gBACZ;AAAA,gBACA,kBAAkB;AAAA,gBAClB,OAAO;AAAA,gBACP,gBAAgB,KAAK,OAAO;AAAA,gBAC5B;AAAA,cACF,CAAC;AAAA,YACH,OAAO;AAKL,oBAAM,YAAY,KAAK;AAAA,gBACrB;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAMA,oBAAM,gBAAgB,MAAM,KAAK;AAAA,gBAC/B,UAAU;AAAA,cACZ;AACA,oBAAM,iBAAkD,gBACpD,IAAI,IAAI,UAAU,qBAAqB,IACvC;AAUJ,oBAAM,mBACJ,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAAK;AACnD,oBAAM,uBACJ,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,KAAK;AACvD,oBAAM,eACJ,oBAAoB,uBAChB,MAAM,iBAAiB,IACvB;AAAA,gBACE,UAAU;AAAA,gBACV,iBAAiB;AAAA,gBACjB,qBAAqB;AAAA,gBACrB,aAAa;AAAA,cACf;AACN,kBAAI,gBAAgB;AACpB,kBAAI,iBAAiB,kBAAkB;AACrC,gCAAgB;AAAA,kBACd;AAAA,kBACA,aAAa;AAAA,gBACf;AAIA,oBAAI,KAAK,kCAAkC;AAAA,kBACzC,SAAS,QAAQ,aAAa,eAAe;AAAA,kBAC7C,uBAAuB,aAAa,iBAAiB,UAAU;AAAA,kBAC/D,iBAAiB;AAAA,oBACf,aAAa,iBAAiB;AAAA,sBAC5B;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF,CAAC;AAAA,cACH;AACA,kBAAI,iBAAiB,sBAAsB;AAIzC,gCAAgB;AAAA,kBACd;AAAA,kBACA,aAAa,cACT,aAAa,sBACb;AAAA,gBACN;AACA,gCAAgB;AAAA,kBACd;AAAA,kBACA,aAAa;AAAA,gBACf;AAIA,oBAAI,KAAK,+BAA+B;AAAA,kBACtC,qBAAqB,aAAa;AAAA,kBAClC,MAAM,aAAa;AAAA,gBACrB,CAAC;AAAA,cACH;AAQA,oBAAM,eAAe;AAAA,gBACnB,GAAI,iBAAiB,CAAC;AAAA,gBACtB,GAAI,iBAAiB,CAAC;AAAA,cACxB;AACA,oBAAM,qBACJ,aAAa,SAAS,IAAI,eAAe;AAE3C,kBAAI,CAAC,eAAe,oBAAoB;AACtC,8BAAc,MAAM,KAAK,kBAAkB,oBAAoB,EAAE;AAAA,cACnE;AAQA,oBAAM,sBACJ,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,KAAK;AAUvD,oBAAM,kBAAkB,gBACpB,oBAAoB,aAAa,IACjC,CAAC;AACL,oBAAM,kBAA4B,CAAC;AACnC,kBAAI,KAAK,OAAO,cAAc,WAAY,iBAAgB,KAAK,WAAW;AAC1E,oBAAM,gBAAgB,CAAC,GAAG,iBAAiB,GAAG,eAAe;AAC7D,oBAAM,MAAM,KAAK;AAAA,gBACf;AAAA,gBACA,aAAa,WAAW;AAAA,gBACxB;AAAA,gBACA;AAAA,cACF;AACA,oBAAM,mBAAmB,gBACrB,SACA;AAAA,gBACE;AAAA,gBACA,KAAK,OAAO,0BAA0B;AAAA,gBACtC;AAAA,kBACE,GAAG,sBAAsB,QAAQ,MAAM;AAAA,kBACvC,GAAI,mBAAmB,CAAC,sBAAsB,IAAI,CAAC;AAAA,kBACnD,GAAI,sBAAsB,CAAC,mBAAmB,IAAI,CAAC;AAAA,gBACrD;AAAA,cACF;AACJ,wBAAU,aAAa;AAAA,gBACrB,YAAY;AAAA,gBACZ;AAAA,gBACA,OAAO,KAAK;AAAA,gBACZ,gBAAgB,KAAK,OAAO;AAAA,gBAC5B,WAAW,IAAI;AAAA,gBACf,iBAAiB,KAAK,OAAO;AAAA,gBAC7B,iBAAiB,cAAc,SAAS,IAAI,gBAAgB;AAAA,gBAC5D,wBAAwB;AAAA,gBACxB,GAAG,KAAK,mBAAmB;AAAA,gBAC3B;AAAA,cACF,CAAC;AACD,sCAAwB;AACxB,iCAAmB;AACnB,6BAAe,IAAI;AAAA,YACrB;AAEA,gBAAI,iBAAiB,CAAC,gBAAgB;AACpC,qBAAO,cAAc;AACrB,4BAAc,cAAc;AAC5B,kBAAI,MAAM,0BAA0B,EAAE,GAAG,CAAC;AAAA,YAC5C,OAAO;AACL,oBAAM,KAAK;AAAA,gBACT;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,KAAK,OAAO;AAAA,cACd;AACA,qBAAO,GAAG;AACV,4BAAc,GAAG;AACjB,8BAAgB;AAAA,YAClB;AAAA,UACA;AAEA,qBAAW,QAAQ,EAAE,MAAM,gBAAgB,SAAS,CAAC;AAErD,cAAI,gBAA+B;AACnC,gBAAM,mBAAmB,oBAAI,IAAY;AAEzC,gBAAM,iBAAiB,MAAc;AACnC,gBAAI,eAAe;AACjB,yBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,cAAc,CAAC;AAAA,YAC5D;AACA,kBAAM,KAAK,WAAW;AACtB,4BAAgB;AAChB,uBAAW,QAAQ,EAAE,MAAM,cAAc,GAAG,CAAQ;AACpD,mBAAO;AAAA,UACT;AAEA,gBAAM,eAAe,MAAY;AAC/B,gBAAI,eAAe;AACjB,yBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,cAAc,CAAC;AAC1D,8BAAgB;AAAA,YAClB;AAAA,UACF;AAEA,gBAAM,eAAe,oBAAI,IAAoB;AAC7C,gBAAM,mBAAmB,oBAAI,IAAqB;AAClD,cAAI,4BAA4B;AAEhC,cAAI,gBAAgB;AACpB,cAAI,mBAAmB;AACvB,cAAI,0BAA+C;AACnD,cAAI,sBAA4D;AAChE,cAAI,0BAA+C;AACnD,cAAI,qBAAqB;AACzB,cAAI,2BAA2B;AAC/B,cAAI,+BAA+B;AACnC,cAAI,4BAA4B;AAChC,cAAI,+BAA+B;AACnC,cAAI,gCAAgC;AAIpC,cAAI,iBAAgC;AACpC,gBAAM,oBAAuC;AAAA,YAC3C,SAAS,KAAK,OAAO;AAAA,YACrB,UAAU;AAAA,YACV,WAAW,KAAK,IAAI;AAAA,YACpB,iBAAiB;AAAA,UACnB;AAEA,gBAAM,qBAAqB,MAAM;AAC/B,gBAAI,qBAAqB;AACvB,2BAAa,mBAAmB;AAChC,oCAAsB;AAAA,YACxB;AAAA,UACF;AAQA,gBAAM,sBAAsB,CAAC,UAAU,QAAW;AAChD,+BAAmB;AACnB,gBAAI,CAAC,sBAAsB,iBAAkB;AAC7C,kCAAsB,WAAW,MAAM;AACrC,kBAAI,iBAAkB;AACtB,kBAAI,KAAK,0EAAqE;AAAA,gBAC5E;AAAA,cACF,CAAC;AACD,2BAAa;AAAA,YACf,GAAG,OAAO;AAAA,UACZ;AAWA,gBAAM,qBAAqB,MAAM;AAC/B,kBAAM,MAAM,QAAQ,IAAI;AACxB,kBAAM,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE,IAAI;AAChD,mBAAO,OAAO,SAAS,MAAM,KAAK,SAAS,IAAI,SAAS;AAAA,UAC1D,GAAG;AACH,cAAI,gBAAsD;AAC1D,cAAI,mBAAmB;AACvB,gBAAM,qBAAqB,MAAM;AAC/B,gBAAI,eAAe;AACjB,2BAAa,aAAa;AAC1B,8BAAgB;AAAA,YAClB;AAAA,UACF;AACA,gBAAM,sBAAsB,MAAM;AAChC,4BAAgB;AAChB,gBAAI,oBAAoB,mBAAoB;AAC5C,gBAAI,kBAAkB;AACpB,kBAAI;AAAA,gBACF;AAAA,gBACA,EAAE,YAAY,GAAG;AAAA,cACnB;AACA,kCAAoB,EAAE;AACtB,oCAAsB,EAAE;AACxB,iCAAmB;AACnB,0BAAY;AACZ,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,OAAO,IAAI;AAAA,kBACT;AAAA,gBACF;AAAA,cACF,CAAC;AACD,kBAAI;AACF,2BAAW,MAAM;AAAA,cACnB,QAAQ;AAAA,cAAC;AACT;AAAA,YACF;AACA,+BAAmB;AACnB,gBAAI;AAAA,cACF;AAAA,cACA,EAAE,YAAY,IAAI,iBAAiB,kBAAkB;AAAA,YACvD;AACA,wBAAY,IAAI,QAAQ,WAAW;AACnC,wBAAY,IAAI,SAAS,YAAY;AACrC,iBAAK,IAAI,SAAS,gBAAgB;AAClC,kBAAM,QAAQ;AAAA,cACZ;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK,OAAO;AAAA,YACd;AACA,gBAAI,CAAC,OAAO;AACV,kBAAI;AAAA,gBACF;AAAA,gBACA,EAAE,YAAY,GAAG;AAAA,cACnB;AACA,iCAAmB;AACnB,0BAAY;AACZ,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,OAAO,IAAI;AAAA,kBACT;AAAA,gBACF;AAAA,cACF,CAAC;AACD,kBAAI;AACF,2BAAW,MAAM;AAAA,cACnB,QAAQ;AAAA,cAAC;AACT;AAAA,YACF;AACA,mBAAO,MAAM;AACb,0BAAc,MAAM;AACpB,4BAAgB;AAChB,wBAAY,GAAG,QAAQ,WAAW;AAClC,wBAAY,GAAG,SAAS,YAAY;AACpC,iBAAK,GAAG,SAAS,gBAAgB;AACjC,gBAAI;AACF,mBAAK,OAAO,MAAM,UAAU,IAAI;AAChC,kBAAI,MAAM,sCAAsC;AAAA,gBAC9C,YAAY,QAAQ;AAAA,cACtB,CAAC;AAAA,YACH,SAAS,KAAK;AACZ,kBAAI,MAAM,4CAA4C;AAAA,gBACpD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,cACxD,CAAC;AAAA,YACH;AACA,4BAAgB;AAAA,cACd;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA,gBAAM,mBAAmB,MAAM;AAC7B,+BAAmB;AACnB,gBAAI,iBAAkB;AACtB,4BAAgB,WAAW,qBAAqB,iBAAiB;AAAA,UACnE;AAEA,gBAAM,cAAc,oBAAI,IAGtB;AAKF,gBAAM,mBAAmB,oBAAI,IAAY;AACzC,gBAAM,gBAAgB,oBAAI,IAGxB;AAEF,cAAI,aAKA,CAAC;AAMP,gBAAM,cAAkC,CAAC;AACzC,cAAI,aAAmD;AACvD,gBAAM,iBAAiB;AAEvB,gBAAM,sBAAsB,CAAC,UAA8B;AACzD,gBAAI,iBAAkB;AACtB,gBAAI,MAAM,WAAW,EAAG;AACxB,uBAAW,QAAQ,OAAO;AACxB,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,KAAK;AAAA,gBACT,UAAU,KAAK;AAAA,cACjB,CAAQ;AACR,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,YAAY,KAAK;AAAA,gBACjB,UAAU,KAAK;AAAA,gBACf,OAAO,KAAK,UAAU,KAAK,KAAK;AAAA,gBAChC,kBAAkB;AAAA,cACpB,CAAQ;AACR,+BAAiB,IAAI,KAAK,UAAU;AAAA,YACtC;AACA,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,cAAc,eAAe,YAAY;AAAA,cACzC,OAAO,QAAQ,WAAW,KAAK;AAAA,cAC/B,kBAAkB;AAAA,gBAChB,eAAe;AAAA,cACjB;AAAA,YACF,CAAC;AACD,+BAAmB;AACnB,wBAAY;AACZ,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAAC;AAAA,UACX;AAEA,gBAAM,6BAA6B,CACjC,SACG;AACH,gBAAI,iBAAkB;AACtB,yBAAa;AACb,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,IAAI,KAAK;AAAA,cACT,UAAU,KAAK;AAAA,cACf,kBAAkB;AAAA,YACpB,CAAQ;AACR,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,YAAY,KAAK;AAAA,cACjB,UAAU,KAAK;AAAA,cACf,OAAO,KAAK,UAAU,KAAK,KAAK;AAAA,cAChC,kBAAkB;AAAA,YACpB,CAAQ;AACR,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,cAAc,eAAe,YAAY;AAAA,cACzC,OAAO,QAAQ,WAAW,KAAK;AAAA,cAC/B,kBAAkB;AAAA,gBAChB,eAAe;AAAA,cACjB;AAAA,YACF,CAAC;AACD,+BAAmB;AACnB,wBAAY;AACZ,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAAC;AAAA,UACX;AAEA,gBAAM,WAAW,MAAM;AACrB,gBAAI,YAAY;AACd,2BAAa,UAAU;AACvB,2BAAa;AAAA,YACf;AACA,gBAAI,YAAY,WAAW,EAAG;AAC9B,gBAAI,iBAAkB;AACtB,kBAAM,QAAQ,YAAY,OAAO,GAAG,YAAY,MAAM;AACtD,gBAAI,KAAK,mDAAmD;AAAA,cAC1D,YAAY;AAAA,cACZ,OAAO,MAAM;AAAA,cACb,aAAa,MAAM,IAAI,CAAC,MAAM,EAAE,UAAU;AAAA,YAC5C,CAAC;AACD,gCAAoB,KAAK;AAAA,UAC3B;AAEA,gBAAM,uBAAuB,MAAM;AACjC,yBAAa;AACb,kBAAMC,kBAAiB;AACvB,sCAA0B;AAC1B,gBAAI,CAACA,mBAAkB,iBAAkB;AACzC,gBAAI,YAAY,SAAS,GAAG;AAC1B,uBAAS;AACT;AAAA,YACF;AACA,YAAAA,gBAAe;AAAA,UACjB;AAEA,gBAAM,yBAAyB,CAC7BA,iBACA,YACG;AACH,sCAA0BA;AAC1B,gBAAI,WAAY,cAAa,UAAU;AACvC,yBAAa,WAAW,sBAAsB,OAAO;AAAA,UACvD;AAEA,gBAAM,yBAAyB,MAAe;AAC5C,gBAAI,CAAC,wBAAyB,QAAO;AACrC,gBAAI,WAAY,cAAa,UAAU;AACvC,yBAAa,WAAW,sBAAsB,cAAc;AAC5D,mBAAO;AAAA,UACT;AAEA,gBAAM,kBAAkB,CAAC,SAAiB;AACxC,wCAA4B;AAC5B,4CAAgC;AAAA,UAClC;AAEA,gBAAM,4BAA4B,MAAM;AACtC,2CAA+B;AAAA,UACjC;AAEA,gBAAM,gBAAgB,MAAM;AAC1B,wCAA4B;AAAA,UAC9B;AAEA,gBAAM,mBAAmB,MAAM;AAC7B,2CAA+B;AAAA,UACjC;AAEA,gBAAM,oBAAoB,MAAM;AAC9B,4CAAgC;AAAA,UAClC;AAEA,gBAAM,0BAA0B,MAAM;AACpC,uCAA2B;AAC3B,2CAA+B;AAC/B,wCAA4B;AAC5B,2CAA+B;AAC/B,4CAAgC;AAChC,6BAAiB;AAAA,UACnB;AAEA,gBAAM,iBAAiB,CAAC,QAA6B;AACnD,gBAAI,iBAAkB;AACtB,gBAAI,YAAY,SAAS,GAAG;AAC1B,uBAAS;AACT;AAAA,YACF;AAEA,kBAAM,kBAAkB,qBAAqB,EAAE;AAC/C,gBAAI,gBAAgB,SAAS,GAAG;AAC9B,kBAAI,KAAK,2DAA2D;AAAA,gBAClE,YAAY;AAAA,gBACZ,OAAO,gBAAgB;AAAA,cACzB,CAAC;AAAA,YACH;AAEA,kBAAM,eAAe;AAAA,cACnB;AAAA,cACA;AAAA,gBACE,MAAM;AAAA,gBACN,iBAAiB;AAAA,gBACjB,cAAc;AAAA,gBACd,iBAAiB;AAAA,gBACjB,kBAAkB;AAAA,gBAClB,SAAS,IAAI;AAAA,gBACb,YAAY;AAAA,cACd;AAAA,YACF;AACA,gBAAI,aAAa,UAAU;AACzB,oBAAM,YAAY,sBAAsB;AAAA,gBACtC,MAAM;AAAA,gBACN,iBAAiB;AAAA,gBACjB,cAAc;AAAA,gBACd,iBAAiB;AAAA,gBACjB,kBAAkB;AAAA,gBAClB,SAAS,IAAI;AAAA,cACf,CAAC;AACD,gCAAkB,kBAChB,cAAc,kBAAkB,gBAC5B,kBAAkB,kBAAkB,IACpC;AACN,gCAAkB,gBAAgB;AAClC,gCAAkB;AAClB,kBAAI,OAAO,4CAA4C;AAAA,gBACrD,YAAY;AAAA,gBACZ,QAAQ,aAAa;AAAA,gBACrB,UAAU,kBAAkB;AAAA,gBAC5B,YAAY,yBAAyB;AAAA,gBACrC,gBAAgB,6BAA6B;AAAA,gBAC7C,cAAc;AAAA,gBACd,iBAAiB;AAAA,gBACjB,kBAAkB;AAAA,cACpB,CAAC;AACD,8BAAgB;AAChB,sCAAwB;AACxB,mBAAK,OAAO,MAAM,wBAAwB,IAAI,IAAI;AAClD;AAAA,YACF;AACA,gBAAI,OAAO,6BAA6B;AAAA,cACtC,YAAY;AAAA,cACZ,QAAQ,aAAa;AAAA,cACrB,YAAY;AAAA,cACZ,UAAU,kBAAkB;AAAA,cAC5B,YAAY,yBAAyB;AAAA,cACrC,gBAAgB,6BAA6B;AAAA,cAC7C,cAAc;AAAA,cACd,iBAAiB;AAAA,cACjB,kBAAkB;AAAA,YACpB,CAAC;AAED,uBAAW,CAAC,KAAK,WAAW,KAAK,cAAc;AAC7C,kBAAI,iBAAiB,IAAI,GAAG,GAAG;AAC7B,2BAAW,QAAQ;AAAA,kBACjB,MAAM;AAAA,kBACN,IAAI;AAAA,gBACN,CAAQ;AAAA,cACV;AAAA,YACF;AAEA,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,cAAc,eAAe,MAAM;AAAA,cACnC,OAAO,QAAQ,IAAI,KAAK;AAAA,cACxB,kBAAkB;AAAA,gBAChB,eAAe;AAAA,kBACb,GAAG;AAAA,kBACH,GAAI,iBACA,EAAE,iBAAiB,iBAAiB,IACpC,CAAC;AAAA,gBACP;AAAA,gBACA,GAAI,OAAO,IAAI,OAAO,gCAAgC,WAClD;AAAA,kBACE,WAAW;AAAA,oBACT,0BACE,IAAI,MAAM;AAAA,kBACd;AAAA,gBACF,IACA,CAAC;AAAA,cACP;AAAA,YACF,CAAC;AAED,+BAAmB;AACnB,wBAAY;AAEZ,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAAC;AAAA,UACX;AAKA,cAAI,mBAAmB;AAEvB,gBAAM,cAAc,CAAC,SAAiB;AACpC,gBAAI,CAAC,KAAK,KAAK,EAAG;AAClB,gBAAI,iBAAkB;AAItB,gCAAoB;AAGpB,+BAAmB;AAEnB,gBAAI;AACF,oBAAM,QAA6B,KAAK,MAAM,IAAI;AAIlD,oBAAM,MACJ,MAAM,SAAS,kBAAkB,MAAM,QACnC,EAAE,GAAG,MAAM,OAAO,YAAY,MAAM,WAAW,IAC/C;AAEN,kBAAI,MAAM,SAAS,gBAAgB;AACjC,mCAAmB;AAAA,cACrB;AAEA,kBAAI,qBAAqB,KAAK,IAAI,GAAG;AACnC;AAAA,cACF;AAEA,kBAAI,MAAM,kBAAkB;AAAA,gBAC1B,MAAM,IAAI;AAAA,gBACV,SAAS,IAAI;AAAA,cACf,CAAC;AAGD,kBAAI,IAAI,SAAS,YAAY,IAAI,YAAY,QAAQ;AACnD,oBAAI,IAAI,YAAY;AAClB,qCAAmB,IAAI,IAAI,UAAU;AACrC,sBAAI,KAAK,uBAAuB;AAAA,oBAC9B,iBAAiB,IAAI;AAAA,kBACvB,CAAC;AAAA,gBACH;AAAA,cACF;AAGA,kBACE,IAAI,SAAS,yBACb,IAAI,iBACJ,IAAI,UAAU,QACd;AACA,sBAAM,QAAQ,IAAI;AAClB,sBAAM,MAAM,IAAI;AAEhB,oBAAI,MAAM,SAAS,YAAY;AAC7B,gCAAc;AACd,wBAAM,cAAc,WAAW;AAC/B,+BAAa,IAAI,KAAK,WAAW;AAAA,gBACnC;AAEA,oBAAI,MAAM,SAAS,QAAQ;AACzB,mCAAiB,IAAI,GAAG;AAIxB,4CAA0B;AAC1B,sBAAI,MAAM,MAAM;AACd,wBAAI,CAAC,cAAe,gBAAe;AACnC,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO,MAAM;AAAA,oBACf,CAAC;AACD,oCAAgB,MAAM,IAAI;AAC1B,yCAAqB;AAAA,kBACvB;AAAA,gBACF;AAEA,oBAAI,MAAM,SAAS,cAAc,MAAM,MAAM,MAAM,MAAM;AACvD,mCAAiB;AACjB,wBAAM,QAAQ;AAAA,oBACZ,IAAI,MAAM;AAAA,oBACV,MAAM,MAAM;AAAA,oBACZ,WAAW;AAAA,oBACX,SAAS;AAAA,kBACX;AACA,8BAAY,IAAI,KAAK,KAAK;AAE1B,sBACE,MAAM,SAAS,qBACf,MAAM,SAAS,uBACf,MAAM,SAAS,kBACf,CAAC,MAAM,KAAK,WAAW,iBAAiB,GACxC;AACA,0BAAM,EAAE,MAAM,YAAY,MAAM,SAAS,IAAI;AAAA,sBAC3C,MAAM;AAAA,sBACN;AAAA,sBACA;AAAA,wBACE,WAAW,KAAK,OAAO;AAAA,wBACvB,WAAW,mBAAmB,EAAE;AAAA,wBAChC,WAAW,MAAM;AAAA,sBACnB;AAAA,oBACF;AACA,wBAAI,CAAC,MAAM;AACT,4BAAM,UAAU;AAChB,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM;AAAA,wBACV,UAAU;AAAA,wBACV,kBAAkB;AAAA,sBACpB,CAAQ;AACR,0BAAI,KAAK,gBAAgB;AAAA,wBACvB,MAAM,MAAM;AAAA,wBACZ;AAAA,wBACA,IAAI,MAAM;AAAA,sBACZ,CAAC;AAAA,oBACH;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAGA,kBACE,IAAI,SAAS,yBACb,IAAI,SACJ,IAAI,UAAU,QACd;AACA,sBAAM,QAAQ,IAAI;AAClB,sBAAM,MAAM,IAAI;AAEhB,oBAAI,MAAM,SAAS,oBAAoB,MAAM,UAAU;AACrD,gCAAc;AACd,8CAA4B;AAC5B,wBAAM,cAAc,aAAa,IAAI,GAAG;AACxC,sBAAI,aAAa;AACf,wBAAI,CAAC,iBAAiB,IAAI,GAAG,GAAG;AAC9B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI;AAAA,sBACN,CAAQ;AACR,uCAAiB,IAAI,KAAK,IAAI;AAAA,oBAChC;AACA,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO,MAAM;AAAA,oBACf,CAAQ;AAAA,kBACV;AAAA,gBACF;AAEA,oBAAI,MAAM,SAAS,gBAAgB,MAAM,MAAM;AAC7C,sBAAI,CAAC,cAAe,gBAAe;AACnC,6BAAW,QAAQ;AAAA,oBACjB,MAAM;AAAA,oBACN,IAAI;AAAA,oBACJ,OAAO,MAAM;AAAA,kBACf,CAAC;AACD,kCAAgB,MAAM,IAAI;AAC1B,uCAAqB;AAAA,gBACvB;AAEA,oBAAI,MAAM,SAAS,sBAAsB,MAAM,cAAc;AAC3D,wBAAM,KAAK,YAAY,IAAI,GAAG;AAC9B,sBAAI,IAAI;AACN,uBAAG,aAAa,MAAM;AAOtB,wBAAI,GAAG,SAAS;AACd,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,GAAG;AAAA,wBACP,OAAO,MAAM;AAAA,sBACf,CAAQ;AAAA,oBACV;AAAA,kBACF;AAAA,gBACF;AAEA,oBAAI,CAAC,kBAAkB,IAAI,MAAM,IAAI,GAAG;AACtC,sBAAI,MAAM,yCAAyC;AAAA,oBACjD,MAAM,MAAM;AAAA,oBACZ;AAAA,oBACA,MAAM,OAAO,KAAK,KAAK;AAAA,kBACzB,CAAC;AAAA,gBACH;AAAA,cACF;AAGA,kBACE,IAAI,SAAS,wBACb,IAAI,UAAU,QACd;AACA,sBAAM,MAAM,IAAI;AAEhB,sBAAM,cAAc,aAAa,IAAI,GAAG;AACxC,oBAAI,eAAe,iBAAiB,IAAI,GAAG,GAAG;AAC5C,6BAAW,QAAQ;AAAA,oBACjB,MAAM;AAAA,oBACN,IAAI;AAAA,kBACN,CAAQ;AACR,mCAAiB,OAAO,GAAG;AAAA,gBAC7B;AAEA,oBAAI,iBAAiB,IAAI,GAAG,GAAG;AAC7B,+BAAa;AACb,mCAAiB,OAAO,GAAG;AAAA,gBAC7B;AAEA,sBAAM,KAAK,YAAY,IAAI,GAAG;AAC9B,oBAAI,IAAI;AACN,sBAAI,cAAmB,CAAC;AACxB,sBAAI;AACF,kCAAc,KAAK,MAAM,GAAG,aAAa,IAAI;AAAA,kBAC/C,QAAQ;AAAA,kBAAC;AAET,sBAAI,sBAAsB,GAAG,IAAI,GAAG;AAIlC,sCAAkB,qBAAqB;AACvC,0BAAM,QAAQ,eAAe;AAC7B,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO,sBAAsB,WAAW;AAAA,oBAC1C,CAAC;AACD,iCAAa;AAAA,kBACf,WAAW,GAAG,SAAS,gBAAgB;AACrC,0BAAM,OAAQ,aAAa,QAAmB;AAE9C,wBAAI,wBAAwB;AAI1B,4BAAM,eAAe;AAAA,wBACnB;AAAA,wBACA,GAAG;AAAA,wBACH;AAAA,sBACF;AACA,4BAAMC,UAAS,eAAe;AAC9B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAIA;AAAA,wBACJ,OAAO,aAAa;AAAA,sBACtB,CAAC;AACD,iDAA2B,YAAY;AACvC;AAAA,oBACF;AAEA,0BAAM,SAAS,eAAe;AAC9B,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO;AAAA;AAAA,EAAO,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oBACpB,CAAC;AACD,iCAAa;AAAA,kBACf,WACE,gBAAgB,GAAG,IAAI,KACvB,wBAAwB,KAAK,OAAO,SAAS,GAC7C;AAKA,0BAAM,QACJ,OAAO,aAAa,UAAU,WAC1B,YAAY,QACZ,KAAK,UAAU,WAAW;AAChC,0BAAM,WAAW,eAAe;AAChC,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO;AAAA,oBAAuB,KAAK;AAAA;AAAA,oBACrC,CAAC;AACD,iCAAa;AAAA,kBACf,WAAW,GAAG,KAAK,WAAW,iBAAiB,GAAG;AAChD,sCAAkB;AAClB,wBAAI,MAAM,oDAAoD;AAAA,sBAC5D,MAAM,GAAG;AAAA,sBACT,IAAI,GAAG;AAAA,oBACT,CAAC;AAAA,kBACH,OAAO;AACL,0BAAM;AAAA,sBACJ,MAAM;AAAA,sBACN,OAAO;AAAA,sBACP;AAAA,sBACA;AAAA,oBACF,IAAI,QAAQ,GAAG,MAAM,aAAa;AAAA,sBAChC,WAAW,KAAK,OAAO;AAAA,sBACvB,WAAW,mBAAmB,EAAE;AAAA,sBAChC,WAAW,GAAG;AAAA,oBAChB,CAAC;AAED,wBAAI,CAAC,MAAM;AACT,oCAAc,IAAI,GAAG,IAAI;AAAA,wBACvB,IAAI,GAAG;AAAA,wBACP,MAAM,GAAG;AAAA,wBACT,OAAO;AAAA,sBACT,CAAC;AACD,0BAAI,CAAC,SAAU,kBAAiB,IAAI,GAAG,EAAE;AAEzC,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,YAAY,GAAG;AAAA,wBACf,UAAU;AAAA,wBACV,OAAO,KAAK,UAAU,WAAW;AAAA,wBACjC,kBAAkB;AAAA,sBACpB,CAAQ;AAAA,oBACV;AACA,wBAAI,KAAK,sBAAsB;AAAA,sBAC7B,MAAM,GAAG;AAAA,sBACT;AAAA,sBACA,IAAI,GAAG;AAAA,sBACP;AAAA,oBACF,CAAC;AAAA,kBACH;AAAA,gBACF;AAAA,cACF;AAMA,kBACE,oBACA,IAAI,SAAS,mBACb,OAAQ,IAAY,OAAO,gBAAgB,UAC3C;AACA,iCAAkB,IAAY,MAAM;AAAA,cACtC;AAOA,kBACE,IAAI,SAAS,eACb,IAAI,WACJ,OAAQ,IAAI,QAAgB,gBAAgB,UAC5C;AACA,iCAAkB,IAAI,QAAgB;AAAA,cACxC;AAIA,kBACE,IAAI,SAAS,eACb,IAAI,SAAS,WACb,kBACA;AACA,sBAAM,iBAAkB,IAAI,QAAQ,QAAkB;AAAA,kBACpD,CAAC,MAAM,EAAE,SAAS;AAAA,gBACpB;AACA,oBAAI,eAAe,SAAS,GAAG;AAC7B,sBAAI,KAAK,qCAAqC;AAAA,oBAC5C,OAAO,eAAe;AAAA,oBACtB,SAAS,eAAe;AAAA,sBACtB,CAAC,MAAM,OAAO,EAAE,aAAa,YAAY,EAAE,SAAS,SAAS;AAAA,oBAC/D;AAAA,oBACA,mBAAmB;AAAA,kBACrB,CAAC;AACD,sBAAI,CAAC,2BAA2B;AAC9B,+BAAW,SAAS,gBAAgB;AAClC,0BAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAC/C,sCAAc;AACd,oDAA4B;AAC5B,8BAAM,aAAa,WAAW;AAC9B,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN,CAAQ;AACR,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAI;AAAA,0BACJ,OAAO,MAAM;AAAA,wBACf,CAAQ;AACR,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN,CAAQ;AAAA,sBACV;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AACA,kBACE,IAAI,SAAS,eACb,IAAI,SAAS,WACb,CAAC,kBACD;AACA,sBAAM,UAAU,IAAI,QAAQ,QAAQ;AAAA,kBAClC,CAAC,MAAW,EAAE,SAAS,UAAU,EAAE;AAAA,gBACrC;AACA,sBAAM,aAAa,IAAI,QAAQ,QAAQ;AAAA,kBACrC,CAAC,MAAW,EAAE,SAAS;AAAA,gBACzB;AAEA,oBAAI,SAAS;AACX,uCAAqB;AAAA,gBACvB;AAEA,oBAAI,WAAW,CAAC,YAAY;AAC1B,sCAAoB;AAAA,gBACtB;AACA,oBAAI,YAAY;AACd,qCAAmB;AAAA,gBACrB;AAEA,2BAAW,SAAS,IAAI,QAAQ,SAAS;AACvC,sBAAI,MAAM,SAAS,UAAU,MAAM,MAAM;AAGvC,8CAA0B;AAC1B,0BAAM,UAAU,eAAe;AAC/B,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO,MAAM;AAAA,oBACf,CAAC;AACD,iCAAa;AACb,oCAAgB,MAAM,IAAI;AAC1B,yCAAqB;AAAA,kBACvB;AAEA,sBAAI,MAAM,SAAS,cAAc,MAAM,UAAU;AAC/C,kCAAc;AACd,0BAAM,aAAa,WAAW;AAC9B,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,oBACN,CAAQ;AACR,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,sBACJ,OAAO,MAAM;AAAA,oBACf,CAAQ;AACR,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI;AAAA,oBACN,CAAQ;AAAA,kBACV;AAEA,sBAAI,MAAM,SAAS,cAAc,MAAM,MAAM,MAAM,MAAM;AACvD,qCAAiB;AACjB,0BAAM,cAAe,MAAM,SAAS,CAAC;AAKrC,wBAAI,sBAAsB,MAAM,IAAI,GAAG;AACrC,4BAAM,QAAQ,eAAe;AAC7B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI;AAAA,wBACJ,OAAO,sBAAsB,WAAW;AAAA,sBAC1C,CAAC;AACD,mCAAa;AAAA,oBACf,WAAW,MAAM,SAAS,gBAAgB;AACxC,4BAAM,OAAQ,aAAa,QAAmB;AAE9C,0BAAI,wBAAwB;AAC1B,8BAAM,eAAe;AAAA,0BACnB;AAAA,0BACA,MAAM;AAAA,0BACN;AAAA,wBACF;AACA,8BAAMA,UAAS,eAAe;AAC9B,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAIA;AAAA,0BACJ,OAAO,aAAa;AAAA,wBACtB,CAAC;AACD,mDAA2B,YAAY;AACvC;AAAA,sBACF;AAEA,4BAAM,SAAS,eAAe;AAC9B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI;AAAA,wBACJ,OAAO;AAAA;AAAA,EAAO,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,sBACpB,CAAC;AACD,mCAAa;AAAA,oBACf,WACE,gBAAgB,MAAM,IAAI,KAC1B,wBAAwB,KAAK,OAAO,SAAS,GAC7C;AAIA,oCAAc,OAAO,MAAM,EAAE;AAC7B,4BAAM,QACJ,OAAO,aAAa,UAAU,WAC1B,YAAY,QACZ,KAAK,UAAU,WAAW;AAChC,4BAAM,WAAW,eAAe;AAChC,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI;AAAA,wBACJ,OAAO;AAAA,oBAAuB,KAAK;AAAA;AAAA,sBACrC,CAAC;AACD,mCAAa;AAAA,oBACf,WAAW,MAAM,KAAK,WAAW,iBAAiB,GAAG;AACnD,wCAAkB;AAClB,0BAAI,MAAM,kDAAkD;AAAA,wBAC1D,MAAM,MAAM;AAAA,wBACZ,IAAI,MAAM;AAAA,sBACZ,CAAC;AAAA,oBACH,OAAO;AACL,4BAAM;AAAA,wBACJ,MAAM;AAAA,wBACN,OAAO;AAAA,wBACP;AAAA,wBACA;AAAA,sBACF,IAAI,QAAQ,MAAM,MAAM,aAAa;AAAA,wBACnC,WAAW,KAAK,OAAO;AAAA,wBACvB,WAAW,mBAAmB,EAAE;AAAA,wBAChC,WAAW,MAAM;AAAA,sBACnB,CAAC;AAED,0BAAI,CAAC,MAAM;AACT,sCAAc,IAAI,MAAM,IAAI;AAAA,0BAC1B,IAAI,MAAM;AAAA,0BACV,MAAM,MAAM;AAAA,0BACZ,OAAO;AAAA,wBACT,CAAC;AACD,4BAAI,CAAC,SAAU,kBAAiB,IAAI,MAAM,EAAE;AAC5C,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAI,MAAM;AAAA,0BACV,UAAU;AAAA,0BACV,kBAAkB;AAAA,wBACpB,CAAQ;AACR,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,YAAY,MAAM;AAAA,0BAClB,UAAU;AAAA,0BACV,OAAO,KAAK,UAAU,WAAW;AAAA,0BACjC,kBAAkB;AAAA,wBACpB,CAAQ;AAAA,sBACV;AACA,0BAAI,KAAK,mCAAmC;AAAA,wBAC1C,MAAM,MAAM;AAAA,wBACZ;AAAA,wBACA,IAAI,MAAM;AAAA,wBACV;AAAA,sBACF,CAAC;AAAA,oBACH;AAAA,kBACF;AAEA,sBAAI,MAAM,SAAS,eAAe;AAChC,wBAAI,MAAM,eAAe;AAAA,sBACvB,WAAW,MAAM;AAAA,oBACnB,CAAC;AAAA,kBACH;AAAA,gBACF;AAAA,cACF;AAGA,kBAAI,IAAI,SAAS,UAAU,IAAI,SAAS,SAAS;AAC/C,2BAAW,SAAS,IAAI,QAAQ,SAAS;AACvC,sBAAI,MAAM,SAAS,iBAAiB,MAAM,aAAa;AACrD,wBAAI,iBAAiB,IAAI,MAAM,WAAW,GAAG;AAC3C,0BAAI,MAAM,2CAA2C;AAAA,wBACnD,WAAW,MAAM;AAAA,sBACnB,CAAC;AACD;AAAA,oBACF;AAEA,wBAAI,aAAa;AACjB,wBAAI,OAAO,MAAM,YAAY,UAAU;AACrC,mCAAa,MAAM;AAAA,oBACrB,WAAW,MAAM,QAAQ,MAAM,OAAO,GAAG;AACvC,mCAAa,MAAM,QAChB;AAAA,wBACC,CACE,MAEA,EAAE,SAAS,UACX,OAAO,EAAE,SAAS;AAAA,sBACtB,EACC,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AAAA,oBACd;AAKA,0BAAM,kBAAkB,mBAAmB,EAAE;AAC7C,wBAAI,iBAAiB;AACnB,4BAAM,OAAO;AAAA,wBACX;AAAA,wBACA,MAAM;AAAA,wBACN;AAAA,sBACF;AACA,0BAAI,MAAM;AACR,8BAAM,UAAU,aAAa,MAAM,WAAW;AAC9C,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,IAAI;AAAA,0BACJ,UAAU;AAAA,0BACV,kBAAkB;AAAA,wBACpB,CAAQ;AACR,mCAAW,QAAQ;AAAA,0BACjB,MAAM;AAAA,0BACN,YAAY;AAAA,0BACZ,UAAU;AAAA,0BACV,OAAO,KAAK,UAAU;AAAA,4BACpB,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,8BACtB,IAAI,EAAE;AAAA,8BACN,SAAS,EAAE;AAAA,8BACX,QAAQ,EAAE;AAAA,8BACV,UAAU;AAAA,4BACZ,EAAE;AAAA,0BACJ,CAAC;AAAA,0BACD,kBAAkB;AAAA,wBACpB,CAAQ;AACR,yCAAiB;AAAA,sBACnB;AAAA,oBACF;AAEA,0BAAM,WAAW,cAAc,IAAI,MAAM,WAAW;AACpD,wBAAI,UAAU;AACZ,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,YAAY,MAAM;AAAA,wBAClB,UAAU,SAAS;AAAA,wBACnB,QAAQ;AAAA,0BACN,QAAQ;AAAA,0BACR,OAAO,SAAS;AAAA,0BAChB,UAAU,CAAC;AAAA,wBACb;AAAA,wBACA,kBAAkB;AAAA,sBACpB,CAAQ;AACR,uCAAiB;AACjB,0BAAI,KAAK,uBAAuB;AAAA,wBAC9B,WAAW,MAAM;AAAA,wBACjB,MAAM,SAAS;AAAA,sBACjB,CAAC;AACD,oCAAc,OAAO,MAAM,WAAW;AAAA,oBACxC;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAGA,kBAAI,IAAI,SAAS,UAAU;AACzB,mCAAmB;AAEnB,oBAAI,IAAI,YAAY;AAClB,qCAAmB,IAAI,IAAI,UAAU;AAAA,gBACvC;AAKA,oBACE,CAAC,iBACD,IAAI,YACJ,OAAO,IAAI,WAAW,YACtB,IAAI,OAAO,KAAK,EAAE,SAAS,GAC3B;AACA,wBAAM,QAAQ,eAAe;AAC7B,6BAAW,QAAQ;AAAA,oBACjB,MAAM;AAAA,oBACN,IAAI;AAAA,oBACJ,OAAO,IAAI;AAAA,kBACb,CAAC;AAAA,gBACH;AAEA,6BAAa;AAAA,kBACX,WAAW,IAAI;AAAA,kBACf,SAAS,IAAI;AAAA,kBACb,YAAY,IAAI;AAAA,kBAChB,OAAO,IAAI;AAAA,gBACb;AAEA,oBAAI,KAAK,uBAAuB;AAAA,kBAC9B,WAAW,IAAI;AAAA,kBACf,YAAY,IAAI;AAAA,kBAChB,UAAU,IAAI;AAAA,kBACd,SAAS,IAAI;AAAA,gBACf,CAAC;AAED,gCAAgB;AAEhB,6BAAa;AAEb,sBAAM,oBACJ,CAAC,IAAI,YACL,CAAC,kBAAkB,WACnB,CAAC,kBAAkB;AAErB,oBAAI,YAAY,SAAS,KAAK,mBAAmB;AAC/C,sBAAI;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,YAAY;AAAA,sBACZ,OAAO,YAAY;AAAA,oBACrB;AAAA,kBACF;AACA;AAAA,oBACE,MAAM,eAAe,GAAG;AAAA,oBACxB;AAAA,kBACF;AACA;AAAA,gBACF;AAEA,oBACE,YAAY,WAAW,KACvB,iCACA,mBACA;AACA,sBAAI;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,YAAY;AAAA,sBACZ,SAAS;AAAA,oBACX;AAAA,kBACF;AACA;AAAA,oBACE,MAAM,eAAe,GAAG;AAAA,oBACxB;AAAA,kBACF;AACA;AAAA,gBACF;AAEA,+BAAe,GAAG;AAAA,cACpB;AAAA,YACF,SAAS,GAAG;AACV,kBAAI,MAAM,wBAAwB;AAAA,gBAChC,OACE,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,cAC7C,CAAC;AAAA,YACH;AAAA,UACF;AAEA,gBAAM,eAAe,MAAM;AACzB,gBAAI,MAAM,iBAAiB;AAC3B,gBAAI,iBAAkB;AAItB,gBAAI,YAAY,SAAS,KAAK,qBAAqB,EAAE,EAAE,SAAS,GAAG;AACjE;AAAA,gBACE;AAAA,gBACA,IAAI;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AACA,0BAAY,SAAS;AAAA,YACvB;AACA,+BAAmB;AACnB,wBAAY;AACZ,yBAAa;AACb,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,cAAc,eAAe,MAAM;AAAA,cACnC,OAAO,QAAQ;AAAA,cACf,kBAAkB;AAAA,gBAChB,eAAe;AAAA,kBACb,GAAG;AAAA,kBACH,GAAI,iBACA,EAAE,iBAAiB,iBAAiB,IACpC,CAAC;AAAA,gBACP;AAAA,cACF;AAAA,YACF,CAAC;AACD,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAAC;AAAA,UACX;AAIA,cAAI,YAAY;AAChB,gBAAM,cAAc,MAAM;AACxB,gBAAI,UAAW;AACf,wBAAY;AACZ,+BAAmB;AACnB,sCAA0B;AAC1B,+BAAmB;AACnB,gBAAI,YAAY;AACd,2BAAa,UAAU;AACvB,2BAAa;AAAA,YACf;AACA,wBAAY,IAAI,QAAQ,WAAW;AACnC,wBAAY,IAAI,SAAS,YAAY;AACrC,sCAA0B;AAC1B,sCAA0B;AAC1B,iBAAK,IAAI,SAAS,gBAAgB;AAAA,UACpC;AAEA,gBAAM,mBAAmB,CAAC,QAAe;AACvC,gBAAI,MAAM,iBAAiB,EAAE,OAAO,IAAI,QAAQ,CAAC;AACjD,gCAAoB,EAAE;AACtB,kCAAsB,EAAE;AACxB,gBAAI,iBAAkB;AAItB,gBAAI,YAAY,SAAS,KAAK,qBAAqB,EAAE,EAAE,SAAS,GAAG;AACjE;AAAA,gBACE;AAAA,gBACA,IAAI;AAAA,kBACF,gCAAgC,IAAI,OAAO;AAAA,gBAC7C;AAAA,cACF;AACA,0BAAY,SAAS;AAAA,YACvB;AACA,+BAAmB;AACnB,wBAAY;AACZ,uBAAW,QAAQ,EAAE,MAAM,SAAS,OAAO,IAAI,CAAC;AAChD,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAAC;AAAA,UACX;AAEA,sBAAY,GAAG,QAAQ,WAAW;AAClC,sBAAY,GAAG,SAAS,YAAY;AAEpC,oCAA0B,mBAAmB,IAAI,CAAC,SAAS;AACzD,gBAAI,kBAAkB;AAIpB,kBAAI;AAAA,gBACF;AAAA,gBACA;AAAA,kBACE,YAAY;AAAA,kBACZ,YAAY,KAAK;AAAA,kBACjB,UAAU,KAAK;AAAA,gBACjB;AAAA,cACF;AACA;AAAA,gBACE,KAAK;AAAA,gBACL,IAAI;AAAA,kBACF,uBAAuB,KAAK,QAAQ;AAAA,gBACtC;AAAA,cACF;AACA;AAAA,YACF;AACA,gBAAI,KAAK,2CAA2C;AAAA,cAClD,YAAY;AAAA,cACZ,YAAY,KAAK;AAAA,cACjB,UAAU,KAAK;AAAA,YACjB,CAAC;AACD,8BAAkB;AAClB,6BAAiB;AACjB,wBAAY,KAAK,IAAI;AACrB,gBAAI,uBAAuB,EAAG;AAC9B,gBAAI,WAAY,cAAa,UAAU;AACvC,yBAAa,WAAW,UAAU,cAAc;AAAA,UAClD,CAAC;AAED,eAAK,GAAG,SAAS,gBAAgB;AAGjC,cAAI,QAAQ,aAAa;AACvB,oBAAQ,YAAY,iBAAiB,SAAS,MAAM;AAClD,gCAAkB,UAAU;AAC5B,kBAAI,iBAAiB,iBAAkB;AAEvC,kBAAI,CAAC,oBAAoB;AACvB,oBAAI;AAAA,kBACF;AAAA,kBACA,EAAE,IAAI;AAAA,gBACR;AACA,oBACE,YAAY,SAAS,KACrB,qBAAqB,EAAE,EAAE,SAAS,GAClC;AACA;AAAA,oBACE;AAAA,oBACA,IAAI;AAAA,sBACF;AAAA,oBACF;AAAA,kBACF;AACA,8BAAY,SAAS;AAAA,gBACvB;AACA,mCAAmB;AACnB,4BAAY;AACZ,oBAAI;AACF,6BAAW,MAAM;AAAA,gBACnB,QAAQ;AAAA,gBAAC;AACT;AAAA,cACF;AAEA,kBAAI;AAAA,gBACF;AAAA,gBACA,EAAE,IAAI;AAAA,cACR;AAEA,kCAAoB,GAAK;AAAA,YAC3B,CAAC;AAAA,UACH;AAEA,cAAI,0BAA0B;AAO5B,uBAAW,EAAE,MAAM,OAAO,KAAK,6BAA6B;AAC1D,kBAAI,QAAQ;AACV,oBAAI,KAAK,wDAAwD;AAAA,kBAC/D,YAAY;AAAA,kBACZ,YAAY,KAAK;AAAA,kBACjB,UAAU,KAAK;AAAA,gBACjB,CAAC;AACD,4CAA4B,KAAK,YAAY,MAAM;AAAA,cACrD,OAAO;AACL,oBAAI;AAAA,kBACF;AAAA,kBACA;AAAA,oBACE,YAAY;AAAA,oBACZ,YAAY,KAAK;AAAA,oBACjB,UAAU,KAAK;AAAA,kBACjB;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AACA;AAAA,UACF;AAMA,cAAI,0BAA0B,SAAS,GAAG;AACxC,uBAAW,QAAQ,2BAA2B;AAC5C;AAAA,gBACE,KAAK;AAAA,gBACL,IAAI;AAAA,kBACF,uBAAuB,KAAK,QAAQ,MAAM,KAAK,UAAU;AAAA,gBAC3D;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAGA,eAAK,OAAO,MAAM,UAAU,IAAI;AAChC,cAAI,MAAM,qBAAqB,EAAE,YAAY,QAAQ,OAAO,CAAC;AAI7D,2BAAiB;AAAA,QACjB;AAEA,aAAK,MAAM,EAAE,MAAM,CAAC,QAAQ;AAC1B,cAAI,MAAM,6BAA6B;AAAA,YACrC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,UACxD,CAAC;AACD,qBAAW,QAAQ;AAAA,YACjB,MAAM;AAAA,YACN,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,UAC3D,CAAC;AACD,cAAI;AACF,uBAAW,MAAM;AAAA,UACnB,QAAQ;AAAA,UAAC;AAAA,QACX,CAAC;AAAA,MACH;AAAA,MACA,SAAS;AAAA,MAET;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE;AAAA,MACnC,UAAU,EAAE,SAAS,CAAC,EAAE;AAAA,IAC1B;AAAA,EACF;AACF;;;AexrHA,IAAM,cAAc;AACpB,IAAM,MAAM;AAEZ,IAAM,oBAA6D;AAAA,EACjE,KAAK,EAAE,iBAAiB,MAAM;AAAA,EAC9B,QAAQ,EAAE,iBAAiB,SAAS;AAAA,EACpC,MAAM,EAAE,iBAAiB,OAAO;AAAA,EAChC,OAAO,EAAE,iBAAiB,QAAQ;AAAA,EAClC,KAAK,EAAE,iBAAiB,MAAM;AAChC;AAEA,IAAM,mBAAmB;AAAA,EACvB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,OAAO,EAAE,MAAM,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,OAAO,KAAK,MAAM;AAAA,EACzE,QAAQ,EAAE,MAAM,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,MAAM;AAAA,EAC3E,aAAa;AACf;AAEA,SAAS,YAAY,MAkBH;AAChB,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,YAAY;AAAA,IACZ,KAAK,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,IACtC,MAAM,GAAG,KAAK,IAAI,KAAK,KAAK,UAAU;AAAA,IACtC,QAAQ,KAAK;AAAA,IACb,cAAc,EAAE,GAAG,kBAAkB,WAAW,KAAK,UAAU;AAAA,IAC/D,MAAM;AAAA,MACJ,OAAO,KAAK,KAAK;AAAA,MACjB,QAAQ,KAAK,KAAK;AAAA,MAClB,OAAO,EAAE,MAAM,KAAK,KAAK,WAAW,OAAO,KAAK,KAAK,WAAW;AAAA,IAClE;AAAA,IACA,OAAO,EAAE,SAAS,KAAK,SAAS,QAAQ,KAAK,OAAO;AAAA,IACpD,QAAQ,KAAK,UAAU;AAAA,IACvB,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,cAAc,KAAK;AAAA,IACnB,UAAU,KAAK,YAAY,oBAAoB;AAAA,EACjD;AACF;AAYA,IAAM,YAAY,EAAE,OAAO,MAAM,QAAQ,MAAM,WAAW,MAAM,YAAY,OAAQ;AACpF,IAAM,aAAa,EAAE,OAAO,MAAM,QAAQ,OAAO,WAAW,MAAM,YAAY,OAAQ;AAGtF,IAAM,cAAc,EAAE,OAAO,MAAM,QAAQ,MAAO,WAAW,MAAM,YAAY,MAAO;AAGtF,IAAM,WAAW,EAAE,OAAO,MAAM,QAAQ,OAAO,WAAW,MAAQ,YAAY,OAAQ;AAItF,IAAM,YAAY,EAAE,OAAO,MAAO,QAAQ,MAAO,WAAW,MAAM,YAAY,OAAQ;AAO/E,SAAS,cAAc,OAA+C;AAC3E,QAAM,YAAsB,CAAC;AAC7B,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,aAAa,KAAK,GAAG;AAC7D,QAAI,EAAG,WAAU,KAAK,CAAC;AAAA,EACzB;AACA,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,aAAa,MAAM,GAAG;AAC9D,QAAI,EAAG,YAAW,KAAK,CAAC;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,IAAI,MAAM,IAAI;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,QAAQ,MAAM;AAAA,IACd,QAAQ,MAAM,UAAU;AAAA,IACxB,cAAc,MAAM;AAAA,IAEpB,aAAa,MAAM,aAAa;AAAA,IAChC,WAAW,MAAM,aAAa;AAAA,IAC9B,YAAY,MAAM,aAAa;AAAA,IAC/B,WAAW,MAAM,aAAa;AAAA,IAC9B,YAAY,EAAE,OAAO,WAAW,QAAQ,WAAW;AAAA,IAEnD,MAAM;AAAA,MACJ,OAAO,MAAM,KAAK;AAAA,MAClB,QAAQ,MAAM,KAAK;AAAA,MACnB,YAAY,MAAM,KAAK,MAAM;AAAA,MAC7B,aAAa,MAAM,KAAK,MAAM;AAAA,IAChC;AAAA,IAEA,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,EAClB;AACF;AAEO,IAAM,gBAA+C;AAAA,EAC1D,oBAAoB,YAAY;AAAA,IAC9B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,qBAAqB,YAAY;AAAA,IAC/B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,qBAAqB,YAAY;AAAA,IAC/B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,iBAAiB,YAAY;AAAA,IAC3B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA,EACD,kBAAkB,YAAY;AAAA,IAC5B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKD,mBAAmB,YAAY;AAAA,IAC7B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,CAAC;AACH;;;AC7PA,SAAS,OAAO,OAAO,OAAO,UAAU,SAAS,iBAAiB;AAClE,OAAOC,WAAU;AAGV,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AAE/B,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,qBAAqB,SAAyB;AAC5D,SAAO,QACJ,KAAK,EACL,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAEO,SAAS,gBAAgB,OAAiC;AAC/D,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAElC,QAAM,WAAW,MACd,IAAI,CAAC,YAAY,qBAAqB,OAAO,OAAO,CAAC,CAAC,EACtD,OAAO,OAAO;AAEjB,SAAO,MAAM,KAAK,oBAAI,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,CAAC;AAC3D;AAEO,SAAS,kBAAkB,SAAyB;AACzD,SAAO,GAAG,gBAAgB,IAAI,qBAAqB,OAAO,CAAC;AAC7D;AAEO,SAAS,mBAAmB,SAAyB;AAC1D,SAAO,gBAAgB,gBAAgB,OAAO,CAAC;AACjD;AAEO,SAAS,mBAAmB,SAAqC;AACtE,QAAM,aAAa,qBAAqB,OAAO;AAC/C,SAAO,eAAe,kBAAkB,SAAY;AACtD;AAEO,SAAS,iBAAiB,SAAqC;AACpE,QAAM,aAAa,qBAAqB,OAAO;AAE/C,MAAI,CAAC,cAAc,eAAe,gBAAiB,QAAO;AAE1D,SAAO,aAAa,UAAU;AAChC;AAEO,SAAS,WAAW,OAAuB;AAChD,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AAE7C,MAAI,UAAU,IAAK,QAAO,QAAQ;AAElC,MAAI,MAAM,WAAW,IAAI,KAAK,MAAM,WAAW,KAAK,GAAG;AACrD,WAAO,OAAOC,MAAK,KAAK,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;AAAA,EAClD;AAEA,SAAO;AACT;AAEA,eAAsB,qBACpB,SACA,aACkD;AAClD,QAAM,YAAY,iBAAiB,OAAO;AAE1C,MAAI,CAAC,UAAW,QAAO,EAAE,SAAS,YAAY;AAE9C,QAAM,oBAAoB,WAAW,SAAS;AAC9C,QAAM,MAAM,mBAAmB,EAAE,WAAW,KAAK,CAAC;AAElD,MAAI;AACF,UAAM,yBAAyB,iBAAiB;AAAA,EAClD,SAAS,KAAK;AACZ,QAAI,KAAK,4DAA4D;AAAA,MACnE;AAAA,MACA,WAAW;AAAA,MACX,OAAO,OAAO,GAAG;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB,qBAAqB,OAAO;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,WAAW,kBAAkB;AACjD;AAEA,eAAe,yBAAyB,YAAmC;AACzE,QAAM,aAAa,WAAW,WAAW;AAEzC,aAAW,QAAQ,yBAAyB;AAC1C,UAAM,2BAA2B,YAAY,YAAY,IAAI;AAAA,EAC/D;AACF;AAEA,eAAe,2BACb,YACA,YACA,MACe;AACf,QAAM,SAASA,MAAK,KAAK,YAAY,IAAI;AACzC,QAAM,SAASA,MAAK,KAAK,YAAY,IAAI;AAEzC,MAAI;AACJ,MAAI;AACF,iBAAa,MAAM,MAAM,MAAM;AAAA,EACjC,QAAQ;AACN;AAAA,EACF;AAEA,MAAI;AACF,UAAM,aAAa,MAAM,MAAM,MAAM;AAErC,QAAI,WAAW,eAAe,GAAG;AAC/B,YAAM,UAAU,MAAM,SAAS,MAAM;AACrC,YAAM,kBAAkBA,MAAK,QAAQA,MAAK,QAAQ,MAAM,GAAG,OAAO;AAClE,YAAM,iBAAiBA,MAAK,QAAQ,MAAM;AAE1C,UAAI,oBAAoB,eAAgB;AAAA,IAC1C;AAEA,QAAI,KAAK,8DAA8D;AAAA,MACrE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,OAAO,WAAW,YAAY,IAChC,QAAQ,aAAa,UACnB,aACA,QACF;AAEJ,QAAM,QAAQ,QAAQ,QAAQ,IAAI;AACpC;AAEA,eAAe,oBACb,SACA,aACA,WACiB;AACjB,QAAM,YAAYA,MAAK;AAAA,IACrB,QAAQ,IAAI,kBAAkB,WAAW,UAAU;AAAA,IACnD;AAAA,EACF;AACA,QAAM,cAAcA,MAAK,KAAK,WAAW,UAAU,OAAO,EAAE;AAC5D,QAAM,SAAS,IAAI,OAAO;AAE1B,QAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAE1C,QAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAOQ,iBAAiB,MAAM,CAAC;AAAA,wBACzB,iBAAiB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAUrB,iBAAiB,SAAS,CAAC;AAAA,OAC/C,iBAAiB,WAAW,CAAC;AAAA;AAGlC,QAAM,UAAU,aAAa,QAAQ,MAAM;AAC3C,QAAM,MAAM,aAAa,GAAK;AAE9B,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,IAAI,MAAM,QAAQ,MAAM,OAAO,CAAC;AACzC;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,MAAM,QAAQ,YAAY,MAAM;AACzC;AAEA,SAAS,gBAAgB,SAAyB;AAChD,SAAO,qBAAqB,OAAO,EAChC,MAAM,GAAG,EACT,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AACb;;;AC1MA;AAAA,EACE,cAAAC;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,OACK;AACP,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,qBAAqB;AAG9B,IAAM,qBAAqB;AAC3B,IAAM,4BAA4B;AAElC,IAAI,aAAa;AAEjB,SAAS,sBAAgC;AACvC,QAAM,MAAM,QAAQ,IAAI;AACxB,SAAO;AAAA,IACL,MAAMC,MAAK,KAAK,UAAU,IAAI;AAAA,IAC9BA,MAAKC,SAAQ,GAAG,UAAU,UAAU;AAAA,IACpCD,MAAKC,SAAQ,GAAG,WAAW,UAAU,UAAU;AAAA,EACjD,EAAE,OAAO,CAAC,MAAmB,QAAQ,CAAC,CAAC;AACzC;AAEA,SAAS,uBAA+B;AACtC,QAAM,YAAY,QAAQ,IAAI,mBAAmBD,MAAKC,SAAQ,GAAG,SAAS;AAC1E,SAAOD,MAAK,WAAW,YAAY,eAAe;AACpD;AAEA,SAAS,2BAAoC;AAC3C,QAAM,MAAM,qBAAqB;AACjC,MAAI,CAACE,YAAW,GAAG,EAAG,QAAO;AAC7B,MAAI;AACF,UAAM,OAAO,KAAK,MAAMC,cAAa,KAAK,MAAM,CAAC;AACjD,UAAM,UAAmB,KAAK;AAC9B,QAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,WAAO,QAAQ;AAAA,MACb,CAAC,UACC,OAAO,UAAU,YACjB,yCAAyC,KAAK,KAAK;AAAA,IACvD;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAA8B;AACrC,MAAI;AACF,UAAM,WAAW,cAAc,YAAY,GAAG;AAC9C,WAAO,aAAaC,SAAQ,UAAU,MAAM,IAAI,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,8BAAoC;AAClD,MAAI,WAAY;AAChB,eAAa;AAEb,MAAI,QAAQ,IAAI,2CAA2C,IAAK;AAChE,MAAI,yBAAyB,EAAG;AAEhC,QAAM,SAAS,aAAa;AAE5B,aAAW,aAAa,oBAAoB,GAAG;AAC7C,QAAI;AACF,iBAAW,WAAW,MAAM;AAAA,IAC9B,SAAS,KAAK;AACZ,UAAI,KAAK,8CAA8C;AAAA,QACrD;AAAA,QACA,OAAO,OAAO,GAAG;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,WAAW,WAAmB,QAA6B;AAClE,MAAI,CAACF,YAAW,SAAS,EAAG;AAE5B,QAAM,YAAYF,MAAK,WAAW,gBAAgB,kBAAkB;AACpE,MAAI,CAACE,YAAW,SAAS,EAAG;AAG5B,MAAI,gBAAgB;AACpB,MAAI;AACF,oBAAgB,aAAa,SAAS;AAAA,EACxC,QAAQ;AAAA,EAER;AACA,MAAI,UAAU,kBAAkB,OAAQ;AAGxC,QAAM,cAAcF,MAAK,WAAW,cAAc;AAClD,MAAI,CAACE,YAAW,WAAW,EAAG;AAC9B,MAAI,MAA+C,CAAC;AACpD,MAAI;AACF,UAAM,KAAK,MAAMC,cAAa,aAAa,MAAM,CAAC;AAAA,EACpD,QAAQ;AACN;AAAA,EACF;AACA,MAAI,IAAI,SAAS,mBAAoB;AACrC,MAAI,CAAC,IAAI,aAAa,SAAS,yBAAyB,EAAG;AAE3D,MAAI,KAAK,4CAA4C,EAAE,UAAU,CAAC;AAClE,MAAI;AACF,IAAAE,QAAO,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACpD,SAAS,KAAK;AACZ,QAAI,KAAK,gCAAgC;AAAA,MACvC;AAAA,MACA,OAAO,OAAO,GAAG;AAAA,IACnB,CAAC;AACD;AAAA,EACF;AAKA,QAAM,eAAeL,MAAK,WAAW,cAAc;AACnD,MAAI,CAACE,YAAW,YAAY,EAAG;AAC/B,MAAI;AACF,UAAM,MAAM,KAAK,MAAMC,cAAa,cAAc,MAAM,CAAC;AACzD,QAAI,KAAK,eAAe,kBAAkB,GAAG;AAC3C,aAAO,IAAI,aAAa,kBAAkB;AAC1C,MAAAG,eAAc,cAAc,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAC/D,UAAI,KAAK,mDAAmD;AAAA,IAC9D;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,KAAK,mDAAmD;AAAA,MAC1D,OAAO,OAAO,GAAG;AAAA,IACnB,CAAC;AAAA,EACH;AACF;;;AC1IA,SAAS,YAAAC,iBAAgB;AACzB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,iBAAAC,sBAAqB;AAsC9B,IAAI;AAGG,SAAS,gBAAwB;AACtC,MAAI,oBAAqB,QAAO;AAChC,MAAI;AACF,UAAM,OAAY,cAAQC,eAAc,YAAY,GAAG,CAAC;AACxD,UAAM,MAAS,iBAAkB,WAAK,MAAM,MAAM,cAAc,GAAG,MAAM;AACzE,UAAM,UAAW,KAAK,MAAM,GAAG,EAA4B;AAC3D,0BAAsB,OAAO,YAAY,WAAW,UAAU;AAAA,EAChE,QAAQ;AACN,0BAAsB;AAAA,EACxB;AACA,SAAO;AACT;AAWO,SAAS,oBAAoB,OAAoC;AACtE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAO,MAA4B;AACzC,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,UAAW,IAA8B;AAC/C,QAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,EAAG,QAAO;AAAA,EAChE;AACA,QAAM,SAAU,MAAgC;AAChD,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,EAAG,QAAO;AAC5D,SAAO;AACT;AAEA,IAAMC,iBAAgBC,WAAUC,SAAQ;AAExC,IAAI;AAWG,SAAS,sBACd,WAAmB,QAAQ,UACE;AAC7B,MAAI,qBAAsB,QAAO;AACjC,0BAAwB,YAAyC;AAC/D,QAAI,CAAM,eAAS,QAAQ,EAAE,YAAY,EAAE,SAAS,UAAU,GAAG;AAC/D,UAAI,MAAM,6DAA6D,EAAE,SAAS,CAAC;AACnF,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAMF,eAAc,UAAU,CAAC,WAAW,GAAG,EAAE,SAAS,IAAK,CAAC;AACjF,YAAM,QAAQ,mBAAmB,KAAK,OAAO,KAAK,CAAC;AACnD,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC5B,SAAS,KAAK;AACZ,UAAI,MAAM,iCAAiC;AAAA,QACzC;AAAA,QACA,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AACH,SAAO;AACT;AAcO,SAAS,iBACd,YACA,OAAe,QAAQ,IAAI,GAC3B,WAA+B,4BAA4B,GAClB;AACzC,MAAI,OAAO,eAAe,YAAY,WAAW,SAAS,GAAG;AAC3D,WAAO,EAAE,UAAU,YAAY,QAAQ,aAAa;AAAA,EACtD;AACA,MAAI,kBAAkB,IAAI,EAAG,QAAO,EAAE,UAAU,MAAM,QAAQ,UAAU;AACxE,MAAI,kBAAkB,QAAQ,EAAG,QAAO,EAAE,UAAU,UAAU,QAAQ,WAAW;AACjF,SAAO,EAAE,UAAU,MAAM,QAAQ,aAAa;AAChD;AAEA,SAAS,WAAW,OAA0B;AAC5C,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AAC3E;AAEA,SAAS,YACP,WACA,KACS;AACT,aAAW,SAAS,OAAO,OAAO,SAAS,GAAG;AAC5C,UAAM,QAAQ,OAAO,UAAU,GAAG;AAClC,QAAI,UAAU,OAAW,QAAO;AAAA,EAClC;AACA,SAAO;AACT;AAEO,SAAS,0BACd,WACA,iBACmE;AACnE,QAAM,WAAqB,CAAC;AAC5B,aAAW,SAAS,OAAO,OAAO,SAAS,GAAG;AAC5C,UAAM,UAAU,OAAO,SAAS;AAChC,QAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,EAAG,UAAS,KAAK,OAAO;AAAA,EAC9E;AAEA,QAAM,MAAM,iBAAiB,YAAY,WAAW,KAAK,CAAC;AAE1D,MAAI,aAAuB,CAAC;AAC5B,MAAI;AAIF,iBAAa,iBAAiB,IAAI,QAAQ,EAAE;AAAA,EAC9C,SAAS,KAAK;AACZ,QAAI,MAAM,iDAAiD;AAAA,MACzD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ,cAAc;AAAA,IACtB,UAAU,mBAAmB,QAAQ,IAAI,oBAAoB;AAAA,IAC7D,eAAe,OAAO,YAAY,WAAW,SAAS,KAAK,QAAQ;AAAA,IACnE;AAAA,IACA,WAAW,OAAO,KAAK,SAAS;AAAA,IAChC;AAAA,IACA,YAAY,WAAW,YAAY,WAAW,YAAY,CAAC;AAAA,IAC3D;AAAA,IACA,sBACE,YAAY,WAAW,aAAa,MAAM,QAC1C,QAAQ,IAAI,sCAAsC;AAAA,IACpD,kBAAkB,YAAY,WAAW,kBAAkB,MAAM;AAAA,IACjE,sBAAsB;AAAA,MACpB,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAAA,IAC/C;AAAA,EACF;AACF;AAEA,IAAI,SAAS;AAON,SAAS,sBACd,WACA,iBACM;AACN,MAAI,OAAQ;AACZ,WAAS;AACT,QAAM,YAAY;AAChB,QAAI;AAGF,YAAM,UACJ,mBAAmB,QAAQ,IAAI,oBAAqB,MAAM,sBAAsB;AAClF,YAAM,EAAE,eAAe,GAAG,KAAK,IAAI,0BAA0B,WAAW,OAAO;AAC/E,YAAM,MAAM,MAAM,iBAAiB,aAAa;AAChD,YAAM,cAAkC;AAAA,QACtC,GAAG;AAAA,QACH,WAAW,EAAE,MAAM,eAAe,SAAS,KAAK,OAAO,eAAe;AAAA,MACxE;AACA,UAAI,OAAO,4BAA4B,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3D,SAAS,KAAK;AACZ,UAAI,MAAM,8BAA8B;AAAA,QACtC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF,GAAG;AACL;;;ACpMA,SAAS,sBAAsB,OAAoC;AACjE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAM;AACZ,MAAI,kBAAkB,IAAI,SAAS,EAAG,QAAO,IAAI;AACjD,MAAI,kBAAkB,IAAI,QAAQ,EAAG,QAAO,IAAI;AAChD,SAAO;AACT;AAEA,IAAI,wBAAwB;AAQ5B,IAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,sBAAsB,QAAmC;AAChE,MAAI,sBAAuB;AAC3B,MAAI,CAAC,QAAQ,IAAI,qBAAqB,CAAC,QAAQ,IAAI,qBAAsB;AACzE,0BAAwB;AACxB,MAAI,QAAQ;AACV,QAAI;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,iBACd,WAAuC,CAAC,GACpB;AACpB,MAAI,SAAS,SAAS;AACpB,oBAAgB;AAAA,MACd,MAAM,SAAS,QAAQ,QAAQ;AAAA,MAC/B,KAAK,SAAS,QAAQ,OAAO;AAAA,MAC7B,MAAM,SAAS,QAAQ,QAAQ;AAAA,MAC/B,OAAO,SAAS,QAAQ,SAAS;AAAA,IACnC,CAAC;AAAA,EACH;AACA,wBAAsB,SAAS,qBAAqB;AACpD,QAAM,UACJ,SAAS,WAAW,QAAQ,IAAI,mBAAmB;AACrD,QAAM,eAAe,SAAS,cAAc,SAAS,QAAQ;AAC7D,QAAM,aAAa,SAAS,cAAc,CAAC,GAAG,wBAAwB;AAEtE,QAAM,cAAc,CAAC,YAAqC;AACxD,WAAO,IAAI,wBAAwB,SAAS;AAAA,MAC1C,UAAU;AAAA,MACV;AAAA,MACA,KAAK,SAAS;AAAA,MACd,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,iBAAiB,SAAS,mBAAmB;AAAA,MAC7C,gBAAgB,SAAS;AAAA,MACzB,WAAW,SAAS;AAAA,MACpB,iBAAiB,SAAS;AAAA,MAC1B,mBAAmB,SAAS,qBAAqB;AAAA,MACjD,wBAAwB,SAAS,0BAA0B;AAAA,MAC3D,6BAA6B,SAAS;AAAA,MACtC,2BAA2B,SAAS;AAAA,MACpC;AAAA,MACA,oBAAoB,SAAS;AAAA,MAC7B,kBAAkB,SAAS,oBAAoB;AAAA,MAC/C,WAAW,SAAS;AAAA,MACpB,cAAc,SAAS,gBAAgB;AAAA,MACvC,uBAAuB,SAAS,yBAAyB;AAAA,MACzD,uBAAuB,SAAS,yBAAyB;AAAA,MACzD,6BACE,SAAS,+BAA+B;AAAA,MAC1C,iBAAiB,SAAS;AAAA,MAC1B,uBAAuB,SAAS;AAAA,MAChC,aAAa,SAAS;AAAA,MACtB,mBAAmB,SAAS;AAAA,MAC5B,uBAAuB,SAAS;AAAA,MAChC,yBAAyB,SAAS;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,SAAU,SAAiB;AAC1C,WAAO,YAAY,OAAO;AAAA,EAC5B;AAEA,WAAS,uBAAuB;AAChC,WAAS,gBAAgB;AAEzB,SAAO;AACT;AAMA,IAAMG,eAAc;AACpB,IAAM,cAAc;AAEpB,SAAS,mBAA2B;AAClC,SAAO,YAAY,IAAI,WAAW,OAAO,IAAI,YAAY,MAAM;AACjE;AAEA,SAAS,qBACP,UAAmC,CAAC,GACX;AACzB,QAAM,SAAS,EAAE,GAAG,QAAQ;AAC5B,SAAO,OAAO;AACd,SAAO;AACT;AAEA,SAAS,yBACP,gBACA,aAAaA,cACb,aACA;AACA,QAAM,SAAS,OAAO;AAAA,IACpB,OAAO,QAAQ,aAAa,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;AACjD,YAAM,UAAU,cAAc,GAAG,EAAE,IAAI,WAAW,KAAK;AACvD,YAAM,WAAW,eAAe,EAAE,KAAK,eAAe,OAAO;AAC7D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,UACE,GAAG;AAAA,UACH,IAAI;AAAA,UACJ;AAAA,UACA,KAAK;AAAA,YACH,GAAG,MAAM;AAAA,YACT,IAAI;AAAA,YACJ,KAAK,UAAU,KAAK,OAAO,MAAM,IAAI;AAAA,YACrC,KAAK,UAAU,KAAK,OAAO,MAAM,IAAI;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACxD,QAAI,EAAE,MAAM,SAAS;AACnB,aAAO,EAAE,IAAI;AAAA,QACX,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,wBACd,gBACA,YACA,aACyC;AACzC,QAAM,SAAkD,CAAC;AAEzD,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACvD,UAAM,UAAU,cAAc,GAAG,EAAE,IAAI,WAAW,KAAK;AACvD,UAAM,WAAW,eAAe,EAAE,KAAK,eAAe,OAAO;AAC7D,UAAM,mBACJ,YAAY,OAAQ,SAAoC,aAAa,WAC/D,SAAoE,YAAY,CAAC,IACnF,CAAC;AACP,UAAM,OAAsB;AAAA,MAC1B,GAAG;AAAA,MACH,IAAI;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,QACH,GAAG,MAAM;AAAA,QACT,IAAI;AAAA,QACJ,KAAK,UAAU,KAAK,OAAO,MAAM,IAAI;AAAA,QACrC,KAAK,UAAU,KAAK,OAAO,MAAM,IAAI;AAAA,MACvC;AAAA,MACA,UAAU;AAAA,QACR,GAAI,MAAM,YAAY,CAAC;AAAA,QACvB,GAAG;AAAA,MACL;AAAA,IACF;AACA,WAAO,OAAO,IAAI,cAAc,IAAI;AAAA,EACtC;AAEA,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACxD,QAAI,EAAE,MAAM,SAAS;AACnB,aAAO,EAAE,IAAI,cAAc,EAAE,GAAG,OAAO,WAAW,CAAkB;AAAA,IACtE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,eACb,UAMA,aAAaA,cACb,iBAA0C,CAAC,GAC3C,aACA;AACA,QAAM,gBAAyC;AAAA,IAC7C,SAAS;AAAA,IACT,YAAY,CAAC,GAAG,wBAAwB;AAAA,IACxC,GAAG;AAAA,IACH,GAAG,qBAAqB,UAAU,OAAO;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,UAAU,OAAO,cAAc,WAAW,QAAQ;AACxD,QAAM,UACJ,OAAO,cAAc,YAAY,WAAW,cAAc,UAAU;AACtE,QAAM,UAAU,UACZ,MAAM,qBAAqB,SAAS,OAAO,IAC3C,EAAE,QAAQ;AAEd,SAAO;AAAA,IACL,MAAM,eAAe,UAAU;AAAA,IAC/B,KAAK,UAAU,OAAO,iBAAiB;AAAA,IACvC,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA;AAAA;AAAA;AAAA,EAIF;AACF;AAOO,SAAS,oBACd,WAC0C;AAC1C,QAAM,MAAgD,CAAC;AACvD,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,aAAa,CAAC,CAAC,GAAG;AACzD,QAAI,OAAOA,gBAAe,GAAG,WAAW,GAAGA,YAAW,GAAG,EAAG,KAAI,EAAE,IAAI;AAAA,EACxE;AACA,SAAO;AACT;AAEA,eAAe,uBAAuB,QAUjB;AACnB,QAAM,OAAO,OAAO,WAAWA,YAAW;AAC1C,QAAM,WAAW,gBAAgB,MAAM,SAAS,QAAQ;AAExD,MAAI,CAAC,SAAU,QAAO;AAEtB,SAAO,aAAa,CAAC;AAErB,QAAM,cAAc,qBAAqB,MAAM,OAAO;AACtD,MAAI,gBAAgB;AAEpB,aAAW,WAAW,UAAU;AAC9B,UAAM,aAAa,kBAAkB,OAAO;AAC5C,QAAI;AACF,YAAM,WAAW,OAAO,SAAS,UAAU;AAC3C,YAAM,cAAc,mBAAmB,OAAO;AAE9C,aAAO,SAAS,UAAU,IAAI;AAAA,QAC5B,GAAG;AAAA,QACH,GAAI,MAAM;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,YACE,GAAG;AAAA,YACH;AAAA,UACF;AAAA,UACA,mBAAmB,OAAO;AAAA,QAC5B;AAAA,QACA,QAAQ;AAAA,UACL,UAAU,UAAU,MAAM,UAAU,CAAC;AAAA,UACtC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,MAAM,qCAAqC;AAAA,QAC7C;AAAA,QACA;AAAA,QACA,OAAO,OAAO,GAAG;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,gBAAgB,GAAG;AACrB,WAAO,OAAO,SAASA,YAAW;AAAA,EACpC;AAEA,SAAO,gBAAgB;AACzB;AAEA,IAAM,SAAyB,OAAO,UAAU;AAC9C,8BAA4B;AAE5B,QAAM,kBAAkB,oBAAoB,KAAK;AAMjD,MAAI,SAAS,OAAO,UAAU,YAAY,YAAY,OAAO;AAC3D,sBAAmB,MAA+B,MAAM;AAAA,EAC1D;AAOA,8BAA4B,sBAAsB,KAAK,CAAC;AAExD,SAAO;AAAA,IACL,QAAQ,OAAO,WAAW;AACxB,aAAO,aAAa,CAAC;AAErB,YAAM,WAAW,MAAM,uBAAuB,MAAM;AACpD,UAAI,UAAU;AACZ;AAAA,UACE,oBAAoB,OAAO,QAAQ;AAAA,UACnC;AAAA,QACF;AACA;AAAA,MACF;AAEA,YAAM,WAAW,OAAO,SAASA,YAAW;AAC5C,aAAO,SAASA,YAAW,IAAI;AAAA,QAC7B,GAAG;AAAA,QACH,GAAI,MAAM,eAAe,QAAQ;AAAA,QACjC,QAAQ;AAAA,UACL,UAAU,UAAU,CAAC;AAAA,UACtBA;AAAA,QACF;AAAA,MACF;AACA;AAAA,QACE,oBAAoB,OAAO,QAAQ;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AAAA,MACR,IAAIA;AAAA,MACJ,QAAQ,OAAO,aAAa,yBAAyB,SAAS,MAAM;AAAA,IACtE;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,eAAe,OAAOC,QAAO,WAAW;AACtC,YAAM,aAAaA,OAAM,OAAO,cAAcA,OAAM,UAAU,MAAM;AAIpE,UAAI,MAAM,0BAA0B;AAAA,QAClC,OAAOA,OAAM;AAAA,QACb;AAAA,QACA,WAAWA,OAAM;AAAA,MACnB,CAAC;AACD,UAAI,OAAO,eAAe,SAAU;AACpC,UAAI,eAAeD,gBAAe,CAAC,WAAW,WAAW,GAAGA,YAAW,GAAG,EAAG;AAM7E,UAAI,OAAOC,OAAM,cAAc,YAAYA,OAAM,UAAU,SAAS,GAAG;AACrE,eAAO,YAAY,CAAC;AACnB,QAAC,OAAO,QAAoC,oBAAoBA,OAAM;AAAA,MACzE;AAEA,UAAI,CAACA,OAAM,MAAO;AAMlB,aAAO,YAAY,CAAC;AACnB,MAAC,OAAO,QAAoC,gBAAgBA,OAAM;AACnE,UAAI,MAAM,sCAAsC;AAAA,QAC9C,OAAOA,OAAM;AAAA,QACb,WAAWA,OAAM;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;AAAA,EACb,IAAI;AAAA,EACJ;AACF;","names":["sessionKey","fs","path","os","resolve","sessionKey","EventEmitter","unlink","os","fs","path","EventEmitter","unlink","fs","path","crypto","EventEmitter","EventEmitter","server","resolve","EventEmitter","EventEmitter","sessionKey","readFileSync","writeFileSync","unlink","homedir","tmpdir","randomUUID","dirname","join","content","path","spawn","createInterface","resolve","stream","completeResult","planId","path","path","existsSync","readFileSync","rmSync","writeFileSync","homedir","join","resolve","join","homedir","existsSync","readFileSync","resolve","rmSync","writeFileSync","execFile","fs","path","promisify","fileURLToPath","fileURLToPath","execFileAsync","promisify","execFile","PROVIDER_ID","input"]}
|
|
1
|
+
{"version":3,"sources":["../src/claude-code-language-model.ts","../src/logger.ts","../src/todo-ledger.ts","../src/tool-mapping.ts","../src/message-builder.ts","../src/plan-mode-question.ts","../src/mcp-bridge.ts","../src/tmp.ts","../src/runtime-status.ts","../src/session-manager.ts","../src/cli-version.ts","../src/claude-session-wrapper.ts","../src/claude-session-bun.ts","../src/compression-store.ts","../src/proxy-mcp.ts","../src/proxy-broker.ts","../src/models.ts","../src/accounts.ts","../src/cleanup-stale.ts","../src/startup-diagnostics.ts","../src/index.ts"],"sourcesContent":["import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n SharedV3Warning,\n} from \"@ai-sdk/provider\"\nimport { generateId } from \"@ai-sdk/provider-utils\"\nimport type {\n ClaudeCodeConfig,\n ControlRequestBehavior,\n ClaudeStreamMessage,\n ReasoningEffort,\n} from \"./types.js\"\nimport { mapTool, isWebSearchTool, isWebSearchHandledByCli } from \"./tool-mapping.js\"\nimport { applyTaskCreateToolResult } from \"./todo-ledger.js\"\nimport { getClaudeUserMessage } from \"./message-builder.js\"\nimport {\n QUESTION_TOOL_NAME,\n consumeExitPlanModeQuestionResult,\n createExitPlanModeQuestionCall,\n isPlanModeQuestionActive,\n} from \"./plan-mode-question.js\"\nimport { bridgeOpencodeMcp, type RuntimeMcpStatus } from \"./mcp-bridge.js\"\nimport {\n getRuntimeMcpStatus,\n fetchOpencodeToolList,\n resolveSpawnCwd,\n} from \"./runtime-status.js\"\nimport {\n getActiveProcess,\n setActiveProcess,\n spawnClaudeProcess,\n buildCliArgs,\n setClaudeSessionId,\n getClaudeSessionId,\n deleteClaudeSessionId,\n deleteActiveProcess,\n deleteActiveProcessAndWait,\n respawnActiveProcess,\n claudeSpawnEnv,\n isClaudeThinkingDisabled,\n sessionKey,\n} from \"./session-manager.js\"\nimport { spawnInteractiveProcess } from \"./claude-session-wrapper.js\"\nimport {\n clearCompression,\n consumeCompressionRestart,\n getCompressionSummary,\n storeCompressionSummary,\n} from \"./compression-store.js\"\nimport { log } from \"./logger.js\"\nimport { detectCliVersion } from \"./cli-version.js\"\nimport {\n createProxyMcpServer,\n disallowedToolFlags,\n DEFAULT_PROXY_TOOLS,\n overlayTaskProxyDescription,\n overlayQuestionProxyDescription,\n filterQuestionProxyByOpencodeSupport,\n PROXY_TOOL_PREFIX,\n type ProxyMcpServer,\n type ProxyToolCall,\n type ProxyToolDef,\n type ProxyToolInterceptor,\n type ProxyToolResult,\n} from \"./proxy-mcp.js\"\nimport {\n getPendingProxyCalls,\n onPendingProxyCall,\n queuePendingProxyCall,\n rejectAllPendingProxyCallsForSession,\n rejectPendingProxyCallById,\n resolvePendingProxyCallById,\n type PendingProxyCall,\n} from \"./proxy-broker.js\"\nimport { readFileSync, writeFileSync } from \"node:fs\"\nimport { unlink } from \"node:fs/promises\"\nimport { homedir, tmpdir } from \"node:os\"\nimport { randomUUID } from \"node:crypto\"\nimport { dirname, join } from \"node:path\"\n\n/**\n * Default model used for opencode `/compact`. Haiku 4.5 is fast\n * (~150 tok/s), has a hard 8k output cap that bounds latency, and is a\n * strong structured summarizer. Override per-project via the\n * `compactionModel` provider setting in opencode.json / opencode.jsonc,\n * or per-run via the `CLAUDE_CODE_COMPACTION_MODEL` env var (env wins).\n */\nexport const DEFAULT_COMPACTION_MODEL = \"claude-haiku-4-5\"\n\n/**\n * Pick the model used to handle /compact. Precedence:\n * 1. `CLAUDE_CODE_COMPACTION_MODEL` env var (per-process override)\n * 2. `configured` argument (the `compactionModel` provider setting)\n * 3. `DEFAULT_COMPACTION_MODEL`\n *\n * Exported as a free function so it can be unit-tested without\n * instantiating the language model class.\n */\nexport function resolveCompactionModel(configured?: string): string {\n const env = process.env.CLAUDE_CODE_COMPACTION_MODEL?.trim()\n if (env) return env\n const trimmed = configured?.trim()\n if (trimmed) return trimmed\n return DEFAULT_COMPACTION_MODEL\n}\n\n/**\n * Resolve the session affinity token for a given LLM call. The affinity\n * token is part of the session key in session-manager so two different\n * opencode sessions sharing the same cwd+model still get separate Claude\n * CLI processes.\n *\n * Priority:\n * 1. `x-session-affinity` request header (primary — opencode sets it for\n * third-party providers in packages/opencode/src/session/llm.ts).\n * 2. `opencodeSessionID` inside `providerOptions` (injected by the\n * `chat.params` hook in index.ts). Covers cases where the header is\n * absent: provider switch mid-session, title synthesis paths, older\n * opencode versions. opencode wraps `output.options` under the\n * providerID before passing it to the language model, so we look up\n * both the configured provider key and the canonical `\"claude-code\"`.\n * 3. `\"default\"` — safe fallback when neither source is available.\n *\n * Exported as a free function so it can be unit-tested without\n * instantiating the language model class.\n */\nexport function resolveSessionAffinity(\n headers: Record<string, string | undefined> | undefined,\n providerOptions: Record<string, unknown> | undefined,\n providerKey: string,\n): string {\n if (headers) {\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === \"x-session-affinity\") {\n const v = headers[key]\n if (typeof v === \"string\" && v.length > 0) return v\n }\n }\n }\n if (providerOptions) {\n const bag =\n (providerOptions as any)[providerKey] ??\n (providerOptions as any)[\"claude-code\"]\n const sid = bag?.opencodeSessionID\n if (typeof sid === \"string\" && sid.length > 0) return sid\n }\n return \"default\"\n}\n\n/**\n * Stream delta types we handle explicitly. `signature_delta` is listed as\n * known-and-silent: it carries encrypted thinking-block signatures that\n * are opaque to clients (the server uses them to reconstitute thinking\n * across turns), so there's nothing for us to do but ignore it.\n */\nconst KNOWN_DELTA_TYPES = new Set([\n \"thinking_delta\",\n \"text_delta\",\n \"input_json_delta\",\n \"signature_delta\",\n])\n\n/**\n * True if the prompt has any user-side content after the last assistant\n * message (text, tool_result, or any user role entry). False when the\n * prompt ends with an assistant message and there is nothing for Claude\n * to respond to — opencode sometimes iterates the agent loop one more\n * time after a turn naturally completed; without short-circuiting we'd\n * spawn Claude CLI on an empty turn and the model would reply with a\n * stub like \"Did you mean to send a message?\".\n */\nexport function hasNewUserContent(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n): boolean {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role === \"assistant\") return false\n // Tool-result turns from opencode's outer loop arrive in `tool`-role\n // messages (AI SDK V3 shape). Treat any tool-result part as new\n // content so the short-circuit doesn't drop turns where opencode is\n // delivering the result for a still-pending proxy MCP call — letting\n // that fire `stop` is what was forcing the user to press \"continue\".\n if (msg.role === \"tool\") {\n const content: any = msg.content\n if (Array.isArray(content)) {\n for (const part of content as any[]) {\n if (part?.type === \"tool-result\") return true\n }\n }\n continue\n }\n if (msg.role !== \"user\") continue\n const content: any = msg.content\n if (typeof content === \"string\") {\n if (content.trim()) return true\n continue\n }\n if (Array.isArray(content)) {\n for (const part of content as any[]) {\n if (part.type === \"text\" && part.text && part.text.trim()) return true\n if (part.type === \"tool-result\") return true\n // Image/file-only user turns count as new input — without this the\n // short-circuit drops them as if the turn were empty.\n if (part.type === \"image\" || part.type === \"file\") return true\n }\n }\n }\n return false\n}\n\nconst AUTO_CONTINUE_MAX_ATTEMPTS = 8\nconst AUTO_CONTINUE_MAX_ELAPSED_MS = 10 * 60 * 1000\nconst AUTO_CONTINUE_NO_PROGRESS_LIMIT = 2\nconst PROXY_RESULT_BOUNDARY_GRACE_MS = 250\n\nconst AUTO_CONTINUE_PROMPT =\n \"Continue the task from where you stopped. Do not summarize; keep working until the requested task is complete, you need clarification, or you hit a real blocker.\"\n\n/** One per-turn snapshot of opencode's live tool registry. */\ninterface LiveToolInfo {\n /** False when nothing answered (no SDK client, fetch failed). */\n resolved: boolean\n taskDescription: string | undefined\n questionDescription: string | undefined\n hasQuestion: boolean\n}\n\ninterface AutoContinueState {\n enabled: boolean | \"smart\" | undefined\n attempts: number\n startedAt: number\n noProgressCount: number\n lastSignature?: string\n aborted?: boolean\n /**\n * Latched true once AskUserQuestion is rendered this turn. Auto-continue\n * must never fire afterwards: the model has handed control to the operator\n * and is waiting for a real reply. Without this, a short trailing text after\n * the question (one that doesn't trip looksLikeQuestion) would let the turn\n * look \"incomplete\", and the auto-continue nudge would make the model\n * proceed on its own — which the operator sees as the question being\n * answered/cancelled without them ever interacting.\n */\n sawAskUserQuestion?: boolean\n}\n\ninterface AutoContinueSnapshot {\n text: string\n /**\n * Text of the most recent assistant text block only. Used for final-answer\n * detection so mid-task narration like \"Implementing now. Updated the\n * search index.\" in an earlier block doesn't trip the keyword regex.\n */\n lastVisibleText: string\n hadReasoning: boolean\n hadToolActivity: boolean\n hadProxyActivity: boolean\n isError?: boolean\n /**\n * Protocol-level stop signal from the Claude API (forwarded by Claude\n * CLI). When present and non-empty, we trust it as authoritative — the\n * model itself signaled why the turn ended (`end_turn`, `max_tokens`,\n * `stop_sequence`, `refusal`, `pause_turn`, `tool_use`, etc.) — and stop\n * without running the keyword regex. The heuristic only runs as a\n * fallback when `stop_reason` is missing (older CLI versions, abrupt\n * termination).\n */\n stopReason?: string | null\n now?: number\n}\n\ninterface AutoContinueDecision {\n continue: boolean\n reason: string\n}\n\nfunction normalizeVisibleText(text: string): string {\n return text.replace(/\\s+/g, \" \").trim()\n}\n\n/** Tool names that mean \"ask the human a question\" (CLI casing variants). */\nexport function isAskUserQuestionTool(name: string | undefined): boolean {\n if (!name) return false\n const n = name.toLowerCase()\n return n === \"askuserquestion\" || n === \"ask_user_question\"\n}\n\n/**\n * Deny message returned to the model when it invokes AskUserQuestion.\n *\n * AskUserQuestion is denied (see controlRequestBehaviorForTool) so the\n * headless CLI cannot self-answer against an empty TTY. The question is\n * already rendered to the operator by formatAskUserQuestion, so this text\n * tells the model to stop and wait — unconditionally. Earlier versions\n * offered an \"if this is non-interactive, proceed with a reasonable guess\"\n * escape hatch, but the model could not reliably tell interactive opencode\n * from a headless run and routinely took it, so questions appeared to be\n * skipped (issue #8). Stopping is the correct default for opencode; a\n * headless run simply ends the turn with the question as its final output.\n */\nconst ASK_USER_QUESTION_DENY_MESSAGE =\n \"Your question and its options have already been presented to the\" +\n \" operator verbatim. This is NOT a cancellation or a refusal — the\" +\n \" operator simply has not answered yet. Stop now: end your turn without\" +\n \" calling any more tools and without answering the question yourself. Do\" +\n \" not say the question was cancelled, skipped, or declined, and do not\" +\n \" guess, assume, or proceed on their behalf. Wait for the operator's\" +\n \" reply, which arrives as the next user message.\"\n\n/** Build the deny message for an auto-denied control request. */\nexport function denyMessageForTool(\n toolName: string | undefined,\n configuredDenyMessage?: string,\n): string {\n if (isAskUserQuestionTool(toolName)) return ASK_USER_QUESTION_DENY_MESSAGE\n return (\n configuredDenyMessage ??\n `Denied by opencode-claude-code policy for tool ${toolName}`\n )\n}\n\n/**\n * Render Claude Code's `AskUserQuestion` tool input as visible markdown.\n *\n * This is the fallback path used when the `Question` proxy is off or the\n * opencode build lacks the `question` registry entry. When the proxy is\n * enabled, `AskUserQuestion` is disabled via `--disallowedTools` and the\n * model calls `mcp__opencode_proxy__question` instead (opencode's native\n * `question` tool renders the TUI form). Here, the question + every\n * option is rendered as readable assistant text and the user answers in\n * the next turn — same approach as the `ExitPlanMode` handling. The\n * previous behavior collapsed the whole payload to a single faint\n * `_Asking: <q>_` line, dropping all options and any question past the\n * first.\n */\nfunction formatAskUserQuestion(input: Record<string, unknown>): string {\n const anyInput = input as any\n const questions: any[] = Array.isArray(anyInput?.questions)\n ? anyInput.questions\n : []\n\n if (questions.length === 0) {\n const single = anyInput?.question ?? anyInput?.text\n const q =\n typeof single === \"string\" && single.trim() ? single.trim() : \"Question?\"\n return `\\n\\n**${q}**\\n\\n_Reply with your answer to continue._\\n\\n`\n }\n\n const out: string[] = [\"\\n\\n\"]\n const multiQ = questions.length > 1\n questions.forEach((q, i) => {\n const text =\n (typeof q?.question === \"string\" && q.question.trim()) ||\n (typeof q?.text === \"string\" && q.text.trim()) ||\n \"Question?\"\n const header =\n typeof q?.header === \"string\" && q.header.trim() ? q.header.trim() : \"\"\n out.push(`**${multiQ ? `${i + 1}. ` : \"\"}${text}**`)\n if (header) out.push(` _(${header})_`)\n out.push(\"\\n\\n\")\n\n const options: any[] = Array.isArray(q?.options) ? q.options : []\n options.forEach((opt, j) => {\n const label =\n (typeof opt?.label === \"string\" && opt.label.trim()) ||\n (typeof opt === \"string\" && opt.trim()) ||\n `Option ${j + 1}`\n const desc =\n typeof opt?.description === \"string\" && opt.description.trim()\n ? ` — ${opt.description.trim()}`\n : \"\"\n out.push(`${j + 1}. **${label}**${desc}\\n`)\n })\n\n out.push(\n q?.multiSelect === true\n ? \"\\n_Select one or more — reply with the numbers or labels._\\n\\n\"\n : \"\\n_Reply with your choice (the number or label)._\\n\\n\",\n )\n })\n return out.join(\"\")\n}\n\nfunction looksLikeQuestion(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (!normalized) return false\n // v0.4.10 tweak 5a: '?' anywhere in the last block, not just trailing.\n // Catches long answers that pose a question mid-text then list options\n // and end with a period. FP risk on inline code (`result?.value`) is\n // accepted — cost is one extra \"continue\" press, in the safe direction.\n if (normalized.includes(\"?\")) return true\n // v0.4.11 additions: ready when you are / standing by / i'll stand by /\n // let me know when. These are awaiting-input idioms with no '?'. The\n // \"standing by\" addition has historical significance — it's the exact\n // stub phrase Claude CLI emits on empty turns that commit 49345e3 was\n // designed to suppress at the message-builder layer. This adds a second\n // line of defense at the model-output layer for cases where the model\n // organically produces the same idiom.\n //\n // v0.4.12 additions: over to you / your turn / all yours / let me know\n // how / i'm here. Defensive coverage of soft-proceed idioms in the\n // model's vocabulary. \"i'm here\" has the highest FP risk (\"I'm here to\n // help with X\" is a conversational opener) but cost of FP is one extra\n // continue press — safe direction.\n return /\\b(please confirm|can you confirm|should i|would you like|do you want|which option|choose|pick one|need your|need you to|what would you like|let me know if|let me know whether|let me know what|let me know when|let me know how|if you'?d like|if you want to|tell me if|tell me which|tell me whether|say (?:go|yes|no)|push back|sign off|sounds? (?:good|right)|your call|your move|your turn|over to you|all yours|up to you|ready to (?:ship|go|proceed|merge)|ready (?:when|whenever|once|if) you|standing by|i'?ll stand ?by|i'?m here|happy to (?:ship|go|proceed|merge))\\b/.test(normalized)\n}\n\nfunction looksLikeBlocker(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (!normalized) return false\n // v0.4.10 tweak 3: 'needs your' / 'needs you to' / 'action required'\n // are intent-equivalent to 'requires your' but use the verb-with-s form.\n return /\\b(blocked|blocker|cannot proceed|can't proceed|unable to proceed|need clarification|need more information|permission denied|failed and needs|requires your|needs your|needs you to|action required|manual step|required from you)\\b/.test(normalized)\n}\n\nfunction looksLikeFinalAnswer(text: string): boolean {\n const normalized = normalizeVisibleText(text).toLowerCase()\n if (looksLikeQuestion(normalized) || looksLikeBlocker(normalized)) return false\n // v0.4.15: strong-completion phrases bypass the 30-char length floor.\n // These are unambiguous end-of-turn signals at any text length — even\n // a short standalone \"We're done.\" should stop.\n if (/\\b(we'?re done|we are done|all done|all set)\\b/.test(normalized)) {\n return true\n }\n // v0.4.10 tweak 4: floor lowered 40 → 30 chars. Catches short clean\n // completions like \"Task is now completely done. Pushed.\" (36 chars)\n // while keeping a buffer against ambiguous short narration.\n if (normalized.length < 30) return false\n // v0.4.15: keyword list extended with deploy/ship verbs the model\n // routinely uses at turn end (shipped, deployed, merged, tagged, live,\n // pinned). FP risk highest on \"live\" — \"live data\" mid-turn could match\n // — but cost of FP is one extra continue press, safe direction.\n return /\\b(done|completed|fixed|implemented|verified|published|released|sent|delivered|updated|shipped|deployed|merged|tagged|live|pinned)\\b/.test(normalized) ||\n // v0.4.15: also accept present-tense \"tests pass\" / \"checks pass\".\n // Real fire 03:31 ended in \"78/78 tests pass\" — past-tense-only regex\n // missed it.\n /\\b(checks?|tests?) (?:pass|passes|passed)\\b/.test(normalized) ||\n /\\b(summary|what changed|verification)\\b/.test(normalized)\n}\n\nfunction continuationSignature(snapshot: AutoContinueSnapshot): string {\n const text = normalizeVisibleText(snapshot.text).slice(-500)\n return JSON.stringify({\n text,\n reasoning: snapshot.hadReasoning,\n tools: snapshot.hadToolActivity,\n proxy: snapshot.hadProxyActivity,\n })\n}\n\nexport function shouldAutoContinueIncompleteTurn(\n state: AutoContinueState,\n snapshot: AutoContinueSnapshot,\n): AutoContinueDecision {\n if (state.enabled === false) return { continue: false, reason: \"disabled\" }\n if (snapshot.isError) return { continue: false, reason: \"error\" }\n if (state.aborted) return { continue: false, reason: \"aborted\" }\n // Once the model asked the operator a question this turn, never nudge it to\n // continue — it is waiting for a reply, not stalled. Latched so it holds\n // even when the trailing text after the question doesn't read as a question.\n if (state.sawAskUserQuestion) return { continue: false, reason: \"question\" }\n // v0.4.17: trust ANY protocol-level stop_reason as authoritative. If\n // Claude CLI emitted a stop_reason value at all, the model has signaled\n // a stop — honor it without consulting the keyword heuristic. The\n // heuristic only runs as a fallback when stop_reason is missing (older\n // CLI versions / edge cases). Maps snake_case → kebab-case for reason\n // label consistency with other reasons.\n if (snapshot.stopReason) {\n return {\n continue: false,\n reason: snapshot.stopReason.replace(/_/g, \"-\"),\n }\n }\n if (state.attempts >= AUTO_CONTINUE_MAX_ATTEMPTS) {\n return { continue: false, reason: \"max-attempts\" }\n }\n const now = snapshot.now ?? Date.now()\n if (now - state.startedAt > AUTO_CONTINUE_MAX_ELAPSED_MS) {\n return { continue: false, reason: \"max-elapsed\" }\n }\n\n const text = normalizeVisibleText(snapshot.text)\n const lastText = normalizeVisibleText(snapshot.lastVisibleText)\n if (looksLikeQuestion(text)) return { continue: false, reason: \"question\" }\n if (looksLikeBlocker(text)) return { continue: false, reason: \"blocker\" }\n // Final-answer detection runs on the most recent text block only. Earlier\n // blocks may contain mid-task narration that would false-positive the\n // keyword regex; the model's actual \"I'm done\" sentence is in the last\n // block before result/end_turn.\n if (looksLikeFinalAnswer(lastText)) {\n return { continue: false, reason: \"final-answer\" }\n }\n\n const hadActivity =\n snapshot.hadReasoning || snapshot.hadToolActivity || snapshot.hadProxyActivity\n if (!hadActivity) return { continue: false, reason: \"no-activity\" }\n\n const signature = continuationSignature(snapshot)\n const noProgress = signature === state.lastSignature\n if (noProgress && state.noProgressCount + 1 >= AUTO_CONTINUE_NO_PROGRESS_LIMIT) {\n return { continue: false, reason: \"no-progress\" }\n }\n\n if (!text) {\n return { continue: true, reason: \"activity-without-visible-answer\" }\n }\n\n return { continue: true, reason: \"non-final-progress\" }\n}\n\nfunction makeAutoContinueMessage(): string {\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: AUTO_CONTINUE_PROMPT }],\n },\n })\n}\n\nfunction readPromptFileIfPresent(path: string): string | undefined {\n try {\n const content = readFileSync(path, \"utf8\").trim()\n return content || undefined\n } catch {\n return undefined\n }\n}\n\nfunction nearestWorkspaceAgentsPrompt(cwd: string): string | undefined {\n let dir = cwd\n while (true) {\n const content = readPromptFileIfPresent(join(dir, \"AGENTS.md\"))\n if (content) return content\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nconst AGENTS_MAINTENANCE_HINT = `## Keeping AGENTS.md up to date\n\nWhen you complete a task, phase, or to-do item that is listed in AGENTS.md, update the file\nimmediately after the work is done — mark it ✅, check it off, or remove it. Do this inside\nthe same turn so the next session does not repeat work that is already finished.`\n\nconst MULTI_STEP_TASK_HINT = `## Continuing through multi-step tasks\n\nopencode requires the user to press \"continue\" after each turn ends. When a\ntask has multiple steps, do them all in one turn — chain tool calls rather\nthan pausing for user confirmation between subtasks. End the turn only\nwhen the task is done, you need clarification on intent, or you hit a real\nblocker. The user can interrupt or abort at any time; turn endings should\nmark meaningful checkpoints, not every completed substep.`\n\n/**\n * Appended to the system prompt whenever the `task` proxy tool is\n * enabled. Live sessions (2026-07-04) showed models resolving opencode's\n * \"call the task tool with subagent: X\" mention hint to Claude Code's\n * native TaskCreate: haiku created a todo and narrated a dispatch that\n * never happened; sonnet probed TaskCreate's schema before recovering.\n * The proxy tool can also be deferred behind ToolSearch, in which case\n * \"the task tool\" is invisible while TaskCreate is not. Name the exact\n * tool, the recovery path, and the failure mode.\n */\nexport const SUBAGENT_DISPATCH_HINT = `## opencode subagents\n\nSubagent dispatch in this environment goes through exactly one tool: \\`mcp__opencode_proxy__task\\`.\n\n- When the user mentions \\`@<agent>\\` or an instruction says \"call the task tool with subagent: <name>\", call \\`mcp__opencode_proxy__task\\` with \\`subagent_type: \"<name>\"\\`.\n- If that tool is not in your visible tool list it is deferred — load it with ToolSearch (\\`select:mcp__opencode_proxy__task\\`), then call it.\n- Claude Code's built-in TaskCreate/TaskUpdate/TaskList manage a local todo list. They cannot dispatch subagents; creating a task there runs nothing. Never report a subagent as dispatched unless \\`mcp__opencode_proxy__task\\` returned its result.\n- Do not verify a subagent's existence by searching config files — the tool's description lists the available agent types, and invalid types fail fast with a clear error.`\n\n/**\n * Appended to the system prompt whenever the `question` proxy tool is\n * enabled. Live testing (2026-07-05, haiku) showed the model's reasoning\n * correctly identified `mcp__opencode_proxy__question` as the tool to use,\n * but then emitted a tool call for bare `question` — stripping the MCP\n * prefix. opencode's AI SDK bridge has no bare `question` tool, so the\n * call rendered as `⚙ invalid`. Same near-miss pattern the task proxy\n * hit (TaskCreate vs mcp__opencode_proxy__task); the fix is the same:\n * name the exact tool in the system prompt so the model doesn't\n * abbreviate.\n */\nexport const QUESTION_PROXY_HINT = `## Asking the operator questions\n\nStructured questions in this environment go through exactly one tool: \\`mcp__opencode_proxy__question\\`.\n\n- When you need to ask the operator a question with options, call \\`mcp__opencode_proxy__question\\` with a \\`questions\\` array (each item has \\`question\\`, \\`header\\`, \\`options\\` of \\`{label, description}\\`, and optional \\`multiple\\`).\n- If that tool is not in your visible tool list it is deferred — load it with ToolSearch (\\`select:mcp__opencode_proxy__question\\`), then call it by its FULL name.\n- Do NOT call bare \\`question\\` — that is not a tool. Always use the full \\`mcp__opencode_proxy__question\\` name when invoking it.\n- Claude Code's built-in \\`AskUserQuestion\\` is disabled in this environment; the proxy is the only way to ask structured questions.`\n\n/**\n * Prepended to every appended system prompt so Claude knows which\n * context-management tools exist in the Claude CLI runtime versus a\n * direct API provider. DCP and similar plugins forward compress/distill/\n * prune instructions via system.transform; those reach us through\n * extractSystemMessages, but the tools themselves are not available in\n * the CLI environment. Without this note Claude wastes thinking cycles\n * searching for tools that don't exist.\n */\nconst CLAUDE_CLI_CONTEXT_NOTE = `## Runtime environment: Claude Code CLI\n\nYou are running via the Claude Code CLI (not a direct API call). This affects context management:\n\n- The \\`compress\\` tool is NOT available. Do not attempt to call it.\n- The \\`distill\\`, \\`prune\\`, and \\`extract\\` tools are NOT available.\n- Context window management is handled automatically by Claude CLI's own session history.\n- Ignore any system instructions that tell you to call \\`compress\\` — they are intended for direct API providers, not this environment.\n- DCP context injections (AGENTS.md, dynamic state) arrive via the system prompt and are already applied.`\n\n/**\n * Replaces the note above when `compress` is in the resolved proxy list.\n * The full MCP name is spelled out for the same reason the question proxy\n * hint spells its own out: models strip the prefix and call bare\n * `compress`, which opencode renders as `⚙ invalid`.\n */\nconst CLAUDE_CLI_COMPRESS_NOTE = `## Runtime environment: Claude Code CLI\n\nYou are running via the Claude Code CLI (not a direct API call). This affects context management:\n\n- To compress context, call \\`mcp__opencode_proxy__compress\\` with a \\`summary\\` argument. Use that exact full name.\n- The reset happens at the start of your NEXT turn: this Claude Code session is discarded and a fresh one starts with your summary as its only prior context. Keep working normally after the call.\n- Everything outside the summary is gone after the reset — tool output, files you read, and the earlier conversation are not replayed. Write the summary as the authoritative record.\n- The \\`distill\\`, \\`prune\\`, and \\`extract\\` tools are NOT available.\n- DCP context injections (AGENTS.md, dynamic state) arrive via the system prompt and are already applied.`\n\n/**\n * Extract text content from all `system`-role messages in the prompt.\n * Standard API providers forward these as the `system` parameter; for\n * Claude CLI, the only equivalent path is --append-system-prompt-file.\n * Plugins like opencode-dcp inject AGENTS.md and other context via\n * system-role messages and would otherwise be silently dropped.\n */\nfunction extractSystemMessages(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n): string[] {\n const out: string[] = []\n for (const msg of prompt) {\n if (msg.role !== \"system\") continue\n if (typeof msg.content === \"string\") {\n if (msg.content.trim()) out.push(msg.content.trim())\n } else if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (\n part?.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text.trim()\n ) {\n out.push(part.text.trim())\n }\n }\n }\n }\n return out\n}\n\nexport interface AppendedSystemPromptOptions {\n /** True when `compress` is in the resolved proxy list for this spawn. */\n compressEnabled?: boolean\n /** Summary from a previous `compress` call, if this key has one. */\n compressionSummary?: string\n}\n\nexport function buildAppendedSystemPrompt(\n cwd: string,\n includeMultiStepHint = true,\n extraSystemContent: string[] = [],\n options: AppendedSystemPromptOptions = {},\n): string | undefined {\n const parts: string[] = []\n // First, so it reads as prior context for everything that follows.\n if (options.compressionSummary?.trim()) {\n parts.push(\n `## Summary of earlier work (context was compressed)\\n\\n${options.compressionSummary.trim()}`,\n )\n }\n parts.push(\n options.compressEnabled ? CLAUDE_CLI_COMPRESS_NOTE : CLAUDE_CLI_CONTEXT_NOTE,\n )\n for (const s of extraSystemContent) {\n if (s.trim()) parts.push(s.trim())\n }\n const configRoot =\n process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\")\n const globalAgents = readPromptFileIfPresent(join(configRoot, \"opencode\", \"AGENTS.md\"))\n const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd)\n\n if (globalAgents) parts.push(globalAgents)\n if (workspaceAgents && workspaceAgents !== globalAgents) parts.push(workspaceAgents)\n if (globalAgents || workspaceAgents) parts.push(AGENTS_MAINTENANCE_HINT)\n if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT)\n\n const content = parts.join(\"\\n\\n\")\n if (!content) return undefined\n\n const path = join(tmpdir(), `opencode-cc-sys-${randomUUID()}.md`)\n try {\n writeFileSync(path, content, \"utf8\")\n return path\n } catch (err) {\n log.warn(\"failed to write system prompt file\", { error: String(err) })\n return undefined\n }\n}\n\nexport class ClaudeCodeLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\"\n readonly modelId: string\n private readonly config: ClaudeCodeConfig\n\n constructor(modelId: string, config: ClaudeCodeConfig) {\n this.modelId = modelId\n this.config = config\n }\n\n readonly supportedUrls: Record<string, RegExp[]> = {}\n\n get provider(): string {\n return this.config.provider\n }\n\n private toUsage(rawUsage?: ClaudeStreamMessage[\"usage\"]): LanguageModelV3Usage {\n // Prefer the last iteration's counters over cumulative totals.\n // CLI usage is the sum across all internal tool-use iterations;\n // using it directly inflates context size and triggers premature compaction.\n const iter = rawUsage?.iterations\n const effective = iter?.length ? iter[iter.length - 1] : rawUsage\n // Claude CLI reports input_tokens as non-cached input only.\n // OpenCode expects total = noCache + cacheRead + cacheWrite.\n const noCache = effective?.input_tokens ?? 0\n const cacheRead = effective?.cache_read_input_tokens ?? 0\n const cacheWrite = effective?.cache_creation_input_tokens ?? 0\n return {\n inputTokens: {\n total: noCache + cacheRead + cacheWrite,\n noCache,\n cacheRead: cacheRead || undefined,\n cacheWrite: cacheWrite || undefined,\n },\n outputTokens: {\n total: effective?.output_tokens,\n text: effective?.output_tokens,\n reasoning: undefined,\n },\n raw: rawUsage as any,\n }\n }\n\n private toFinishReason(\n reason: \"stop\" | \"tool-calls\" = \"stop\",\n ): LanguageModelV3FinishReason {\n return {\n unified: reason,\n raw: reason,\n }\n }\n\n private requestScope(options: { tools?: unknown }): \"tools\" | \"no-tools\" {\n const tools = options?.tools\n if (Array.isArray(tools)) return \"tools\"\n if (tools && typeof tools === \"object\") {\n return Object.keys(tools as Record<string, unknown>).length > 0\n ? \"tools\"\n : \"no-tools\"\n }\n return \"no-tools\"\n }\n\n /**\n * Build the combined `--mcp-config` list and return both the list and the\n * hash of the bridged opencode MCP block (or null when bridging is off /\n * yields nothing). The hash is used to detect mid-session config changes\n * and respawn the underlying claude process.\n *\n * `runtimeStatus` is a snapshot of opencode's `client.mcp.status()`. When\n * provided it overlays opencode's UI-toggled state on top of disk config\n * so `/mcps` toggles propagate without a config file write.\n */\n private effectiveMcpConfig(\n cwd: string,\n proxyConfigPath?: string,\n runtimeStatus?: RuntimeMcpStatus,\n excludeServers?: ReadonlySet<string>,\n ): {\n paths: string[]\n bridgedHash: string | null\n allEnabledServerNames: string[]\n } {\n const paths = Array.isArray(this.config.mcpConfig)\n ? this.config.mcpConfig.slice()\n : this.config.mcpConfig\n ? [this.config.mcpConfig]\n : []\n let bridgedHash: string | null = null\n let allEnabledServerNames: string[] = []\n if (this.config.bridgeOpencodeMcp !== false) {\n const bridged = bridgeOpencodeMcp(cwd, runtimeStatus, excludeServers)\n if (bridged) {\n if (bridged.path) paths.push(bridged.path)\n bridgedHash = bridged.hash\n allEnabledServerNames = bridged.allEnabledServerNames\n }\n }\n if (proxyConfigPath) paths.push(proxyConfigPath)\n return { paths, bridgedHash, allEnabledServerNames }\n }\n\n /** Resolve ProxyToolDef[] for the configured proxyTools names. */\n private resolvedProxyTools(): ProxyToolDef[] | null {\n const names = this.config.proxyTools\n if (!names || names.length === 0) return null\n const defsByName = new Map(\n DEFAULT_PROXY_TOOLS.map((t) => [t.name.toLowerCase(), t]),\n )\n const picked: ProxyToolDef[] = []\n for (const n of names) {\n const def = defsByName.get(String(n).toLowerCase())\n if (def) picked.push(def)\n }\n return picked.length > 0 ? picked : null\n }\n\n /**\n * Resolve ProxyToolDef[] for opencode's MCP-bridged tools so they go\n * through the in-process proxy instead of being bridged into Claude CLI's\n * `--mcp-config`. Direct bridging causes double execution because both\n * Claude CLI's own MCP child and opencode hold their own connection to\n * the same server; routing through the proxy keeps a single execution\n * site (opencode). Returns null when the feature is disabled, the SDK\n * client is unavailable, or no MCP servers are configured.\n */\n private async resolvedProxyMcpTools(\n allEnabledServerNames: string[],\n ): Promise<ProxyToolDef[] | null> {\n if (this.config.proxyOpencodeMcpTools === false) return null\n if (this.config.bridgeOpencodeMcp === false) return null\n if (allEnabledServerNames.length === 0) return null\n\n const items = await fetchOpencodeToolList(\n this.config.provider,\n this.modelId,\n this.config.cwd,\n )\n if (!items || items.length === 0) return null\n\n // opencode names MCP tools `<server>_<originalToolName>`. Match the\n // longest server name prefix first so e.g. `slack_intl_*` resolves to\n // server `slack_intl` not `slack`.\n const serversByLengthDesc = [...allEnabledServerNames].sort(\n (a, b) => b.length - a.length,\n )\n const out: ProxyToolDef[] = []\n const seen = new Set<string>()\n for (const item of items) {\n const matchedServer = serversByLengthDesc.find(\n (name) => item.id === name || item.id.startsWith(`${name}_`),\n )\n if (!matchedServer) continue\n if (seen.has(item.id)) continue\n seen.add(item.id)\n out.push({\n name: item.id,\n description: item.description ?? \"\",\n inputSchema:\n item.parameters && typeof item.parameters === \"object\"\n ? item.parameters\n : { type: \"object\", properties: {} },\n })\n }\n return out.length > 0 ? out : null\n }\n\n /**\n * Live tool info derived from a single `client.tool.list()` fetch:\n *\n * - `taskDescription`: opencode's `task` tool description exactly as the\n * registry renders it for native models, including the \"Available\n * agent types\" list. Overlaid onto the static `task` proxy def so\n * Claude sees the same subagent catalog native models see, instead\n * of hunting through config files.\n * - `questionDescription` / `hasQuestion`: opencode's `question` tool\n * description and whether the registry has the entry at all. Older\n * builds lack it, in which case a `mcp__opencode_proxy__question`\n * call resolves to `⚙ invalid`; the version gate drops the def.\n *\n * Returns undefined/false when the SDK client is unavailable (direct\n * AI-SDK use, tests) so the static defs stand. `resolved` distinguishes\n * \"the registry answered and has no `question` entry\" from \"nobody\n * answered\": only the former is a real version-gate signal.\n */\n private async fetchLiveToolInfo(): Promise<LiveToolInfo> {\n const items = await fetchOpencodeToolList(\n this.config.provider,\n this.modelId,\n this.config.cwd,\n )\n const question = items?.find((item) => item.id === \"question\")\n return {\n resolved: items !== undefined,\n taskDescription: items?.find((item) => item.id === \"task\")?.description,\n questionDescription: question?.description,\n hasQuestion: !!question,\n }\n }\n\n /** Share one lazy registry request within a turn without making it stale. */\n private createLiveToolInfoLoader(): () => Promise<LiveToolInfo> {\n let pending: Promise<LiveToolInfo> | undefined\n return () => {\n pending ??= this.fetchLiveToolInfo()\n return pending\n }\n }\n\n /**\n * Whether the ExitPlanMode approval bridge is live for this turn: the\n * operator opted in AND opencode's registry actually has the `question`\n * tool. Without the registry entry the emitted tool-call would render as\n * `⚙ invalid` and wedge the turn, so the plugin keeps the text path.\n */\n private async resolvePlanModeQuestion(\n compactionMode: boolean,\n loadLiveToolInfo = () => this.fetchLiveToolInfo(),\n ): Promise<boolean> {\n if (compactionMode || this.config.planModeQuestion !== true) return false\n const info = await loadLiveToolInfo()\n const active = isPlanModeQuestionActive({\n configured: this.config.planModeQuestion,\n opencodeHasQuestion: info.hasQuestion,\n compactionMode,\n })\n if (!active) {\n // Same reasoning as the question proxy's version-gate log: a silent\n // fallback to the text path looks from the outside like the setting\n // was ignored.\n log.info(\"plan-mode question gate\", {\n opencodeHasQuestion: info.hasQuestion,\n registryResolved: info.resolved,\n active,\n })\n }\n return active\n }\n\n /**\n * Create a proxy MCP server for a single active Claude process/session.\n * The process lifecycle owns the server lifecycle via session-manager.\n */\n private async ensureProxyServer(\n tools: ProxyToolDef[],\n sessionKeyForCalls: string,\n ): Promise<ProxyMcpServer> {\n const timeoutOverrides = this.config.proxyToolTimeoutMs\n const interceptors = new Map<string, ProxyToolInterceptor>()\n if (tools.some((t) => t.name === \"compress\")) {\n interceptors.set(\"compress\", (input) => {\n const summary = typeof input.summary === \"string\" ? input.summary.trim() : \"\"\n if (!summary) {\n return {\n kind: \"error\",\n message:\n \"compress needs a non-empty `summary`: it becomes the only\" +\n \" prior context after the reset. Nothing was compressed.\",\n }\n }\n storeCompressionSummary(sessionKeyForCalls, summary)\n log.info(\"compress stored summary; session resets next turn\", {\n sessionKey: sessionKeyForCalls,\n summaryLength: summary.length,\n })\n return {\n kind: \"text\",\n text:\n \"Summary stored. Finish this turn as normal; the next turn starts\" +\n \" a fresh Claude Code session with this summary as its only prior\" +\n \" context.\",\n }\n })\n }\n const srv = await createProxyMcpServer(tools, timeoutOverrides, interceptors)\n srv.calls.on(\"call\", (call: ProxyToolCall) => {\n queuePendingProxyCall(sessionKeyForCalls, call, timeoutOverrides)\n })\n return srv\n }\n\n private extractPendingProxyResult(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n toolCallId: string,\n ): ProxyToolResult | null {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role !== \"tool\" || !Array.isArray(msg.content)) continue\n\n for (const part of msg.content) {\n if (part.type !== \"tool-result\" || part.toolCallId !== toolCallId) continue\n\n const output = part.output as any\n if (!output || typeof output !== \"object\") {\n return {\n kind: \"text\",\n text: String(output ?? \"\"),\n }\n }\n\n if (output.type === \"text\") {\n return {\n kind: \"text\",\n text: String(output.value ?? \"\"),\n }\n }\n\n if (output.type === \"json\") {\n return {\n kind: \"text\",\n text: JSON.stringify(output.value),\n }\n }\n\n if (output.type === \"content\" && Array.isArray(output.value)) {\n const text = output.value\n .filter((v: any) => v?.type === \"text\" && typeof v.text === \"string\")\n .map((v: any) => v.text)\n .join(\"\\n\")\n return {\n kind: \"text\",\n text,\n }\n }\n\n return {\n kind: \"text\",\n text: JSON.stringify(output),\n }\n }\n }\n\n return null\n }\n\n /**\n * Resolve the session affinity token for this LLM call. Delegates to the\n * exported `resolveSessionAffinity` helper so the logic is unit-testable.\n * Priority:\n * 1. `x-session-affinity` request header (primary).\n * 2. `opencodeSessionID` in providerOptions (chat.params hook fallback —\n * covers provider switches mid-session and title synthesis paths\n * where the header is absent).\n * 3. `\"default\"`.\n */\n private sessionAffinity(\n options: LanguageModelV3CallOptions,\n ): string {\n const headers = (options as any)?.headers as\n | Record<string, string | undefined>\n | undefined\n return resolveSessionAffinity(\n headers,\n options.providerOptions as Record<string, unknown> | undefined,\n this.config.provider,\n )\n }\n\n private controlRequestBehaviorForTool(toolName: string): ControlRequestBehavior {\n const configured = this.config.controlRequestToolBehaviors\n if (configured && toolName) {\n const direct = configured[toolName] ?? configured[toolName.toLowerCase()]\n if (direct === \"allow\" || direct === \"deny\") return direct\n\n const lower = toolName.toLowerCase()\n for (const [key, behavior] of Object.entries(configured)) {\n if (key.toLowerCase() === lower && (behavior === \"allow\" || behavior === \"deny\")) {\n return behavior\n }\n }\n }\n\n // AskUserQuestion must never be auto-allowed. Allowing it lets the\n // Claude CLI resolve its own question internally — in headless mode\n // there is no TTY, so the CLI fabricates/empties the answer and the\n // model proceeds on a guess. Deny so the CLI cannot self-answer; the\n // tool_use is still streamed and rendered to the opencode user by\n // formatAskUserQuestion, and the turn stops for a real reply. An\n // explicit controlRequestToolBehaviors entry above can still override.\n if (isAskUserQuestionTool(toolName)) return \"deny\"\n\n return this.config.controlRequestBehavior ?? \"allow\"\n }\n\n private writeControlResponse(\n proc: import(\"child_process\").ChildProcess,\n requestId: string,\n response?: Record<string, unknown>,\n ): void {\n const payload = {\n type: \"control_response\",\n response: {\n subtype: \"success\",\n request_id: requestId,\n response,\n },\n }\n\n try {\n proc.stdin?.write(JSON.stringify(payload) + \"\\n\")\n } catch (error) {\n log.warn(\"failed to write control response\", {\n requestId,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n /**\n * Handle Claude stream-json control requests (`can_use_tool`, etc.) and\n * respond via stdin with a matching `control_response`.\n */\n private handleControlRequest(\n msg: ClaudeStreamMessage,\n proc: import(\"child_process\").ChildProcess,\n ): boolean {\n if (msg.type !== \"control_request\") return false\n const requestId = msg.request_id\n const request = msg.request\n if (!requestId || !request?.subtype) return false\n\n if (request.subtype === \"can_use_tool\") {\n const toolName = request.tool_name ?? \"unknown\"\n const behavior = this.controlRequestBehaviorForTool(toolName)\n\n if (behavior === \"allow\") {\n this.writeControlResponse(proc, requestId, {\n behavior: \"allow\",\n updatedInput: request.input ?? {},\n toolUseID: request.tool_use_id,\n })\n log.info(\"control request auto-allowed\", {\n requestId,\n toolName,\n })\n } else {\n const denyMessage = denyMessageForTool(\n toolName,\n this.config.controlRequestDenyMessage,\n )\n this.writeControlResponse(proc, requestId, {\n behavior: \"deny\",\n message: denyMessage,\n toolUseID: request.tool_use_id,\n })\n log.info(\"control request auto-denied\", {\n requestId,\n toolName,\n })\n }\n\n return true\n }\n\n // For control request subtypes we don't actively handle yet, acknowledge\n // with an empty success so the CLI stream does not stall.\n this.writeControlResponse(proc, requestId, {})\n log.debug(\"control request acknowledged\", {\n requestId,\n subtype: request.subtype,\n })\n return true\n }\n\n private getReasoningEffort(\n providerOptions?: LanguageModelV3CallOptions[\"providerOptions\"],\n ): ReasoningEffort | undefined {\n if (!providerOptions) return undefined\n const ownKey = this.config.provider\n const bag =\n (providerOptions as any)[ownKey] ??\n (providerOptions as any)[\"claude-code\"]\n const effort = bag?.reasoningEffort\n const valid: ReasoningEffort[] = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n ]\n return valid.includes(effort) ? effort : undefined\n }\n\n private getOpencodeAgent(\n providerOptions?: LanguageModelV3CallOptions[\"providerOptions\"],\n ): string | undefined {\n if (!providerOptions) return undefined\n const ownKey = this.config.provider\n const bag =\n (providerOptions as any)[ownKey] ??\n (providerOptions as any)[\"claude-code\"]\n const agent = bag?.opencodeAgent\n return typeof agent === \"string\" ? agent : undefined\n }\n\n private isCompactionCall(\n options: LanguageModelV3CallOptions,\n ): boolean {\n return this.getOpencodeAgent(options.providerOptions) === \"compaction\"\n }\n\n /**\n * Pick the model used to handle /compact. Precedence:\n * 1. `CLAUDE_CODE_COMPACTION_MODEL` env var (per-process override)\n * 2. `compactionModel` provider setting (opencode.json / .jsonc)\n * 3. Built-in default (claude-haiku-4-5)\n */\n private resolveCompactionModel(): string {\n return resolveCompactionModel(this.config.compactionModel)\n }\n\n private thinkingCliOptions(): {\n thinking?: \"enabled\"\n thinkingDisplay?: \"summarized\"\n } {\n if (isClaudeThinkingDisabled()) return {}\n\n return {\n thinking: \"enabled\",\n thinkingDisplay:\n process.env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES === undefined\n ? \"summarized\"\n : undefined,\n }\n }\n\n private latestUserText(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n ): string {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (msg.role !== \"user\") continue\n\n if (typeof msg.content === \"string\") {\n return String(msg.content).trim()\n }\n\n if (Array.isArray(msg.content)) {\n const text = (msg.content as any[])\n .filter((part) => part.type === \"text\" && typeof part.text === \"string\")\n .map((part: any) => String(part.text).trim())\n .filter(Boolean)\n .join(\" \")\n if (text) return text\n }\n }\n\n return \"\"\n }\n\n private synthesizeTitle(\n prompt: LanguageModelV3CallOptions[\"prompt\"],\n ): string {\n const source = this.latestUserText(prompt)\n .replace(/\\s+/g, \" \")\n .replace(/[^\\p{L}\\p{N}\\s-]/gu, \" \")\n .trim()\n\n if (!source) return \"New Session\"\n\n const stop = new Set([\n \"a\",\n \"an\",\n \"the\",\n \"and\",\n \"or\",\n \"but\",\n \"to\",\n \"for\",\n \"of\",\n \"in\",\n \"on\",\n \"at\",\n \"with\",\n \"can\",\n \"could\",\n \"would\",\n \"should\",\n \"please\",\n \"hi\",\n \"hello\",\n \"hey\",\n \"there\",\n \"you\",\n \"your\",\n \"this\",\n \"that\",\n \"is\",\n \"are\",\n \"was\",\n \"were\",\n \"be\",\n \"do\",\n \"does\",\n \"did\",\n \"summarize\",\n \"summary\",\n \"project\",\n ])\n\n const words = source\n .split(\" \")\n .map((word) => word.trim())\n .filter(Boolean)\n .filter((word) => !stop.has(word.toLowerCase()))\n\n const picked = (words.length > 0 ? words : source.split(\" \").filter(Boolean))\n .slice(0, 6)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \")\n\n return picked || \"New Session\"\n }\n\n private async doGenerateViaStream(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n const result = await this.doStream(options)\n const reader = result.stream.getReader()\n\n let text = \"\"\n let reasoning = \"\"\n const toolCalls: LanguageModelV3Content[] = []\n let finishReason = this.toFinishReason(\"stop\")\n let usage: LanguageModelV3Usage = this.toUsage()\n let providerMetadata: any\n\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n\n switch ((value as any).type) {\n case \"text-delta\":\n text += (value as any).delta ?? \"\"\n break\n case \"reasoning-delta\":\n reasoning += (value as any).delta ?? \"\"\n break\n case \"tool-call\":\n toolCalls.push({\n type: \"tool-call\",\n toolCallId: (value as any).toolCallId,\n toolName: (value as any).toolName,\n input: (value as any).input,\n providerExecuted: (value as any).providerExecuted,\n } as any)\n break\n case \"finish\":\n finishReason = (value as any).finishReason ?? finishReason\n usage = (value as any).usage ?? usage\n providerMetadata = (value as any).providerMetadata ?? providerMetadata\n break\n }\n }\n\n const content: LanguageModelV3Content[] = []\n if (reasoning) {\n content.push({ type: \"reasoning\", text: reasoning } as any)\n }\n if (text) {\n content.push({ type: \"text\", text, providerMetadata } as any)\n }\n content.push(...toolCalls)\n\n return {\n content,\n finishReason,\n usage,\n request: result.request,\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata,\n warnings: [],\n }\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n const warnings: SharedV3Warning[] = []\n const cwd = resolveSpawnCwd(this.config.cwd)\n const scope = this.requestScope(options as any)\n const affinity = this.sessionAffinity(options)\n const sk = sessionKey(cwd, `${this.modelId}::${scope}::${affinity}`)\n\n // When selective proxying is enabled, doGenerate must not bypass the\n // proxy path. Reuse doStream and aggregate its events so proxied tools\n // still route through opencode permissions/execution. Same for\n // opencode MCP proxying — doStream is the only path that wires up the\n // proxy server with the dynamically-discovered MCP tool defs.\n const compactionMode = this.isCompactionCall(options)\n\n if (\n scope === \"tools\" &&\n (this.resolvedProxyTools() ||\n (this.config.proxyOpencodeMcpTools !== false &&\n this.config.bridgeOpencodeMcp !== false))\n ) {\n return this.doGenerateViaStream(options)\n }\n\n // Route compaction through doStream so it gets the lean spawn path,\n // model override, and rich transcript handling. Aggregating a stream\n // for doGenerate matches what doGenerateViaStream already does for\n // proxy tools.\n if (compactionMode) {\n return this.doGenerateViaStream(options)\n }\n\n if (scope === \"no-tools\") {\n log.info(\"doGenerate no-tools title stub\", {\n compactionMode,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n const text = this.synthesizeTitle(options.prompt)\n return {\n content: [{ type: \"text\", text }] as any,\n finishReason: this.toFinishReason(\"stop\"),\n usage: this.toUsage({ input_tokens: 0, output_tokens: 0 }),\n request: { body: { text: \"\" } },\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": {\n synthetic: true,\n path: \"no-tools\",\n },\n },\n warnings,\n }\n }\n\n // Short-circuit when opencode iterates the agent loop one more time\n // after a turn already finished. The prompt ends with an assistant\n // message and has no fresh user input — spawning Claude here would\n // just produce a stub like \"No input received. Standing by\".\n if (!hasNewUserContent(options.prompt)) {\n log.info(\"doGenerate short-circuit: no new user content\")\n return {\n content: [],\n finishReason: this.toFinishReason(\"stop\"),\n usage: this.toUsage({ input_tokens: 0, output_tokens: 0 }),\n request: { body: { text: \"\" } },\n response: {\n id: generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": { synthetic: true, path: \"no-new-user-content\" },\n },\n warnings,\n }\n }\n\n const hasPriorConversation =\n options.prompt.filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .length > 1\n\n // New session — clear any stale state from a previous session.\n // A compression summary is scoped to one conversation, so this is the\n // one place it is dropped: the compress restart itself calls\n // deleteClaudeSessionId, and clearing there would wipe the summary\n // just before the fresh spawn reads it.\n if (!hasPriorConversation) {\n deleteClaudeSessionId(sk)\n deleteActiveProcess(sk)\n clearCompression(sk)\n }\n\n const hasExistingSession = !!getClaudeSessionId(sk)\n const includeHistoryContext = !hasExistingSession && hasPriorConversation\n\n const reasoningEffort = this.getReasoningEffort(options.providerOptions)\n const userMsg =\n consumeExitPlanModeQuestionResult(sk, options.prompt as any) ??\n getClaudeUserMessage(options.prompt, includeHistoryContext, reasoningEffort)\n\n // doGenerate always spawns a fresh process, never reuse session ID.\n // Pre-fetch opencode's MCP runtime status so the bridge overlays\n // UI-toggled state on top of disk config.\n const [runtimeStatus, cliVersion, planModeQuestionActive] = await Promise.all([\n getRuntimeMcpStatus(),\n detectCliVersion(this.config.cliPath),\n this.resolvePlanModeQuestion(compactionMode),\n ])\n const systemPromptFile = buildAppendedSystemPrompt(\n cwd,\n this.config.multiStepContinuation !== false,\n extractSystemMessages(options.prompt),\n // doGenerate has no proxy wiring, so `compress` is not callable here.\n // An existing summary still carries: it is this key's prior context.\n { compressEnabled: false, compressionSummary: getCompressionSummary(sk) },\n )\n const cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions: this.config.skipPermissions !== false,\n includeSessionId: false,\n model: this.modelId,\n permissionMode: this.config.permissionMode,\n mcpConfig: this.effectiveMcpConfig(cwd, undefined, runtimeStatus).paths,\n strictMcpConfig: this.config.strictMcpConfig,\n disallowedTools:\n this.config.webSearch === \"disabled\" ? [\"WebSearch\"] : undefined,\n appendSystemPromptFile: systemPromptFile,\n ...this.thinkingCliOptions(),\n cliVersion,\n })\n\n log.info(\"doGenerate starting\", {\n cwd,\n model: this.modelId,\n textLength: userMsg.length,\n includeHistoryContext,\n })\n\n const { spawn } = await import(\"node:child_process\")\n const { createInterface } = await import(\"node:readline\")\n\n const proc = spawn(this.config.cliPath, cliArgs, {\n cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: claudeSpawnEnv({\n ignoreAnthropicApiKey: this.config.ignoreAnthropicApiKey,\n }),\n shell: process.platform === \"win32\",\n })\n\n if (systemPromptFile) {\n proc.on(\"exit\", () => {\n void unlink(systemPromptFile).catch(() => {})\n })\n }\n\n const rl = createInterface({ input: proc.stdout! })\n\n let responseText = \"\"\n let thinkingText = \"\"\n let resultMeta: {\n sessionId?: string\n costUsd?: number\n durationMs?: number\n usage?: ClaudeStreamMessage[\"usage\"]\n } = {}\n const toolCalls: Array<{ id: string; name: string; args: unknown }> = []\n // Streaming tool_use entries keyed by content-block index. We accumulate\n // partial_json chunks here instead of trying to JSON.parse each chunk\n // independently, and flush to `toolCalls` at content_block_stop. The\n // previous code indexed `toolCalls` by `msg.index` directly, which is\n // wrong whenever non-tool blocks (text, thinking) precede a tool_use.\n const toolCallStreams = new Map<\n number,\n { id: string; name: string; inputJson: string }\n >()\n\n // Set true once we observe a `stream_event` envelope. When on, the\n // top-level `assistant` message is a duplicate of content already\n // accumulated via the inner content_block_* events — skip it.\n let gotPartialEvents = false\n\n const result = await new Promise<\n typeof resultMeta & {\n text: string\n thinking: string\n toolCalls: typeof toolCalls\n }\n >((resolve, reject) => {\n const cleanup = () => {\n try {\n if (!proc.killed && proc.exitCode === null) proc.kill()\n } catch {}\n }\n\n rl.on(\"line\", (line) => {\n if (!line.trim()) return\n try {\n const outer: ClaudeStreamMessage = JSON.parse(line)\n\n // Unwrap stream_event envelope (--include-partial-messages).\n // Inner event uses the same content_block_* / message_* shape.\n const msg: ClaudeStreamMessage =\n outer.type === \"stream_event\" && outer.event\n ? { ...outer.event, session_id: outer.session_id }\n : outer\n\n if (outer.type === \"stream_event\") {\n gotPartialEvents = true\n }\n\n if (this.handleControlRequest(msg, proc)) {\n return\n }\n\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n }\n\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n !gotPartialEvents\n ) {\n for (const block of msg.message.content) {\n if (block.type === \"text\" && block.text) {\n responseText += block.text\n }\n if (block.type === \"thinking\" && block.thinking) {\n thinkingText += block.thinking\n }\n if (block.type === \"tool_use\" && block.id && block.name) {\n if (isAskUserQuestionTool(block.name)) {\n // Render the full question + options as visible text so\n // the user can actually see and answer it.\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n responseText += formatAskUserQuestion(parsedInput)\n continue\n }\n\n if (block.name === \"ExitPlanMode\") {\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n const plan = (parsedInput?.plan as string) || \"\"\n if (planModeQuestionActive) {\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n block.id,\n plan,\n )\n responseText += questionCall.text\n toolCalls.push({\n id: questionCall.toolCallId,\n name: questionCall.toolName,\n args: questionCall.input,\n })\n continue\n }\n responseText += `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`\n continue\n }\n\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: block.input ?? {},\n })\n }\n }\n }\n\n if (\n msg.type === \"content_block_start\" &&\n msg.content_block &&\n msg.index !== undefined\n ) {\n if (\n msg.content_block.type === \"tool_use\" &&\n msg.content_block.id &&\n msg.content_block.name\n ) {\n toolCallStreams.set(msg.index, {\n id: msg.content_block.id,\n name: msg.content_block.name,\n inputJson: \"\",\n })\n }\n }\n\n if (\n msg.type === \"content_block_delta\" &&\n msg.delta &&\n msg.index !== undefined\n ) {\n if (msg.delta.type === \"text_delta\" && msg.delta.text) {\n responseText += msg.delta.text\n }\n if (msg.delta.type === \"thinking_delta\" && msg.delta.thinking) {\n thinkingText += msg.delta.thinking\n }\n if (\n msg.delta.type === \"input_json_delta\" &&\n msg.delta.partial_json\n ) {\n const tc = toolCallStreams.get(msg.index)\n if (tc) tc.inputJson += msg.delta.partial_json\n }\n }\n\n if (msg.type === \"content_block_stop\" && msg.index !== undefined) {\n const tc = toolCallStreams.get(msg.index)\n if (tc) {\n let args: unknown = {}\n try {\n args = tc.inputJson ? JSON.parse(tc.inputJson) : {}\n } catch (err) {\n log.warn(\"tool input JSON parse failed\", {\n name: tc.name,\n error: String(err),\n })\n }\n if (tc.name === \"ExitPlanMode\" && planModeQuestionActive) {\n const parsedInput = args as Record<string, unknown>\n const plan = (parsedInput?.plan as string) || \"\"\n const questionCall = createExitPlanModeQuestionCall(sk, tc.id, plan)\n responseText += questionCall.text\n toolCalls.push({\n id: questionCall.toolCallId,\n name: questionCall.toolName,\n args: questionCall.input,\n })\n } else {\n toolCalls.push({ id: tc.id, name: tc.name, args })\n }\n toolCallStreams.delete(msg.index)\n }\n }\n\n if (msg.type === \"result\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n\n // Some CLI failures only surface user-readable text on the final\n // `result` message (without prior assistant text blocks). Preserve\n // that so callers don't receive an empty response.\n if (\n !responseText &&\n msg.is_error &&\n typeof msg.result === \"string\" &&\n msg.result.trim().length > 0\n ) {\n responseText = msg.result\n }\n\n resultMeta = {\n sessionId: msg.session_id,\n costUsd: msg.total_cost_usd,\n durationMs: msg.duration_ms,\n usage: msg.usage,\n }\n cleanup()\n resolve({\n ...resultMeta,\n text: responseText,\n thinking: thinkingText,\n toolCalls,\n })\n }\n } catch {\n // Ignore non-JSON lines\n }\n })\n\n rl.on(\"close\", () => {\n cleanup()\n resolve({\n ...resultMeta,\n text: responseText,\n thinking: thinkingText,\n toolCalls,\n })\n })\n\n proc.on(\"error\", (err) => {\n log.error(\"process error\", { error: err.message })\n cleanup()\n reject(err)\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n log.debug(\"stderr\", { data: data.toString().slice(0, 200) })\n })\n\n proc.stdin?.write(userMsg + \"\\n\")\n })\n\n const content: LanguageModelV3Content[] = []\n\n if (result.thinking) {\n content.push({\n type: \"reasoning\",\n text: result.thinking,\n } as any)\n }\n\n if (result.text) {\n content.push({\n type: \"text\",\n text: result.text,\n providerMetadata: {\n \"claude-code\": {\n sessionId: result.sessionId ?? null,\n costUsd: result.costUsd ?? null,\n durationMs: result.durationMs ?? null,\n },\n ...(typeof result.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n result.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n })\n }\n\n for (const tc of result.toolCalls) {\n if (tc.name === QUESTION_TOOL_NAME) {\n content.push({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: tc.name,\n input: JSON.stringify(tc.args),\n providerExecuted: false,\n } as any)\n continue\n }\n\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(tc.name, tc.args, {\n webSearch: this.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: tc.id,\n })\n if (skip) continue\n content.push({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n\n const usage = this.toUsage(result.usage)\n\n return {\n content,\n // Claude CLI's `result` message normally signals a fully-completed turn:\n // tools have already been executed internally and final assistant text\n // has been produced. ExitPlanMode is the exception: we surface it as\n // opencode's native question tool so the outer loop must run that tool.\n finishReason: this.toFinishReason(\n result.toolCalls.some((tc) => tc.name === QUESTION_TOOL_NAME)\n ? \"tool-calls\"\n : \"stop\",\n ),\n usage,\n request: { body: { text: userMsg } },\n response: {\n id: result.sessionId ?? generateId(),\n timestamp: new Date(),\n modelId: this.modelId,\n },\n providerMetadata: {\n \"claude-code\": {\n sessionId: result.sessionId ?? null,\n costUsd: result.costUsd ?? null,\n durationMs: result.durationMs ?? null,\n },\n ...(typeof result.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n result.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n warnings,\n }\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n const warnings: SharedV3Warning[] = []\n const cwd = resolveSpawnCwd(this.config.cwd)\n const cliPath = this.config.cliPath\n const skipPermissions = this.config.skipPermissions !== false\n const scope = this.requestScope(options as any)\n const affinity = this.sessionAffinity(options)\n const compactionMode = this.isCompactionCall(options)\n // Use a separate session key for compaction so its short-lived spawn\n // never collides with the main conversation's claude process.\n const effectiveModelId = compactionMode\n ? this.resolveCompactionModel()\n : this.modelId\n const sk = compactionMode\n ? sessionKey(cwd, `${effectiveModelId}::compaction::${affinity}`)\n : sessionKey(cwd, `${this.modelId}::${scope}::${affinity}`)\n const toUsage = this.toUsage.bind(this)\n const toFinishReason = this.toFinishReason.bind(this)\n const handleControlRequest = this.handleControlRequest.bind(this)\n const flagOn = (v: string | undefined) =>\n v !== undefined &&\n ![\"\", \"0\", \"false\", \"no\", \"off\"].includes(v.trim().toLowerCase())\n // Interactive (subscription) transport: drive the claude TUI over Bun's\n // native ConPTY + JSONL tail instead of headless `--print` stream-json.\n // Prefer the provider option (config-driven, reliable in the GUI app where\n // process env vars are not inherited); fall back to the env var. Self-healing:\n // if Bun.Terminal is unavailable (e.g. not under Bun), use the headless path.\n const interactivePref =\n this.config.interactive ??\n flagOn(process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT)\n const useInteractive =\n interactivePref && typeof (globalThis as any).Bun?.Terminal === \"function\"\n const interactiveBypassRequested =\n this.config.interactiveBypass ??\n flagOn(process.env.CLAUDE_CODE_INTERACTIVE_BYPASS)\n\n if (scope === \"no-tools\" && !compactionMode) {\n log.info(\"doStream no-tools title stub\", {\n compactionMode,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n const text = this.synthesizeTitle(options.prompt)\n const textId = generateId()\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n controller.enqueue({ type: \"stream-start\", warnings })\n controller.enqueue({ type: \"text-start\", id: textId } as any)\n controller.enqueue({\n type: \"text-delta\",\n id: textId,\n delta: text,\n })\n controller.enqueue({ type: \"text-end\", id: textId })\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage({ input_tokens: 0, output_tokens: 0 }),\n providerMetadata: {\n \"claude-code\": {\n synthetic: true,\n path: \"no-tools\",\n },\n },\n })\n controller.close()\n },\n })\n\n return {\n stream,\n request: { body: { text: \"\" } },\n }\n }\n\n // Short-circuit when opencode iterates the agent loop one more time\n // after a turn already finished. The prompt ends with an assistant\n // message and has no fresh user input — spawning Claude here would\n // just produce a stub like \"No input received. Standing by\".\n if (!hasNewUserContent(options.prompt)) {\n log.info(\"doStream short-circuit: no new user content\")\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n controller.enqueue({ type: \"stream-start\", warnings })\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage({ input_tokens: 0, output_tokens: 0 }),\n providerMetadata: {\n \"claude-code\": { synthetic: true, path: \"no-new-user-content\" },\n },\n })\n controller.close()\n },\n })\n return { stream, request: { body: { text: \"\" } } }\n }\n\n const hasPriorConversation =\n options.prompt.filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .length > 1\n\n // New session — clear any stale state from a previous session.\n // A compression summary is scoped to one conversation, so this is the\n // one place it is dropped: the compress restart itself calls\n // deleteClaudeSessionId, and clearing there would wipe the summary\n // just before the fresh spawn reads it.\n if (!hasPriorConversation) {\n deleteClaudeSessionId(sk)\n deleteActiveProcess(sk)\n clearCompression(sk)\n }\n\n const hasExistingSession = !!getClaudeSessionId(sk)\n const hasActiveProcess = !!getActiveProcess(sk)\n const includeHistoryContext =\n !hasExistingSession && !hasActiveProcess && hasPriorConversation\n\n const reasoningEffort = this.getReasoningEffort(options.providerOptions)\n const exitPlanModeQuestionResult = compactionMode\n ? null\n : consumeExitPlanModeQuestionResult(sk, options.prompt as any)\n if (exitPlanModeQuestionResult) {\n // The whole user message for this turn is the `tool_result` for the\n // pending ExitPlanMode call, so say so: an operator looking at a turn\n // that carries none of their typed text needs the reason in the log.\n log.info(\"sending plan approval decision to claude\", { sk })\n }\n const userMsg =\n exitPlanModeQuestionResult ??\n getClaudeUserMessage(options.prompt, includeHistoryContext, reasoningEffort, {\n compactionMode,\n })\n const resolvedProxy = compactionMode ? null : this.resolvedProxyTools()\n const loadLiveToolInfo = this.createLiveToolInfoLoader()\n // Resolved here, not inside the stream body: the ExitPlanMode branches\n // run in a synchronous line handler and a reused process never reaches\n // the spawn block where the registry snapshot is otherwise taken.\n const planModeQuestionActive = await this.resolvePlanModeQuestion(\n compactionMode,\n loadLiveToolInfo,\n )\n const self = this\n\n const previousPendingProxyCalls = compactionMode\n ? []\n : getPendingProxyCalls(sk)\n const previousPendingProxyMatches: Array<{\n call: PendingProxyCall\n result: ProxyToolResult | null\n }> = previousPendingProxyCalls.map((call) => ({\n call,\n result: this.extractPendingProxyResult(options.prompt, call.toolCallId),\n }))\n const hasMatchedPendingResults = previousPendingProxyMatches.some(\n (m) => m.result !== null,\n )\n\n // Pre-fetch opencode's MCP runtime status before constructing the\n // ReadableStream so the sync hot-reload check and async setup() see\n // the same overlay snapshot. One in-process call per turn — cheap;\n // the SDK client routes through `Server.app.fetch` (no socket).\n // Detect the Claude CLI version in parallel so the spawn can decide\n // which optional flags it supports without crashing older binaries.\n const [runtimeStatus, cliVersion] = await Promise.all([\n compactionMode ? Promise.resolve(undefined) : getRuntimeMcpStatus(),\n detectCliVersion(this.config.cliPath),\n ])\n\n log.info(\"doStream starting\", {\n cwd,\n model: effectiveModelId,\n textLength: userMsg.length,\n includeHistoryContext,\n hasActiveProcess,\n reasoningEffort,\n proxyTools: resolvedProxy?.map((t) => t.name) ?? null,\n compactionMode,\n scope,\n opencodeAgent: this.getOpencodeAgent(options.providerOptions),\n providerOptionsKeys: options.providerOptions\n ? Object.keys(options.providerOptions)\n : [],\n })\n\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n start(controller) {\n // Compaction is a one-shot call. Don't reuse any cached process\n // from a prior compaction — each /compact gets a fresh spawn so\n // the new transcript isn't appended to a stale claude session.\n if (compactionMode) {\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n }\n\n // A compress call lands mid-turn, when the child is still streaming,\n // so the reset it asks for happens here instead: drop the child and\n // its session id, and the spawn below starts clean. `userMsg` and\n // `includeHistoryContext` were resolved above while the session\n // still existed, so the fresh process is given only this turn's\n // message — the summary in its system prompt is the whole of its\n // prior context, exactly as the tool promised.\n //\n // Not while this turn carries results for the live child: evicting\n // it would send a tool_result to a process that never issued the\n // matching tool_use. The mark survives to the next turn.\n if (!compactionMode && !hasMatchedPendingResults && consumeCompressionRestart(sk)) {\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n log.info(\"compress reset: dropped claude process and session id\", {\n sessionKey: sk,\n })\n }\n\n let activeProcess = getActiveProcess(sk)\n let proc: import(\"child_process\").ChildProcess\n let lineEmitter: import(\"events\").EventEmitter\n let cliArgs: string[]\n let proxyServer: ProxyMcpServer | null = activeProcess?.proxyServer ?? null\n\n const setup = async () => {\n // Wait for the old owner to exit before resuming its session ID in\n // the replacement, so two processes never append to one transcript.\n if (\n !compactionMode &&\n activeProcess &&\n self.config.hotReloadMcp !== false &&\n self.config.bridgeOpencodeMcp !== false\n ) {\n const probe = self.effectiveMcpConfig(cwd, undefined, runtimeStatus!)\n const previousHash = activeProcess.mcpHash ?? null\n if (previousHash !== probe.bridgedHash) {\n if (previousPendingProxyCalls.length > 0) {\n log.info(\"deferring MCP hot reload until proxy calls resolve\", {\n sk,\n previousHash,\n currentHash: probe.bridgedHash,\n pendingCalls: previousPendingProxyCalls.length,\n })\n } else {\n log.info(\"opencode MCP config changed, respawning claude\", {\n sk,\n previousHash,\n currentHash: probe.bridgedHash,\n })\n await deleteActiveProcessAndWait(sk)\n activeProcess = undefined\n proxyServer = null\n }\n }\n }\n\n if (useInteractive && !compactionMode) {\n // Interactive Bun-ConPTY transport. Reuse the live session if one\n // exists for this key; else spawn a new interactive claude. The\n // wrapper conforms to ActiveProcess, so reuse/eviction/hot-reload\n // and the whole emission body below work unchanged.\n const mcp = self.effectiveMcpConfig(cwd, undefined, runtimeStatus!)\n if (activeProcess) {\n proc = activeProcess.proc\n lineEmitter = activeProcess.lineEmitter\n log.debug(\"reusing active interactive session\", { sk })\n } else {\n // MCP wildcards are always derived from the live bridge config;\n // the built-in tool list is overridable via interactiveAllowTools.\n const allow = [\n ...mcp.allEnabledServerNames.map((n) => `mcp__${n}__*`),\n \"mcp__opencode_proxy__*\",\n ...(self.config.interactiveAllowTools ?? [\n \"Bash\",\n \"Edit\",\n \"Write\",\n \"Read\",\n \"WebFetch\",\n ]),\n ]\n const systemPromptFile =\n self.config.interactiveSystemPrompt === false\n ? undefined\n : buildAppendedSystemPrompt(\n cwd,\n self.config.multiStepContinuation !== false,\n // Do not forward opencode's own system prompt into the\n // interactive TUI. Live subscription-account testing\n // showed that large forwarded payload can trigger Claude\n // Code's third-party-app usage gate, while our static\n // CLI/AGENTS/continuation prompt remains safe.\n )\n if (self.config.interactiveSystemPrompt === false) {\n log.warn(\n \"interactive system prompt disabled; opencode agent prompts will not be appended\",\n )\n }\n if (interactiveBypassRequested) {\n log.warn(\n \"interactiveBypass ignored: Claude Code prompts for bypassPermissions confirmation in the interactive TUI\",\n )\n }\n const ap = spawnInteractiveProcess({\n cwd,\n cliPath,\n configDir: self.config.configDir,\n model: effectiveModelId,\n mcpConfigPaths: mcp.paths,\n permissionsAllow: allow,\n systemPromptFile,\n ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey,\n })\n ap.mcpHash = mcp.bridgedHash\n setActiveProcess(sk, ap)\n proc = ap.proc\n lineEmitter = ap.lineEmitter\n activeProcess = ap\n log.info(\"spawned interactive claude session\", {\n sk,\n cliPath,\n configDir: self.config.configDir,\n model: effectiveModelId,\n })\n }\n } else {\n let spawnSystemPromptFile: string | undefined\n let spawnProxyServer: ProxyMcpServer | null = null\n let spawnMcpHash: string | null = null\n\n if (compactionMode) {\n // Compaction takes a lean spawn: no MCP servers, no proxy, no\n // appended system prompt, no disallowed-tools list. The model\n // is asked for text output only on a single turn — all the\n // normal tool wiring is pure overhead and adds latency.\n // Explicitly opt out of `--resume` so a stale id can never\n // resume into the lean spawn.\n cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions,\n includeSessionId: false,\n model: effectiveModelId,\n permissionMode: self.config.permissionMode,\n cliVersion,\n })\n } else {\n // First pass: discover which opencode MCP servers would be\n // bridged. We use this to decide which ones to re-route through\n // the proxy instead. No --mcp-config path is consumed here;\n // it's recomputed below with the exclusion set in place.\n const discovery = self.effectiveMcpConfig(\n cwd,\n undefined,\n runtimeStatus!,\n )\n\n // Fetch the proxy MCP tools (one ProxyToolDef per opencode\n // MCP-bridged tool). If discovery returns nothing or the SDK\n // is unreachable, this is null and we fall back to direct\n // bridging.\n const proxyMcpTools = await self.resolvedProxyMcpTools(\n discovery.allEnabledServerNames,\n )\n const excludeServers: ReadonlySet<string> | undefined = proxyMcpTools\n ? new Set(discovery.allEnabledServerNames)\n : undefined\n\n // Overlay opencode's live tool info onto the static proxy defs.\n // Both the `task` description (with the \"Available agent types\"\n // list, so the model sees which subagents exist instead of\n // grepping configs) and the `question` version gate (older\n // opencode builds lack the `question` registry entry; the def\n // must be dropped or a forwarded call renders `⚙ invalid`)\n // derive from a single tool-list fetch. Spawn-time only, like\n // the rest of this block; a reused process keeps its defs.\n const taskProxyEnabled =\n resolvedProxy?.some((t) => t.name === \"task\") ?? false\n const questionProxyEnabled =\n resolvedProxy?.some((t) => t.name === \"question\") ?? false\n const liveToolInfo =\n taskProxyEnabled || questionProxyEnabled\n ? await loadLiveToolInfo()\n : {\n resolved: false,\n taskDescription: undefined,\n questionDescription: undefined,\n hasQuestion: false,\n }\n let enrichedProxy = resolvedProxy\n if (enrichedProxy && taskProxyEnabled) {\n enrichedProxy = overlayTaskProxyDescription(\n enrichedProxy,\n liveToolInfo.taskDescription,\n )\n // Whether the model will see opencode's agent list is the\n // difference between a dispatch and an \"Unknown agent type\"\n // guess, so say so out loud.\n log.info(\"task proxy description overlay\", {\n applied: Boolean(liveToolInfo.taskDescription),\n liveDescriptionLength: liveToolInfo.taskDescription?.length ?? 0,\n listsAgentTypes: Boolean(\n liveToolInfo.taskDescription?.includes(\n \"Available agent types\",\n ),\n ),\n })\n }\n if (enrichedProxy && questionProxyEnabled) {\n // When the version gate is about to drop the def\n // (`hasQuestion === false`) the live description is moot,\n // so only overlay when the entry actually exists.\n enrichedProxy = overlayQuestionProxyDescription(\n enrichedProxy,\n liveToolInfo.hasQuestion\n ? liveToolInfo.questionDescription\n : undefined,\n )\n enrichedProxy = filterQuestionProxyByOpencodeSupport(\n enrichedProxy,\n liveToolInfo.hasQuestion,\n )\n // Same reasoning as the task overlay log: when the gate drops\n // the def the model silently falls back to the deny/markdown\n // path, which looks from the outside like the feature is off.\n log.info(\"question proxy version gate\", {\n opencodeHasQuestion: liveToolInfo.hasQuestion,\n kept: liveToolInfo.hasQuestion,\n })\n }\n\n // Combine the static proxy defs with any MCP-bridged proxy\n // tools. Guard against the empty case: a version gate can\n // drop every configured def (e.g. `proxyTools: [\"Question\"]`\n // on an opencode build that lacks the `question` registry\n // entry), and spinning up an MCP server with zero tools is\n // wasteful and wrong shape.\n const combinedList = [\n ...(enrichedProxy ?? []),\n ...(proxyMcpTools ?? []),\n ]\n const combinedProxyTools: ProxyToolDef[] | null =\n combinedList.length > 0 ? combinedList : null\n\n if (!proxyServer && combinedProxyTools) {\n proxyServer = await self.ensureProxyServer(combinedProxyTools, sk)\n }\n\n // Whether the question proxy actually survived the version\n // gate (post-filter). Used to decide whether to inject the\n // QUESTION_PROXY_HINT — if the gate dropped the def, the\n // model must fall back to AskUserQuestion (the deny/markdown\n // path) and must NOT be told to call a proxy tool that does\n // not exist.\n const questionProxyActive =\n enrichedProxy?.some((t) => t.name === \"question\") ?? false\n\n // Compute disallowed flags from the POST-FILTER proxy list\n // (enrichedProxy), not the pre-filter one (resolvedProxy).\n // When the version gate drops `question` on an older opencode\n // build, AskUserQuestion must NOT be added to\n // --disallowedTools — otherwise the native tool is disabled\n // while the proxy replacement is absent, leaving the model\n // with no way to ask questions at all (neither proxy nor the\n // deny/markdown fallback path fires).\n const proxyDisallowed = enrichedProxy\n ? disallowedToolFlags(enrichedProxy)\n : []\n const extraDisallowed: string[] = []\n if (self.config.webSearch === \"disabled\") extraDisallowed.push(\"WebSearch\")\n const allDisallowed = [...proxyDisallowed, ...extraDisallowed]\n const mcp = self.effectiveMcpConfig(\n cwd,\n proxyServer?.configPath(),\n runtimeStatus!,\n excludeServers,\n )\n const systemPromptFile = activeProcess\n ? undefined\n : buildAppendedSystemPrompt(\n cwd,\n self.config.multiStepContinuation !== false,\n [\n ...extractSystemMessages(options.prompt),\n ...(taskProxyEnabled ? [SUBAGENT_DISPATCH_HINT] : []),\n ...(questionProxyActive ? [QUESTION_PROXY_HINT] : []),\n ],\n {\n compressEnabled:\n enrichedProxy?.some((t) => t.name === \"compress\") ?? false,\n compressionSummary: getCompressionSummary(sk),\n },\n )\n cliArgs = buildCliArgs({\n sessionKey: sk,\n skipPermissions,\n model: self.modelId,\n permissionMode: self.config.permissionMode,\n mcpConfig: mcp.paths,\n strictMcpConfig: self.config.strictMcpConfig,\n disallowedTools: allDisallowed.length > 0 ? allDisallowed : undefined,\n appendSystemPromptFile: systemPromptFile,\n ...self.thinkingCliOptions(),\n cliVersion,\n })\n spawnSystemPromptFile = systemPromptFile\n spawnProxyServer = proxyServer\n spawnMcpHash = mcp.bridgedHash\n }\n\n if (activeProcess && !compactionMode) {\n proc = activeProcess.proc\n lineEmitter = activeProcess.lineEmitter\n log.debug(\"reusing active process\", { sk })\n } else {\n const ap = spawnClaudeProcess(\n cliPath,\n cliArgs,\n cwd,\n sk,\n spawnProxyServer,\n spawnMcpHash,\n spawnSystemPromptFile,\n self.config.ignoreAnthropicApiKey,\n )\n proc = ap.proc\n lineEmitter = ap.lineEmitter\n activeProcess = ap\n }\n }\n\n controller.enqueue({ type: \"stream-start\", warnings })\n\n let currentTextId: string | null = null\n const textBlockIndices = new Set<number>()\n\n const startTextBlock = (): string => {\n if (currentTextId) {\n controller.enqueue({ type: \"text-end\", id: currentTextId })\n }\n const id = generateId()\n currentTextId = id\n controller.enqueue({ type: \"text-start\", id } as any)\n return id\n }\n\n const endTextBlock = (): void => {\n if (currentTextId) {\n controller.enqueue({ type: \"text-end\", id: currentTextId })\n currentTextId = null\n }\n }\n\n const reasoningIds = new Map<number, string>()\n const reasoningStarted = new Map<number, boolean>()\n let hadThinkingTextFromStream = false\n\n let turnCompleted = false\n let controllerClosed = false\n let pendingProxyUnsubscribe: (() => void) | null = null\n let resultFallbackTimer: ReturnType<typeof setTimeout> | null = null\n let pendingResultCompletion: (() => void) | null = null\n let hasReceivedContent = false\n let visibleTextSinceContinue = \"\"\n let lastVisibleTextSinceContinue = \"\"\n let hadReasoningSinceContinue = false\n let hadToolActivitySinceContinue = false\n let hadProxyActivitySinceContinue = false\n // v0.4.16: protocol-level stop signal captured from Claude CLI's\n // stream. Set by either the `message_delta` partial event or the\n // top-level `assistant` message, whichever arrives first.\n let lastStopReason: string | null = null\n const autoContinueState: AutoContinueState = {\n enabled: self.config.autoContinueIncompleteTurns,\n attempts: 0,\n startedAt: Date.now(),\n noProgressCount: 0,\n }\n\n const clearFallbackTimer = () => {\n if (resultFallbackTimer) {\n clearTimeout(resultFallbackTimer)\n resultFallbackTimer = null\n }\n }\n\n // Wire-inactivity watchdog. Resets on every line received from the\n // CLI; only fires if the CLI has emitted content and then gone\n // silent on stdout for `delayMs` without sending a `result`. The\n // previous design armed this on every text content_block_stop,\n // which killed legitimate mid-turn think pauses (most visibly\n // with sonnet between text-end and the next tool_use_start).\n const startResultFallback = (delayMs = 60_000) => {\n clearFallbackTimer()\n if (!hasReceivedContent || controllerClosed) return\n resultFallbackTimer = setTimeout(() => {\n if (controllerClosed) return\n log.warn(\"result fallback timer fired — closing stream without result event\", {\n delayMs,\n })\n closeHandler()\n }, delayMs)\n }\n\n // Start watchdog: complementary to the inactivity watchdog above.\n // That one only arms once content has arrived; this one covers the\n // gap the other explicitly skips — a reused process that produces\n // NO stdout at all after a fresh-turn envelope write. Seen after a\n // very long proxy-blocked tool call resumed successfully (the child\n // stays silent on stdout). On first fire we respawn the child with\n // --session-id to resume the conversation transparently; on a\n // second fire (respawn also silent) we end the turn cleanly so the\n // next opencode turn spawns fresh. Tunable via env for reproduces.\n const START_WATCHDOG_MS = (() => {\n const env = process.env.CLAUDE_CODE_START_WATCHDOG_MS\n const parsed = env ? Number.parseInt(env, 10) : NaN\n return Number.isFinite(parsed) && parsed > 0 ? parsed : 90_000\n })()\n let startWatchdog: ReturnType<typeof setTimeout> | null = null\n let respawnAttempted = false\n const clearStartWatchdog = () => {\n if (startWatchdog) {\n clearTimeout(startWatchdog)\n startWatchdog = null\n }\n }\n const onStartWatchdogFire = () => {\n startWatchdog = null\n if (controllerClosed || hasReceivedContent) return\n if (respawnAttempted) {\n log.error(\n \"claude process still silent after respawn; ending turn\",\n { sessionKey: sk },\n )\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({\n type: \"error\",\n error: new Error(\n \"Claude process produced no output after the envelope write (start watchdog timeout).\",\n ),\n })\n try {\n controller.close()\n } catch {}\n return\n }\n respawnAttempted = true\n log.warn(\n \"no stdout after envelope write; respawning claude process to resume conversation\",\n { sessionKey: sk, startWatchdogMs: START_WATCHDOG_MS },\n )\n lineEmitter.off(\"line\", lineHandler)\n lineEmitter.off(\"close\", closeHandler)\n proc.off(\"error\", procErrorHandler)\n const newAp = respawnActiveProcess(\n sk,\n cliPath,\n cliArgs,\n cwd,\n self.config.ignoreAnthropicApiKey,\n )\n if (!newAp) {\n log.error(\n \"no active process to respawn (start watchdog); ending turn\",\n { sessionKey: sk },\n )\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({\n type: \"error\",\n error: new Error(\n \"No active claude process to respawn after start watchdog timeout.\",\n ),\n })\n try {\n controller.close()\n } catch {}\n return\n }\n proc = newAp.proc\n lineEmitter = newAp.lineEmitter\n activeProcess = newAp\n lineEmitter.on(\"line\", lineHandler)\n lineEmitter.on(\"close\", closeHandler)\n proc.on(\"error\", procErrorHandler)\n try {\n proc.stdin?.write(userMsg + \"\\n\")\n log.debug(\"re-sent user message after respawn\", {\n textLength: userMsg.length,\n })\n } catch (err) {\n log.error(\"failed to re-send envelope after respawn\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n startWatchdog = setTimeout(\n onStartWatchdogFire,\n START_WATCHDOG_MS,\n )\n }\n const armStartWatchdog = () => {\n clearStartWatchdog()\n if (controllerClosed) return\n startWatchdog = setTimeout(onStartWatchdogFire, START_WATCHDOG_MS)\n }\n\n const toolCallMap = new Map<\n number,\n { id: string; name: string; inputJson: string; started: boolean }\n >()\n // Tool calls the plugin reported as providerExecuted:false — opencode\n // will run these itself and emit its own tool-result, so we must NOT\n // forward Claude CLI's tool_result for them (would short-circuit\n // opencode's execute).\n const skipResultForIds = new Set<string>()\n const toolCallsById = new Map<\n string,\n { id: string; name: string; input: unknown }\n >()\n\n let resultMeta: {\n sessionId?: string\n costUsd?: number\n durationMs?: number\n usage?: ClaudeStreamMessage[\"usage\"]\n } = {}\n\n // Batched drain so claude CLI's parallel tool_use blocks (e.g. two\n // bash calls in one assistant message) end up in a single\n // tool-calls finish event. Without this, the broker would reject\n // every overlapping call and claude would see spurious tool errors.\n const drainBuffer: PendingProxyCall[] = []\n let drainTimer: ReturnType<typeof setTimeout> | null = null\n const DRAIN_QUIET_MS = 100\n\n const finishWithToolCalls = (calls: PendingProxyCall[]) => {\n if (controllerClosed) return\n if (calls.length === 0) return\n for (const call of calls) {\n controller.enqueue({\n type: \"tool-input-start\",\n id: call.toolCallId,\n toolName: call.toolName,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: JSON.stringify(call.input),\n providerExecuted: false,\n } as any)\n skipResultForIds.add(call.toolCallId)\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"tool-calls\"),\n usage: toUsage(resultMeta.usage),\n providerMetadata: {\n \"claude-code\": resultMeta,\n },\n })\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n }\n\n const finishWithExitPlanQuestion = (\n call: ReturnType<typeof createExitPlanModeQuestionCall>,\n ) => {\n if (controllerClosed) return\n endTextBlock()\n controller.enqueue({\n type: \"tool-input-start\",\n id: call.toolCallId,\n toolName: call.toolName,\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: JSON.stringify(call.input),\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"tool-calls\"),\n usage: toUsage(resultMeta.usage),\n providerMetadata: {\n \"claude-code\": resultMeta,\n },\n })\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n }\n\n const drainNow = () => {\n if (drainTimer) {\n clearTimeout(drainTimer)\n drainTimer = null\n }\n if (drainBuffer.length === 0) return\n if (controllerClosed) return\n const batch = drainBuffer.splice(0, drainBuffer.length)\n log.info(\"draining pending proxy calls into stream finish\", {\n sessionKey: sk,\n count: batch.length,\n toolCallIds: batch.map((c) => c.toolCallId),\n })\n finishWithToolCalls(batch)\n }\n\n const settleResultBoundary = () => {\n drainTimer = null\n const completeResult = pendingResultCompletion\n pendingResultCompletion = null\n if (!completeResult || controllerClosed) return\n if (drainBuffer.length > 0) {\n drainNow()\n return\n }\n completeResult()\n }\n\n const scheduleResultBoundary = (\n completeResult: () => void,\n delayMs: number,\n ) => {\n pendingResultCompletion = completeResult\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(settleResultBoundary, delayMs)\n }\n\n const noteResultBoundaryCall = (): boolean => {\n if (!pendingResultCompletion) return false\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(settleResultBoundary, DRAIN_QUIET_MS)\n return true\n }\n\n const noteVisibleText = (text: string) => {\n visibleTextSinceContinue += text\n lastVisibleTextSinceContinue += text\n }\n\n const resetLastVisibleTextBlock = () => {\n lastVisibleTextSinceContinue = \"\"\n }\n\n const noteReasoning = () => {\n hadReasoningSinceContinue = true\n }\n\n const noteToolActivity = () => {\n hadToolActivitySinceContinue = true\n }\n\n const noteProxyActivity = () => {\n hadProxyActivitySinceContinue = true\n }\n\n const resetAutoContinueWindow = () => {\n visibleTextSinceContinue = \"\"\n lastVisibleTextSinceContinue = \"\"\n hadReasoningSinceContinue = false\n hadToolActivitySinceContinue = false\n hadProxyActivitySinceContinue = false\n lastStopReason = null\n }\n\n const completeResult = (msg: ClaudeStreamMessage) => {\n if (controllerClosed) return\n if (drainBuffer.length > 0) {\n drainNow()\n return\n }\n\n const pendingSiblings = getPendingProxyCalls(sk)\n if (pendingSiblings.length > 0) {\n log.info(\"leaving parallel proxy calls pending at result boundary\", {\n sessionKey: sk,\n count: pendingSiblings.length,\n })\n }\n\n const autoDecision = shouldAutoContinueIncompleteTurn(\n autoContinueState,\n {\n text: visibleTextSinceContinue,\n lastVisibleText: lastVisibleTextSinceContinue,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n isError: msg.is_error,\n stopReason: lastStopReason,\n },\n )\n if (autoDecision.continue) {\n const signature = continuationSignature({\n text: visibleTextSinceContinue,\n lastVisibleText: lastVisibleTextSinceContinue,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n isError: msg.is_error,\n })\n autoContinueState.noProgressCount =\n signature === autoContinueState.lastSignature\n ? autoContinueState.noProgressCount + 1\n : 0\n autoContinueState.lastSignature = signature\n autoContinueState.attempts++\n log.notice(\"auto-continuing incomplete claude result\", {\n sessionKey: sk,\n reason: autoDecision.reason,\n attempts: autoContinueState.attempts,\n textLength: visibleTextSinceContinue.length,\n lastTextLength: lastVisibleTextSinceContinue.length,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n })\n turnCompleted = false\n resetAutoContinueWindow()\n proc.stdin?.write(makeAutoContinueMessage() + \"\\n\")\n return\n }\n log.notice(\"auto-continuation stopped\", {\n sessionKey: sk,\n reason: autoDecision.reason,\n stopReason: lastStopReason,\n attempts: autoContinueState.attempts,\n textLength: visibleTextSinceContinue.length,\n lastTextLength: lastVisibleTextSinceContinue.length,\n hadReasoning: hadReasoningSinceContinue,\n hadToolActivity: hadToolActivitySinceContinue,\n hadProxyActivity: hadProxyActivitySinceContinue,\n })\n\n for (const [idx, reasoningId] of reasoningIds) {\n if (reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-end\",\n id: reasoningId,\n } as any)\n }\n }\n\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage(msg.usage),\n providerMetadata: {\n \"claude-code\": {\n ...resultMeta,\n ...(compactionMode\n ? { compactionModel: effectiveModelId }\n : {}),\n },\n ...(typeof msg.usage?.cache_creation_input_tokens === \"number\"\n ? {\n anthropic: {\n cacheCreationInputTokens:\n msg.usage.cache_creation_input_tokens,\n },\n }\n : {}),\n },\n })\n\n controllerClosed = true\n cleanupTurn()\n\n try {\n controller.close()\n } catch {}\n }\n\n // Set true once we observe a `stream_event` envelope. When on, the\n // top-level `assistant` message is a duplicate of what we already\n // streamed via content_block_* deltas — skip its content.\n let gotPartialEvents = false\n\n const lineHandler = (line: string) => {\n if (!line.trim()) return\n if (controllerClosed) return\n\n // Any line from the CLI counts as activity — reset the inactivity\n // watchdog so mid-turn pauses between blocks don't get killed.\n startResultFallback()\n // First stdout line means the child is alive and responding —\n // disarm the start watchdog (covers the \"no output at all\" gap).\n clearStartWatchdog()\n\n try {\n const outer: ClaudeStreamMessage = JSON.parse(line)\n\n // Unwrap stream_event envelope (--include-partial-messages).\n // Inner event uses the same content_block_* / message_* shape.\n const msg: ClaudeStreamMessage =\n outer.type === \"stream_event\" && outer.event\n ? { ...outer.event, session_id: outer.session_id }\n : outer\n\n if (outer.type === \"stream_event\") {\n gotPartialEvents = true\n }\n\n if (handleControlRequest(msg, proc)) {\n return\n }\n\n log.debug(\"stream message\", {\n type: msg.type,\n subtype: msg.subtype,\n })\n\n // Handle system init\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n log.info(\"session initialized\", {\n claudeSessionId: msg.session_id,\n })\n }\n }\n\n // content_block_start\n if (\n msg.type === \"content_block_start\" &&\n msg.content_block &&\n msg.index !== undefined\n ) {\n const block = msg.content_block\n const idx = msg.index\n\n if (block.type === \"thinking\") {\n noteReasoning()\n const reasoningId = generateId()\n reasoningIds.set(idx, reasoningId)\n }\n\n if (block.type === \"text\") {\n textBlockIndices.add(idx)\n // New text block — clear last-block buffer so final-answer\n // detection only considers this block's contents, not earlier\n // mid-task narration.\n resetLastVisibleTextBlock()\n if (block.text) {\n if (!currentTextId) startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: currentTextId!,\n delta: block.text,\n })\n noteVisibleText(block.text)\n hasReceivedContent = true\n }\n }\n\n if (block.type === \"tool_use\" && block.id && block.name) {\n noteToolActivity()\n const entry = {\n id: block.id,\n name: block.name,\n inputJson: \"\",\n started: false,\n }\n toolCallMap.set(idx, entry)\n\n if (\n block.name !== \"AskUserQuestion\" &&\n block.name !== \"ask_user_question\" &&\n block.name !== \"ExitPlanMode\" &&\n !block.name.startsWith(PROXY_TOOL_PREFIX)\n ) {\n const { name: mappedName, skip, executed } = mapTool(\n block.name,\n undefined,\n {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: block.id,\n },\n )\n if (!skip) {\n entry.started = true\n controller.enqueue({\n type: \"tool-input-start\",\n id: block.id,\n toolName: mappedName,\n providerExecuted: executed,\n } as any)\n log.info(\"tool started\", {\n name: block.name,\n mappedName,\n id: block.id,\n })\n }\n }\n }\n }\n\n // content_block_delta\n if (\n msg.type === \"content_block_delta\" &&\n msg.delta &&\n msg.index !== undefined\n ) {\n const delta = msg.delta\n const idx = msg.index\n\n if (delta.type === \"thinking_delta\" && delta.thinking) {\n noteReasoning()\n hadThinkingTextFromStream = true\n const reasoningId = reasoningIds.get(idx)\n if (reasoningId) {\n if (!reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-start\",\n id: reasoningId,\n } as any)\n reasoningStarted.set(idx, true)\n }\n controller.enqueue({\n type: \"reasoning-delta\",\n id: reasoningId,\n delta: delta.thinking,\n } as any)\n }\n }\n\n if (delta.type === \"text_delta\" && delta.text) {\n if (!currentTextId) startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: currentTextId!,\n delta: delta.text,\n })\n noteVisibleText(delta.text)\n hasReceivedContent = true\n }\n\n if (delta.type === \"input_json_delta\" && delta.partial_json) {\n const tc = toolCallMap.get(idx)\n if (tc) {\n tc.inputJson += delta.partial_json\n // Only forward deltas for tool calls whose tool-input-start\n // was actually emitted. Skipped tools (CLAUDE_INTERNAL_TOOLS,\n // TaskCreate/TaskUpdate, CLI-internal WebSearch, AskUserQuestion,\n // ExitPlanMode, proxy tools) never get a named start part, so\n // forwarding their deltas makes opencode's AI SDK bridge fall\n // back to a nameless pending part rendered as `⚙ unknown`.\n if (tc.started) {\n controller.enqueue({\n type: \"tool-input-delta\",\n id: tc.id,\n delta: delta.partial_json,\n } as any)\n }\n }\n }\n\n if (!KNOWN_DELTA_TYPES.has(delta.type)) {\n log.debug(\"unrecognized content_block_delta type\", {\n type: delta.type,\n idx,\n keys: Object.keys(delta),\n })\n }\n }\n\n // content_block_stop\n if (\n msg.type === \"content_block_stop\" &&\n msg.index !== undefined\n ) {\n const idx = msg.index\n\n const reasoningId = reasoningIds.get(idx)\n if (reasoningId && reasoningStarted.get(idx)) {\n controller.enqueue({\n type: \"reasoning-end\",\n id: reasoningId,\n } as any)\n reasoningStarted.delete(idx)\n }\n\n if (textBlockIndices.has(idx)) {\n endTextBlock()\n textBlockIndices.delete(idx)\n }\n\n const tc = toolCallMap.get(idx)\n if (tc) {\n let parsedInput: any = {}\n try {\n parsedInput = JSON.parse(tc.inputJson || \"{}\")\n } catch {}\n\n if (isAskUserQuestionTool(tc.name)) {\n // Latch: the model handed control to the operator. Block any\n // auto-continue nudge for the rest of the turn so it can't\n // proceed on its own before the operator replies.\n autoContinueState.sawAskUserQuestion = true\n const askId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: askId,\n delta: formatAskUserQuestion(parsedInput),\n })\n endTextBlock()\n } else if (tc.name === \"ExitPlanMode\") {\n const plan = (parsedInput?.plan as string) || \"\"\n\n if (planModeQuestionActive) {\n // Approval bridge: render the plan, then hand the\n // yes/no back to opencode's own `question` tool and end\n // the turn on \"tool-calls\" so the outer loop runs it.\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n tc.id,\n plan,\n )\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: questionCall.text,\n })\n finishWithExitPlanQuestion(questionCall)\n return\n }\n\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`,\n })\n endTextBlock()\n } else if (\n isWebSearchTool(tc.name) &&\n isWebSearchHandledByCli(self.config.webSearch)\n ) {\n // Claude CLI runs WebSearch internally. Forwarding the\n // \"WebSearch\" tool-call part would render an invalid tool\n // row in opencode (no registry entry), so show the query\n // as a text line instead. The result stays CLI-internal.\n const query =\n typeof parsedInput?.query === \"string\"\n ? parsedInput.query\n : JSON.stringify(parsedInput)\n const searchId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: searchId,\n delta: `\\n> **Web search:** ${query}\\n`,\n })\n endTextBlock()\n } else if (tc.name.startsWith(PROXY_TOOL_PREFIX)) {\n noteProxyActivity()\n log.debug(\"ignoring proxy tool_use block; broker handles it\", {\n name: tc.name,\n id: tc.id,\n })\n } else {\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(tc.name, parsedInput, {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: tc.id,\n })\n\n if (!skip) {\n toolCallsById.set(tc.id, {\n id: tc.id,\n name: tc.name,\n input: parsedInput,\n })\n if (!executed) skipResultForIds.add(tc.id)\n\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n log.info(\"tool call complete\", {\n name: tc.name,\n mappedName,\n id: tc.id,\n executed,\n })\n }\n }\n }\n\n // Capture protocol-level stop_reason from the streaming\n // `message_delta` event (sent right before the final\n // `message_stop`). Any non-empty value is the source-of-truth\n // for why the turn ended — used to bypass the keyword heuristic.\n if (\n gotPartialEvents &&\n msg.type === \"message_delta\" &&\n typeof (msg as any).delta?.stop_reason === \"string\"\n ) {\n lastStopReason = (msg as any).delta.stop_reason\n }\n\n // assistant message (complete, not streaming).\n // When --include-partial-messages is on, this is a duplicate of\n // what we already streamed via content_block_* events. Skip it\n // for content, but still capture stop_reason from it for the\n // non-partial path.\n if (\n msg.type === \"assistant\" &&\n msg.message &&\n typeof (msg.message as any).stop_reason === \"string\"\n ) {\n lastStopReason = (msg.message as any).stop_reason\n }\n // Fallback: extract thinking from the complete assistant\n // message. opus-4-7's CLI strips thinking_delta from stream\n // events but may include thinking in the final message.\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n gotPartialEvents\n ) {\n const thinkingBlocks = (msg.message.content as any[]).filter(\n (b) => b.type === \"thinking\",\n )\n if (thinkingBlocks.length > 0) {\n log.info(\"assistant message thinking blocks\", {\n count: thinkingBlocks.length,\n hasText: thinkingBlocks.some(\n (b) => typeof b.thinking === \"string\" && b.thinking.length > 0,\n ),\n hadStreamThinking: hadThinkingTextFromStream,\n })\n if (!hadThinkingTextFromStream) {\n for (const block of thinkingBlocks) {\n if (block.thinking && block.thinking.length > 0) {\n noteReasoning()\n hadThinkingTextFromStream = true\n const thinkingId = generateId()\n controller.enqueue({\n type: \"reasoning-start\",\n id: thinkingId,\n } as any)\n controller.enqueue({\n type: \"reasoning-delta\",\n id: thinkingId,\n delta: block.thinking,\n } as any)\n controller.enqueue({\n type: \"reasoning-end\",\n id: thinkingId,\n } as any)\n }\n }\n }\n }\n }\n if (\n msg.type === \"assistant\" &&\n msg.message?.content &&\n !gotPartialEvents\n ) {\n const hasText = msg.message.content.some(\n (b: any) => b.type === \"text\" && b.text,\n )\n const hasToolUse = msg.message.content.some(\n (b: any) => b.type === \"tool_use\",\n )\n\n if (hasText) {\n hasReceivedContent = true\n }\n\n if (hasText && !hasToolUse) {\n startResultFallback()\n }\n if (hasToolUse) {\n clearFallbackTimer()\n }\n\n for (const block of msg.message.content) {\n if (block.type === \"text\" && block.text) {\n // New text block — keep only this block's text in the\n // last-block buffer for final-answer detection.\n resetLastVisibleTextBlock()\n const blockId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: blockId,\n delta: block.text,\n })\n endTextBlock()\n noteVisibleText(block.text)\n hasReceivedContent = true\n }\n\n if (block.type === \"thinking\" && block.thinking) {\n noteReasoning()\n const thinkingId = generateId()\n controller.enqueue({\n type: \"reasoning-start\",\n id: thinkingId,\n } as any)\n controller.enqueue({\n type: \"reasoning-delta\",\n id: thinkingId,\n delta: block.thinking,\n } as any)\n controller.enqueue({\n type: \"reasoning-end\",\n id: thinkingId,\n } as any)\n }\n\n if (block.type === \"tool_use\" && block.id && block.name) {\n noteToolActivity()\n const parsedInput = (block.input ?? {}) as Record<\n string,\n unknown\n >\n\n if (isAskUserQuestionTool(block.name)) {\n const askId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: askId,\n delta: formatAskUserQuestion(parsedInput),\n })\n endTextBlock()\n } else if (block.name === \"ExitPlanMode\") {\n const plan = (parsedInput?.plan as string) || \"\"\n\n if (planModeQuestionActive) {\n const questionCall = createExitPlanModeQuestionCall(\n sk,\n block.id,\n plan,\n )\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: questionCall.text,\n })\n finishWithExitPlanQuestion(questionCall)\n return\n }\n\n const planId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: planId,\n delta: `\\n\\n${plan}\\n\\n---\\n**Do you want to proceed with this plan?** (yes/no)\\n`,\n })\n endTextBlock()\n } else if (\n isWebSearchTool(block.name) &&\n isWebSearchHandledByCli(self.config.webSearch)\n ) {\n // CLI-internal WebSearch: render the query as text and\n // drop the call/result parts (no opencode registry entry\n // for \"WebSearch\" — would render as an invalid tool row).\n toolCallsById.delete(block.id)\n const query =\n typeof parsedInput?.query === \"string\"\n ? parsedInput.query\n : JSON.stringify(parsedInput)\n const searchId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: searchId,\n delta: `\\n> **Web search:** ${query}\\n`,\n })\n endTextBlock()\n } else if (block.name.startsWith(PROXY_TOOL_PREFIX)) {\n noteProxyActivity()\n log.debug(\"ignoring proxy tool_use from assistant message\", {\n name: block.name,\n id: block.id,\n })\n } else {\n const {\n name: mappedName,\n input: mappedInput,\n executed,\n skip,\n } = mapTool(block.name, parsedInput, {\n webSearch: self.config.webSearch,\n sessionId: getClaudeSessionId(sk),\n toolUseId: block.id,\n })\n\n if (!skip) {\n toolCallsById.set(block.id, {\n id: block.id,\n name: block.name,\n input: parsedInput,\n })\n if (!executed) skipResultForIds.add(block.id)\n controller.enqueue({\n type: \"tool-input-start\",\n id: block.id,\n toolName: mappedName,\n providerExecuted: executed,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: block.id,\n toolName: mappedName,\n input: JSON.stringify(mappedInput),\n providerExecuted: executed,\n } as any)\n }\n log.info(\"tool_use from assistant message\", {\n name: block.name,\n mappedName,\n id: block.id,\n executed,\n })\n }\n }\n\n if (block.type === \"tool_result\") {\n log.debug(\"tool_result\", {\n toolUseId: block.tool_use_id,\n })\n }\n }\n }\n\n // user message (tool results from Claude CLI)\n if (msg.type === \"user\" && msg.message?.content) {\n for (const block of msg.message.content) {\n if (block.type === \"tool_result\" && block.tool_use_id) {\n if (skipResultForIds.has(block.tool_use_id)) {\n log.debug(\"skipping tool-result (opencode runs it)\", {\n toolUseId: block.tool_use_id,\n })\n continue\n }\n\n let resultText = \"\"\n if (typeof block.content === \"string\") {\n resultText = block.content\n } else if (Array.isArray(block.content)) {\n resultText = block.content\n .filter(\n (\n c,\n ): c is { type: string; text: string } =>\n c.type === \"text\" &&\n typeof c.text === \"string\",\n )\n .map((c) => c.text)\n .join(\"\\n\")\n }\n\n // Ledger hook: commit pending TaskCreate to opencode's todo\n // panel via a synthetic todowrite emission. Pass-through —\n // returns null for non-TaskCreate ids, so cheap and silent.\n const claudeSessionId = getClaudeSessionId(sk)\n if (claudeSessionId) {\n const list = applyTaskCreateToolResult(\n claudeSessionId,\n block.tool_use_id,\n resultText,\n )\n if (list) {\n const synthId = `todowrite_${block.tool_use_id}`\n controller.enqueue({\n type: \"tool-input-start\",\n id: synthId,\n toolName: \"todowrite\",\n providerExecuted: false,\n } as any)\n controller.enqueue({\n type: \"tool-call\",\n toolCallId: synthId,\n toolName: \"todowrite\",\n input: JSON.stringify({\n todos: list.map((t) => ({\n id: t.id,\n content: t.content,\n status: t.status,\n priority: \"medium\",\n })),\n }),\n providerExecuted: false,\n } as any)\n noteToolActivity()\n }\n }\n\n const toolCall = toolCallsById.get(block.tool_use_id)\n if (toolCall) {\n controller.enqueue({\n type: \"tool-result\",\n toolCallId: block.tool_use_id,\n toolName: toolCall.name,\n result: {\n output: resultText,\n title: toolCall.name,\n metadata: {},\n },\n providerExecuted: true,\n } as any)\n noteToolActivity()\n log.info(\"tool result emitted\", {\n toolUseId: block.tool_use_id,\n name: toolCall.name,\n })\n toolCallsById.delete(block.tool_use_id)\n }\n }\n }\n }\n\n // result - end of conversation turn\n if (msg.type === \"result\") {\n clearFallbackTimer()\n\n if (msg.session_id) {\n setClaudeSessionId(sk, msg.session_id)\n }\n\n // Some CLI failures only include user-readable text in\n // `result.result` (no prior assistant text blocks). Emit it so\n // opencode users don't see a blank turn.\n if (\n !currentTextId &&\n msg.is_error &&\n typeof msg.result === \"string\" &&\n msg.result.trim().length > 0\n ) {\n const errId = startTextBlock()\n controller.enqueue({\n type: \"text-delta\",\n id: errId,\n delta: msg.result,\n })\n }\n\n resultMeta = {\n sessionId: msg.session_id,\n costUsd: msg.total_cost_usd,\n durationMs: msg.duration_ms,\n usage: msg.usage,\n }\n\n log.info(\"conversation result\", {\n sessionId: msg.session_id,\n durationMs: msg.duration_ms,\n numTurns: msg.num_turns,\n isError: msg.is_error,\n })\n\n turnCompleted = true\n\n endTextBlock()\n\n const shouldDeferResult =\n !msg.is_error &&\n !autoContinueState.aborted &&\n !autoContinueState.sawAskUserQuestion\n\n if (drainBuffer.length > 0 && shouldDeferResult) {\n log.info(\n \"waiting for parallel proxy calls at turn-result boundary\",\n {\n sessionKey: sk,\n count: drainBuffer.length,\n },\n )\n scheduleResultBoundary(\n () => completeResult(msg),\n DRAIN_QUIET_MS,\n )\n return\n }\n\n if (\n drainBuffer.length === 0 &&\n hadProxyActivitySinceContinue &&\n shouldDeferResult\n ) {\n log.info(\n \"waiting for delayed proxy call at turn-result boundary\",\n {\n sessionKey: sk,\n graceMs: PROXY_RESULT_BOUNDARY_GRACE_MS,\n },\n )\n scheduleResultBoundary(\n () => completeResult(msg),\n PROXY_RESULT_BOUNDARY_GRACE_MS,\n )\n return\n }\n\n completeResult(msg)\n }\n } catch (e) {\n log.debug(\"failed to parse line\", {\n error:\n e instanceof Error ? e.message : String(e),\n })\n }\n }\n\n const closeHandler = () => {\n log.debug(\"readline closed\")\n if (controllerClosed) return\n // Claude CLI's stdio is gone. The proxy-mcp HTTP requests that\n // backed any pending tool calls have no one to answer them now —\n // reject so the handlers return errors rather than hang.\n if (drainBuffer.length > 0 || getPendingProxyCalls(sk).length > 0) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n \"Claude CLI subprocess closed before pending tool calls were resolved\",\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n endTextBlock()\n controller.enqueue({\n type: \"finish\",\n finishReason: toFinishReason(\"stop\"),\n usage: toUsage(),\n providerMetadata: {\n \"claude-code\": {\n ...resultMeta,\n ...(compactionMode\n ? { compactionModel: effectiveModelId }\n : {}),\n },\n },\n })\n try {\n controller.close()\n } catch {}\n }\n\n // Centralised per-turn teardown. Every exit path funnels through here\n // so we don't accumulate listeners across turns on a reused process.\n let cleanedUp = false\n const cleanupTurn = () => {\n if (cleanedUp) return\n cleanedUp = true\n clearFallbackTimer()\n pendingResultCompletion = null\n clearStartWatchdog()\n if (drainTimer) {\n clearTimeout(drainTimer)\n drainTimer = null\n }\n lineEmitter.off(\"line\", lineHandler)\n lineEmitter.off(\"close\", closeHandler)\n pendingProxyUnsubscribe?.()\n pendingProxyUnsubscribe = null\n proc.off(\"error\", procErrorHandler)\n }\n\n const procErrorHandler = (err: Error) => {\n log.error(\"process error\", { error: err.message })\n deleteActiveProcess(sk)\n deleteClaudeSessionId(sk)\n if (controllerClosed) return\n // Subprocess failure invalidates every pending HTTP-bound tool\n // call for this session. Reject them so proxy-mcp returns errors\n // to Claude rather than letting the sockets stall.\n if (drainBuffer.length > 0 || getPendingProxyCalls(sk).length > 0) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n `Claude CLI subprocess error: ${err.message}`,\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n controller.enqueue({ type: \"error\", error: err })\n try {\n controller.close()\n } catch {}\n }\n\n lineEmitter.on(\"line\", lineHandler)\n lineEmitter.on(\"close\", closeHandler)\n\n pendingProxyUnsubscribe = onPendingProxyCall(sk, (call) => {\n if (controllerClosed) {\n // Stream already closed (we already drained). Late arrival —\n // reject immediately so the proxy-mcp HTTP request returns\n // instead of hanging until its 10-min timeout.\n log.warn(\n \"pending proxy call arrived after stream close; rejecting\",\n {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n },\n )\n rejectPendingProxyCallById(\n call.toolCallId,\n new Error(\n `Pending proxy call '${call.toolName}' arrived after the stream was already closed`,\n ),\n )\n return\n }\n log.info(\"received pending proxy call for session\", {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n })\n noteProxyActivity()\n noteToolActivity()\n drainBuffer.push(call)\n if (noteResultBoundaryCall()) return\n if (drainTimer) clearTimeout(drainTimer)\n drainTimer = setTimeout(drainNow, DRAIN_QUIET_MS)\n })\n\n proc.on(\"error\", procErrorHandler)\n\n // On abort, keep process alive for next message\n if (options.abortSignal) {\n options.abortSignal.addEventListener(\"abort\", () => {\n autoContinueState.aborted = true\n if (turnCompleted || controllerClosed) return\n\n if (!hasReceivedContent) {\n log.info(\n \"abort signal received before content, closing stream immediately\",\n { cwd },\n )\n if (\n drainBuffer.length > 0 ||\n getPendingProxyCalls(sk).length > 0\n ) {\n rejectAllPendingProxyCallsForSession(\n sk,\n new Error(\n \"Provider stream was aborted before pending proxy calls were emitted\",\n ),\n )\n drainBuffer.length = 0\n }\n controllerClosed = true\n cleanupTurn()\n try {\n controller.close()\n } catch {}\n return\n }\n\n log.info(\n \"abort signal received mid-turn, starting grace period\",\n { cwd },\n )\n // Abort grace period — short, since the user already asked to stop.\n startResultFallback(5_000)\n })\n }\n\n if (hasMatchedPendingResults) {\n // Tool-result turn: the prompt carries opencode's results for the\n // proxy tool calls we drained on the previous turn. Resolve each\n // matched call (claude CLI's HTTP handlers wake up and continue).\n // Parallel tools may complete in separate opencode turns. Keep\n // unmatched siblings pending until their own result, an explicit\n // abort/new user turn, or the proxy deadline.\n for (const { call, result } of previousPendingProxyMatches) {\n if (result) {\n log.info(\"resolving pending proxy call from tool result prompt\", {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n })\n resolvePendingProxyCallById(call.toolCallId, result)\n } else {\n log.info(\n \"leaving unmatched parallel proxy call pending\",\n {\n sessionKey: sk,\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n },\n )\n }\n }\n return\n }\n\n // No pending calls had matching tool-results. If any pending calls\n // are still hanging around from a prior turn, reject them so the\n // HTTP handlers in proxy-mcp don't sit blocked forever while we\n // proceed with a brand new user message.\n if (previousPendingProxyCalls.length > 0) {\n for (const call of previousPendingProxyCalls) {\n rejectPendingProxyCallById(\n call.toolCallId,\n new Error(\n `Pending proxy call '${call.toolName}' (${call.toolCallId}) was orphaned by a new user turn; rejecting`,\n ),\n )\n }\n }\n\n // Send the user message for a fresh turn.\n proc.stdin?.write(userMsg + \"\\n\")\n log.debug(\"sent user message\", { textLength: userMsg.length })\n // Arm the start watchdog so a reused child that goes silent after\n // the envelope write (seen after a long proxy-blocked tool call)\n // is respawned with --session-id instead of hanging the turn.\n armStartWatchdog()\n }\n\n void setup().catch((err) => {\n log.error(\"failed to set up doStream\", {\n error: err instanceof Error ? err.message : String(err),\n })\n controller.enqueue({\n type: \"error\",\n error: err instanceof Error ? err : new Error(String(err)),\n })\n try {\n controller.close()\n } catch {}\n })\n },\n cancel() {\n // Consumer cancelled the stream\n },\n })\n\n return {\n stream,\n request: { body: { text: userMsg } },\n response: { headers: {} },\n }\n }\n}\n","import { appendFileSync, mkdirSync, renameSync, statSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, join } from \"node:path\"\n\nexport type LogLevel = \"debug\" | \"info\" | \"notice\" | \"warn\" | \"error\"\nexport type LogMode = \"silent\" | \"debug\"\n\nexport interface LoggerConfig {\n file: boolean\n dir: string | null\n mode: LogMode\n level: LogLevel\n}\n\nconst LEVEL_RANK: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n notice: 2,\n warn: 3,\n error: 4,\n}\n\nconst MAX_LOG_BYTES = 5 * 1024 * 1024 // 5 MB\nconst DEFAULT_DIR = join(homedir(), \".local\", \"share\", \"opencode-claude-code\")\n\nconst DEFAULT_CONFIG: LoggerConfig = {\n file: false,\n dir: null,\n mode: \"silent\",\n level: \"info\",\n}\n\nfunction parseBoolEnv(v: string | undefined): boolean | undefined {\n if (v == null) return undefined\n const s = v.toLowerCase().trim()\n if (s === \"\") return undefined\n if (s === \"0\" || s === \"false\" || s === \"no\" || s === \"off\") return false\n return true\n}\n\nfunction parseLevelEnv(v: string | undefined): LogLevel | undefined {\n if (v == null) return undefined\n const s = v.toLowerCase().trim()\n if (s === \"\") return undefined\n if (s === \"debug\" || s === \"info\" || s === \"notice\" || s === \"warn\" || s === \"error\") {\n return s\n }\n return undefined\n}\n\nfunction parseModeFromDebugEnv(v: string | undefined): LogMode | undefined {\n if (v == null || v === \"\") return undefined\n return v.includes(\"opencode-claude-code\") ? \"debug\" : undefined\n}\n\nfunction withEnvOverrides(base: LoggerConfig): LoggerConfig {\n const result: LoggerConfig = { ...base }\n const envFile = parseBoolEnv(process.env.OPENCODE_CLAUDE_CODE_LOG_FILE)\n if (envFile !== undefined) result.file = envFile\n const envDir = process.env.OPENCODE_CLAUDE_CODE_LOG_DIR\n if (envDir !== undefined && envDir !== \"\") result.dir = envDir\n const envMode = parseModeFromDebugEnv(process.env.DEBUG)\n if (envMode !== undefined) result.mode = envMode\n const envLevel = parseLevelEnv(process.env.OPENCODE_CLAUDE_CODE_LOG_LEVEL)\n if (envLevel !== undefined) result.level = envLevel\n return result\n}\n\nlet activeConfig: LoggerConfig = withEnvOverrides(DEFAULT_CONFIG)\nlet fileLoggingDisabled = false\n\n/**\n * Configure the logger from plugin settings. Env vars override the supplied\n * config when explicitly set, so a developer can flip behavior for a single\n * process without editing opencode.jsonc.\n *\n * `OPENCODE_CLAUDE_CODE_LOG_FILE` → `file` (1/true/on/yes vs 0/false/no/off)\n * `OPENCODE_CLAUDE_CODE_LOG_DIR` → `dir`\n * `DEBUG=opencode-claude-code` → `mode: \"debug\"`\n * `OPENCODE_CLAUDE_CODE_LOG_LEVEL` → `level` (debug | info | notice | warn | error)\n */\nexport function configureLogger(input: Partial<LoggerConfig>): void {\n const merged: LoggerConfig = { ...DEFAULT_CONFIG, ...input }\n activeConfig = withEnvOverrides(merged)\n fileLoggingDisabled = false\n}\n\nexport function getLoggerConfig(): LoggerConfig {\n return { ...activeConfig }\n}\n\n/** Test-only helper. Resets to defaults+env so tests are deterministic. */\nexport function _resetLoggerForTests(): void {\n activeConfig = withEnvOverrides(DEFAULT_CONFIG)\n fileLoggingDisabled = false\n}\n\nfunction resolvedLogFile(): string {\n return join(activeConfig.dir ?? DEFAULT_DIR, \"plugin.log\")\n}\n\nfunction rotateIfNeeded(logFile: string): void {\n try {\n const stat = statSync(logFile)\n if (stat.size > MAX_LOG_BYTES) {\n renameSync(logFile, `${logFile}.1`)\n }\n } catch {\n // file does not exist yet — nothing to rotate\n }\n}\n\nfunction writeToFile(line: string): void {\n if (!activeConfig.file) return\n if (fileLoggingDisabled) return\n try {\n const logFile = resolvedLogFile()\n mkdirSync(dirname(logFile), { recursive: true })\n rotateIfNeeded(logFile)\n appendFileSync(logFile, line + \"\\n\", \"utf8\")\n } catch {\n // Disable on first failure to avoid spamming errors on a read-only FS.\n fileLoggingDisabled = true\n }\n}\n\nfunction fmt(level: string, msg: string, data?: Record<string, unknown>): string {\n const ts = new Date().toISOString()\n const base = `[${ts}] [opencode-claude-code] ${level}: ${msg}`\n if (data && Object.keys(data).length > 0) {\n return `${base} ${JSON.stringify(data)}`\n }\n return base\n}\n\nfunction shouldEmit(level: LogLevel): boolean {\n return LEVEL_RANK[level] >= LEVEL_RANK[activeConfig.level]\n}\n\nfunction shouldTui(level: LogLevel): boolean {\n // warn/error are alwaysStderr: a developer who passes the level threshold\n // should still see real problems in the TUI regardless of mode. Below-\n // threshold entries are filtered earlier by shouldEmit().\n if (level === \"warn\" || level === \"error\") return true\n return activeConfig.mode === \"debug\"\n}\n\nfunction emit(level: LogLevel, msg: string, data?: Record<string, unknown>): void {\n if (!shouldEmit(level)) return\n const line = fmt(level.toUpperCase(), msg, data)\n if (shouldTui(level)) {\n console.error(line)\n }\n writeToFile(line)\n}\n\nexport const log = {\n debug(msg: string, data?: Record<string, unknown>) {\n emit(\"debug\", msg, data)\n },\n info(msg: string, data?: Record<string, unknown>) {\n emit(\"info\", msg, data)\n },\n notice(msg: string, data?: Record<string, unknown>) {\n emit(\"notice\", msg, data)\n },\n warn(msg: string, data?: Record<string, unknown>) {\n emit(\"warn\", msg, data)\n },\n error(msg: string, data?: Record<string, unknown>) {\n emit(\"error\", msg, data)\n },\n}\n","import { log } from \"./logger.js\"\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\"\n\nexport interface TodoEntry {\n id: string\n content: string\n status: TodoStatus\n}\n\ninterface PendingCreate {\n subject: string\n createdAt: number\n}\n\ninterface SessionLedger {\n todos: Map<string, TodoEntry>\n pendingCreates: Map<string, PendingCreate>\n}\n\nconst ledgers = new Map<string, SessionLedger>()\n\nconst PENDING_CREATE_TTL_MS = 60_000\nconst TASK_CREATED_PATTERN = /Task\\s*#?\\s*(\\d+)\\s+created/i\nconst VALID_STATUSES: ReadonlySet<TodoStatus> = new Set([\"pending\", \"in_progress\", \"completed\"])\n\nfunction getOrCreate(sessionId: string): SessionLedger {\n let ledger = ledgers.get(sessionId)\n if (!ledger) {\n ledger = { todos: new Map(), pendingCreates: new Map() }\n ledgers.set(sessionId, ledger)\n }\n return ledger\n}\n\nfunction prunePending(ledger: SessionLedger): void {\n const cutoff = Date.now() - PENDING_CREATE_TTL_MS\n for (const [id, pending] of ledger.pendingCreates) {\n if (pending.createdAt < cutoff) ledger.pendingCreates.delete(id)\n }\n}\n\nfunction materialize(ledger: SessionLedger): TodoEntry[] {\n return Array.from(ledger.todos.values())\n}\n\nfunction resolveSubject(input: { subject?: unknown; description?: unknown } | undefined): string {\n const subject = typeof input?.subject === \"string\" ? input.subject.trim() : \"\"\n if (subject) return subject\n const description = typeof input?.description === \"string\" ? input.description.trim() : \"\"\n if (description) return description\n return \"(no subject)\"\n}\n\nexport function applyTaskCreateToolUse(\n sessionId: string,\n toolUseId: string,\n input: { subject?: unknown; description?: unknown } | undefined,\n): void {\n if (!sessionId || !toolUseId) return\n const ledger = getOrCreate(sessionId)\n prunePending(ledger)\n ledger.pendingCreates.set(toolUseId, {\n subject: resolveSubject(input),\n createdAt: Date.now(),\n })\n}\n\nexport function applyTaskCreateToolResult(\n sessionId: string,\n toolUseId: string,\n resultText: string,\n): TodoEntry[] | null {\n if (!sessionId || !toolUseId) return null\n const ledger = ledgers.get(sessionId)\n if (!ledger) return null\n const pending = ledger.pendingCreates.get(toolUseId)\n if (!pending) return null\n ledger.pendingCreates.delete(toolUseId)\n const match = typeof resultText === \"string\" ? resultText.match(TASK_CREATED_PATTERN) : null\n if (!match) {\n log.debug(\"TaskCreate result did not match expected format\", { sessionId, toolUseId, resultText })\n return null\n }\n const claudeId = match[1]\n if (ledger.todos.has(claudeId)) {\n log.debug(\"TaskCreate result for already-known claude id; overwriting\", { sessionId, claudeId })\n }\n ledger.todos.set(claudeId, { id: claudeId, content: pending.subject, status: \"pending\" })\n return materialize(ledger)\n}\n\nexport function applyTaskUpdate(\n sessionId: string,\n input: { taskId?: unknown; subject?: unknown; status?: unknown } | undefined,\n): TodoEntry[] | null {\n if (!sessionId) return null\n const taskId = typeof input?.taskId === \"string\" ? input.taskId : null\n if (!taskId) return null\n const ledger = ledgers.get(sessionId)\n if (!ledger) return null\n const entry = ledger.todos.get(taskId)\n if (!entry) {\n log.debug(\"TaskUpdate for unknown task id\", { sessionId, taskId })\n return null\n }\n if (input?.status === \"deleted\") {\n ledger.todos.delete(taskId)\n return materialize(ledger)\n }\n if (typeof input?.status === \"string\" && VALID_STATUSES.has(input.status as TodoStatus)) {\n entry.status = input.status as TodoStatus\n }\n if (typeof input?.subject === \"string\" && input.subject.trim().length > 0) {\n entry.content = input.subject.trim()\n }\n return materialize(ledger)\n}\n\nexport function clearLedger(sessionId: string): void {\n if (!sessionId) return\n ledgers.delete(sessionId)\n}\n\nexport function getLedger(sessionId: string): TodoEntry[] {\n const ledger = ledgers.get(sessionId)\n if (!ledger) return []\n return materialize(ledger)\n}\n\nexport function _resetAllLedgersForTests(): void {\n ledgers.clear()\n}\n","import { log } from \"./logger.js\"\nimport { applyTaskCreateToolUse, applyTaskUpdate, type TodoEntry } from \"./todo-ledger.js\"\nimport type { WebSearchRouting } from \"./types.js\"\n\nexport interface MapToolOptions {\n webSearch?: WebSearchRouting\n sessionId?: string\n toolUseId?: string\n}\n\n/** Claude CLI's built-in web search tool (name varies by CLI version). */\nexport function isWebSearchTool(name: string): boolean {\n return name === \"WebSearch\" || name === \"web_search\"\n}\n\n/**\n * True when WebSearch runs inside Claude CLI (default) rather than being\n * forwarded to an opencode tool. In that case the tool-call part must not\n * reach opencode — \"WebSearch\" has no registry entry there and renders as\n * an invalid tool row. Callers show the query as a text line instead.\n */\nexport function isWebSearchHandledByCli(route?: WebSearchRouting): boolean {\n return !route || route === \"claude\" || route === \"disabled\"\n}\n\n/**\n * Map Claude CLI tool input (snake_case) to OpenCode tool input (camelCase)\n */\nfunction mapToolInput(name: string, input: any): any {\n if (!input) return input\n\n switch (name) {\n case \"Write\":\n return {\n filePath: input.file_path ?? input.filePath,\n content: input.content,\n }\n case \"Edit\":\n return {\n filePath: input.file_path ?? input.filePath,\n oldString: input.old_string ?? input.oldString,\n newString: input.new_string ?? input.newString,\n replaceAll: input.replace_all ?? input.replaceAll,\n }\n case \"Read\":\n return {\n filePath: input.file_path ?? input.filePath,\n offset: input.offset,\n limit: input.limit,\n }\n case \"Bash\":\n return {\n command: input.command,\n description:\n input.description ||\n `Execute: ${String(input.command || \"\").slice(0, 50)}${String(input.command || \"\").length > 50 ? \"...\" : \"\"}`,\n timeout: input.timeout,\n }\n case \"NotebookEdit\":\n return {\n notebookPath: input.notebook_path ?? input.notebookPath,\n cellNumber: input.cell_number ?? input.cellNumber,\n newSource: input.new_source ?? input.newSource,\n cellType: input.cell_type ?? input.cellType,\n editMode: input.edit_mode ?? input.editMode,\n }\n case \"Glob\":\n return {\n pattern: input.pattern,\n path: input.path,\n }\n case \"Grep\":\n return {\n pattern: input.pattern,\n path: input.path,\n include: input.include,\n }\n case \"TodoWrite\":\n if (Array.isArray(input.todos)) {\n const mappedTodos = input.todos.map((todo: any, index: number) => ({\n content: todo.content,\n status: todo.status || \"pending\",\n priority: todo.priority || \"medium\",\n id: todo.id || `todo_${Date.now()}_${index}`,\n }))\n return { todos: mappedTodos }\n }\n return input\n default:\n return input\n }\n}\n\n// Tools that Claude CLI executes internally but we report to opencode for UI display\nconst OPENCODE_HANDLED_TOOLS = new Set([\n \"Edit\",\n \"Write\",\n \"Bash\",\n \"NotebookEdit\",\n \"Read\",\n \"Glob\",\n \"Grep\",\n])\n\n// Claude CLI internal tools that should not be forwarded to opencode.\n// These are part of Claude Code's own system and have no opencode equivalent.\n// Tools the Claude CLI emits for its own internal bookkeeping (sub-agents,\n// task tracking, search). opencode has no matching tool registry entry, so\n// forwarding them surfaces as `⚙ invalid` rows in the UI. Skip them.\n// TaskOutput is intentionally NOT here — it has an explicit bash-echo mapping\n// below so the result stays visible.\nconst CLAUDE_INTERNAL_TOOLS = new Set([\n \"ToolSearch\",\n \"Agent\",\n \"AskFollowupQuestion\",\n \"TaskList\",\n \"TaskGet\",\n \"TaskStop\",\n])\n\nfunction emitTodoWrite(todos: TodoEntry[]) {\n return {\n name: \"todowrite\",\n input: {\n todos: todos.map((todo) => ({\n id: todo.id,\n content: todo.content,\n status: todo.status,\n priority: \"medium\",\n })),\n },\n executed: false,\n }\n}\n\nexport function mapTool(\n name: string,\n input?: any,\n opts?: MapToolOptions,\n): { name: string; input?: any; executed: boolean; skip?: boolean } {\n // Claude CLI internal tools — skip entirely\n if (CLAUDE_INTERNAL_TOOLS.has(name)) {\n log.debug(\"skipping Claude CLI internal tool\", { name })\n return { name, input, executed: true, skip: true }\n }\n\n // TaskCreate: stash subject keyed by tool_use_id; emission happens on tool_result.\n // Without sessionId+toolUseId we cannot maintain the ledger, so fall back to skip\n // (preserves old behavior for callers that haven't been threaded yet).\n if (name === \"TaskCreate\") {\n if (opts?.sessionId && opts?.toolUseId) {\n applyTaskCreateToolUse(opts.sessionId, opts.toolUseId, input)\n }\n return { name, input, executed: true, skip: true }\n }\n\n // TaskUpdate: mutate ledger and emit full list as opencode todowrite. Without\n // sessionId, fall back to skip. Unknown task ids return null from the ledger\n // and we drop the event.\n if (name === \"TaskUpdate\") {\n if (opts?.sessionId) {\n const list = applyTaskUpdate(opts.sessionId, input)\n if (list !== null) return emitTodoWrite(list)\n }\n return { name, input, executed: true, skip: true }\n }\n\n // Plan mode tools\n if (name === \"EnterPlanMode\") return { name: \"plan_enter\", input: {}, executed: false }\n if (name === \"ExitPlanMode\") return { name: \"plan_exit\", input, executed: false }\n\n // TodoWrite needs opencode to run it locally so Todo.Service (and the UI\n // widget backed by it) gets populated. Reporting as provider-executed would\n // short-circuit opencode's own execute and leave the todo panel empty.\n if (name === \"TodoWrite\") {\n const mappedInput = mapToolInput(name, input)\n return { name: \"todowrite\", input: mappedInput, executed: false }\n }\n\n // WebSearch — routing controlled by config.webSearch\n if (isWebSearchTool(name)) {\n const mappedInput = input?.query ? { query: input.query } : input\n const route = opts?.webSearch\n if (route && route !== \"claude\" && route !== \"disabled\") {\n log.debug(\"routing WebSearch to opencode tool\", { target: route, mappedInput })\n return { name: route, input: mappedInput, executed: false }\n }\n // Claude CLI runs WebSearch internally; \"WebSearch\" has no opencode\n // registry entry, so forwarding the tool-call part surfaces a\n // \"Model tried to call unavailable tool\" invalid row in opencode.\n // Skip the part — callers render the query as a text line instead.\n log.debug(\"WebSearch executed by Claude CLI\", { mappedInput })\n return { name: \"WebSearch\", input: mappedInput, executed: true, skip: true }\n }\n\n // TaskOutput -> bash echo\n if (name === \"TaskOutput\") {\n if (!input) return { name: \"bash\", executed: false }\n const output = input?.content || input?.output || JSON.stringify(input)\n return {\n name: \"bash\",\n input: {\n command: `echo \"TASK OUTPUT: ${String(output).replace(/\"/g, '\\\\\"')}\"`,\n description: \"Displaying task output\",\n },\n executed: false,\n }\n }\n\n // Third-party MCP tools: mcp__<server>__<tool> -> <server>_<tool>.\n // Marked provider-executed because Claude CLI runs these internally via\n // its own --mcp-config; the tool-result is already in the stream. If we\n // reported executed:false, opencode would look up the tool in its own\n // registry, fail to find it, and emit an `invalid` tool error that\n // shadows the real result.\n //\n // Our own proxy tools (`mcp__opencode_proxy__*`) are filtered out by\n // callers before reaching here, so this branch only ever sees user MCP\n // servers configured in Claude CLI's settings.\n if (name.startsWith(\"mcp__\")) {\n const parts = name.slice(5).split(\"__\")\n if (parts.length >= 2) {\n const serverName = parts[0]\n const toolName = parts.slice(1).join(\"_\")\n const openCodeName = `${serverName}_${toolName}`\n log.debug(\"mapping MCP tool\", { original: name, mapped: openCodeName })\n return { name: openCodeName, input, executed: true }\n }\n }\n\n // Tools executed by Claude CLI internally - map to lowercase for opencode\n if (OPENCODE_HANDLED_TOOLS.has(name)) {\n const mappedInput = mapToolInput(name, input)\n const openCodeName = name.toLowerCase()\n log.debug(\"mapping CLI-executed tool\", { name, openCodeName })\n return { name: openCodeName, input: mappedInput, executed: true }\n }\n\n // Unknown tools - treated as provider-executed\n return { name, input, executed: true }\n}\n","import type { LanguageModelV3 } from \"@ai-sdk/provider\"\nimport { log } from \"./logger.js\"\nimport type { ReasoningEffort } from \"./types.js\"\n\ntype Prompt = Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"prompt\"]\n\nconst THINKING_KEYWORDS: Record<ReasoningEffort, string | null> = {\n minimal: null,\n low: \"think\",\n medium: \"think hard\",\n high: \"think harder\",\n xhigh: \"megathink\",\n max: \"ultrathink\",\n}\n\nexport function reasoningKeyword(effort?: ReasoningEffort): string | null {\n if (!effort) return null\n return THINKING_KEYWORDS[effort] ?? null\n}\n\nconst SUPPORTED_IMAGE_TYPES = new Set([\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n])\n\nfunction toImageBlock(part: any): any | null {\n const raw: unknown = part.image ?? part.data ?? part.url ?? part.source?.data\n if (!raw) {\n log.warn(\"file part without data, skipping\")\n return null\n }\n\n let resolvedMediaType: string = part.mediaType || part.mimeType || part.mime || \"\"\n let base64: string | null = null\n\n if (typeof raw === \"string\") {\n if (raw.startsWith(\"data:\")) {\n const match = /^data:([^;,]+)(?:;[^,]*)*(?:;base64)?,(.*)$/s.exec(raw)\n if (!match) {\n log.warn(\"malformed data URI, skipping file part\")\n return null\n }\n resolvedMediaType = resolvedMediaType || match[1]\n base64 = match[2]\n } else if (/^https?:\\/\\//i.test(raw)) {\n log.warn(\"remote URL images are not supported by Claude CLI, skipping\")\n return null\n } else {\n base64 = raw\n }\n } else if (raw instanceof URL) {\n log.warn(\"remote URL images are not supported by Claude CLI, skipping\")\n return null\n } else if (raw instanceof Uint8Array || Buffer.isBuffer(raw)) {\n base64 = Buffer.from(raw as Uint8Array).toString(\"base64\")\n } else {\n log.warn(\"unsupported file part data type\", { dataType: typeof raw })\n return null\n }\n\n if (!resolvedMediaType || !SUPPORTED_IMAGE_TYPES.has(resolvedMediaType)) {\n log.warn(\"unsupported media type for Claude image block, skipping\", {\n mediaType: resolvedMediaType,\n })\n return null\n }\n\n return {\n type: \"image\",\n source: { type: \"base64\", media_type: resolvedMediaType, data: base64 },\n }\n}\n\nfunction getToolResultText(part: any): string {\n const value = part.output ?? part.result\n\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\") {\n return JSON.stringify(value)\n }\n\n switch (value.type) {\n case \"text\":\n case \"error-text\":\n return String(value.value)\n case \"json\":\n case \"error-json\":\n return JSON.stringify(value.value)\n case \"execution-denied\":\n return value.reason ? `Execution denied: ${value.reason}` : \"Execution denied\"\n case \"content\":\n return Array.isArray(value.value)\n ? value.value\n .map((item: any) => {\n if (item?.type === \"text\") return item.text\n return JSON.stringify(item)\n })\n .join(\"\\n\")\n : JSON.stringify(value.value)\n default:\n return JSON.stringify(value)\n }\n}\n\n// Compaction-mode caps. These are the only knobs that affect how much\n// transcript content reaches the model when opencode invokes /compact.\n// 180k chars ≈ 60k tokens worst-case — well under Haiku 4.5's 200k window\n// after accounting for system prompt + output budget.\nconst MAX_HISTORY_CHARS = 180_000\nconst MAX_TOOL_RESULT_CHARS = 10_000\nconst MAX_TOOL_INPUT_CHARS = 2_000\n\nfunction clipWithMarker(text: string, max: number): string {\n if (text.length <= max) return text\n return `${text.slice(0, max)}\\n…[truncated ${text.length - max} chars]`\n}\n\nfunction renderToolInput(input: unknown): string {\n let raw: string\n try {\n raw = typeof input === \"string\" ? input : JSON.stringify(input)\n } catch {\n raw = String(input)\n }\n return clipWithMarker(raw, MAX_TOOL_INPUT_CHARS)\n}\n\nfunction renderMessageContentForCompaction(\n msg: any,\n): { text: string; toolResultCount: number } {\n const lines: string[] = []\n let toolResultCount = 0\n\n if (typeof msg.content === \"string\") {\n return { text: msg.content, toolResultCount: 0 }\n }\n\n if (!Array.isArray(msg.content)) {\n return { text: \"\", toolResultCount: 0 }\n }\n\n for (const part of msg.content as any[]) {\n if (!part) continue\n switch (part.type) {\n case \"text\":\n if (part.text) lines.push(part.text)\n break\n case \"tool-call\":\n lines.push(\n `[tool_use:${part.toolName ?? \"unknown\"}(${renderToolInput(part.input)})]`,\n )\n break\n case \"tool-result\":\n toolResultCount++\n lines.push(\n `[tool_result:${part.toolName ?? part.toolCallId ?? \"unknown\"}]\\n${clipWithMarker(\n getToolResultText(part),\n MAX_TOOL_RESULT_CHARS,\n )}`,\n )\n break\n case \"image\":\n lines.push(\n `[image: ${part.mediaType ?? part.mimeType ?? \"unknown\"}]`,\n )\n break\n case \"file\":\n lines.push(\n `[file: ${part.mediaType ?? part.mimeType ?? \"unknown\"}]`,\n )\n break\n case \"reasoning\":\n // Skip reasoning blocks in compaction — they bloat input without\n // helping the summarizer.\n break\n }\n }\n\n return { text: lines.join(\"\\n\"), toolResultCount }\n}\n\n/**\n * Compact conversation history into a context summary.\n *\n * - mode \"fresh-session\" (default): legacy behavior. Filters to\n * user/assistant only, clips each message at 2000 chars, drops tool\n * payloads to placeholders. Used when starting a fresh CLI session\n * that lost its prior session id.\n * - mode \"compaction\": rich serializer for opencode /compact. Includes\n * tool roles, renders tool_use input and tool_result content (each\n * clipped at MAX_TOOL_RESULT_CHARS), and caps aggregate output at\n * MAX_HISTORY_CHARS by dropping oldest entries first.\n */\nexport function compactConversationHistory(\n prompt: Prompt,\n opts: { mode?: \"fresh-session\" | \"compaction\" } = {},\n): string | null {\n const mode = opts.mode ?? \"fresh-session\"\n\n if (mode === \"compaction\") {\n return buildCompactionHistory(prompt)\n }\n\n const conversationMessages = prompt.filter(\n (m) => m.role === \"user\" || m.role === \"assistant\",\n )\n\n if (conversationMessages.length <= 1) {\n return null\n }\n\n const historyParts: string[] = []\n\n for (let i = 0; i < conversationMessages.length - 1; i++) {\n const msg = conversationMessages[i]\n const role = msg.role === \"user\" ? \"User\" : \"Assistant\"\n\n let text = \"\"\n if (typeof msg.content === \"string\") {\n text = msg.content\n } else if (Array.isArray(msg.content)) {\n const textParts = (msg.content as any[])\n .filter((p) => p.type === \"text\" && p.text)\n .map((p) => p.text)\n text = textParts.join(\"\\n\")\n\n const toolCalls = (msg.content as any[]).filter(\n (p) => p.type === \"tool-call\",\n )\n const toolResults = (msg.content as any[]).filter(\n (p) => p.type === \"tool-result\",\n )\n\n if (toolCalls.length > 0) {\n text += `\\n[Called ${toolCalls.length} tool(s): ${toolCalls.map((t: any) => t.toolName).join(\", \")}]`\n }\n if (toolResults.length > 0) {\n text += `\\n[Received ${toolResults.length} tool result(s)]`\n }\n }\n\n if (text.trim()) {\n const truncated =\n text.length > 2000 ? text.slice(0, 2000) + \"...\" : text\n historyParts.push(`${role}: ${truncated}`)\n }\n }\n\n if (historyParts.length === 0) {\n return null\n }\n\n return historyParts.join(\"\\n\\n\")\n}\n\nfunction buildCompactionHistory(prompt: Prompt): string | null {\n // Iterate newest-first, accumulate up to MAX_HISTORY_CHARS, then reverse\n // to chronological order. Oldest messages get dropped when the budget\n // is exhausted — they are the least relevant for a summary of recent\n // work.\n const entries: string[] = []\n let total = 0\n let totalToolResults = 0\n let droppedOldest = 0\n\n // Skip the trailing user message: opencode's /compact appends the\n // synthesis instruction as the final user turn. The instruction itself\n // is added by getClaudeUserMessage after the transcript block, so we\n // don't want it duplicated inside the transcript.\n const end = prompt.length > 0 && prompt[prompt.length - 1].role === \"user\"\n ? prompt.length - 1\n : prompt.length\n\n for (let i = end - 1; i >= 0; i--) {\n const msg = prompt[i] as any\n const roleLabel =\n msg.role === \"user\"\n ? \"User\"\n : msg.role === \"assistant\"\n ? \"Assistant\"\n : msg.role === \"tool\"\n ? \"Tool\"\n : msg.role\n\n const { text, toolResultCount } = renderMessageContentForCompaction(msg)\n if (!text.trim()) continue\n\n const entry = `${roleLabel}: ${text}`\n if (total + entry.length > MAX_HISTORY_CHARS) {\n droppedOldest = i + 1\n break\n }\n entries.push(entry)\n total += entry.length + 2 // +2 for the \"\\n\\n\" join\n totalToolResults += toolResultCount\n }\n\n if (entries.length === 0) return null\n\n entries.reverse()\n log.info(\"built compaction history\", {\n entries: entries.length,\n chars: total,\n toolResults: totalToolResults,\n droppedOldestBefore: droppedOldest,\n })\n\n return entries.join(\"\\n\\n\")\n}\n\n/**\n * Convert AI SDK prompt into a Claude CLI stream-json user message.\n *\n * `compactionMode` switches behavior for opencode /compact: the prior\n * transcript is rendered with rich tool content (not placeholders), the\n * wrapper framing tells the model this is the authoritative thread, and\n * the reasoning keyword is suppressed so the full output budget goes\n * toward the summary.\n */\nexport function getClaudeUserMessage(\n prompt: Prompt,\n includeHistoryContext: boolean = false,\n reasoningEffort?: ReasoningEffort,\n opts: { compactionMode?: boolean } = {},\n): string {\n const compactionMode = opts.compactionMode === true\n const content: any[] = []\n\n if (compactionMode) {\n const transcript = compactConversationHistory(prompt, {\n mode: \"compaction\",\n })\n if (transcript) {\n log.info(\"including compaction transcript\", {\n historyLength: transcript.length,\n })\n content.push({\n type: \"text\",\n text: `<conversation_transcript>\n${transcript}\n</conversation_transcript>\n\nThe complete prior conversation appears above. The synthesis instructions follow below.\n\n`,\n })\n }\n } else if (includeHistoryContext) {\n const historyContext = compactConversationHistory(prompt)\n if (historyContext) {\n log.info(\"including conversation history context\", {\n historyLength: historyContext.length,\n })\n content.push({\n type: \"text\",\n text: `<conversation_history>\nThe following is a summary of our conversation so far (from a previous session that couldn't be resumed):\n\n${historyContext}\n\n</conversation_history>\n\nNow continuing with the current message:\n\n`,\n })\n }\n }\n\n // Find messages since last assistant message\n const messages: typeof prompt = []\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === \"assistant\") break\n messages.unshift(prompt[i])\n }\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n const str = msg.content as string\n if (str.trim()) {\n content.push({ type: \"text\", text: str })\n }\n } else if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (part.type === \"text\") {\n if (part.text && part.text.trim()) {\n content.push({ type: \"text\", text: part.text })\n }\n } else if (part.type === \"file\" || part.type === \"image\") {\n const block = toImageBlock(part)\n if (block) {\n content.push(block)\n } else {\n log.debug(\"skipped non-image file part\", {\n mediaType: part.mediaType,\n })\n }\n } else if (part.type === \"tool-result\") {\n const p = part as any\n content.push({\n type: \"tool_result\",\n tool_use_id: p.toolCallId,\n content: getToolResultText(p),\n })\n }\n }\n }\n } else if (msg.role === \"tool\") {\n // AI SDK V3 delivers tool results in `tool`-role messages, not `user`.\n // Without this branch we'd hit the empty-content sentinel path and\n // send \"(empty)\" to Claude CLI instead of the actual tool result —\n // forcing the user to press \"continue\" between proxy tool calls.\n if (Array.isArray(msg.content)) {\n for (const part of msg.content as any[]) {\n if (part?.type === \"tool-result\") {\n const p = part as any\n content.push({\n type: \"tool_result\",\n tool_use_id: p.toolCallId,\n content: getToolResultText(p),\n })\n }\n }\n }\n }\n }\n\n if (content.length === 0) {\n // CLI rejects a zero-block message with 400, and Anthropic rejects\n // whitespace-only text blocks — so we need a non-whitespace sentinel.\n // \"(empty)\" matches the parenthetical meta-note convention this file\n // already uses for reasoning keywords (\"(think)\", \"(megathink)\", etc.),\n // which the model reads as out-of-band metadata rather than a prompt to\n // continue its previous turn.\n log.warn(\"empty user content; sending sentinel to satisfy CLI\")\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: \"(empty)\" }],\n },\n })\n }\n\n // Reasoning keyword is a Claude CLI hint that triggers extended thinking.\n // For compaction we want the full output budget to go to the summary\n // itself, not internal reasoning — so skip injection.\n if (!compactionMode) {\n const keyword = reasoningKeyword(reasoningEffort)\n if (keyword) {\n const lastTextPart = [...content].reverse().find((p) => p.type === \"text\")\n if (lastTextPart) {\n lastTextPart.text = lastTextPart.text\n ? `${lastTextPart.text}\\n\\n(${keyword})`\n : `(${keyword})`\n } else {\n content.push({ type: \"text\", text: `(${keyword})` })\n }\n log.debug(\"injected reasoning keyword\", { effort: reasoningEffort, keyword })\n }\n }\n\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content,\n },\n })\n}\n","export const QUESTION_TOOL_NAME = \"question\"\n\nexport const APPROVED_EXIT_PLAN_MODE_MESSAGE =\n \"User has approved your plan. You can now start coding. Start with updating your todo list if applicable.\"\n\nconst REJECTED_EXIT_PLAN_MODE_PREFIX =\n \"The user doesn't want to proceed with this tool use. The tool use was rejected. To tell you how to proceed, the user said:\"\n\nconst PLAN_MODE_APPROVAL_QUESTION = \"Do you want to proceed with this plan?\"\nconst OPENCODE_QUESTION_RESULT_PREFIX =\n `User has answered your questions: \"${PLAN_MODE_APPROVAL_QUESTION}\"=\"`\nconst OPENCODE_QUESTION_RESULT_SUFFIX =\n `\". You can now continue with the user's answers in mind.`\n\nconst KEY_SEPARATOR = \"\\u0000\"\n\nexport interface ExitPlanModeQuestionCall {\n toolCallId: string\n toolName: typeof QUESTION_TOOL_NAME\n input: {\n questions: Array<{\n header: string\n question: string\n options: Array<{ label: string; description: string }>\n multiple: boolean\n custom: boolean\n }>\n }\n text: string\n}\n\n/**\n * Whether to bridge `ExitPlanMode` into opencode's native `question` tool\n * this turn.\n *\n * Opt-in (`planModeQuestion`) because opencode's question form does not\n * currently render (anomalyco/opencode#36604), so an enabled bridge hangs the\n * turn until the operator interrupts, where the text path still works.\n * Gated on the live registry because emitting a `question` tool-call on a\n * build without that entry renders `⚙ invalid` and wedges the turn just the\n * same. Never bridged during compaction: that turn is text-only and its\n * answer would have nowhere to go.\n */\nexport function isPlanModeQuestionActive(input: {\n configured: boolean | undefined\n opencodeHasQuestion: boolean\n compactionMode: boolean\n}): boolean {\n if (input.compactionMode) return false\n if (input.configured !== true) return false\n return input.opencodeHasQuestion\n}\n\nconst pendingQuestions = new Map<string, string>()\n\nfunction pendingKey(sessionKey: string, questionToolCallId: string): string {\n return `${sessionKey}${KEY_SEPARATOR}${questionToolCallId}`\n}\n\nexport function clearExitPlanModeQuestions(sessionKey: string): void {\n const prefix = `${sessionKey}${KEY_SEPARATOR}`\n for (const key of pendingQuestions.keys()) {\n if (key.startsWith(prefix)) pendingQuestions.delete(key)\n }\n}\n\nexport function createExitPlanModeQuestionCall(\n sessionKey: string,\n exitPlanModeToolUseId: string,\n plan: string,\n questionToolCallId = `exit_plan_question_${exitPlanModeToolUseId}`,\n): ExitPlanModeQuestionCall {\n pendingQuestions.set(pendingKey(sessionKey, questionToolCallId), exitPlanModeToolUseId)\n\n return {\n toolCallId: questionToolCallId,\n toolName: QUESTION_TOOL_NAME,\n input: {\n questions: [\n {\n header: \"Plan approval\",\n question: PLAN_MODE_APPROVAL_QUESTION,\n options: [\n { label: \"yes\", description: \"\" },\n { label: \"no\", description: \"\" },\n ],\n multiple: false,\n custom: true,\n },\n ],\n },\n text: plan ? `\\n\\n${plan}\\n` : \"\\n\\n\",\n }\n}\n\nfunction buildToolResultMessage(input: {\n toolUseId: string\n approved: boolean\n feedback: string\n}): string {\n return JSON.stringify({\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n input.approved\n ? {\n type: \"tool_result\",\n tool_use_id: input.toolUseId,\n content: APPROVED_EXIT_PLAN_MODE_MESSAGE,\n }\n : {\n type: \"tool_result\",\n tool_use_id: input.toolUseId,\n content: `${REJECTED_EXIT_PLAN_MODE_PREFIX}\\n${input.feedback || \"no\"}`,\n is_error: true,\n },\n ],\n },\n })\n}\n\nfunction tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction unwrapToolOutput(part: any): unknown {\n const output = part?.output ?? part?.result\n if (typeof output === \"string\") return tryParseJson(output)\n if (!output || typeof output !== \"object\") return output\n\n switch (output.type) {\n case \"json\":\n case \"error-json\":\n return output.value\n case \"text\":\n case \"error-text\":\n return tryParseJson(String(output.value ?? \"\"))\n case \"execution-denied\":\n return {\n denied: true,\n reason: String(output.reason ?? \"question rejected\"),\n }\n case \"content\":\n return Array.isArray(output.value)\n ? output.value\n .map((item: any) => {\n if (item?.type === \"text\") return item.text\n return JSON.stringify(item)\n })\n .join(\"\\n\")\n : output.value\n default:\n return output\n }\n}\n\nfunction unwrapOpencodeQuestionResult(value: string): string {\n if (\n value.startsWith(OPENCODE_QUESTION_RESULT_PREFIX) &&\n value.endsWith(OPENCODE_QUESTION_RESULT_SUFFIX)\n ) {\n return value.slice(\n OPENCODE_QUESTION_RESULT_PREFIX.length,\n -OPENCODE_QUESTION_RESULT_SUFFIX.length,\n )\n }\n return value\n}\n\nfunction collectAnswerStrings(value: unknown): string[] {\n if (typeof value === \"string\") return [unwrapOpencodeQuestionResult(value)]\n if (Array.isArray(value)) return value.flatMap(collectAnswerStrings)\n if (!value || typeof value !== \"object\") return []\n\n const obj = value as Record<string, unknown>\n if (obj.denied === true) return [String(obj.reason ?? \"question rejected\")]\n\n for (const key of [\"answers\", \"answer\", \"selected\", \"selection\", \"value\"]) {\n if (key in obj) return collectAnswerStrings(obj[key])\n }\n\n return []\n}\n\nfunction classifyQuestionResult(part: any): { approved: boolean; feedback: string } {\n const output = unwrapToolOutput(part)\n const answers = collectAnswerStrings(output)\n .map((answer) => answer.trim())\n .filter(Boolean)\n\n if (answers.length === 1 && answers[0].toLowerCase() === \"yes\") {\n return { approved: true, feedback: \"\" }\n }\n\n return {\n approved: false,\n feedback: answers.length > 0 ? answers.join(\"\\n\") : \"no\",\n }\n}\n\nexport function consumeExitPlanModeQuestionResult(\n sessionKey: string,\n prompt: Array<{ role: string; content?: unknown }>,\n): string | null {\n for (let i = prompt.length - 1; i >= 0; i--) {\n const msg = prompt[i]\n if (!Array.isArray(msg.content)) continue\n\n for (const part of msg.content as any[]) {\n if (part?.type !== \"tool-result\" || typeof part.toolCallId !== \"string\") {\n continue\n }\n\n const key = pendingKey(sessionKey, part.toolCallId)\n const exitPlanModeToolUseId = pendingQuestions.get(key)\n if (!exitPlanModeToolUseId) continue\n\n pendingQuestions.delete(key)\n const result = classifyQuestionResult(part)\n return buildToolResultMessage({\n toolUseId: exitPlanModeToolUseId,\n approved: result.approved,\n feedback: result.feedback,\n })\n }\n }\n\n return null\n}\n","import * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport * as os from \"node:os\"\nimport * as crypto from \"node:crypto\"\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\"\nimport { log } from \"./logger.js\"\nimport { pluginTmpDir } from \"./tmp.js\"\n\n/**\n * Bridge opencode's `mcp` config block into a Claude CLI `--mcp-config` file.\n *\n * Opencode core schema (packages/opencode/src/config/mcp.ts):\n * {\n * \"mcp\": {\n * \"name\": {\n * \"type\": \"local\" | \"remote\",\n * \"command\"?: string[], // local\n * \"environment\"?: Record<string,string>,\n * \"url\"?: string, // remote\n * \"headers\"?: Record<string,string>,\n * \"oauth\"?: object | false, // remote — NOT bridged (Claude --mcp-config has no slot)\n * \"timeout\"?: number, // NOT bridged (Claude --mcp-config has no slot)\n * \"enabled\"?: boolean\n * }\n * }\n * }\n *\n * Claude CLI `--mcp-config` schema:\n * {\n * \"mcpServers\": {\n * \"name\": {\n * \"type\": \"stdio\" | \"http\",\n * \"command\"?: string, \"args\"?: string[], \"env\"?: Record<string,string>,\n * \"url\"?: string, \"headers\"?: Record<string,string>\n * }\n * }\n * }\n *\n * Discovery + merge are aligned with opencode core's `loadInstanceState`\n * (packages/opencode/src/config/config.ts). In merge order (last wins),\n * opencode loads:\n *\n * 1. Auth `.well-known` remote configs ← NOT bridged\n * 2. Global: ~/.config/opencode/{config.json,opencode.json,opencode.jsonc}\n * — all three deep-merged, jsonc highest priority\n * 3. OPENCODE_CONFIG env var (single file)\n * 4. Project walk-up: opencode.json[c] in each dir from cwd up to (not past)\n * worktree, both extensions per dir, parent-most first\n * 5. .opencode/ siblings: from cwd up + home dir + OPENCODE_CONFIG_DIR,\n * both extensions per dir, opencode-iteration order (cwd-most first\n * in walk-up — so parent-most `.opencode/` wins, matching upstream)\n * 6. OPENCODE_CONFIG_CONTENT env var (inline JSON) ← NOT bridged\n * 7. Active org remote config ← NOT bridged\n * 8. Managed config dir / macOS MDM ← NOT bridged\n *\n * Sources marked NOT bridged are niche and would require live opencode\n * runtime state (auth tokens, account context, MDM access). Document them\n * here so the gap is explicit; functionality of the common path is intact.\n *\n * Per-server merge is deep-merge (matching opencode's `mergeConfigConcatArrays`\n * → `mergeDeep`), so a project layer can override one field of a global server\n * spec — e.g. `{ \"linear\": { \"enabled\": true } }` lifts global linear's URL.\n */\n\nconst FILE_NAMES = [\"opencode.jsonc\", \"opencode.json\", \"config.json\"] as const\nconst PROJECT_FILE_NAMES = [\"opencode.json\", \"opencode.jsonc\"] as const\n\nfunction fileExists(p: string): boolean {\n try {\n return fs.statSync(p).isFile()\n } catch {\n return false\n }\n}\n\nfunction dirExists(p: string): boolean {\n try {\n return fs.statSync(p).isDirectory()\n } catch {\n return false\n }\n}\n\nfunction readAndParse(file: string): Record<string, unknown> | null {\n try {\n const raw = fs.readFileSync(file, \"utf8\")\n const errors: ParseError[] = []\n const parsed = parseJsonc(raw, errors, { allowTrailingComma: true })\n if (errors.length > 0) {\n const first = errors[0]\n throw new Error(\n `${printParseErrorCode(first.error)} at offset ${first.offset}`,\n )\n }\n return parsed as Record<string, unknown>\n } catch (e) {\n log.warn(\"failed to parse opencode config\", {\n file,\n error: e instanceof Error ? e.message : String(e),\n })\n return null\n }\n}\n\n/**\n * Deep merge two plain-object trees. Arrays and primitives are replaced\n * (not concatenated). Matches the effective behavior of opencode's\n * `mergeDeep` from `remeda` for the MCP block — opencode does not special\n * case array fields inside `mcp.<server>` (its only special case is\n * `instructions`, which is concat-deduped at the config root).\n */\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\n return typeof x === \"object\" && x !== null && !Array.isArray(x)\n}\n\nfunction deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...target }\n for (const [k, v] of Object.entries(source)) {\n if (v === undefined) continue\n const existing = out[k]\n if (isPlainObject(existing) && isPlainObject(v)) {\n out[k] = deepMerge(existing, v)\n } else {\n out[k] = v\n }\n }\n return out\n}\n\n/**\n * Walk up from `start` toward filesystem root (or `stop` if provided),\n * collecting paths where each `target` exists. Mirrors opencode core's\n * `FileSystem.up` (packages/core/src/filesystem.ts): cwd-most first,\n * parent-most last.\n */\nfunction walkUp(opts: {\n start: string\n stop?: string\n targets: readonly string[]\n predicate: (p: string) => boolean\n}): string[] {\n const out: string[] = []\n let current = path.resolve(opts.start)\n while (true) {\n for (const target of opts.targets) {\n const candidate = path.join(current, target)\n if (opts.predicate(candidate)) out.push(candidate)\n }\n if (opts.stop && current === path.resolve(opts.stop)) break\n const parent = path.dirname(current)\n if (parent === current) break\n current = parent\n }\n return out\n}\n\n/**\n * Find the worktree root by walking up from `cwd` looking for a `.git`\n * entry (file or directory — submodules use a file). If no `.git` is\n * found, walk to filesystem root. Honors OPENCODE_WORKTREE override.\n */\nfunction detectWorktree(cwd: string): string | undefined {\n const override = process.env.OPENCODE_WORKTREE\n if (override) return path.resolve(override)\n let current = path.resolve(cwd)\n while (true) {\n const gitPath = path.join(current, \".git\")\n try {\n if (fs.existsSync(gitPath)) return current\n } catch {\n // ignore\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\nfunction globalConfigDir(): string {\n const xdg = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), \".config\")\n return path.join(xdg, \"opencode\")\n}\n\n/**\n * Load the merged global config from `~/.config/opencode/`. Mirrors\n * opencode core's `loadGlobal`: deep-merges config.json → opencode.json\n * → opencode.jsonc in that order (jsonc wins).\n */\nfunction loadGlobalConfig(): Record<string, unknown> {\n const dir = globalConfigDir()\n let merged: Record<string, unknown> = {}\n for (const name of FILE_NAMES.slice().reverse()) {\n // FILE_NAMES is jsonc-first; reverse to get config.json-first order.\n const file = path.join(dir, name)\n if (!fileExists(file)) continue\n const parsed = readAndParse(file)\n if (parsed) merged = deepMerge(merged, parsed)\n }\n return merged\n}\n\n/** Load both `opencode.json` and `opencode.jsonc` in `dir`, deep-merged. */\nfunction loadProjectFilesInDir(dir: string): Record<string, unknown> {\n let merged: Record<string, unknown> = {}\n for (const name of PROJECT_FILE_NAMES) {\n const file = path.join(dir, name)\n if (!fileExists(file)) continue\n const parsed = readAndParse(file)\n if (parsed) merged = deepMerge(merged, parsed)\n }\n return merged\n}\n\n/**\n * Build the list of `.opencode/` directories to consider, in opencode core's\n * order (matching `ConfigPaths.directories`):\n * project walk-up (cwd-most first) → home-dir `.opencode/` → OPENCODE_CONFIG_DIR\n */\nfunction dotOpencodeDirs(cwd: string, worktree?: string): string[] {\n const dirs: string[] = []\n const seen = new Set<string>()\n const push = (p: string) => {\n const abs = path.resolve(p)\n if (!seen.has(abs) && dirExists(abs)) {\n seen.add(abs)\n dirs.push(abs)\n }\n }\n\n for (const dir of walkUp({\n start: cwd,\n stop: worktree,\n targets: [\".opencode\"],\n predicate: dirExists,\n })) {\n push(dir)\n }\n\n const home = os.homedir()\n if (home) {\n const homeDot = path.join(home, \".opencode\")\n if (dirExists(homeDot)) push(homeDot)\n }\n\n const envDir = process.env.OPENCODE_CONFIG_DIR\n if (envDir && dirExists(envDir)) push(envDir)\n\n return dirs\n}\n\ninterface OpencodeLocalServer {\n type?: \"local\"\n command?: string[]\n environment?: Record<string, string>\n enabled?: boolean\n}\n\ninterface OpencodeRemoteServer {\n type?: \"remote\"\n url?: string\n headers?: Record<string, string>\n enabled?: boolean\n}\n\ntype OpencodeServer = OpencodeLocalServer | OpencodeRemoteServer | { enabled?: boolean }\n\n/**\n * Substitute opencode's `{env:VAR}` interpolation in a string-keyed record\n * using values from `process.env`. Returns a new object. If the source is\n * not a flat string-valued record, returns it unchanged.\n *\n * Opencode performs this substitution itself when it spawns MCP servers\n * directly, but the spec we read from disk still contains the literal\n * placeholders. Without substituting them here, Claude CLI hands the\n * literal string `{env:FOO}` to the MCP subprocess as the env value, and\n * any server that validates credentials at startup (e.g. slack-mcp-server)\n * crashes before exposing tools. Servers that defer validation to\n * request time (e.g. github-mcp-server) appear to register but every API\n * call 401s.\n */\nfunction substituteEnvPlaceholders(\n source: Record<string, unknown>,\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(source)) {\n if (typeof v !== \"string\") continue\n out[k] = v.replace(/\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name) => {\n const resolved = process.env[name]\n return typeof resolved === \"string\" ? resolved : \"\"\n })\n }\n return out\n}\n\nfunction translateServer(\n name: string,\n spec: Record<string, unknown>,\n): Record<string, unknown> | null {\n if (spec.enabled === false) return null\n\n const type = spec.type\n if (type === \"local\") {\n const cmd = spec.command\n if (!Array.isArray(cmd) || cmd.length === 0) {\n log.warn(\"skipping local MCP server with no command\", { name })\n return null\n }\n const out: Record<string, unknown> = {\n type: \"stdio\",\n command: String(cmd[0]),\n }\n if (cmd.length > 1) out.args = cmd.slice(1).map((s) => String(s))\n if (spec.environment && typeof spec.environment === \"object\") {\n out.env = substituteEnvPlaceholders(\n spec.environment as Record<string, unknown>,\n )\n }\n return out\n }\n\n if (type === \"remote\") {\n if (typeof spec.url !== \"string\" || !spec.url) {\n log.warn(\"skipping remote MCP server with no url\", { name })\n return null\n }\n const out: Record<string, unknown> = {\n type: \"http\",\n url: spec.url,\n }\n if (spec.headers && typeof spec.headers === \"object\") {\n out.headers = substituteEnvPlaceholders(\n spec.headers as Record<string, unknown>,\n )\n }\n return out\n }\n\n log.warn(\"skipping MCP server with unknown type\", {\n name,\n type: type ?? null,\n })\n return null\n}\n\nfunction extractMcpBlock(\n config: Record<string, unknown>,\n): Record<string, OpencodeServer> {\n const mcp = config.mcp\n if (!mcp || typeof mcp !== \"object\" || Array.isArray(mcp)) return {}\n return mcp as Record<string, OpencodeServer>\n}\n\n/**\n * Deep-merge per-server specs from `source` into `target`. Mirrors opencode's\n * `mergeDeep` semantics for the `mcp` record: each server entry is recursively\n * merged so a partial layer (e.g. `{ \"linear\": { \"enabled\": true } }`) can\n * override one field without dropping the rest.\n */\nfunction mergeMcp(\n target: Record<string, OpencodeServer>,\n source: Record<string, OpencodeServer>,\n): Record<string, OpencodeServer> {\n const out: Record<string, OpencodeServer> = { ...target }\n for (const [name, spec] of Object.entries(source)) {\n if (!spec || typeof spec !== \"object\") continue\n const existing = out[name]\n if (existing && typeof existing === \"object\") {\n out[name] = deepMerge(\n existing as Record<string, unknown>,\n spec as Record<string, unknown>,\n ) as OpencodeServer\n } else {\n out[name] = spec\n }\n }\n return out\n}\n\nexport interface BridgedMcp {\n /** Path to the temp file containing the translated `--mcp-config`. */\n path: string\n /** Stable hash of the merged opencode mcp block (pre-translation). */\n hash: string\n /**\n * Names of opencode MCP servers that were bridged into Claude CLI's\n * `--mcp-config`. Excludes any servers passed in `excludeServers`.\n */\n serverNames: string[]\n /**\n * Names of every enabled opencode MCP server after merge + runtime\n * overlay, regardless of whether they ended up bridged or excluded.\n * Callers (e.g. the proxy-tool builder) use this to decide which\n * `<server>_<tool>` IDs in opencode's tool catalog are MCP-origin.\n */\n allEnabledServerNames: string[]\n}\n\n/** Result of merging opencode's MCP config layers + applying runtime overlay. */\nexport interface MergedMcp {\n /** Merged, overlay-applied server specs keyed by opencode server name. */\n servers: Record<string, OpencodeServer>\n /** Server names whose final spec is enabled (or implicitly enabled). */\n enabledServerNames: string[]\n /** Stable hash of the merged (pre-translation) MCP block. */\n hash: string\n}\n\n/**\n * Per-server runtime status from opencode's `client.mcp.status()`. Used as\n * an overlay on top of the on-disk merged config so opencode's UI-toggled\n * state — which lives only in-memory; `connect()`/`disconnect()` never\n * touch disk — propagates to the bridged claude subprocess.\n *\n * Treatment per server:\n * - \"connected\" → force `enabled: true` (mirror opencode)\n * - any other status → force `enabled: false` (don't ship a server\n * opencode can't run; user fixes it in opencode first)\n * - missing entry → leave disk value\n *\n * Omit the overlay and the bridge falls back to disk-only.\n */\nexport type RuntimeMcpStatus = Record<string, string>\n\n/**\n * Read opencode config layers, deep-merge their `mcp` blocks per opencode's\n * own semantics, optionally apply an opencode runtime-status overlay, then\n * translate each server to Claude CLI format, write a scratch file, and\n * return its path + a stable hash. Returns null when no enabled MCP servers\n * remain after the merge + overlay.\n */\nexport function bridgeOpencodeMcp(\n cwd: string,\n runtimeStatus?: RuntimeMcpStatus,\n excludeServers?: ReadonlySet<string>,\n): BridgedMcp | null {\n const {\n servers: merged,\n enabledServerNames: allEnabledServerNames,\n hash,\n } = mergeOpencodeMcp(cwd, runtimeStatus)\n\n // Translate every still-enabled server, skipping any caller has asked us\n // to exclude (because they're being routed through the proxy instead).\n const servers: Record<string, unknown> = {}\n const bridgedServerNames: string[] = []\n for (const [name, spec] of Object.entries(merged)) {\n if (!spec || typeof spec !== \"object\") continue\n if (excludeServers?.has(name)) continue\n const translated = translateServer(name, spec as Record<string, unknown>)\n if (translated) {\n servers[name] = translated\n bridgedServerNames.push(name)\n }\n }\n return finishBridge({\n servers,\n bridgedServerNames,\n allEnabledServerNames,\n hash,\n excludeServers,\n })\n}\n\n/**\n * Merge opencode's MCP config layers (global → `OPENCODE_CONFIG` → project\n * walk-up → `.opencode/` siblings), apply the opencode runtime-status\n * overlay, and hash the result. Split out of `bridgeOpencodeMcp` so\n * read-only callers (startup diagnostics) can inspect what would be bridged\n * without translating servers or writing a scratch config file.\n */\nexport function mergeOpencodeMcp(\n cwd: string,\n runtimeStatus?: RuntimeMcpStatus,\n): MergedMcp {\n const worktree = detectWorktree(cwd)\n\n // Layer 1: global merged\n let merged: Record<string, OpencodeServer> = {}\n merged = mergeMcp(merged, extractMcpBlock(loadGlobalConfig()))\n\n // Layer 2: OPENCODE_CONFIG (single file, applied before project walk-up)\n const explicitConfig = process.env.OPENCODE_CONFIG\n if (explicitConfig && fileExists(explicitConfig)) {\n const parsed = readAndParse(explicitConfig)\n if (parsed) merged = mergeMcp(merged, extractMcpBlock(parsed))\n }\n\n // Layer 3: project walk-up — opencode.json[c] in each dir from cwd to\n // (not past) worktree, both extensions per dir. walkUp returns cwd-most\n // first; collect distinct dirs in that order then reverse for merge so\n // cwd-most wins under last-merge-wins.\n const projectFiles = walkUp({\n start: cwd,\n stop: worktree,\n targets: PROJECT_FILE_NAMES,\n predicate: fileExists,\n })\n const projectDirs: string[] = []\n const seenProjectDirs = new Set<string>()\n for (const f of projectFiles) {\n const d = path.dirname(f)\n if (!seenProjectDirs.has(d)) {\n seenProjectDirs.add(d)\n projectDirs.push(d)\n }\n }\n for (const dir of projectDirs.slice().reverse()) {\n merged = mergeMcp(merged, extractMcpBlock(loadProjectFilesInDir(dir)))\n }\n\n // Layer 4: `.opencode/` siblings — project walk-up then home-dir then\n // OPENCODE_CONFIG_DIR, in that order. Iteration order matches opencode's\n // (cwd-most first within walk-up), so under deep-merge \"later wins\"\n // parent-most `.opencode/` overrides cwd-most. This is upstream's\n // behavior, surprising though it is.\n for (const dir of dotOpencodeDirs(cwd, worktree)) {\n merged = mergeMcp(merged, extractMcpBlock(loadProjectFilesInDir(dir)))\n }\n\n // Layer 5: opencode runtime overlay. opencode's `/mcps` UI toggle calls\n // `mcp.connect()` / `mcp.disconnect()` which only mutate in-memory state,\n // never the on-disk config. Without this overlay the bridge can't see\n // those toggles and claude misses servers the user just enabled.\n if (runtimeStatus) {\n for (const name of Object.keys(merged)) {\n const status = runtimeStatus[name]\n if (status === undefined) continue\n const existing = merged[name]\n const base =\n existing && typeof existing === \"object\"\n ? (existing as Record<string, unknown>)\n : {}\n merged[name] = { ...base, enabled: status === \"connected\" } as OpencodeServer\n }\n }\n\n // Compute the set of enabled server names BEFORE exclusion so callers can\n // tell whether a tool ID like `slack_conversations_add_message` came from\n // an opencode MCP server (vs a built-in tool that happens to contain `_`).\n const enabledServerNames: string[] = []\n for (const [name, spec] of Object.entries(merged)) {\n if (!spec || typeof spec !== \"object\") continue\n const enabled = (spec as { enabled?: unknown }).enabled\n if (enabled === false) continue\n enabledServerNames.push(name)\n }\n\n // Hash the pre-exclusion merged block so the hot-reload detector picks up\n // upstream config changes even when every server is excluded.\n const mergedBody = JSON.stringify({ mcpServers: merged }, null, 2)\n const hash = crypto\n .createHash(\"sha256\")\n .update(mergedBody)\n .digest(\"hex\")\n .slice(0, 12)\n\n return { servers: merged, enabledServerNames, hash }\n}\n\n/** Write the translated config (if any) and shape `bridgeOpencodeMcp`'s result. */\nfunction finishBridge(input: {\n servers: Record<string, unknown>\n bridgedServerNames: string[]\n allEnabledServerNames: string[]\n hash: string\n excludeServers?: ReadonlySet<string>\n}): BridgedMcp | null {\n const { servers, bridgedServerNames, allEnabledServerNames, hash, excludeServers } =\n input\n\n if (Object.keys(servers).length === 0) {\n const allEnabledServersExcluded =\n excludeServers &&\n allEnabledServerNames.length > 0 &&\n allEnabledServerNames.every((name) => excludeServers.has(name))\n\n if (!allEnabledServersExcluded) return null\n\n return {\n path: \"\",\n hash,\n serverNames: [],\n allEnabledServerNames,\n }\n }\n\n const body = JSON.stringify({ mcpServers: servers }, null, 2)\n const outPath = path.join(\n pluginTmpDir(),\n `mcp-${hash}.json`,\n )\n try {\n if (!fileExists(outPath)) {\n fs.writeFileSync(outPath, body, { encoding: \"utf8\", mode: 0o600 })\n }\n } catch (e) {\n log.warn(\"failed to write bridged MCP config\", {\n error: e instanceof Error ? e.message : String(e),\n })\n return null\n }\n\n log.info(\"bridged opencode MCP config\", {\n target: outPath,\n hash,\n servers: bridgedServerNames,\n excluded: excludeServers ? Array.from(excludeServers) : [],\n })\n return {\n path: outPath,\n hash,\n serverNames: bridgedServerNames,\n allEnabledServerNames,\n }\n}\n\n// Internal helpers exported for tests only.\nexport const __test = {\n deepMerge,\n mergeMcp,\n translateServer,\n substituteEnvPlaceholders,\n detectWorktree,\n loadGlobalConfig,\n loadProjectFilesInDir,\n dotOpencodeDirs,\n}\n","import * as fs from \"node:fs\"\nimport * as os from \"node:os\"\nimport * as path from \"node:path\"\n\n/**\n * Per-process scratch directory for plugin tmp files (bridged MCP config,\n * proxy server config, etc.). Created lazily on first use and rm'd on\n * normal process exit so we don't leak across runs. PID-isolated so two\n * concurrent opencode processes don't race on the same files.\n *\n * Caveat: `process.on(\"exit\")` does not fire for SIGKILL or unhandled\n * external signals, so abnormal terminations still leak. OS-level tmpdir\n * cleanup (`systemd-tmpfiles`, macOS periodic) handles those eventually.\n */\nconst PLUGIN_TMP_DIR = path.join(\n os.tmpdir(),\n `opencode-claude-code-${process.pid}`,\n)\n\nlet registered = false\n\nexport function pluginTmpDir(): string {\n if (!fs.existsSync(PLUGIN_TMP_DIR)) {\n fs.mkdirSync(PLUGIN_TMP_DIR, { recursive: true })\n }\n if (!registered) {\n registered = true\n process.on(\"exit\", () => {\n try {\n fs.rmSync(PLUGIN_TMP_DIR, { recursive: true, force: true })\n } catch {}\n })\n }\n return PLUGIN_TMP_DIR\n}\n","import type { RuntimeMcpStatus } from \"./mcp-bridge.js\"\nimport { log } from \"./logger.js\"\n\n/**\n * Captured opencode runtime context (SDK client + project directory) from\n * `PluginInput`. Lives in its own module to break the cycle that would\n * otherwise form between `index.ts` and `claude-code-language-model.ts`.\n * Values are `null`/`undefined` until the plugin's `server` factory runs\n * (e.g. early provider lookups, direct AI-SDK use, tests).\n */\ntype OpencodeClient = {\n mcp?: {\n status?: () => Promise<{ data?: unknown; error?: unknown }>\n }\n tool?: {\n list?: (options: {\n query: { provider: string; model: string; directory?: string }\n }) => Promise<{ data?: unknown; error?: unknown }>\n }\n}\n\nlet opencodeClient: OpencodeClient | null = null\n\nexport function setOpencodeClient(client: unknown): void {\n if (client && typeof client === \"object\") {\n opencodeClient = client as OpencodeClient\n }\n}\n\n/**\n * Captured opencode project directory from `PluginInput.directory` (with\n * `worktree` as secondary signal). Used as a *fallback* at Claude CLI\n * spawn time only when `process.cwd()` is unusable (macOS GUI launches\n * where launchd hands the process `cwd=/`).\n *\n * IMPORTANT: never bake this into provider config (`mergedOptions.cwd`).\n * Doing so freezes the value at plugin init and breaks workspace\n * switching mid-session, because subsequent workspace changes in\n * opencode's UI never get reflected in `this.config.cwd`. See issue #4.\n */\nlet opencodeProjectDirectory: string | undefined\n\nexport function setOpencodeProjectDirectory(dir: string | undefined): void {\n opencodeProjectDirectory = dir\n}\n\nexport function getOpencodeProjectDirectory(): string | undefined {\n return opencodeProjectDirectory\n}\n\nexport function isUsableDirectory(d: unknown): d is string {\n return typeof d === \"string\" && d.length > 1 && d !== \"/\"\n}\n\n/**\n * Resolve the cwd for a Claude CLI subprocess spawn. Priority:\n *\n * 1. Explicit `configured` value (`options.cwd` from `opencode.json`).\n * Users who pinned a directory keep their override unconditionally.\n * 2. Live `process.cwd()` when it's a real directory. Restores the lazy\n * resolution that lets opencode's project-aware behavior (chdir on\n * workspace switch, project-per-shell on terminal launch) flow\n * through without restarting the plugin.\n * 3. Captured project directory from plugin init. Rescues macOS GUI\n * launches where `process.cwd()` is `/`.\n * 4. Final fallback to `process.cwd()` (returns `/` in the pathological\n * case where neither override nor capture is available).\n */\nexport function resolveSpawnCwd(configured: string | undefined): string {\n return resolveSpawnCwdFrom(\n configured,\n process.cwd(),\n opencodeProjectDirectory,\n )\n}\n\nexport function resolveSpawnCwdFrom(\n configured: string | undefined,\n live: string,\n captured: string | undefined,\n): string {\n if (configured) return configured\n if (isUsableDirectory(live)) return live\n return captured ?? live\n}\n\n/**\n * Snapshot opencode's current MCP runtime status so the bridge can overlay\n * UI-toggled state on top of disk config. Returns `undefined` on any\n * failure (no client captured, status call rejected, malformed response)\n * so the bridge falls back to disk-only.\n */\nexport async function getRuntimeMcpStatus(): Promise<\n RuntimeMcpStatus | undefined\n> {\n const client = opencodeClient\n if (!client?.mcp?.status) return undefined\n try {\n const res = await client.mcp.status()\n const data = (res as { data?: unknown }).data\n if (!data || typeof data !== \"object\") return undefined\n const out: RuntimeMcpStatus = {}\n for (const [name, entry] of Object.entries(data as Record<string, unknown>)) {\n if (entry && typeof entry === \"object\") {\n const status = (entry as { status?: unknown }).status\n if (typeof status === \"string\") out[name] = status\n }\n }\n return out\n } catch (err) {\n log.warn(\"failed to fetch opencode MCP runtime status\", {\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n}\n\nexport interface OpencodeToolListItem {\n id: string\n description: string\n parameters: Record<string, unknown>\n}\n\n/**\n * Fetch opencode's full tool catalog (built-ins + MCP-bridged) with JSON\n * Schema parameters via `client.tool.list()`. The provider/model query\n * narrows the schema variants opencode returns; in practice MCP-origin\n * tool schemas are model-agnostic, so any registered (provider, model)\n * works as the query target. Returns `undefined` on any failure so callers\n * can fall back to direct-bridge behavior.\n */\nexport async function fetchOpencodeToolList(\n provider: string,\n model: string,\n directory?: string,\n): Promise<OpencodeToolListItem[] | undefined> {\n const client = opencodeClient\n if (!client?.tool?.list) return undefined\n try {\n const res = await client.tool.list({\n query: { provider, model, ...(directory ? { directory } : {}) },\n })\n const data = (res as { data?: unknown }).data\n if (!Array.isArray(data)) return undefined\n const out: OpencodeToolListItem[] = []\n for (const entry of data as unknown[]) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const id = typeof e.id === \"string\" ? e.id : null\n const description =\n typeof e.description === \"string\" ? e.description : \"\"\n const parameters =\n e.parameters && typeof e.parameters === \"object\"\n ? (e.parameters as Record<string, unknown>)\n : {}\n if (!id) continue\n out.push({ id, description, parameters })\n }\n return out\n } catch (err) {\n log.warn(\"failed to fetch opencode tool list\", {\n provider,\n model,\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n}\n","import { spawn, type ChildProcess } from \"node:child_process\"\nimport { createInterface } from \"node:readline\"\nimport { EventEmitter } from \"node:events\"\nimport { unlink } from \"node:fs/promises\"\nimport { log } from \"./logger.js\"\nimport type { ProxyMcpServer } from \"./proxy-mcp.js\"\nimport { clearLedger } from \"./todo-ledger.js\"\nimport { clearExitPlanModeQuestions } from \"./plan-mode-question.js\"\nimport {\n cliSupportsThinking,\n cliSupportsThinkingDisplay,\n type CliVersion,\n} from \"./cli-version.js\"\n\nexport interface ActiveProcess {\n proc: ChildProcess\n lineEmitter: EventEmitter\n proxyServer?: ProxyMcpServer | null\n /**\n * Hash of the bridged opencode MCP config the process was spawned with.\n * `null` when the bridge produced nothing (no MCP servers). `undefined`\n * when the bridge was disabled. Used to detect mid-session config drift\n * and force a respawn.\n */\n mcpHash?: string | null\n /** Temp file holding `--append-system-prompt-file` content; unlinked on exit. */\n systemPromptFile?: string\n}\n\n// One active CLI process per session key. Keyed by a composite\n// (cwd + model + opencode session-affinity) so two chats don't race.\n// Iteration order is insertion order, which we refresh on access to\n// make this a poor-man's LRU; see `touch()` below.\nconst activeProcesses = new Map<string, ActiveProcess>()\nconst claudeSessions = new Map<string, string>()\n\n// Cap on live CLI subprocesses. Session-affinity-keyed entries accumulate\n// one-per-chat, so an unbounded map would leak processes as users open new\n// chats. This caps at a reasonable working-set and evicts the oldest.\nconst MAX_ACTIVE_PROCESSES = 16\nconst PROCESS_EXIT_TIMEOUT_MS = 1_500\nconst PROCESS_FORCE_EXIT_TIMEOUT_MS = 500\n\nfunction envFlagEnabled(value: string | undefined): boolean {\n if (value === undefined) return false\n const normalized = value.trim().toLowerCase()\n if (!normalized) return false\n return ![\"0\", \"false\", \"no\", \"off\"].includes(normalized)\n}\n\nexport function isClaudeThinkingDisabled(): boolean {\n return (\n envFlagEnabled(process.env.CLAUDE_CODE_DISABLE_THINKING) ||\n envFlagEnabled(process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING)\n )\n}\n\nexport function claudeSpawnEnv(opts?: {\n ignoreAnthropicApiKey?: boolean\n}): Record<string, string | undefined> {\n const env: Record<string, string | undefined> = {\n ...process.env,\n TERM: \"xterm-256color\",\n }\n\n // Force subscription auth: with an API key in the env, Claude Code bills\n // pay-as-you-go (Console) instead of the logged-in plan, bypassing the\n // Agent SDK credit. Opt-in via `ignoreAnthropicApiKey`.\n if (opts?.ignoreAnthropicApiKey) {\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_AUTH_TOKEN\n }\n\n // Default-on thinking summaries for opus-4-7 (which omits thinking by\n // default on the CLI side). Any var the user has explicitly set in their\n // shell is passed through untouched; the plugin only fills in the default.\n if (\n !isClaudeThinkingDisabled() &&\n process.env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES === undefined\n ) {\n env.CLAUDE_CODE_SHOW_THINKING_SUMMARIES = \"1\"\n }\n\n return env\n}\n\nfunction touch(key: string): void {\n const existing = activeProcesses.get(key)\n if (existing) {\n activeProcesses.delete(key)\n activeProcesses.set(key, existing)\n }\n}\n\nfunction evictIfNeeded(): void {\n while (activeProcesses.size >= MAX_ACTIVE_PROCESSES) {\n const oldestKey = activeProcesses.keys().next().value\n if (!oldestKey) break\n log.info(\"evicting LRU claude process\", { sessionKey: oldestKey })\n deleteActiveProcess(oldestKey)\n }\n}\n\nexport function getActiveProcess(key: string): ActiveProcess | undefined {\n const ap = activeProcesses.get(key)\n if (ap) touch(key)\n return ap\n}\n\nexport function setActiveProcess(key: string, ap: ActiveProcess): void {\n activeProcesses.set(key, ap)\n}\n\nfunction detachActiveProcess(key: string): ActiveProcess | undefined {\n const ap = activeProcesses.get(key)\n if (!ap) return undefined\n activeProcesses.delete(key)\n void ap.proxyServer?.close()\n return ap\n}\n\nexport function deleteActiveProcess(key: string): void {\n const ap = detachActiveProcess(key)\n ap?.proc.kill()\n}\n\nfunction hasProcessExited(proc: ChildProcess): boolean {\n return proc.exitCode !== null || proc.signalCode !== null\n}\n\nfunction waitForProcessExit(\n proc: ChildProcess,\n timeoutMs: number,\n): Promise<boolean> {\n if (hasProcessExited(proc)) return Promise.resolve(true)\n\n return new Promise((resolve) => {\n const onExit = () => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n proc.off(\"exit\", onExit)\n resolve(hasProcessExited(proc))\n }, timeoutMs)\n proc.once(\"exit\", onExit)\n })\n}\n\nexport async function deleteActiveProcessAndWait(\n key: string,\n options: {\n exitTimeoutMs?: number\n forceExitTimeoutMs?: number\n } = {},\n): Promise<boolean> {\n const ap = detachActiveProcess(key)\n if (!ap || hasProcessExited(ap.proc)) return true\n\n const gracefulExit = waitForProcessExit(\n ap.proc,\n options.exitTimeoutMs ?? PROCESS_EXIT_TIMEOUT_MS,\n )\n ap.proc.kill()\n if (await gracefulExit) return true\n\n const forcedExit = waitForProcessExit(\n ap.proc,\n options.forceExitTimeoutMs ?? PROCESS_FORCE_EXIT_TIMEOUT_MS,\n )\n ap.proc.kill(\"SIGKILL\")\n if (await forcedExit) return true\n\n log.warn(\"claude process did not exit; starting a fresh session\", {\n sessionKey: key,\n })\n deleteClaudeSessionId(key)\n return false\n}\n\nexport function getClaudeSessionId(key: string): string | undefined {\n return claudeSessions.get(key)\n}\n\nexport function setClaudeSessionId(key: string, sessionId: string): void {\n claudeSessions.set(key, sessionId)\n}\n\nexport function deleteClaudeSessionId(key: string): void {\n clearExitPlanModeQuestions(key)\n const claudeSessionId = claudeSessions.get(key)\n if (claudeSessionId) clearLedger(claudeSessionId)\n claudeSessions.delete(key)\n}\n\nexport function spawnClaudeProcess(\n cliPath: string,\n cliArgs: string[],\n cwd: string,\n sessionKey: string,\n proxyServer?: ProxyMcpServer | null,\n mcpHash?: string | null,\n systemPromptFile?: string,\n ignoreAnthropicApiKey?: boolean,\n): ActiveProcess {\n evictIfNeeded()\n log.info(\"spawning new claude process\", { cliPath, cliArgs, cwd, sessionKey })\n\n const proc = spawn(cliPath, cliArgs, {\n cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: claudeSpawnEnv({ ignoreAnthropicApiKey }),\n shell: process.platform === \"win32\",\n })\n\n const lineEmitter = new EventEmitter()\n\n const rl = createInterface({ input: proc.stdout! })\n rl.on(\"line\", (line: string) => {\n lineEmitter.emit(\"line\", line)\n })\n rl.on(\"close\", () => {\n lineEmitter.emit(\"close\")\n })\n\n const ap: ActiveProcess = {\n proc,\n lineEmitter,\n proxyServer: proxyServer ?? null,\n mcpHash,\n systemPromptFile,\n }\n activeProcesses.set(sessionKey, ap)\n\n // Baseline 'error' listener so Node doesn't throw when the process emits\n // an error between stream turns (no per-stream listener attached then).\n proc.on(\"error\", (err) => {\n log.error(\"claude process error\", { sessionKey, error: err.message })\n })\n\n proc.on(\"exit\", (code, signal) => {\n log.info(\"claude process exited\", { code, signal, sessionKey })\n void proxyServer?.close()\n if (systemPromptFile) {\n void unlink(systemPromptFile).catch(() => {})\n }\n const ownsSessionKey = activeProcesses.get(sessionKey) === ap\n if (ownsSessionKey) activeProcesses.delete(sessionKey)\n if (ownsSessionKey && code !== 0 && code !== null) {\n log.info(\"process exited with error, clearing session\", {\n code,\n sessionKey,\n })\n claudeSessions.delete(sessionKey)\n }\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n const stderr = data.toString()\n log.debug(\"stderr\", { data: stderr.slice(0, 200) })\n\n // \"No conversation found with session ID: <uuid>\" is what `--resume`\n // prints for a purged transcript — note the lowercase \"session ID\",\n // which the capitalized match below does not catch.\n if (\n stderr.includes(\"No conversation found\") ||\n (stderr.includes(\"Session ID\") &&\n (stderr.includes(\"already in use\") ||\n stderr.includes(\"not found\") ||\n stderr.includes(\"invalid\")))\n ) {\n if (activeProcesses.get(sessionKey) === ap) {\n log.warn(\"claude session ID error, clearing session\", {\n sessionKey,\n error: stderr.slice(0, 200),\n })\n claudeSessions.delete(sessionKey)\n } else {\n log.debug(\"ignoring session ID error from stale claude process\", {\n sessionKey,\n })\n }\n }\n })\n\n return ap\n}\n\n/**\n * Append `--resume <id>` to an already-built args vector when a Claude\n * conversation id is known for the session and the args don't already carry\n * a session flag. Used by `respawnActiveProcess` to resume the conversation\n * in a fresh child without rebuilding the whole (version-gated) args vector.\n * `--resume`, not `--session-id`: the latter means \"create a NEW session\n * with this UUID\" and the CLI rejects it with \"Session ID ... is already in\n * use\" whenever a transcript exists on disk — which is exactly the state a\n * mid-conversation respawn is in. If the wedged child died before writing\n * any transcript, `--resume` fails with \"No conversation found with session\n * ID\", which the stderr recovery matcher already catches (fresh-session\n * fallback).\n */\nexport function appendResumeIfNeeded(\n sessionKey: string,\n cliArgs: string[],\n): string[] {\n if (cliArgs.includes(\"--resume\") || cliArgs.includes(\"--session-id\")) {\n return cliArgs\n }\n const sid = claudeSessions.get(sessionKey)\n if (!sid) return cliArgs\n return [...cliArgs, \"--resume\", sid]\n}\n\n/**\n * Replace a wedged reused process with a fresh one, resuming the same\n * Claude conversation. Used by the doStream start-watchdog when a reused\n * process produces no stdout within a grace window after a fresh-turn\n * envelope write — observed after a very long proxy-blocked tool call\n * (e.g. a multi-minute `task` subagent). Before the per-tool proxy timeout\n * fix this was masked because the flat 10-minute ceiling ended the turn\n * first; now that the task proxy blocks and returns successfully, resuming\n * a reused child after such a long wait can leave it silent on stdout.\n *\n * Reuses the existing proxy server, system-prompt file, and MCP hash (their\n * handles are already baked into `cliArgs`' `--mcp-config`/append-prompt\n * paths), so this only swaps the child process. The old child's exit\n * handler is silenced before kill so it doesn't close the proxy server we\n * are reusing; the new child gets its own exit handler from\n * `spawnClaudeProcess`. `claudeSessions` is left intact so the respawn can\n * add `--resume` (see `appendResumeIfNeeded`).\n *\n * Returns the new `ActiveProcess`, or `undefined` if there was no active\n * process for the key (caller should treat that as \"nothing to respawn\").\n */\nexport function respawnActiveProcess(\n sessionKey: string,\n cliPath: string,\n cliArgs: string[],\n cwd: string,\n ignoreAnthropicApiKey?: boolean,\n): ActiveProcess | undefined {\n const old = activeProcesses.get(sessionKey)\n if (!old) return undefined\n activeProcesses.delete(sessionKey)\n // Silence the old exit handler so it doesn't close the proxy server,\n // unlink the system-prompt file, or touch claudeSessions on its way out\n // — those handles are reused by the new child. spawnClaudeProcess wires\n // a fresh exit handler for the respawned child.\n old.proc.removeAllListeners(\"exit\")\n try {\n old.proc.kill()\n } catch {}\n return spawnClaudeProcess(\n cliPath,\n appendResumeIfNeeded(sessionKey, cliArgs),\n cwd,\n sessionKey,\n old.proxyServer,\n old.mcpHash,\n old.systemPromptFile,\n ignoreAnthropicApiKey,\n )\n}\n\nexport function buildCliArgs(opts: {\n sessionKey: string\n skipPermissions: boolean\n includeSessionId?: boolean\n model?: string\n permissionMode?: string\n mcpConfig?: string | string[]\n strictMcpConfig?: boolean\n disallowedTools?: string[]\n appendSystemPromptFile?: string\n thinking?: \"enabled\" | \"disabled\"\n thinkingDisplay?: \"summarized\" | \"omitted\"\n cliVersion?: CliVersion | null\n}): string[] {\n const {\n sessionKey,\n skipPermissions,\n includeSessionId = true,\n model,\n permissionMode,\n mcpConfig,\n strictMcpConfig,\n disallowedTools,\n appendSystemPromptFile,\n thinking,\n thinkingDisplay,\n cliVersion,\n } = opts\n const args = [\n \"--print\",\n \"--output-format\",\n \"stream-json\",\n \"--input-format\",\n \"stream-json\",\n \"--include-partial-messages\",\n \"--verbose\",\n ]\n\n if (model) {\n args.push(\"--model\", model)\n }\n\n if (permissionMode) {\n args.push(\"--permission-mode\", permissionMode)\n }\n\n // `--session-id` means \"create a NEW session with this UUID\" and the CLI\n // exits with \"Session ID ... is already in use\" whenever a transcript for\n // that ID already exists on disk. Continuing an existing session requires\n // `--resume` (which keeps the same session ID in print mode).\n if (includeSessionId) {\n const sessionId = claudeSessions.get(sessionKey)\n if (sessionId && !activeProcesses.has(sessionKey)) {\n args.push(\"--resume\", sessionId)\n }\n }\n\n if (mcpConfig) {\n const configs = Array.isArray(mcpConfig) ? mcpConfig : [mcpConfig]\n const filtered = configs.filter((c) => typeof c === \"string\" && c.length > 0)\n if (filtered.length > 0) {\n args.push(\"--mcp-config\", ...filtered)\n }\n }\n\n if (strictMcpConfig) {\n args.push(\"--strict-mcp-config\")\n }\n\n if (disallowedTools && disallowedTools.length > 0) {\n args.push(\"--disallowedTools\", ...disallowedTools)\n }\n\n // `--thinking` is only present from Claude Code 2.x onward; gate so\n // pre-2.x binaries don't crash with a parse error. Unknown version →\n // skip (the spawn still works, the user just doesn't get extended\n // thinking until they upgrade).\n if (thinking && cliSupportsThinking(cliVersion ?? null)) {\n args.push(\"--thinking\", thinking)\n }\n\n // `--thinking-display` was added in Claude Code 2.1.142. Older CLIs\n // reject it with a parse error, so gate on detected version. When\n // version is unknown (detection failed), be conservative and skip.\n if (thinkingDisplay && cliSupportsThinkingDisplay(cliVersion ?? null)) {\n args.push(\"--thinking-display\", thinkingDisplay)\n }\n\n if (appendSystemPromptFile) {\n args.push(\"--append-system-prompt-file\", appendSystemPromptFile)\n }\n\n if (skipPermissions) {\n args.push(\"--dangerously-skip-permissions\")\n }\n\n return args\n}\n\n/**\n * Build a session key that includes both cwd and model,\n * so different models get separate processes.\n */\nexport function sessionKey(cwd: string, modelId: string): string {\n return `${cwd}::${modelId}`\n}\n","import { execFile } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { log } from \"./logger.js\"\n\nconst execFileAsync = promisify(execFile)\n\nexport interface CliVersion {\n major: number\n minor: number\n patch: number\n raw: string\n}\n\nconst cache = new Map<string, Promise<CliVersion | null>>()\n\n/**\n * Run `claude --version` once per cliPath and parse the leading semver.\n * Returns null on any failure (binary missing, unparseable output, etc.)\n * so callers can fall back to the most conservative flag set.\n */\nexport function detectCliVersion(cliPath: string): Promise<CliVersion | null> {\n const cached = cache.get(cliPath)\n if (cached) return cached\n const promise = (async (): Promise<CliVersion | null> => {\n try {\n const { stdout } = await execFileAsync(cliPath, [\"--version\"], {\n timeout: 5000,\n })\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)/.exec(stdout.trim())\n if (!match) {\n log.warn(\"claude --version output unparseable\", { stdout: stdout.trim() })\n return null\n }\n const v: CliVersion = {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n raw: stdout.trim(),\n }\n log.info(\"detected claude cli version\", { cliPath, version: v.raw })\n if (!cliSupportsThinkingDisplay(v)) {\n log.notice(\n \"claude cli < 2.1.142 detected; Opus 4.7 thinking summaries unavailable. Run `npm i -g @anthropic-ai/claude-code` to upgrade.\",\n { version: v.raw },\n )\n }\n return v\n } catch (err) {\n log.warn(\"failed to detect claude cli version\", {\n cliPath,\n error: err instanceof Error ? err.message : String(err),\n })\n return null\n }\n })()\n cache.set(cliPath, promise)\n return promise\n}\n\nfunction gte(v: CliVersion, target: { major: number; minor: number; patch: number }): boolean {\n if (v.major !== target.major) return v.major > target.major\n if (v.minor !== target.minor) return v.minor > target.minor\n return v.patch >= target.patch\n}\n\n/**\n * `--thinking-display` was introduced in Claude Code 2.1.142 alongside\n * Opus 4.7's \"omitted by default\" thinking behavior. Older CLIs reject\n * the flag with a parse error, so we gate it. Unknown version → return\n * false so we don't risk crashing the spawn.\n */\nexport function cliSupportsThinkingDisplay(v: CliVersion | null): boolean {\n if (!v) return false\n return gte(v, { major: 2, minor: 1, patch: 142 })\n}\n\n/**\n * `--thinking` has been part of Claude Code's CLI since the 2.x line.\n * We require a detected 2.0.0+ before passing it; unknown version → skip\n * to avoid crashing a pre-flag binary. Anyone on the 1.x line should\n * upgrade.\n */\nexport function cliSupportsThinking(v: CliVersion | null): boolean {\n if (!v) return false\n return gte(v, { major: 2, minor: 0, patch: 0 })\n}\n\n/** For tests. */\nexport function _clearCache(): void {\n cache.clear()\n}\n","import { EventEmitter } from \"node:events\"\nimport { unlink } from \"node:fs/promises\"\nimport { ClaudeSession } from \"./claude-session-bun.js\"\nimport type { ActiveProcess } from \"./session-manager.js\"\nimport { log } from \"./logger.js\"\n\nexport interface InteractiveSpawnOptions {\n cwd: string\n /** Claude CLI executable or account wrapper path. */\n cliPath?: string\n /** Claude config root used for JSONL transcripts. */\n configDir?: string\n model?: string\n /** Bridged Claude `--mcp-config` file paths (from effectiveMcpConfig). */\n mcpConfigPaths?: string[]\n /** permissions.allow rules (e.g. mcp__server__*, Bash, Edit). */\n permissionsAllow?: string[]\n /** Optional permission mode. `bypassPermissions` is ignored for interactive\n * sessions because Claude Code shows a safety confirmation screen first. */\n permissionMode?: string\n /** Temp file for --append-system-prompt-file (parity with the headless\n * spawn; unlinked when the session is killed). */\n systemPromptFile?: string\n /** \"\" = skip CLAUDE.md + ambient settings (fast e2e); null/undefined =\n * normal settings (default — parity with the headless transport). */\n settingSources?: string | null\n /** Strip ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN from the spawn env so the\n * CLI uses subscription auth instead of pay-as-you-go API billing. */\n ignoreAnthropicApiKey?: boolean\n}\n\n/**\n * doStream writes stream-json user envelopes to stdin\n * (`{\"type\":\"user\",\"message\":{content:[...]}}`). The interactive TUI expects\n * plain typed text, so decode the envelope: extract the text blocks and drop\n * anything that can't be typed into a terminal (an image block would paste\n * megabytes of base64 into the chat). Tool results are rendered as labeled\n * text so the model still sees the outcome. Non-envelope input (already plain\n * text) passes through verbatim.\n */\nexport function decodeUserEnvelope(chunk: string): string {\n let parsed: any\n try {\n parsed = JSON.parse(chunk)\n } catch {\n return chunk\n }\n if (!parsed || parsed.type !== \"user\" || !parsed.message) return chunk\n const content = parsed.message.content\n if (typeof content === \"string\") return content\n if (!Array.isArray(content)) return chunk\n\n const parts: string[] = []\n let dropped = 0\n for (const block of content) {\n if (block?.type === \"text\" && typeof block.text === \"string\") {\n parts.push(block.text)\n } else if (block?.type === \"tool_result\") {\n const v = block.content\n const text =\n typeof v === \"string\"\n ? v\n : Array.isArray(v)\n ? v\n .map((i: any) => (i?.type === \"text\" ? i.text : \"\"))\n .filter(Boolean)\n .join(\"\\n\")\n : \"\"\n parts.push(\n `[Tool result${block.tool_use_id ? ` ${block.tool_use_id}` : \"\"}]\\n${text}`,\n )\n } else {\n dropped++\n }\n }\n if (dropped > 0) {\n log.warn(\"interactive transport dropped non-text content blocks\", {\n dropped,\n })\n }\n return parts.join(\"\\n\\n\")\n}\n\n/**\n * Adapt a ClaudeSession (interactive Bun ConPTY transport) to the ActiveProcess\n * contract the doStream line handler depends on. The shim's `proc.stdin.write`\n * injects a turn into the live interactive `claude` and re-emits each new JSONL\n * transcript record on `lineEmitter` as a 'line' event, plus a synthetic\n * `{type:'result'}` line on a terminal stop_reason so the existing finish branch\n * (usage + providerMetadata + controller.close) fires unchanged.\n *\n * No node-pty, no node sidecar: runs in-process under opencode's Bun (which\n * bundles a Bun version with native ConPTY). Interactive = subscription billing.\n */\nexport function spawnInteractiveProcess(\n opts: InteractiveSpawnOptions,\n): ActiveProcess {\n const extraArgs: string[] = []\n if (opts.mcpConfigPaths && opts.mcpConfigPaths.length > 0) {\n extraArgs.push(\n \"--mcp-config\",\n ...opts.mcpConfigPaths,\n \"--strict-mcp-config\",\n )\n }\n if (opts.permissionsAllow && opts.permissionsAllow.length > 0) {\n extraArgs.push(\n \"--settings\",\n JSON.stringify({ permissions: { allow: opts.permissionsAllow } }),\n )\n }\n if (opts.permissionMode === \"bypassPermissions\") {\n log.warn(\n \"interactive permissionMode bypassPermissions ignored: Claude Code prompts for confirmation in the TUI\",\n )\n } else if (opts.permissionMode) {\n extraArgs.push(\"--permission-mode\", opts.permissionMode)\n }\n if (opts.systemPromptFile) {\n extraArgs.push(\"--append-system-prompt-file\", opts.systemPromptFile)\n }\n\n const session = new ClaudeSession({\n cwd: opts.cwd,\n cliPath: opts.cliPath,\n configDir: opts.configDir,\n model: opts.model,\n // Default null = normal CLAUDE.md + settings load, matching what the\n // headless spawn does. \"\" (skip everything) is for fast e2e runs only.\n settingSources:\n opts.settingSources === undefined ? null : opts.settingSources,\n extraArgs,\n ignoreAnthropicApiKey: opts.ignoreAnthropicApiKey,\n })\n log.info(\"prepared interactive claude session\", {\n cwd: opts.cwd,\n cliPath: opts.cliPath ?? \"claude\",\n configDir: session.configDir,\n model: opts.model,\n sessionId: session.sessionId,\n jsonlPath: session.jsonlPath,\n })\n\n const lineEmitter = new EventEmitter()\n const errorHandlers = new Set<(err: Error) => void>()\n let startPromise: Promise<void> | null = null\n\n const ensureStarted = (): Promise<void> => {\n if (!startPromise) startPromise = session.start()\n return startPromise\n }\n\n const emitResult = (\n subtype: string,\n isError: boolean,\n result?: string,\n usage?: unknown,\n ): void => {\n lineEmitter.emit(\n \"line\",\n JSON.stringify({\n type: \"result\",\n subtype,\n is_error: isError,\n result,\n session_id: session.sessionId,\n usage: usage ?? {},\n total_cost_usd: null,\n duration_ms: 0,\n }),\n )\n }\n\n const runTurn = (userMsg: string): void => {\n void (async () => {\n try {\n await ensureStarted()\n const { stopReason, usage } = await session.tailTurn(userMsg, (raw) => {\n lineEmitter.emit(\"line\", raw)\n })\n // Synthesize the `result` line the headless transport would have\n // emitted, so doStream's existing finish branch runs verbatim. A turn\n // with no terminal stop_reason (timeout / session exit mid-turn) is\n // reported HONESTLY as an error result — not a clean end_turn — so\n // truncation is visible to the user and to auto-continue.\n const timedOut = !stopReason\n emitResult(\n timedOut ? \"error_during_execution\" : stopReason,\n timedOut,\n timedOut\n ? \"Interactive transport: the turn ended without a terminal stop_reason (turn timeout or claude exit). Output above may be incomplete.\"\n : undefined,\n usage,\n )\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err))\n log.error(\"interactive turn failed\", { error: e.message })\n emitResult(\n \"error_during_execution\",\n true,\n `Interactive transport failed: ${e.message}`,\n )\n if (errorHandlers.size > 0) {\n for (const h of errorHandlers) h(e)\n } else {\n lineEmitter.emit(\"close\")\n }\n }\n })()\n }\n\n // Minimal ChildProcess-shaped shim: only the members doStream/session-manager\n // actually touch (stdin.write, on/off 'error', kill).\n const proc: any = {\n stdin: {\n write(chunk: string): boolean {\n const raw =\n typeof chunk === \"string\" && chunk.endsWith(\"\\n\")\n ? chunk.slice(0, -1)\n : chunk\n // doStream writes stream-json envelopes; the TUI needs plain text.\n runTurn(decodeUserEnvelope(raw))\n return true\n },\n end(): void {},\n },\n stdout: null,\n stderr: null,\n pid: -1,\n killed: false,\n on(event: string, fn: (err: Error) => void): unknown {\n if (event === \"error\") errorHandlers.add(fn)\n return proc\n },\n once(): unknown {\n return proc\n },\n off(event: string, fn: (err: Error) => void): unknown {\n if (event === \"error\") errorHandlers.delete(fn)\n return proc\n },\n kill(): boolean {\n try {\n session.dispose()\n } catch {}\n if (opts.systemPromptFile) {\n void unlink(opts.systemPromptFile).catch(() => {})\n }\n proc.killed = true\n return true\n },\n }\n\n return {\n proc: proc as unknown as ActiveProcess[\"proc\"],\n lineEmitter,\n proxyServer: null,\n mcpHash: undefined,\n systemPromptFile: opts.systemPromptFile,\n }\n}\n","import * as os from \"node:os\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport { execFileSync } from \"node:child_process\"\nimport { randomUUID } from \"node:crypto\"\n\n/**\n * Persistent interactive Claude Code session driven over Bun's NATIVE PTY\n * (Bun.spawn `terminal` option = openpty on POSIX, ConPTY on Windows). This is\n * the in-process Bun port of claude-tui-bridge/src/claudeSession.ts: same\n * design, node-pty swapped for Bun's own ConPTY so it runs inside opencode's\n * Bun runtime with NO node sidecar and NO node-pty dependency.\n *\n * - ONE long-lived interactive `claude` process per session (multi-turn),\n * - turns injected by writing into the terminal (bracketed paste + Enter),\n * - replies captured by tailing the session JSONL transcript\n * (<CLAUDE_CONFIG_DIR>/projects/<encoded-cwd>/<session-id>.jsonl) and\n * parsing the assistant records; completion detected by a terminal\n * `stop_reason`.\n *\n * Driving the INTERACTIVE TUI (real TTY) keeps model calls on the subscription\n * billing path (not `claude -p` / Agent SDK, which meter after 2026-06-15).\n */\n\nfunction resolveClaude(cmd = \"claude\"): string {\n if (path.isAbsolute(cmd) && fs.existsSync(cmd)) return cmd\n const viaBun = Bun.which(cmd)\n if (viaBun) return viaBun\n const isWin = os.platform() === \"win32\"\n try {\n const out = execFileSync(isWin ? \"where\" : \"which\", [cmd], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n const first = out\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean)\n .find((p) => fs.existsSync(p))\n if (first) return first\n } catch {}\n throw new Error(`Could not resolve command on PATH: ${cmd}`)\n}\n\n/** Claude encodes the absolute cwd into the transcript dir name by replacing\n * EVERY non-alphanumeric char with `-` (no collapsing of runs). Verified on\n * Windows against ~/.claude/projects, e.g.:\n * C:\\code\\my-app -> C--code-my-app\n * C:\\dev\\My Project -> C--dev-My-Project (the space also becomes `-`). */\nexport function encodeCwd(cwd: string): string {\n return path.resolve(cwd).replace(/[^a-zA-Z0-9]/g, \"-\")\n}\n\nexport interface TurnResult {\n text: string\n stopReason: string | null\n usage: any | null\n cacheReadTokens: number\n cacheCreationTokens: number\n ephemeral1hTokens: number\n ephemeral5mTokens: number\n inputTokens: number\n outputTokens: number\n elapsedMs: number\n}\n\nexport interface ClaudeSessionOptions {\n cwd?: string\n /** Claude CLI executable or account wrapper path. */\n cliPath?: string\n /** Claude config root used for JSONL transcripts (defaults to ~/.claude). */\n configDir?: string\n model?: string\n /** '' bypasses CLAUDE.md + user/project/local settings load (fast tests).\n * null/undefined omits the flag entirely (normal settings). */\n settingSources?: string | null\n extraArgs?: string[]\n /** Strip ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN from the spawn env so the\n * CLI uses subscription auth instead of pay-as-you-go API billing. */\n ignoreAnthropicApiKey?: boolean\n cols?: number\n rows?: number\n bootMinMs?: number\n bootQuietMs?: number\n bootMaxMs?: number\n pollMs?: number\n turnTimeoutMs?: number\n /** false = plain write(prompt)+Enter; true = wrap in bracketed-paste so\n * multi-line prompts don't submit early. Default true. */\n bracketedPaste?: boolean\n /** Submitting a turn: a large/multi-line bracketed paste collapses into a\n * \"[Pasted text]\" placeholder, and an Enter sent while claude is still\n * ingesting the paste is silently DROPPED — so a single fixed-delay Enter is\n * unreliable and the turn can hang until turnTimeoutMs. Instead: wait\n * submitMinMs, send Enter, then confirm the turn was accepted (a new\n * transcript record appears) within submitConfirmMs; if not, resend Enter,\n * up to submitMaxRetries times. */\n submitMinMs?: number\n submitConfirmMs?: number\n submitMaxRetries?: number\n /** Abort the call (during boot or an in-flight turn): kills the process and\n * rejects with an \"aborted\" error. */\n signal?: AbortSignal\n debug?: boolean\n}\n\nconst TERMINAL_STOP = new Set([\"end_turn\", \"stop_sequence\", \"max_tokens\"])\nconst delay = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))\n\nfunction resolveConfigDir(configDir: string | undefined): string {\n const value = configDir ?? process.env.CLAUDE_CONFIG_DIR\n if (!value) return path.join(os.homedir(), \".claude\")\n if (value === \"~\") return os.homedir()\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return path.join(os.homedir(), value.slice(2))\n }\n return path.resolve(value)\n}\n\nexport class ClaudeSession {\n readonly sessionId: string\n readonly cwd: string\n readonly configDir: string\n readonly jsonlPath: string\n raw = \"\"\n\n private proc: BunSubprocess | null = null\n private cursor = 0 // index into transcript split('\\n')\n private lastDataAt = 0\n private exited = false\n private exitCode: number | null = null\n private aborted = false\n private readonly signal?: AbortSignal\n private readonly o: Required<\n Omit<\n ClaudeSessionOptions,\n | \"cliPath\"\n | \"configDir\"\n | \"model\"\n | \"settingSources\"\n | \"extraArgs\"\n | \"signal\"\n | \"ignoreAnthropicApiKey\"\n >\n > &\n Pick<\n ClaudeSessionOptions,\n | \"cliPath\"\n | \"configDir\"\n | \"model\"\n | \"settingSources\"\n | \"extraArgs\"\n | \"ignoreAnthropicApiKey\"\n >\n\n constructor(opts: ClaudeSessionOptions = {}) {\n this.cwd = path.resolve(opts.cwd ?? process.cwd())\n this.configDir = resolveConfigDir(opts.configDir)\n this.signal = opts.signal\n this.sessionId = randomUUID()\n this.jsonlPath = path.join(\n this.configDir,\n \"projects\",\n encodeCwd(this.cwd),\n `${this.sessionId}.jsonl`,\n )\n this.o = {\n cwd: this.cwd,\n cliPath: opts.cliPath,\n configDir: this.configDir,\n model: opts.model,\n settingSources: opts.settingSources,\n extraArgs: opts.extraArgs ?? [],\n ignoreAnthropicApiKey: opts.ignoreAnthropicApiKey,\n cols: opts.cols ?? 200,\n rows: opts.rows ?? 50,\n bootMinMs: opts.bootMinMs ?? 3000,\n bootQuietMs: opts.bootQuietMs ?? 1500,\n bootMaxMs: opts.bootMaxMs ?? 25000,\n pollMs: opts.pollMs ?? 250,\n // Agentic turns (tool loops) routinely run for many minutes; a short\n // cap would surface as a mid-task error result. 30 min mirrors the\n // proxy-tool ceiling rather than a chat-reply expectation.\n turnTimeoutMs: opts.turnTimeoutMs ?? 1_800_000,\n bracketedPaste: opts.bracketedPaste ?? true,\n submitMinMs: opts.submitMinMs ?? 200,\n submitConfirmMs: opts.submitConfirmMs ?? 1500,\n submitMaxRetries: opts.submitMaxRetries ?? 8,\n debug: opts.debug ?? false,\n }\n }\n\n async start(): Promise<void> {\n if (this.signal?.aborted) throw new Error(\"aborted before start\")\n this.signal?.addEventListener(\n \"abort\",\n () => {\n this.aborted = true\n this.dispose()\n },\n { once: true },\n )\n const claude = resolveClaude(this.o.cliPath ?? \"claude\")\n const args: string[] = [\"--session-id\", this.sessionId]\n if (this.o.model) args.push(\"--model\", this.o.model)\n if (this.o.settingSources !== null && this.o.settingSources !== undefined) {\n args.push(\"--setting-sources\", this.o.settingSources)\n }\n if (this.o.extraArgs && this.o.extraArgs.length) args.push(...this.o.extraArgs)\n\n if (this.o.debug)\n process.stderr.write(`[session] spawn: ${claude} ${args.join(\" \")}\\n`)\n\n this.lastDataAt = Date.now()\n this.proc = Bun.spawn([claude, ...args], {\n cwd: this.cwd,\n env: {\n ...process.env,\n CLAUDE_CONFIG_DIR: this.o.configDir,\n TERM: \"xterm-256color\",\n ...(this.o.ignoreAnthropicApiKey\n ? { ANTHROPIC_API_KEY: undefined, ANTHROPIC_AUTH_TOKEN: undefined }\n : {}),\n },\n terminal: {\n cols: this.o.cols,\n rows: this.o.rows,\n data: (_term, d) => {\n this.lastDataAt = Date.now()\n const chunk = Buffer.from(d).toString(\"utf8\")\n this.raw += chunk\n if (this.o.debug) process.stdout.write(chunk)\n },\n },\n })\n this.proc.exited\n .then((code) => {\n this.exitCode = typeof code === \"number\" ? code : null\n this.exited = true\n this.proc = null\n })\n .catch(() => {\n this.exited = true\n this.proc = null\n })\n\n await this.waitForBoot()\n this.cursor = this.lineCount()\n }\n\n /** Wait until the TUI has been quiet for bootQuietMs (Ink ready), bounded by\n * bootMinMs..bootMaxMs. */\n private async waitForBoot(): Promise<void> {\n const start = Date.now()\n while (Date.now() - start < this.o.bootMaxMs) {\n await delay(150)\n if (this.aborted) throw new Error(\"aborted during boot\")\n if (this.exited) {\n throw new Error(this.failureMessage(\"claude exited during boot\", true))\n }\n const elapsed = Date.now() - start\n const sinceData = Date.now() - this.lastDataAt\n if (elapsed >= this.o.bootMinMs && sinceData >= this.o.bootQuietMs) return\n }\n }\n\n /** Submit the freshly-injected prompt and confirm the turn was actually\n * accepted. A large bracketed paste collapses into a \"[Pasted text]\"\n * placeholder; an Enter sent while claude is still ingesting the paste is\n * silently dropped, so a single fixed-delay Enter races the paste and can\n * leave the prompt sitting unsubmitted (→ hang until turnTimeoutMs). Send\n * Enter, then poll for transcript growth past the cursor (the turn's records\n * are written on acceptance); resend Enter until accepted or the retry\n * budget is spent. Polling growth (not a blind delay) also stops us from\n * sending a stray Enter once the turn is in flight. */\n private async submitTurn(): Promise<void> {\n await delay(this.o.submitMinMs)\n for (let attempt = 0; attempt < this.o.submitMaxRetries; attempt++) {\n if (this.aborted || this.exited || !this.proc) return\n this.proc.terminal.write(\"\\r\")\n const until = Date.now() + this.o.submitConfirmMs\n while (Date.now() < until) {\n await delay(80)\n if (this.aborted || this.exited) return\n if (this.lineCount() > this.cursor) return // turn accepted\n }\n }\n }\n\n private readRawLines(): string[] {\n try {\n return fs.readFileSync(this.jsonlPath, \"utf8\").split(\"\\n\")\n } catch {\n return []\n }\n }\n\n /** Count of complete lines (split('\\n') minus the trailing/partial element). */\n private lineCount(): number {\n const lines = this.readRawLines()\n return lines.length > 0 ? lines.length - 1 : 0\n }\n\n private rawTail(max = 600): string {\n const clean = this.raw\n // Strip ANSI escape/control sequences before including terminal output in diagnostics.\n .replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n return clean.length > max ? clean.slice(-max) : clean\n }\n\n private failureMessage(reason: string, includeRaw = false): string {\n const parts = [\n `${reason} (sessionId=${this.sessionId}, jsonlPath=${this.jsonlPath}, exitCode=${this.exitCode ?? \"unknown\"})`,\n ]\n if (includeRaw) {\n const tail = this.rawTail()\n if (tail) parts.push(`terminalTail=${JSON.stringify(tail)}`)\n }\n return parts.join(\"; \")\n }\n\n /**\n * Inject a turn into the live session and return the assistant reply once a\n * terminal stop_reason is observed in the transcript.\n */\n async ask(prompt: string, perTurnTimeoutMs?: number): Promise<TurnResult> {\n if (this.aborted) throw new Error(\"aborted\")\n if (!this.proc || this.exited)\n throw new Error(\"session not started or already exited\")\n const timeout = perTurnTimeoutMs ?? this.o.turnTimeoutMs\n const t0 = Date.now()\n\n // Inject. Bracketed paste keeps multi-line prompts from submitting early;\n // submitTurn() then presses Enter and confirms the turn was accepted,\n // resending Enter if the (collapsed) paste swallowed the first one.\n if (this.o.bracketedPaste) {\n this.proc.terminal.write(\"\\x1b[200~\" + prompt + \"\\x1b[201~\")\n } else {\n this.proc.terminal.write(prompt)\n }\n await this.submitTurn()\n\n const collected: string[] = []\n let lastUsage: any = null\n let stopReason: string | null = null\n const deadline = Date.now() + timeout\n\n while (Date.now() < deadline) {\n await delay(this.o.pollMs)\n if (this.aborted) throw new Error(\"aborted mid-turn\")\n const lines = this.readRawLines()\n const lastComplete = lines.length - 1 // exclusive bound; trailing/partial line skipped\n if (lastComplete <= this.cursor) {\n // Drain the transcript before reacting to exit: a final assistant record\n // can be flushed in the same tick the process exits.\n if (this.exited) throw new Error(this.failureMessage(\"claude exited mid-turn\", true))\n continue\n }\n\n for (let i = this.cursor; i < lastComplete; i++) {\n const s = lines[i]\n if (!s || !s.trim()) continue\n let rec: any\n try {\n rec = JSON.parse(s)\n } catch {\n continue\n }\n if (rec.type === \"assistant\" && rec.message) {\n for (const b of rec.message.content ?? []) {\n if (b?.type === \"text\" && typeof b.text === \"string\")\n collected.push(b.text)\n }\n if (rec.message.usage) lastUsage = rec.message.usage\n if (\n rec.message.stop_reason &&\n TERMINAL_STOP.has(rec.message.stop_reason)\n ) {\n stopReason = rec.message.stop_reason\n }\n }\n }\n this.cursor = lastComplete\n if (stopReason) break\n }\n\n if (!stopReason) {\n throw new Error(\n this.failureMessage(\n `turn timed out after ${timeout}ms (no terminal assistant record; collected ${collected.length} text block(s))`,\n ),\n )\n }\n\n const u = lastUsage ?? {}\n return {\n text: collected.join(\"\\n\").trim(),\n stopReason,\n usage: lastUsage,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n cacheCreationTokens: u.cache_creation_input_tokens ?? 0,\n ephemeral1hTokens: u.cache_creation?.ephemeral_1h_input_tokens ?? 0,\n ephemeral5mTokens: u.cache_creation?.ephemeral_5m_input_tokens ?? 0,\n inputTokens: u.input_tokens ?? 0,\n outputTokens: u.output_tokens ?? 0,\n elapsedMs: Date.now() - t0,\n }\n }\n\n /**\n * Like ask(), but instead of collecting the reply text it re-emits each NEW\n * raw JSONL transcript line via onLine (verbatim) until a terminal\n * stop_reason. Returns the terminal stop_reason + the last assistant usage.\n * Used by the opencode plugin transport shim, which feeds these raw lines\n * into the existing stream-json line handler unchanged.\n */\n async tailTurn(\n prompt: string,\n onLine: (rawLine: string) => void,\n perTurnTimeoutMs?: number\n ): Promise<{ stopReason: string | null; usage: any | null }> {\n if (this.aborted) throw new Error(\"aborted\")\n if (!this.proc || this.exited)\n throw new Error(\"session not started or already exited\")\n const timeout = perTurnTimeoutMs ?? this.o.turnTimeoutMs\n\n if (this.o.bracketedPaste) {\n this.proc.terminal.write(\"\\x1b[200~\" + prompt + \"\\x1b[201~\")\n } else {\n this.proc.terminal.write(prompt)\n }\n await this.submitTurn()\n\n let lastUsage: any = null\n let totalOutput = 0\n let stopReason: string | null = null\n const deadline = Date.now() + timeout\n\n while (Date.now() < deadline) {\n await delay(this.o.pollMs)\n if (this.aborted) throw new Error(\"aborted mid-turn\")\n const lines = this.readRawLines()\n const lastComplete = lines.length - 1\n if (lastComplete <= this.cursor) {\n // Drain the transcript before reacting to exit: the terminal assistant\n // record can land in the same tick the process exits.\n if (this.exited) {\n throw new Error(this.failureMessage(\"claude exited mid-turn\", true))\n }\n continue\n }\n for (let i = this.cursor; i < lastComplete; i++) {\n const s = lines[i]\n if (!s || !s.trim()) continue\n onLine(s)\n let rec: any\n try {\n rec = JSON.parse(s)\n } catch {\n continue\n }\n if (rec.type === \"assistant\" && rec.message) {\n if (rec.message.usage) {\n lastUsage = rec.message.usage\n totalOutput += rec.message.usage.output_tokens ?? 0\n }\n if (\n rec.message.stop_reason &&\n TERMINAL_STOP.has(rec.message.stop_reason)\n ) {\n stopReason = rec.message.stop_reason\n }\n }\n }\n this.cursor = lastComplete\n if (stopReason) break\n }\n\n // Context (input/cache) = the LAST record's full conversation state; output\n // = SUM across all assistant records this turn (each generation), else\n // multi-record tool turns undercount output. toUsage() prefers\n // iterations[last], so patch that entry's output too.\n let usage: any = lastUsage\n if (lastUsage) {\n usage = { ...lastUsage, output_tokens: totalOutput }\n if (Array.isArray(lastUsage.iterations) && lastUsage.iterations.length > 0) {\n const iters = lastUsage.iterations.map((it: any) => ({ ...it }))\n iters[iters.length - 1] = {\n ...iters[iters.length - 1],\n output_tokens: totalOutput,\n }\n usage.iterations = iters\n }\n }\n if (!stopReason) {\n throw new Error(\n this.failureMessage(\n `turn timed out after ${timeout}ms (no terminal assistant record)`,\n ),\n )\n }\n\n return { stopReason, usage }\n }\n\n dispose(): void {\n if (this.proc) {\n try {\n this.proc.terminal.write(\"\\x03\")\n } catch {}\n try {\n this.proc.kill()\n } catch {}\n try {\n this.proc.terminal.close()\n } catch {}\n }\n this.proc = null\n }\n}\n\n/** One-shot convenience (drop-in for `claude -p`): start, ask, dispose. */\nexport async function askOnce(\n prompt: string,\n opts: ClaudeSessionOptions = {},\n): Promise<TurnResult> {\n const s = new ClaudeSession(opts)\n await s.start()\n try {\n return await s.ask(prompt)\n } finally {\n s.dispose()\n }\n}\n","/**\n * Per-session state for the opt-in `compress` proxy tool.\n *\n * Keyed by session key (the same `cwd::modelId::scope::affinity` string\n * session-manager uses). When Claude calls the intercepted `compress` tool\n * the summary is stored here and the session is marked for restart. The\n * next `doStream` turn consumes that mark, evicts the running child and its\n * Claude session id, and the fresh spawn gets the summary prepended to its\n * appended system prompt.\n *\n * The summary deliberately survives `deleteClaudeSessionId()`: the restart\n * path calls it, so clearing there would wipe the summary microseconds\n * before the new spawn reads it (the original fork version did exactly\n * that, which made the whole feature a no-op). It is dropped when a new\n * opencode conversation starts on the same key, and by the entry cap below.\n */\n\nimport { log } from \"./logger.js\"\n\ninterface CompressionState {\n summary: string\n restartPending: boolean\n}\n\n/**\n * Session keys are bounded in practice by workspaces × models, and each\n * entry is one summary string, but a long-lived opencode process that\n * hops workspaces should not accumulate them forever.\n */\nconst MAX_COMPRESSION_ENTRIES = 32\n\nconst compressions = new Map<string, CompressionState>()\n\n/**\n * Record a summary and mark the session for restart. Storing and marking\n * are one event on purpose: a stored summary that never resets the session\n * would silently do nothing.\n */\nexport function storeCompressionSummary(sessionKey: string, summary: string): void {\n compressions.set(sessionKey, { summary, restartPending: true })\n while (compressions.size > MAX_COMPRESSION_ENTRIES) {\n const oldest = compressions.keys().next()\n if (oldest.done) break\n compressions.delete(oldest.value)\n log.info(\"compression store evicted oldest entry\", { sessionKey: oldest.value })\n }\n}\n\nexport function getCompressionSummary(sessionKey: string): string | undefined {\n return compressions.get(sessionKey)?.summary\n}\n\n/**\n * True once per compress call, for the turn that performs the reset. The\n * summary is kept: it is the prior context for every spawn that follows,\n * until a new conversation clears it.\n */\nexport function consumeCompressionRestart(sessionKey: string): boolean {\n const state = compressions.get(sessionKey)\n if (!state?.restartPending) return false\n state.restartPending = false\n return true\n}\n\nexport function clearCompression(sessionKey: string): void {\n compressions.delete(sessionKey)\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport * as crypto from \"node:crypto\"\nimport { EventEmitter } from \"node:events\"\nimport { log } from \"./logger.js\"\nimport { pluginTmpDir } from \"./tmp.js\"\n\n/**\n * Minimal MCP HTTP server embedded in-process. Exposes a set of \"proxy\"\n * tools (Bash, Edit, Write, etc.) that Claude CLI calls when its built-in\n * equivalents are disabled via --disallowedTools. Our handler blocks until\n * an external broker resolves the call, then responds to Claude.\n *\n * Wire protocol: JSON-RPC 2.0 over plain HTTP POST to `/mcp`. MCP spec\n * also supports SSE streaming, but Claude's HTTP transport accepts single\n * JSON responses for short-lived tool calls, so we keep it simple.\n */\n\nexport interface ProxyMcpServer {\n url: string\n serverName: string\n tools: ProxyToolDef[]\n /** Fires when Claude invokes one of our proxy tools. The handler resolves\n * the returned pending call once a result is available. */\n calls: EventEmitter\n /** Write `--mcp-config <path>`-compatible scratch file and return its path. */\n configPath(): string\n close(): Promise<void>\n}\n\nexport interface ProxyToolDef {\n /** Raw name as seen by Claude once proxied: the MCP exposed tool name. */\n name: string\n description: string\n inputSchema: Record<string, unknown>\n}\n\nexport interface ProxyToolCall {\n id: string\n toolName: string\n input: Record<string, unknown>\n resolve: (result: ProxyToolResult) => void\n reject: (err: Error) => void\n}\n\nexport type ProxyToolResult =\n | { kind: \"text\"; text: string; isError?: boolean }\n | { kind: \"error\"; message: string }\n\n/**\n * Handler that answers a `tools/call` inside this process instead of\n * queueing it for opencode. Used by tools that act on plugin state rather\n * than on the workspace (currently only `compress`), so they never reach\n * the broker, never block on a human, and have no deadline.\n */\nexport type ProxyToolInterceptor = (\n input: Record<string, unknown>,\n) => Promise<ProxyToolResult> | ProxyToolResult\n\nexport const SERVER_CLOSED_MESSAGE = \"proxy MCP server closed\"\n\n/** Rejections that fire on normal lifecycle transitions: AFK-permission\n * timeouts, orphan rejections at turn boundaries, stream aborts, and server\n * close while its owning Claude process exits or is replaced. None are\n * user-actionable — file-log them at NOTICE. Anything else stays WARN so\n * genuine bugs remain visible in the TUI. */\nexport function isExpectedCleanupError(message: string): boolean {\n return (\n (message.includes(\"timed out after\") &&\n message.includes(\"waiting for opencode to resolve\")) ||\n message.includes(\"rejecting as orphaned\") ||\n message.includes(\"was orphaned by a new user turn\") ||\n message.includes(\"stream was aborted\") ||\n message.includes(SERVER_CLOSED_MESSAGE)\n )\n}\n\nconst PROTOCOL_VERSION = \"2024-11-05\"\nconst SERVER_NAME = \"opencode_proxy\"\nexport const PROXY_TOOL_PREFIX = `mcp__${SERVER_NAME}__`\n\n// Flat fallback cap on how long a proxy tool call may wait for opencode to\n// resolve it. Matches Claude CLI's hard upper bound for Bash (10 min). The\n// effective deadline is resolved per tool — see `resolveProxyCallTimeoutMs`.\nexport const PROXY_DEFAULT_TIMEOUT_MS = 10 * 60 * 1000\n\n// Per-tool default deadlines, keyed by lowercase proxy tool name. `task`\n// dispatches an opencode subagent that routinely runs 20-40 min; the old\n// flat ceiling fired mid-subagent, made Claude believe its dispatch had\n// failed, and (because the proxy had already returned a timeout error) the\n// late subagent result was dropped on the floor -- the operator had to\n// nudge \"please check now, it seems the task succeeded\" (@jknlsn, live\n// session ses_0cfc0da6, 2026-07-05).\n//\n// `question` blocks on a human reading a TUI form, so the flat ceiling is\n// the wrong unit entirely: a question posed just before the operator steps\n// away would be rejected mid-answer. 30 min is jknlsn's original figure and\n// matches the \"prefer fewer, high-signal questions\" guidance in the def.\nexport const PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS: Record<string, number> = {\n task: 60 * 60 * 1000, // 60 min\n question: 30 * 60 * 1000, // 30 min\n}\n\n// Node's setTimeout delay is a signed 32-bit int; values above 2^31-1 ms\n// (~24.85 days) trigger TimeoutOverflowWarning and fire at ~1ms instead.\n// Clamp absurd overrides / input.timeouts so a misconfigured deadline\n// can't collapse to \"fires immediately\".\nexport const MAX_PROXY_TIMEOUT_MS = 2 ** 31 - 1\n\n/**\n * Resolve the proxy deadline for a tool call. Layers, most-specific last:\n * 1. flat default (`PROXY_DEFAULT_TIMEOUT_MS`, 10 min)\n * 2. per-tool default (`PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS`)\n * 3. user override via `proxyToolTimeoutMs` config (case-insensitive key)\n * 4. for `bash`, the call's own `input.timeout` -- the proxy must never\n * undercut a build the caller explicitly asked to run long. The bash\n * proxy def advertises a `timeout` field; before this fix the proxy\n * ignored it and killed the call at the flat ceiling anyway.\n * Finally clamped to `MAX_PROXY_TIMEOUT_MS` to stay within Node's timer range.\n */\nexport function resolveProxyCallTimeoutMs(\n toolName: string,\n input: Record<string, unknown> | undefined,\n overrides: Record<string, number> | undefined,\n): number {\n const key = toolName.toLowerCase()\n let ms = PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS[key] ?? PROXY_DEFAULT_TIMEOUT_MS\n if (overrides) {\n const ov = lookupCaseInsensitive(overrides, key)\n if (typeof ov === \"number\" && ov > 0) ms = ov\n }\n if (key === \"bash\") {\n const requested = input?.timeout\n if (typeof requested === \"number\" && requested > ms) ms = requested\n }\n return Math.min(ms, MAX_PROXY_TIMEOUT_MS)\n}\n\nfunction lookupCaseInsensitive(\n map: Record<string, number>,\n key: string,\n): number | undefined {\n if (Object.prototype.hasOwnProperty.call(map, key)) return map[key]\n for (const k of Object.keys(map)) {\n if (k.toLowerCase() === key) return map[k]\n }\n return undefined\n}\n\n/**\n * Client-side abort ceiling written into Claude's `--mcp-config` entry for\n * the proxy server. Without a `timeout` there, Claude CLI's remote-HTTP MCP\n * client aborts each call at its 60-second default even while an opencode\n * subagent is still running (@broskees, PR #18). It must be >= the largest\n * server-side deadline or the client gives up before the broker does, so it\n * tracks the max of the flat default, per-tool defaults, and user overrides.\n * (A bash call raising its own `input.timeout` above this ceiling is a known\n * edge; Claude CLI caps bash at 10 min anyway.)\n */\nexport function resolveProxyClientCeilingMs(\n overrides: Record<string, number> | undefined,\n): number {\n let ms = PROXY_DEFAULT_TIMEOUT_MS\n for (const v of Object.values(PROXY_PER_TOOL_DEFAULT_TIMEOUT_MS)) {\n if (v > ms) ms = v\n }\n if (overrides) {\n for (const v of Object.values(overrides)) {\n if (typeof v === \"number\" && v > ms) ms = v\n }\n }\n return Math.min(ms, MAX_PROXY_TIMEOUT_MS)\n}\n\n/**\n * Build the timeout error surfaced to Claude. Keeps the substrings\n * `\"timed out after\"` and `\"waiting for opencode to resolve\"` that the\n * proxy-mcp catch block classifies as expected cleanup (notice, not warn).\n * For `task` we append guidance: a Task timeout means the subagent may\n * still be running but its result is now unreachable, and the model must\n * neither declare the dispatch failed nor \"schedule a wake-up\" -- that is a\n * Claude Code affordance which cannot fire in this headless/proxy context,\n * so deferring silently drops the work.\n */\nexport function buildProxyTimeoutError(toolName: string, ms: number): Error {\n const key = toolName.toLowerCase()\n const base = `Proxy tool '${toolName}' timed out after ${ms}ms waiting for opencode to resolve the call`\n if (key === \"task\") {\n return new Error(\n base +\n \" (the subagent). The subagent may still be running but its result\" +\n \" is no longer reachable in this session. Do not declare the dispatch\" +\n \" failed, and do not 'schedule a wake-up' or defer -- that mechanism\" +\n \" does not apply here. If the result is required, re-dispatch or\" +\n \" verify it directly now.\",\n )\n }\n return new Error(base)\n}\n\n/**\n * Disambiguation appended to the `task` proxy def (both the static\n * fallback and the live overlay). Models routinely resolve opencode's\n * \"call the task tool with subagent: X\" mention hint to Claude Code's\n * native TaskCreate (a todo tool) — creating a todo, dispatching nothing,\n * and then narrating a successful dispatch. Others burn turns grepping\n * config files to verify a subagent exists before daring to call it.\n * Both failure modes are addressed here, at the tool the model reads.\n */\nexport const TASK_PROXY_NOTE =\n \"This is the ONLY tool that dispatches opencode subagents (including\" +\n \" user @-mentions). Claude Code's built-in TaskCreate/TaskUpdate manage\" +\n \" a local todo list and cannot dispatch subagents. Do not search config\" +\n \" files to verify a subagent type exists — invalid types fail fast with\" +\n \" a clear error. Foreground calls block until the subagent finishes; set\" +\n \" `background` to request opencode's background execution mode. Task calls\" +\n \" get a 60-minute proxy deadline by default (configurable via\" +\n \" proxyToolTimeoutMs).\"\n\nconst AGENT_TYPES_HEADING = \"Available agent types\"\n\n/** Longest per-agent blurb we keep; enough to choose, short enough to survive. */\nconst AGENT_BLURB_LIMIT = 140\n\n/**\n * Disambiguation appended to the `question` proxy def. Claude Code ships\n * a built-in `AskUserQuestion` that, when proxied, is disabled via\n * `--disallowedTools`; without an explicit hand-off note models keep\n * reaching for the disabled built-in or fall back to plain text. This\n * states that the proxy is the structured-questions path and summarises\n * the answer shape so the model can act on the result without a second\n * round-trip.\n */\nexport const QUESTION_PROXY_NOTE =\n \"This routes structured questions through opencode's native `question`\" +\n \" tool, which renders a TUI form with the options you provide and\" +\n \" blocks until the operator answers. Claude Code's built-in\" +\n \" AskUserQuestion is disabled in this environment; this proxy is the\" +\n \" ONLY way to ask the operator for a decision or clarification.\" +\n \" Answers come back as arrays of selected labels (set `multiple: true`\" +\n \" to allow more than one). If the operator dismisses the form the call\" +\n \" returns an error — treat that as 'no answer' and stop, do not guess.\" +\n \" Question calls get a 30-minute proxy deadline by default (configurable\" +\n \" via proxyToolTimeoutMs); for long-AFK scenarios prefer fewer,\" +\n \" high-signal questions.\"\n\n/**\n * Disambiguation appended to the `compress` proxy def. Two things the\n * model gets wrong without it: when the reset happens (not mid-turn, so\n * it can keep working after the call), and how much survives it (only\n * the summary, because the fresh spawn is not given the prior transcript).\n */\nexport const COMPRESS_PROXY_NOTE =\n \"The current turn continues normally after this call — finish what you\" +\n \" are doing. The reset happens at the START of the next turn: the\" +\n \" Claude Code session is discarded and a fresh one begins with your\" +\n \" summary as its only prior context. Everything else, including tool\" +\n \" output and files you read, is gone, so write the summary as the\" +\n \" authoritative record. Call this once per compression, when older\" +\n \" resolved work no longer needs full detail.\"\n\n/**\n * Pull *only* the agent-type list out of opencode's live `task` description.\n *\n * jknlsn's original overlaid the whole live description (2.8 KB here) in front\n * of the static def. Live check 2026-07-26 showed that backfires: Claude Code\n * truncates long MCP tool descriptions, and opencode puts the agent list at\n * the *end* (char 2306 of 2858), so the one part the model needs is exactly\n * what gets cut — haiku then guessed `general-purpose`, `default`, and\n * `code-reviewer` (Claude Code's own agent names) and every dispatch failed\n * with \"Unknown agent type\". So: keep the list, drop opencode's preamble\n * (generic delegation advice the model already has), trim each blurb, and let\n * the caller put it first.\n *\n * Returns undefined when the description carries no parsable list, so callers\n * leave the static def alone.\n */\nexport function extractAgentTypeList(\n liveDescription: string | undefined,\n): string | undefined {\n const live = liveDescription?.trim()\n if (!live) return undefined\n const start = live.indexOf(AGENT_TYPES_HEADING)\n if (start === -1) return undefined\n const entries: string[] = []\n for (const raw of live.slice(start).split(\"\\n\")) {\n const match = /^-\\s*([^:]+):\\s*(.+)$/.exec(raw.trim())\n if (!match) continue\n const name = match[1].trim()\n const blurb = match[2].trim()\n entries.push(\n `- ${name}: ${\n blurb.length > AGENT_BLURB_LIMIT\n ? `${blurb.slice(0, AGENT_BLURB_LIMIT).trimEnd()}…`\n : blurb\n }`,\n )\n }\n if (entries.length === 0) return undefined\n return `Valid subagent_type values, from opencode's live registry — anything else fails:\\n${entries.join(\"\\n\")}`\n}\n\n/**\n * Front-load opencode's live agent-type list onto the static `task` proxy def\n * so the model picks a real `subagent_type` instead of guessing a Claude Code\n * name. First, not last: see `extractAgentTypeList` for why position matters.\n * No-op when no list can be extracted (SDK client missing, older opencode) or\n * the `task` def is not among the tools.\n */\nexport function overlayTaskProxyDescription(\n tools: ProxyToolDef[],\n liveDescription: string | undefined,\n): ProxyToolDef[] {\n const agentTypes = extractAgentTypeList(liveDescription)\n if (!agentTypes) return tools\n return tools.map((t) =>\n t.name === \"task\"\n ? { ...t, description: `${agentTypes}\\n\\n${t.description}` }\n : t,\n )\n}\n\n/**\n * Overlay opencode's live `question` tool description onto the static\n * proxy def, then append the disambiguation note. No-op when the live\n * description is unavailable (older opencode, SDK client missing) — the\n * static def + note stands. Mirrors `overlayTaskProxyDescription`.\n */\nexport function overlayQuestionProxyDescription(\n tools: ProxyToolDef[],\n liveDescription: string | undefined,\n): ProxyToolDef[] {\n const live = liveDescription?.trim()\n if (!live) return tools\n return tools.map((t) =>\n t.name === \"question\"\n ? { ...t, description: `${live}\\n\\n${QUESTION_PROXY_NOTE}` }\n : t,\n )\n}\n\n/**\n * Version gate for the `question` proxy. opencode added a built-in\n * `question` tool (registry id `question`) — on older builds that entry\n * is absent and a forwarded `mcp__opencode_proxy__question` call would\n * resolve to `⚙ invalid` in opencode. Drop the def silently when the\n * live registry does not contain it so the model never sees a dead tool.\n */\nexport function filterQuestionProxyByOpencodeSupport(\n tools: ProxyToolDef[],\n opencodeHasQuestion: boolean,\n): ProxyToolDef[] {\n if (opencodeHasQuestion) return tools\n return tools.filter((t) => t.name !== \"question\")\n}\n\nexport const DEFAULT_PROXY_TOOLS: ProxyToolDef[] = [\n {\n name: \"bash\",\n description:\n \"Execute a shell command. Routed through opencode's bash tool so\" +\n \" permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: \"The shell command to execute.\",\n },\n description: {\n type: \"string\",\n description: \"Short human-readable description of what the command does.\",\n },\n timeout: {\n type: \"number\",\n description: \"Optional timeout in milliseconds.\",\n },\n },\n required: [\"command\"],\n },\n },\n {\n name: \"write\",\n description:\n \"Write a file. Routed through opencode's write tool so permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \"The file to write. Absolute paths are preferred.\",\n },\n content: {\n type: \"string\",\n description: \"The full content to write to the file.\",\n },\n },\n required: [\"filePath\", \"content\"],\n },\n },\n {\n name: \"edit\",\n description:\n \"Replace text in an existing file. Routed through opencode's edit tool so permission prompts flow through opencode's UI.\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \"The file to edit. Absolute paths are preferred.\",\n },\n oldString: {\n type: \"string\",\n description: \"The exact text to replace.\",\n },\n newString: {\n type: \"string\",\n description: \"The replacement text.\",\n },\n replaceAll: {\n type: \"boolean\",\n description: \"Replace all occurrences instead of just the first one.\",\n },\n },\n required: [\"filePath\", \"oldString\", \"newString\"],\n },\n },\n {\n name: \"webfetch\",\n description:\n \"Fetch content from a URL. Routed through opencode's webfetch tool so\" +\n \" permission prompts flow through opencode's UI. Returns the page\" +\n \" content in the requested format.\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: {\n type: \"string\",\n description: \"The URL to fetch content from. Must start with http:// or https://.\",\n },\n format: {\n type: \"string\",\n enum: [\"text\", \"markdown\", \"html\"],\n description:\n \"The format to return the content in. Defaults to markdown.\",\n },\n timeout: {\n type: \"number\",\n description: \"Optional timeout in seconds (max 120).\",\n },\n },\n required: [\"url\"],\n },\n },\n {\n name: \"task\",\n description:\n \"Launch an opencode subagent to handle a complex multi-step task\" +\n \" autonomously. Routed through opencode's task tool so subagent\" +\n \" orchestration, permission, and lifecycle are handled by opencode.\" +\n \" Use `subagent_type` to pick which configured subagent runs (e.g.\" +\n \" `build`, `general`, `explore`, or any custom subagent declared in\" +\n \" opencode.json). \" +\n TASK_PROXY_NOTE,\n inputSchema: {\n type: \"object\",\n properties: {\n description: {\n type: \"string\",\n description: \"A short (3-5 words) description of the task\",\n },\n prompt: {\n type: \"string\",\n description: \"The task for the agent to perform\",\n },\n subagent_type: {\n type: \"string\",\n description: \"The type of specialized agent to use for this task\",\n },\n task_id: {\n type: \"string\",\n description:\n \"Set this only if you mean to resume a previous task — pass the\" +\n \" prior task_id to continue the same subagent session instead of\" +\n \" creating a fresh one.\",\n },\n command: {\n type: \"string\",\n description: \"The command that triggered this task\",\n },\n background: {\n type: \"boolean\",\n description:\n \"Run the task in the background when supported by opencode\",\n },\n },\n required: [\"description\", \"prompt\", \"subagent_type\"],\n },\n },\n {\n name: \"question\",\n description:\n \"Ask the operator structured questions with options and receive\" +\n \" their answers back. Routed through opencode's native `question`\" +\n \" tool so the prompt renders as a real TUI form (with options and a\" +\n \" custom-answer field) instead of a plain text turn. Use this when\" +\n \" you need a decision, clarification, or preference from the\" +\n \" operator mid-task. \" +\n QUESTION_PROXY_NOTE,\n inputSchema: {\n type: \"object\",\n properties: {\n questions: {\n type: \"array\",\n description: \"Questions to ask.\",\n items: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"Complete question.\",\n },\n header: {\n type: \"string\",\n description: \"Very short label (max 30 chars).\",\n },\n options: {\n type: \"array\",\n description: \"Available choices.\",\n items: {\n type: \"object\",\n properties: {\n label: {\n type: \"string\",\n description: \"Display text (1-5 words, concise).\",\n },\n description: {\n type: \"string\",\n description: \"Explanation of choice.\",\n },\n },\n required: [\"label\", \"description\"],\n },\n },\n multiple: {\n type: \"boolean\",\n description:\n \"Allow selecting multiple choices. Defaults to false.\",\n },\n },\n required: [\"question\", \"header\", \"options\"],\n },\n },\n },\n required: [\"questions\"],\n },\n },\n {\n name: \"compress\",\n description:\n \"Replace older conversation detail with a summary you write, then\" +\n \" continue in a fresh Claude Code session. Handled inside the plugin,\" +\n \" so it never prompts the operator. \" +\n COMPRESS_PROXY_NOTE,\n inputSchema: {\n type: \"object\",\n properties: {\n summary: {\n type: \"string\",\n description:\n \"Dense technical summary of the work being compressed: decisions\" +\n \" made, files changed, commands run and their outcomes, and what\" +\n \" is still open. This is the ONLY prior context that survives, so\" +\n \" anything omitted is lost.\",\n },\n },\n required: [\"summary\"],\n },\n },\n]\n\nexport async function createProxyMcpServer(\n tools: ProxyToolDef[] = DEFAULT_PROXY_TOOLS,\n timeoutOverrides?: Record<string, number>,\n interceptors?: Map<string, ProxyToolInterceptor>,\n): Promise<ProxyMcpServer> {\n const calls = new EventEmitter()\n const pending = new Map<string, ProxyToolCall>()\n\n const server = createServer(async (req, res) => {\n if (req.method !== \"POST\" || !req.url?.startsWith(\"/mcp\")) {\n res.statusCode = 404\n res.end()\n return\n }\n // Hoist the request id and method so the catch block can echo them\n // in error responses. Without this, a broker rejection (timeout /\n // orphan) on a tools/call lands in the catch with no visible id, and\n // the response goes back with `id: null` which Claude CLI cannot\n // match to the original request. The method is also needed because\n // tools/call errors must be returned as MCP results with isError\n // (not JSON-RPC errors) or Claude CLI rejects them as a \"malformed\n // result that failed schema validation\" (seen live 2026-07-04).\n let requestId: number | string | null = null\n let requestMethod: string | null = null\n try {\n const body = await readBody(req)\n const request = JSON.parse(body) as {\n jsonrpc?: string\n id?: number | string | null\n method?: string\n params?: Record<string, unknown>\n }\n requestId = request?.id ?? null\n requestMethod = typeof request?.method === \"string\" ? request.method : null\n\n if (request?.jsonrpc !== \"2.0\" || typeof request.method !== \"string\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32600, message: \"Invalid request\" },\n })\n return\n }\n\n log.debug(\"proxy-mcp request\", {\n method: request.method,\n id: request.id,\n })\n\n if (request.method === \"initialize\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: {\n name: SERVER_NAME,\n version: \"0.1.0\",\n },\n },\n })\n return\n }\n\n if (request.method === \"notifications/initialized\") {\n res.statusCode = 204\n res.end()\n return\n }\n\n if (request.method === \"tools/list\") {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n tools: tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n },\n })\n return\n }\n\n if (request.method === \"tools/call\") {\n const params = request.params ?? {}\n const toolName = String(params.name ?? \"\")\n const input = (params.arguments ?? {}) as Record<string, unknown>\n\n if (!tools.some((t) => t.name === toolName)) {\n // tools/call failures MUST be MCP results with isError, never\n // JSON-RPC error envelopes: Claude CLI validates every tools/call\n // response against the MCP result schema and rejects JSON-RPC\n // errors as malformed (@jknlsn, seen live 2026-07-04).\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n content: [{ type: \"text\", text: `Unknown proxy tool: ${toolName}` }],\n isError: true,\n },\n })\n return\n }\n\n // Intercepted tools act on plugin state, not on the workspace, so\n // they are answered here and never queued for opencode. The result\n // still goes through the shared MCP envelope below — a JSON-RPC\n // error here would be rejected by Claude CLI exactly like any other\n // tools/call error envelope.\n const interceptor = interceptors?.get(toolName)\n if (interceptor) {\n let intercepted: ProxyToolResult\n try {\n intercepted = await interceptor(input)\n } catch (interceptorError) {\n const message =\n interceptorError instanceof Error\n ? interceptorError.message\n : String(interceptorError)\n log.warn(\"proxy-mcp interceptor failed\", { toolName, error: message })\n intercepted = { kind: \"error\", message }\n }\n writeToolCallResult(res, requestId, intercepted)\n return\n }\n\n const callId = crypto.randomUUID()\n log.info(\"proxy-mcp tool call received\", {\n callId,\n toolName,\n hasInput: input != null,\n })\n\n let timer: ReturnType<typeof setTimeout> | null = null\n const result = await new Promise<ProxyToolResult>(\n (resolve, reject) => {\n const entry: ProxyToolCall = {\n id: callId,\n toolName,\n input,\n resolve,\n reject,\n }\n pending.set(callId, entry)\n const deadlineMs = resolveProxyCallTimeoutMs(\n toolName,\n input,\n timeoutOverrides,\n )\n timer = setTimeout(() => {\n if (!pending.has(callId)) return\n pending.delete(callId)\n // v0.4.13: demoted from warn to notice. Timeouts are usually\n // permission-pending while the user is AFK — surfacing each as\n // a yellow UI bubble produces a wall of noise on return. The\n // file log still captures the event for diagnostics.\n log.notice(\"proxy-mcp tool call timed out\", {\n callId,\n toolName,\n deadlineMs,\n })\n reject(buildProxyTimeoutError(toolName, deadlineMs))\n }, deadlineMs)\n calls.emit(\"call\", entry)\n },\n ).finally(() => {\n if (timer) clearTimeout(timer)\n pending.delete(callId)\n })\n\n writeToolCallResult(res, requestId, result)\n return\n }\n\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: { code: -32601, message: `Unknown method: ${request.method}` },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n const logFn = isExpectedCleanupError(errorMessage) ? log.notice : log.warn\n logFn(\"proxy-mcp error handling request\", {\n error: errorMessage,\n })\n // Broker rejections (timeouts, orphans, server close) surface here for\n // tools/call requests. Same rule as above: respond with an MCP result\n // carrying isError, never a JSON-RPC error envelope, or Claude CLI\n // rejects the response as schema-invalid.\n if (requestMethod === \"tools/call\") {\n try {\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n result: {\n content: [{ type: \"text\", text: errorMessage }],\n isError: true,\n },\n })\n } catch {\n try {\n res.statusCode = 500\n res.end()\n } catch {}\n }\n return\n }\n try {\n // tools/call already returned above with an MCP result; anything\n // reaching here is a protocol-level method (initialize, tools/list)\n // where a JSON-RPC error is the correct shape.\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId,\n error: {\n code: -32603,\n message: error instanceof Error ? error.message : \"Internal error\",\n },\n })\n } catch {\n try {\n res.statusCode = 500\n res.end()\n } catch {}\n }\n }\n })\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n\n const addr = server.address() as AddressInfo | null\n if (!addr) {\n server.close()\n throw new Error(\"Failed to bind proxy MCP server\")\n }\n\n const url = `http://127.0.0.1:${addr.port}/mcp`\n\n log.info(\"proxy-mcp server started\", {\n url,\n tools: tools.map((t) => t.name),\n })\n\n let configFilePath: string | null = null\n\n const api: ProxyMcpServer = {\n url,\n serverName: SERVER_NAME,\n tools,\n calls,\n configPath() {\n if (configFilePath) return configFilePath\n const body = JSON.stringify(\n {\n mcpServers: {\n [SERVER_NAME]: {\n type: \"http\",\n url,\n timeout: resolveProxyClientCeilingMs(timeoutOverrides),\n },\n },\n },\n null,\n 2,\n )\n const hash = crypto\n .createHash(\"sha256\")\n .update(body)\n .digest(\"hex\")\n .slice(0, 12)\n const outPath = path.join(\n pluginTmpDir(),\n `proxy-${hash}.json`,\n )\n fs.writeFileSync(outPath, body, { encoding: \"utf8\", mode: 0o600 })\n configFilePath = outPath\n return outPath\n },\n async close() {\n for (const entry of pending.values()) {\n entry.reject(new Error(SERVER_CLOSED_MESSAGE))\n }\n pending.clear()\n await new Promise<void>((resolve) => {\n server.close(() => resolve())\n })\n if (configFilePath) {\n try {\n fs.unlinkSync(configFilePath)\n } catch {}\n configFilePath = null\n }\n },\n }\n\n return api\n}\n\n/** CLI-ready list of Claude tool names to disable, for each proxied tool. */\nexport function disallowedToolFlags(tools: ProxyToolDef[]): string[] {\n // Map our lowercase MCP tool names to the Claude tool name(s) they replace.\n // `edit` covers both `Edit` and `MultiEdit` because opencode has no\n // MultiEdit equivalent; without disabling MultiEdit, Claude can batch\n // file changes through it and bypass opencode's permission UI.\n // `task` disables Claude CLI's `Agent` tool (its built-in subagent\n // dispatcher) so subagent calls flow through opencode's `task` tool\n // instead — which lets opencode's configured subagent set (`build`,\n // `general`, custom subagents in opencode.json) execute the work\n // under opencode's permission/lifecycle, rather than Claude's\n // internal-only general-purpose / Explore / Plan options.\n const nameMap: Record<string, string[]> = {\n bash: [\"Bash\"],\n read: [\"Read\"],\n write: [\"Write\"],\n edit: [\"Edit\", \"MultiEdit\"],\n glob: [\"Glob\"],\n grep: [\"Grep\"],\n webfetch: [\"WebFetch\"],\n task: [\"Agent\"],\n // `question` disables Claude Code's built-in `AskUserQuestion` so the\n // structured-questions path flows through opencode's native `question`\n // tool instead — same UI/permission/audit benefits as the other\n // proxies. Without this, the model can call both and the two paths\n // diverge (opencode's form vs the headless deny-and-render fallback).\n question: [\"AskUserQuestion\"],\n }\n const out: string[] = []\n const seen = new Set<string>()\n for (const t of tools) {\n const mapped = nameMap[t.name.toLowerCase()]\n if (!mapped) continue\n for (const claudeTool of mapped) {\n if (seen.has(claudeTool)) continue\n seen.add(claudeTool)\n out.push(claudeTool)\n }\n }\n return out\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk))\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")))\n req.on(\"error\", reject)\n })\n}\n\n/**\n * The single exit for every `tools/call`, broker-backed or intercepted.\n * Success and failure share one MCP result envelope: a JSON-RPC error for\n * `kind: \"error\"` was rejected by Claude CLI as a \"malformed result that\n * failed schema validation\", so tool failures must surface as\n * `isError: true` instead.\n */\nfunction writeToolCallResult(\n res: ServerResponse,\n requestId: unknown,\n result: ProxyToolResult,\n): void {\n const text = result.kind === \"error\" ? result.message : result.text\n const isError = result.kind === \"error\" || result.isError === true\n writeJson(res, {\n jsonrpc: \"2.0\",\n id: requestId ?? null,\n result: {\n content: [{ type: \"text\", text }],\n isError,\n },\n })\n}\n\nfunction writeJson(res: ServerResponse, body: unknown): void {\n const payload = JSON.stringify(body)\n res.statusCode = 200\n res.setHeader(\"Content-Type\", \"application/json\")\n res.setHeader(\"Content-Length\", Buffer.byteLength(payload).toString())\n res.end(payload)\n}\n","import { EventEmitter } from \"node:events\"\nimport {\n buildProxyTimeoutError,\n resolveProxyCallTimeoutMs,\n type ProxyToolCall,\n type ProxyToolResult,\n} from \"./proxy-mcp.js\"\nimport { log } from \"./logger.js\"\n\nexport interface PendingProxyCall {\n sessionKey: string\n toolCallId: string\n toolName: string\n input: Record<string, unknown>\n}\n\ntype InternalPending = PendingProxyCall & {\n createdAt: number\n timer: ReturnType<typeof setTimeout>\n resolve(result: ProxyToolResult): void\n reject(error: Error): void\n}\n\n// Primary index: callId -> pending. Tool call IDs are UUIDs produced by\n// proxy-mcp, so they are globally unique across sessions.\nconst pendingByCallId = new Map<string, InternalPending>()\n// Reverse index: sessionKey -> set of callIds, so the language model can\n// drain or reject every pending call for one Claude subprocess at once.\nconst callIdsBySession = new Map<string, Set<string>>()\n\nconst emitter = new EventEmitter()\n\nfunction eventName(sessionKey: string) {\n return `pending:${sessionKey}`\n}\n\nfunction indexAdd(sessionKey: string, callId: string) {\n let s = callIdsBySession.get(sessionKey)\n if (!s) {\n s = new Set()\n callIdsBySession.set(sessionKey, s)\n }\n s.add(callId)\n}\n\nfunction indexRemove(sessionKey: string, callId: string) {\n const s = callIdsBySession.get(sessionKey)\n if (!s) return\n s.delete(callId)\n if (s.size === 0) callIdsBySession.delete(sessionKey)\n}\n\nexport function onPendingProxyCall(\n sessionKey: string,\n handler: (call: PendingProxyCall) => void,\n): () => void {\n const name = eventName(sessionKey)\n emitter.on(name, handler)\n return () => emitter.off(name, handler)\n}\n\nexport function queuePendingProxyCall(\n sessionKey: string,\n call: ProxyToolCall,\n timeoutOverrides?: Record<string, number>,\n): PendingProxyCall {\n // Defensive: if this exact callId is somehow already pending (UUID\n // collision or retry storm), replace it cleanly so we never leak two\n // entries for the same id.\n const previous = pendingByCallId.get(call.id)\n if (previous) {\n clearTimeout(previous.timer)\n previous.reject(\n new Error(`Replaced pending proxy call ${call.id} with a fresh one`),\n )\n pendingByCallId.delete(call.id)\n indexRemove(previous.sessionKey, call.id)\n }\n\n const deadlineMs = resolveProxyCallTimeoutMs(\n call.toolName,\n call.input,\n timeoutOverrides,\n )\n\n const timer = setTimeout(() => {\n const current = pendingByCallId.get(call.id)\n if (!current) return\n pendingByCallId.delete(call.id)\n indexRemove(current.sessionKey, call.id)\n current.reject(buildProxyTimeoutError(call.toolName, deadlineMs))\n // v0.4.13: demoted from warn to notice. AFK-permission-pending\n // sessions can stack many of these; demoting keeps the UI quiet on\n // return while preserving the audit trail in plugin.log.\n log.notice(\"timed out pending proxy call\", {\n sessionKey: current.sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n deadlineMs,\n })\n }, deadlineMs)\n\n const pending: InternalPending = {\n sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n input: call.input,\n createdAt: Date.now(),\n timer,\n resolve: call.resolve,\n reject: call.reject,\n }\n pendingByCallId.set(call.id, pending)\n indexAdd(sessionKey, call.id)\n emitter.emit(eventName(sessionKey), pending)\n log.info(\"queued pending proxy call\", {\n sessionKey,\n toolCallId: call.id,\n toolName: call.toolName,\n })\n return pending\n}\n\nexport function getPendingProxyCalls(sessionKey: string): PendingProxyCall[] {\n const s = callIdsBySession.get(sessionKey)\n if (!s || s.size === 0) return []\n const out: PendingProxyCall[] = []\n for (const id of s) {\n const p = pendingByCallId.get(id)\n if (p) out.push(p)\n }\n return out\n}\n\nexport function resolvePendingProxyCallById(\n toolCallId: string,\n result: ProxyToolResult,\n): boolean {\n const pending = pendingByCallId.get(toolCallId)\n if (!pending) return false\n pendingByCallId.delete(toolCallId)\n indexRemove(pending.sessionKey, toolCallId)\n clearTimeout(pending.timer)\n pending.resolve(result)\n log.info(\"resolved pending proxy call\", {\n sessionKey: pending.sessionKey,\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n })\n return true\n}\n\nexport function rejectPendingProxyCallById(\n toolCallId: string,\n error: Error,\n): boolean {\n const pending = pendingByCallId.get(toolCallId)\n if (!pending) return false\n pendingByCallId.delete(toolCallId)\n indexRemove(pending.sessionKey, toolCallId)\n clearTimeout(pending.timer)\n pending.reject(error)\n // Rejection is the broker's cleanup mechanism — fires on timeouts, orphans,\n // stream closes, etc. None are user-actionable. File-log them at NOTICE so\n // the audit trail is intact; rely on caller sites to decide TUI visibility.\n log.notice(\"rejected pending proxy call\", {\n sessionKey: pending.sessionKey,\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n error: error.message,\n })\n return true\n}\n\nexport function rejectAllPendingProxyCallsForSession(\n sessionKey: string,\n error: Error,\n): number {\n const s = callIdsBySession.get(sessionKey)\n if (!s) return 0\n const ids = [...s]\n let count = 0\n for (const id of ids) {\n if (rejectPendingProxyCallById(id, error)) count++\n }\n return count\n}\n","import type { OpenCodeModel } from \"./opencode-types.js\"\n\nconst PROVIDER_ID = \"claude-code\"\nconst NPM = \"@khalilgharbaoui/opencode-claude-code-plugin\"\n\nconst reasoningVariants: Record<string, Record<string, unknown>> = {\n low: { reasoningEffort: \"low\" },\n medium: { reasoningEffort: \"medium\" },\n high: { reasoningEffort: \"high\" },\n xhigh: { reasoningEffort: \"xhigh\" },\n max: { reasoningEffort: \"max\" },\n}\n\nconst baseCapabilities = {\n temperature: false,\n attachment: true,\n toolcall: true,\n input: { text: true, audio: false, image: true, video: false, pdf: false },\n output: { text: true, audio: false, image: false, video: false, pdf: false },\n interleaved: false as const,\n}\n\nfunction defineModel(opts: {\n id: string\n name: string\n family: string\n reasoning: boolean\n context: number\n output: number\n cost: { input: number; output: number; cacheRead: number; cacheWrite: number }\n releaseDate: string\n // List-price multiplier relative to Haiku (the cheapest model). Derived\n // exactly from published per-token pricing: input AND output ratios both come\n // out to haiku 1, sonnet 3, opus 5, fable/mythos 10. Sonnet 5 is temporarily\n // 2x during its launch-price period through August 31, 2026. Rendered as an\n // `(N×)` suffix so it surfaces in opencode's model picker, which has no\n // dedicated multiplier field.\n // Display-only: model resolution keys off `id`.\n multiplier: number\n status?: OpenCodeModel[\"status\"]\n}): OpenCodeModel {\n return {\n id: opts.id,\n providerID: PROVIDER_ID,\n api: { id: opts.id, url: \"\", npm: NPM },\n name: `${opts.name} (${opts.multiplier}×)`,\n family: opts.family,\n capabilities: { ...baseCapabilities, reasoning: opts.reasoning },\n cost: {\n input: opts.cost.input,\n output: opts.cost.output,\n cache: { read: opts.cost.cacheRead, write: opts.cost.cacheWrite },\n },\n limit: { context: opts.context, output: opts.output },\n status: opts.status ?? \"active\",\n options: {},\n headers: {},\n release_date: opts.releaseDate,\n variants: opts.reasoning ? reasoningVariants : undefined,\n }\n}\n\n// Per-token costs derived from Anthropic per-million-token pricing.\n//\n// There is no long-context premium to model. Anthropic's pricing page states\n// that Claude 4.6 and later ship the full 1M-token context window at standard\n// pricing (\"a 900k-token request is billed at the same per-token rate as a\n// 9k-token request\"), and caching/batch discounts apply unchanged across it.\n// opencode 1.18.5 added optional `cost.tiers` / `cost.experimentalOver200K`\n// fields for above-200K pricing; they stay unset here deliberately, because a\n// tier would misreport the real price. Re-check only if Anthropic introduces\n// one. Verified against the pricing docs 2026-07-26.\nconst haikuCost = { input: 1e-6, output: 5e-6, cacheRead: 1e-7, cacheWrite: 1.25e-6 }\nconst sonnetCost = { input: 3e-6, output: 15e-6, cacheRead: 3e-7, cacheWrite: 3.75e-6 }\n// Introductory pricing through August 31, 2026. Standard pricing from September\n// 1 is the same $3/M input and $15/M output as the other Sonnet models.\nconst sonnet5Cost = { input: 2e-6, output: 10e-6, cacheRead: 2e-7, cacheWrite: 2.5e-6 }\n// Opus 4.5+ standard pricing is $5/M in, $25/M out (the price cut at 4.5; held\n// through 4.6/4.7/4.8/5). Cache read 0.1x input, cache write 1.25x input.\nconst opusCost = { input: 5e-6, output: 25e-6, cacheRead: 0.5e-6, cacheWrite: 6.25e-6 }\n// Fable 5 and Mythos 5 are the Mythos-class tier above Opus and share pricing\n// ($10/M in, $50/M out). Cache read/write follow Anthropic's standard 0.1x / 1.25x\n// input ratios (not separately published).\nconst fableCost = { input: 10e-6, output: 50e-6, cacheRead: 1e-6, cacheWrite: 12.5e-6 }\n\n/**\n * Convert an OpenCodeModel to the flat config schema that OpenCode's\n * provider.ts config parser expects (model.temperature, model.reasoning,\n * model.cost.cache_read, model.modalities, etc.).\n */\nexport function toConfigModel(model: OpenCodeModel): Record<string, unknown> {\n const inputMods: string[] = []\n const outputMods: string[] = []\n for (const [k, v] of Object.entries(model.capabilities.input)) {\n if (v) inputMods.push(k)\n }\n for (const [k, v] of Object.entries(model.capabilities.output)) {\n if (v) outputMods.push(k)\n }\n\n return {\n id: model.api.id,\n name: model.name,\n status: model.status,\n family: model.family ?? \"\",\n release_date: model.release_date,\n\n temperature: model.capabilities.temperature,\n reasoning: model.capabilities.reasoning,\n attachment: model.capabilities.attachment,\n tool_call: model.capabilities.toolcall,\n modalities: { input: inputMods, output: outputMods },\n\n cost: {\n input: model.cost.input,\n output: model.cost.output,\n cache_read: model.cost.cache.read,\n cache_write: model.cost.cache.write,\n },\n\n limit: model.limit,\n options: model.options,\n headers: model.headers,\n variants: model.variants,\n }\n}\n\nexport const defaultModels: Record<string, OpenCodeModel> = {\n \"claude-haiku-4-5\": defineModel({\n id: \"claude-haiku-4-5\",\n name: \"Claude Haiku 4.5\",\n family: \"haiku\",\n reasoning: false,\n context: 200_000,\n output: 64_000,\n cost: haikuCost,\n multiplier: 1,\n releaseDate: \"2025-10-01\",\n }),\n \"claude-sonnet-4-5\": defineModel({\n id: \"claude-sonnet-4-5\",\n name: \"Claude Sonnet 4.5\",\n family: \"sonnet\",\n reasoning: true,\n context: 200_000,\n output: 64_000,\n cost: sonnetCost,\n multiplier: 3,\n releaseDate: \"2025-09-29\",\n }),\n \"claude-sonnet-4-6\": defineModel({\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n family: \"sonnet\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: sonnetCost,\n multiplier: 3,\n releaseDate: \"2025-06-19\",\n }),\n \"claude-sonnet-5\": defineModel({\n id: \"claude-sonnet-5\",\n name: \"Claude Sonnet 5\",\n family: \"sonnet\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: sonnet5Cost,\n multiplier: 2,\n releaseDate: \"2026-06-30\",\n }),\n \"claude-opus-4-5\": defineModel({\n id: \"claude-opus-4-5\",\n name: \"Claude Opus 4.5\",\n family: \"opus\",\n reasoning: true,\n context: 200_000,\n output: 64_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-11-01\",\n }),\n \"claude-opus-4-6\": defineModel({\n id: \"claude-opus-4-6\",\n name: \"Claude Opus 4.6\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-06-19\",\n }),\n \"claude-opus-4-7\": defineModel({\n id: \"claude-opus-4-7\",\n name: \"Claude Opus 4.7\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2025-07-16\",\n }),\n \"claude-opus-4-8\": defineModel({\n id: \"claude-opus-4-8\",\n name: \"Claude Opus 4.8\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2026-05-28\",\n }),\n \"claude-opus-5\": defineModel({\n id: \"claude-opus-5\",\n name: \"Claude Opus 5\",\n family: \"opus\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: opusCost,\n multiplier: 5,\n releaseDate: \"2026-07-24\",\n }),\n \"claude-fable-5\": defineModel({\n id: \"claude-fable-5\",\n name: \"Claude Fable 5\",\n family: \"fable\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: fableCost,\n multiplier: 10,\n releaseDate: \"2026-06-09\",\n }),\n // Mythos 5 shares Fable 5's capabilities and pricing without the safety\n // classifiers; limited availability via Project Glasswing. `claude --model\n // claude-mythos-5` simply errors for accounts without access, so it's safe to\n // register unconditionally.\n \"claude-mythos-5\": defineModel({\n id: \"claude-mythos-5\",\n name: \"Claude Mythos 5\",\n family: \"mythos\",\n reasoning: true,\n context: 1_000_000,\n output: 128_000,\n cost: fableCost,\n multiplier: 10,\n releaseDate: \"2026-06-09\",\n }),\n}\n","import { chmod, lstat, mkdir, readlink, symlink, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { log } from \"./logger.js\"\n\nexport const BASE_PROVIDER_ID = \"claude-code\"\nexport const DEFAULT_ACCOUNT = \"default\"\n\nconst SHARED_CAPABILITY_ITEMS = [\n \"CLAUDE.md\",\n \"settings.json\",\n \"skills\",\n \"agents\",\n \"commands\",\n \"plugins\",\n]\n\nexport function normalizeAccountName(account: string): string {\n return account\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n}\n\nexport function resolveAccounts(value: unknown): string[] | null {\n if (!Array.isArray(value)) return null\n\n const accounts = value\n .map((account) => normalizeAccountName(String(account)))\n .filter(Boolean)\n\n return Array.from(new Set([DEFAULT_ACCOUNT, ...accounts]))\n}\n\nexport function accountProviderId(account: string): string {\n return `${BASE_PROVIDER_ID}-${normalizeAccountName(account)}`\n}\n\nexport function accountDisplayName(account: string): string {\n return `Claude Code (${titleizeAccount(account)})`\n}\n\nexport function accountModelSuffix(account: string): string | undefined {\n const normalized = normalizeAccountName(account)\n return normalized === DEFAULT_ACCOUNT ? undefined : normalized\n}\n\nexport function accountConfigDir(account: string): string | undefined {\n const normalized = normalizeAccountName(account)\n\n if (!normalized || normalized === DEFAULT_ACCOUNT) return undefined\n\n return `~/.claude-${normalized}`\n}\n\nexport function expandHome(value: string): string {\n const home = process.env.HOME ?? process.env.USERPROFILE\n\n if (value === \"~\") return home ?? value\n\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return home ? path.join(home, value.slice(2)) : value\n }\n\n return value\n}\n\nexport async function ensureAccountRuntime(\n account: string,\n baseCliPath: string,\n): Promise<{ cliPath: string; configDir?: string }> {\n const configDir = accountConfigDir(account)\n\n if (!configDir) return { cliPath: baseCliPath }\n\n const expandedConfigDir = expandHome(configDir)\n await mkdir(expandedConfigDir, { recursive: true })\n\n try {\n await ensureSharedCapabilities(expandedConfigDir)\n } catch (err) {\n log.warn(\"failed to symlink shared capabilities; continuing anyway\", {\n account,\n configDir: expandedConfigDir,\n error: String(err),\n })\n }\n\n const cliPath = await writeAccountWrapper(\n normalizeAccountName(account),\n baseCliPath,\n expandedConfigDir,\n )\n\n return { cliPath, configDir: expandedConfigDir }\n}\n\nasync function ensureSharedCapabilities(targetRoot: string): Promise<void> {\n const sourceRoot = expandHome(\"~/.claude\")\n\n for (const item of SHARED_CAPABILITY_ITEMS) {\n await ensureSharedCapabilityItem(sourceRoot, targetRoot, item)\n }\n}\n\nasync function ensureSharedCapabilityItem(\n sourceRoot: string,\n targetRoot: string,\n item: string,\n): Promise<void> {\n const source = path.join(sourceRoot, item)\n const target = path.join(targetRoot, item)\n\n let sourceStat\n try {\n sourceStat = await lstat(source)\n } catch {\n return\n }\n\n try {\n const targetStat = await lstat(target)\n\n if (targetStat.isSymbolicLink()) {\n const current = await readlink(target)\n const resolvedCurrent = path.resolve(path.dirname(target), current)\n const resolvedSource = path.resolve(source)\n\n if (resolvedCurrent === resolvedSource) return\n }\n\n log.warn(\"shared Claude capability already exists; leaving untouched\", {\n item,\n target,\n source,\n })\n\n return\n } catch {\n // Missing target is expected.\n }\n\n const type = sourceStat.isDirectory()\n ? process.platform === \"win32\"\n ? \"junction\"\n : \"dir\"\n : \"file\"\n\n await symlink(source, target, type)\n}\n\nasync function writeAccountWrapper(\n account: string,\n baseCliPath: string,\n configDir: string,\n): Promise<string> {\n const cacheRoot = path.join(\n process.env.XDG_CACHE_HOME ?? expandHome(\"~/.cache\"),\n \"opencode-claude-code-plugin\",\n )\n const wrapperPath = path.join(cacheRoot, `claude-${account}`)\n const suffix = `@${account}`\n\n await mkdir(cacheRoot, { recursive: true })\n\n const script = `#!/usr/bin/env bash\nset -euo pipefail\n\nargs=()\nwhile [[ $# -gt 0 ]]; do\n if [[ \"$1\" == \"--model\" && $# -ge 2 ]]; then\n model=\"$2\"\n if [[ \"$model\" == *${shellDoubleQuote(suffix)} ]]; then\n model=\"\\${model%${shellDoubleQuote(suffix)}}\"\n fi\n args+=(\"$1\" \"$model\")\n shift 2\n else\n args+=(\"$1\")\n shift\n fi\ndone\n\nexport CLAUDE_CONFIG_DIR=${shellSingleQuote(configDir)}\nexec ${shellSingleQuote(baseCliPath)} \"\\${args[@]}\"\n`\n\n await writeFile(wrapperPath, script, \"utf8\")\n await chmod(wrapperPath, 0o755)\n\n return wrapperPath\n}\n\nfunction shellSingleQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n\nfunction shellDoubleQuote(value: string): string {\n return value.replace(/[$`\"\\\\]/g, \"\\\\$&\")\n}\n\nfunction titleizeAccount(account: string): string {\n return normalizeAccountName(account)\n .split(\"-\")\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \")\n}\n","// Removes a stale unscoped `opencode-claude-code-plugin` install left in\n// opencode's plugin cache by older configs. The unscoped name is a different\n// artifact than this scoped plugin and shadows it when both coexist.\n// Disable with OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP=1.\n\nimport {\n existsSync,\n readFileSync,\n realpathSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { log } from \"./logger.js\"\n\nconst STALE_PACKAGE_NAME = \"opencode-claude-code-plugin\"\nconst SUSPECT_DESCRIPTION_TOKEN = \"Claude Code\"\n\nlet alreadyRan = false\n\nfunction candidateCacheRoots(): string[] {\n const xdg = process.env.XDG_CACHE_HOME\n return [\n xdg ? join(xdg, \"opencode\") : null,\n join(homedir(), \".cache\", \"opencode\"),\n join(homedir(), \"Library\", \"Caches\", \"opencode\"),\n ].filter((p): p is string => Boolean(p))\n}\n\nfunction userOpencodeJsonPath(): string {\n const xdgConfig = process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\")\n return join(xdgConfig, \"opencode\", \"opencode.json\")\n}\n\nfunction userIntendsToUseUnscoped(): boolean {\n const cfg = userOpencodeJsonPath()\n if (!existsSync(cfg)) return false\n try {\n const json = JSON.parse(readFileSync(cfg, \"utf8\"))\n const plugins: unknown = json.plugin\n if (!Array.isArray(plugins)) return false\n return plugins.some(\n (entry) =>\n typeof entry === \"string\" &&\n /^opencode-claude-code-plugin(@[^/]+)?$/.test(entry),\n )\n } catch {\n return false\n }\n}\n\nfunction ourLoadedDir(): string | null {\n try {\n const filePath = fileURLToPath(import.meta.url)\n return realpathSync(resolve(filePath, \"..\", \"..\"))\n } catch {\n return null\n }\n}\n\nexport function cleanupStaleUnscopedInstall(): void {\n if (alreadyRan) return\n alreadyRan = true\n\n if (process.env.OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP === \"1\") return\n if (userIntendsToUseUnscoped()) return\n\n const ourDir = ourLoadedDir()\n\n for (const cacheRoot of candidateCacheRoots()) {\n try {\n cleanupOne(cacheRoot, ourDir)\n } catch (err) {\n log.warn(\"cleanup-stale: error processing cache root\", {\n cacheRoot,\n error: String(err),\n })\n }\n }\n}\n\nfunction cleanupOne(cacheRoot: string, ourDir: string | null): void {\n if (!existsSync(cacheRoot)) return\n\n const stalePath = join(cacheRoot, \"node_modules\", STALE_PACKAGE_NAME)\n if (!existsSync(stalePath)) return\n\n // Don't self-delete if we are the unscoped install.\n let realStalePath = stalePath\n try {\n realStalePath = realpathSync(stalePath)\n } catch {\n // ignore\n }\n if (ourDir && realStalePath === ourDir) return\n\n // Verify identity before removing.\n const pkgJsonPath = join(stalePath, \"package.json\")\n if (!existsSync(pkgJsonPath)) return\n let pkg: { name?: string; description?: string } = {}\n try {\n pkg = JSON.parse(readFileSync(pkgJsonPath, \"utf8\"))\n } catch {\n return\n }\n if (pkg.name !== STALE_PACKAGE_NAME) return\n if (!pkg.description?.includes(SUSPECT_DESCRIPTION_TOKEN)) return\n\n log.info(\"cleanup-stale: removing unscoped install\", { stalePath })\n try {\n rmSync(stalePath, { recursive: true, force: true })\n } catch (err) {\n log.warn(\"cleanup-stale: rmSync failed\", {\n stalePath,\n error: String(err),\n })\n return\n }\n\n // Drop the dep from the cache root's package.json so opencode's installer\n // doesn't reinstate it on its next pass. Lockfile is left alone; bun\n // reconciles against package.json on the next install.\n const cachePkgJson = join(cacheRoot, \"package.json\")\n if (!existsSync(cachePkgJson)) return\n try {\n const cfg = JSON.parse(readFileSync(cachePkgJson, \"utf8\"))\n if (cfg?.dependencies?.[STALE_PACKAGE_NAME]) {\n delete cfg.dependencies[STALE_PACKAGE_NAME]\n writeFileSync(cachePkgJson, JSON.stringify(cfg, null, 2) + \"\\n\")\n log.info(\"cleanup-stale: pruned dep from cache package.json\")\n }\n } catch (err) {\n log.warn(\"cleanup-stale: cache package.json update failed\", {\n error: String(err),\n })\n }\n}\n","import { execFile } from \"node:child_process\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { detectCliVersion } from \"./cli-version.js\"\nimport { log } from \"./logger.js\"\nimport { mergeOpencodeMcp } from \"./mcp-bridge.js\"\nimport { getOpencodeProjectDirectory, isUsableDirectory } from \"./runtime-status.js\"\n\n/**\n * One compact status block logged once per process, right after providers are\n * registered. Every field here answers a question that previously cost a live\n * debugging session: which plugin build is loaded, whether the Claude CLI is\n * even reachable, which cwd the spawn will use and why, what is proxied, and\n * how many MCP servers the bridge sees. Keep it cheap and never let it throw:\n * diagnostics must not be able to break provider registration.\n */\nexport interface StartupDiagnostics {\n plugin: string\n opencode: string\n claudeCli: { path: string; version: string }\n cwd: { resolved: string; source: CwdSource }\n providers: string[]\n accounts: string[]\n proxyTools: string[]\n mcpServers: string[]\n interactiveTransport: boolean\n /** ExitPlanMode approval routed through opencode's `question` tool. */\n planModeQuestion: boolean\n anthropicApiKeyInEnv: boolean\n}\n\n/** Which branch of `resolveSpawnCwd` a Claude CLI spawn would take right now. */\nexport type CwdSource = \"configured\" | \"process\" | \"captured\" | \"unresolved\"\n\nexport interface DiagnosticsProviderEntry {\n name?: string\n options?: Record<string, unknown>\n}\n\nlet cachedPluginVersion: string | undefined\n\n/** Version of this plugin, read from the package manifest one level up. */\nexport function pluginVersion(): string {\n if (cachedPluginVersion) return cachedPluginVersion\n try {\n const here = path.dirname(fileURLToPath(import.meta.url))\n const raw = fs.readFileSync(path.join(here, \"..\", \"package.json\"), \"utf8\")\n const version = (JSON.parse(raw) as { version?: unknown }).version\n cachedPluginVersion = typeof version === \"string\" ? version : \"unknown\"\n } catch {\n cachedPluginVersion = \"unknown\"\n }\n return cachedPluginVersion\n}\n\n/**\n * Best-effort opencode version from the plugin input. Re-verified on opencode\n * 1.18.5: nothing on the plugin surface carries it. `PluginInput` has no\n * version field, the SDK client's `app` namespace exposes only `log`/`agents`,\n * and the server has no `/version` route. So this probes a couple of plausible\n * shapes for future opencode releases and otherwise returns undefined, leaving\n * the binary probe (`detectOpencodeVersion`) as the fallback. Do not replace it\n * with a `client.app.get()` call — that method does not exist.\n */\nexport function pickOpencodeVersion(input: unknown): string | undefined {\n if (!input || typeof input !== \"object\") return undefined\n const app = (input as { app?: unknown }).app\n if (app && typeof app === \"object\") {\n const version = (app as { version?: unknown }).version\n if (typeof version === \"string\" && version.length > 0) return version\n }\n const direct = (input as { version?: unknown }).version\n if (typeof direct === \"string\" && direct.length > 0) return direct\n return undefined\n}\n\nconst execFileAsync = promisify(execFile)\n\nlet opencodeVersionProbe: Promise<string | undefined> | undefined\n\n/**\n * The plugin runs *inside* opencode's process, so `process.execPath` is the\n * opencode binary itself — asking it for `--version` is the only reliable way\n * to name the version, since the plugin API exposes it nowhere (see\n * `pickOpencodeVersion`). Guarded on the basename: when opencode is run from\n * source (`bun run packages/opencode/src/index.ts`) execPath is the Bun binary,\n * and reporting Bun's version as opencode's would be worse than \"unknown\".\n * Cached, 5s timeout, never throws.\n */\nexport function detectOpencodeVersion(\n execPath: string = process.execPath,\n): Promise<string | undefined> {\n if (opencodeVersionProbe) return opencodeVersionProbe\n opencodeVersionProbe = (async (): Promise<string | undefined> => {\n if (!path.basename(execPath).toLowerCase().includes(\"opencode\")) {\n log.debug(\"skipping opencode version probe: execPath is not opencode\", { execPath })\n return undefined\n }\n try {\n const { stdout } = await execFileAsync(execPath, [\"--version\"], { timeout: 5000 })\n const match = /\\d+\\.\\d+\\.\\d+\\S*/.exec(stdout.trim())\n return match ? match[0] : undefined\n } catch (err) {\n log.debug(\"opencode version probe failed\", {\n execPath,\n error: err instanceof Error ? err.message : String(err),\n })\n return undefined\n }\n })()\n return opencodeVersionProbe\n}\n\n/** Test seam: drop the cached probe so a fresh execPath is honored. */\nexport function resetOpencodeVersionProbe(): void {\n opencodeVersionProbe = undefined\n}\n\n/**\n * Mirror of `resolveSpawnCwd`'s priority order, but reporting *which* branch\n * won. `configured` means `options.cwd` pinned it, `process` is the normal\n * lazy path, `captured` means `process.cwd()` was unusable (macOS GUI launch\n * at `/`) and the captured project directory rescued it — that one is the\n * fingerprint of issue #4.\n */\nexport function describeSpawnCwd(\n configured: unknown,\n live: string = process.cwd(),\n captured: string | undefined = getOpencodeProjectDirectory(),\n): { resolved: string; source: CwdSource } {\n if (typeof configured === \"string\" && configured.length > 0) {\n return { resolved: configured, source: \"configured\" }\n }\n if (isUsableDirectory(live)) return { resolved: live, source: \"process\" }\n if (isUsableDirectory(captured)) return { resolved: captured, source: \"captured\" }\n return { resolved: live, source: \"unresolved\" }\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value.filter((entry): entry is string => typeof entry === \"string\")\n}\n\nfunction firstOption(\n providers: Record<string, DiagnosticsProviderEntry>,\n key: string,\n): unknown {\n for (const entry of Object.values(providers)) {\n const value = entry?.options?.[key]\n if (value !== undefined) return value\n }\n return undefined\n}\n\nexport function collectStartupDiagnostics(\n providers: Record<string, DiagnosticsProviderEntry>,\n opencodeVersion?: string,\n): Omit<StartupDiagnostics, \"claudeCli\"> & { claudeCliPath: string } {\n const accounts: string[] = []\n for (const entry of Object.values(providers)) {\n const account = entry?.options?.account\n if (typeof account === \"string\" && account.length > 0) accounts.push(account)\n }\n\n const cwd = describeSpawnCwd(firstOption(providers, \"cwd\"))\n\n let mcpServers: string[] = []\n try {\n // Disk-only view: opencode's runtime MCP status isn't settled at plugin\n // init (servers are still connecting), so the per-turn overlay is not\n // applied here. This is what the bridge would ship on a cold start.\n mcpServers = mergeOpencodeMcp(cwd.resolved).enabledServerNames\n } catch (err) {\n log.debug(\"startup diagnostics could not read MCP config\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n\n return {\n plugin: pluginVersion(),\n opencode: opencodeVersion ?? process.env.OPENCODE_VERSION ?? \"unknown\",\n claudeCliPath: String(firstOption(providers, \"cliPath\") ?? \"claude\"),\n cwd,\n providers: Object.keys(providers),\n accounts,\n proxyTools: stringList(firstOption(providers, \"proxyTools\")),\n mcpServers,\n interactiveTransport:\n firstOption(providers, \"interactive\") === true ||\n process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT === \"1\",\n planModeQuestion: firstOption(providers, \"planModeQuestion\") === true,\n anthropicApiKeyInEnv: Boolean(\n process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN,\n ),\n }\n}\n\nlet logged = false\n\n/**\n * Emit the startup block once per process. Fire-and-forget: the Claude CLI\n * version probe is async (`claude --version`, 5s timeout, cached), and a slow\n * or missing binary must never delay provider registration.\n */\nexport function logStartupDiagnostics(\n providers: Record<string, DiagnosticsProviderEntry>,\n opencodeVersion?: string,\n): void {\n if (logged) return\n logged = true\n void (async () => {\n try {\n // Probe the binary only when the plugin input and env gave us nothing,\n // so a future opencode that reports its version costs no spawn.\n const version =\n opencodeVersion ?? process.env.OPENCODE_VERSION ?? (await detectOpencodeVersion())\n const { claudeCliPath, ...rest } = collectStartupDiagnostics(providers, version)\n const cli = await detectCliVersion(claudeCliPath)\n const diagnostics: StartupDiagnostics = {\n ...rest,\n claudeCli: { path: claudeCliPath, version: cli?.raw ?? \"not detected\" },\n }\n log.notice(\"claude-code plugin ready\", { ...diagnostics })\n } catch (err) {\n log.debug(\"startup diagnostics failed\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n })()\n}\n\n/** For tests. */\nexport function _resetStartupDiagnostics(): void {\n logged = false\n}\n","import type { LanguageModelV3 } from \"@ai-sdk/provider\"\nimport { ClaudeCodeLanguageModel } from \"./claude-code-language-model.js\"\nimport { defaultModels, toConfigModel } from \"./models.js\"\nimport type { OpenCodeModel, OpenCodePlugin, OpenCodeProvider } from \"./opencode-types.js\"\nimport type { ClaudeCodeProviderSettings } from \"./types.js\"\nimport {\n BASE_PROVIDER_ID,\n accountDisplayName,\n accountModelSuffix,\n accountProviderId,\n ensureAccountRuntime,\n resolveAccounts,\n} from \"./accounts.js\"\nimport { cleanupStaleUnscopedInstall } from \"./cleanup-stale.js\"\nimport { configureLogger, log } from \"./logger.js\"\nimport {\n isUsableDirectory,\n setOpencodeClient,\n setOpencodeProjectDirectory,\n} from \"./runtime-status.js\"\nimport {\n logStartupDiagnostics,\n pickOpencodeVersion,\n type DiagnosticsProviderEntry,\n} from \"./startup-diagnostics.js\"\n\nexport interface ClaudeCodeProvider {\n specificationVersion: \"v3\"\n (modelId: string): LanguageModelV3\n languageModel(modelId: string): LanguageModelV3\n}\n\n// Picks the best directory from opencode's plugin context (`directory` /\n// `worktree`). Result is handed to runtime-status so it's available as a\n// *fallback* at spawn time only when `process.cwd()` is unusable (macOS\n// GUI launches at `/`). Never baked into provider config — see #4.\nfunction pickOpencodeDirectory(input: unknown): string | undefined {\n if (!input || typeof input !== \"object\") return undefined\n const ctx = input as { directory?: unknown; worktree?: unknown }\n if (isUsableDirectory(ctx.directory)) return ctx.directory\n if (isUsableDirectory(ctx.worktree)) return ctx.worktree\n return undefined\n}\n\nlet warnedAnthropicApiKey = false\n\n// `Question` is deliberately absent: enabling it disables Claude Code's\n// built-in AskUserQuestion (via --disallowedTools) and replaces the\n// stop-and-wait deny/markdown path with an in-turn blocking form. That is a\n// behavior trade against the issue-#8 guarantee, so it stays opt-in until it\n// has the same live mileage Task had before v0.10.0 flipped it on. Users opt\n// in by listing it in `proxyTools`; see README \"Question proxy tool\".\nexport const DEFAULT_PROXY_TOOL_NAMES = [\n \"Bash\",\n \"Edit\",\n \"Write\",\n \"WebFetch\",\n \"Task\",\n]\n\n// One-time heads-up: an API key in the environment makes Claude Code bill\n// pay-as-you-go (Console) instead of the logged-in Pro/Max subscription, which\n// silently bypasses the Agent SDK plan credit. Surfaced once per process.\nfunction warnIfAnthropicApiKey(ignore: boolean | undefined): void {\n if (warnedAnthropicApiKey) return\n if (!process.env.ANTHROPIC_API_KEY && !process.env.ANTHROPIC_AUTH_TOKEN) return\n warnedAnthropicApiKey = true\n if (ignore) {\n log.warn(\n \"ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN detected; stripping it from claude spawns (ignoreAnthropicApiKey) so requests use your subscription auth, not pay-as-you-go API billing.\",\n )\n } else {\n log.warn(\n \"ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN detected; claude may bill as pay-as-you-go API usage instead of your subscription / Agent SDK credit. Set provider option `ignoreAnthropicApiKey: true` to force subscription auth.\",\n )\n }\n}\n\nexport function createClaudeCode(\n settings: ClaudeCodeProviderSettings = {},\n): ClaudeCodeProvider {\n if (settings.logging) {\n configureLogger({\n file: settings.logging.file ?? false,\n dir: settings.logging.dir ?? null,\n mode: settings.logging.mode ?? \"silent\",\n level: settings.logging.level ?? \"info\",\n })\n }\n warnIfAnthropicApiKey(settings.ignoreAnthropicApiKey)\n const cliPath =\n settings.cliPath ?? process.env.CLAUDE_CLI_PATH ?? \"claude\"\n const providerName = settings.providerID ?? settings.name ?? \"claude-code\"\n const proxyTools = settings.proxyTools ?? [...DEFAULT_PROXY_TOOL_NAMES]\n\n const createModel = (modelId: string): LanguageModelV3 => {\n return new ClaudeCodeLanguageModel(modelId, {\n provider: providerName,\n cliPath,\n cwd: settings.cwd,\n account: settings.account,\n configDir: settings.configDir,\n providerID: settings.providerID,\n skipPermissions: settings.skipPermissions ?? true,\n permissionMode: settings.permissionMode,\n mcpConfig: settings.mcpConfig,\n strictMcpConfig: settings.strictMcpConfig,\n bridgeOpencodeMcp: settings.bridgeOpencodeMcp ?? true,\n controlRequestBehavior: settings.controlRequestBehavior ?? \"allow\",\n controlRequestToolBehaviors: settings.controlRequestToolBehaviors,\n controlRequestDenyMessage: settings.controlRequestDenyMessage,\n proxyTools,\n proxyToolTimeoutMs: settings.proxyToolTimeoutMs,\n planModeQuestion: settings.planModeQuestion ?? false,\n webSearch: settings.webSearch,\n hotReloadMcp: settings.hotReloadMcp ?? true,\n proxyOpencodeMcpTools: settings.proxyOpencodeMcpTools ?? true,\n multiStepContinuation: settings.multiStepContinuation ?? true,\n autoContinueIncompleteTurns:\n settings.autoContinueIncompleteTurns ?? \"smart\",\n compactionModel: settings.compactionModel,\n ignoreAnthropicApiKey: settings.ignoreAnthropicApiKey,\n interactive: settings.interactive,\n interactiveBypass: settings.interactiveBypass,\n interactiveAllowTools: settings.interactiveAllowTools,\n interactiveSystemPrompt: settings.interactiveSystemPrompt,\n })\n }\n\n const provider = function (modelId: string) {\n return createModel(modelId)\n } as ClaudeCodeProvider\n\n provider.specificationVersion = \"v3\"\n provider.languageModel = createModel\n\n return provider\n}\n\n// ---------------------------------------------------------------------------\n// OpenCode plugin interface\n// ---------------------------------------------------------------------------\n\nconst PROVIDER_ID = BASE_PROVIDER_ID\nconst PACKAGE_NPM = \"@khalilgharbaoui/opencode-claude-code-plugin\"\n\nfunction pluginEntrypoint(): string {\n return import.meta.url.startsWith(\"file:\") ? import.meta.url : PACKAGE_NPM\n}\n\nfunction cleanProviderOptions(\n options: Record<string, unknown> = {},\n): Record<string, unknown> {\n const result = { ...options }\n delete result.accounts\n return result\n}\n\nfunction defaultModelsForProvider(\n providerModels: OpenCodeProvider[\"models\"],\n providerID = PROVIDER_ID,\n modelSuffix?: string,\n) {\n const models = Object.fromEntries(\n Object.entries(defaultModels).map(([id, model]) => {\n const modelId = modelSuffix ? `${id}@${modelSuffix}` : id\n const existing = providerModels[id] ?? providerModels[modelId]\n return [\n modelId,\n {\n ...model,\n id: modelId,\n providerID,\n api: {\n ...model.api,\n id: modelId,\n npm: existing?.api?.npm ?? model.api.npm,\n url: existing?.api?.url ?? model.api.url,\n },\n },\n ]\n }),\n )\n\n for (const [id, model] of Object.entries(providerModels)) {\n if (!(id in models)) {\n models[id] = {\n ...model,\n providerID,\n }\n }\n }\n\n return models\n}\n\n/**\n * Build models in OpenCode's config schema format (flat properties like\n * `temperature`, `reasoning`, `cost.cache_read`, `modalities`, etc.)\n * so the config-path provider loader parses them correctly.\n */\nexport function configModelsForProvider(\n providerModels: OpenCodeProvider[\"models\"],\n providerID: string,\n modelSuffix?: string,\n): Record<string, Record<string, unknown>> {\n const models: Record<string, Record<string, unknown>> = {}\n\n for (const [id, model] of Object.entries(defaultModels)) {\n const modelId = modelSuffix ? `${id}@${modelSuffix}` : id\n const existing = providerModels[id] ?? providerModels[modelId]\n const existingVariants =\n existing && typeof (existing as { variants?: unknown }).variants === \"object\"\n ? ((existing as { variants?: Record<string, Record<string, unknown>> }).variants ?? {})\n : {}\n const full: OpenCodeModel = {\n ...model,\n id: modelId,\n providerID,\n api: {\n ...model.api,\n id: modelId,\n npm: existing?.api?.npm ?? model.api.npm,\n url: existing?.api?.url ?? model.api.url,\n },\n variants: {\n ...(model.variants ?? {}),\n ...existingVariants,\n },\n }\n models[modelId] = toConfigModel(full)\n }\n\n for (const [id, model] of Object.entries(providerModels)) {\n if (!(id in models)) {\n models[id] = toConfigModel({ ...model, providerID } as OpenCodeModel)\n }\n }\n\n return models\n}\n\nasync function providerConfig(\n existing: {\n name?: string\n npm?: string\n options?: Record<string, unknown>\n models?: Record<string, unknown>\n } | undefined,\n providerID = PROVIDER_ID,\n optionDefaults: Record<string, unknown> = {},\n displayName?: string,\n) {\n const mergedOptions: Record<string, unknown> = {\n cliPath: \"claude\",\n proxyTools: [...DEFAULT_PROXY_TOOL_NAMES],\n ...optionDefaults,\n ...cleanProviderOptions(existing?.options),\n providerID,\n }\n\n const cliPath = String(mergedOptions.cliPath ?? \"claude\")\n const account =\n typeof mergedOptions.account === \"string\" ? mergedOptions.account : undefined\n const runtime = account\n ? await ensureAccountRuntime(account, cliPath)\n : { cliPath }\n\n return {\n name: displayName ?? existing?.name,\n npm: existing?.npm ?? pluginEntrypoint(),\n options: {\n ...mergedOptions,\n ...runtime,\n },\n // models is intentionally omitted: both callers overwrite it with\n // configModelsForProvider(), which emits the flat config schema\n // opencode's config-path loader parses (and merges user variants).\n }\n}\n\n/**\n * Narrow opencode's full provider map down to the ones this plugin owns\n * (`claude-code` plus every `claude-code-<account>` expansion) so startup\n * diagnostics never report another provider's options.\n */\nexport function claudeCodeProviders(\n providers: Record<string, DiagnosticsProviderEntry> | undefined,\n): Record<string, DiagnosticsProviderEntry> {\n const out: Record<string, DiagnosticsProviderEntry> = {}\n for (const [id, entry] of Object.entries(providers ?? {})) {\n if (id === PROVIDER_ID || id.startsWith(`${PROVIDER_ID}-`)) out[id] = entry\n }\n return out\n}\n\nasync function expandAccountProviders(config: {\n provider?: Record<\n string,\n {\n name?: string\n npm?: string\n options?: Record<string, unknown>\n models?: Record<string, unknown>\n }\n >\n}): Promise<boolean> {\n const seed = config.provider?.[PROVIDER_ID]\n const accounts = resolveAccounts(seed?.options?.accounts)\n\n if (!accounts) return false\n\n config.provider ??= {}\n\n const seedOptions = cleanProviderOptions(seed?.options)\n let expandedCount = 0\n\n for (const account of accounts) {\n const providerID = accountProviderId(account)\n try {\n const existing = config.provider[providerID]\n const modelSuffix = accountModelSuffix(account)\n\n config.provider[providerID] = {\n ...existing,\n ...(await providerConfig(\n existing,\n providerID,\n {\n ...seedOptions,\n account,\n },\n accountDisplayName(account),\n )),\n models: configModelsForProvider(\n (existing?.models ?? seed?.models ?? {}) as OpenCodeProvider[\"models\"],\n providerID,\n modelSuffix,\n ),\n }\n expandedCount++\n } catch (err) {\n log.error(\"failed to expand account provider\", {\n account,\n providerID,\n error: String(err),\n })\n }\n }\n\n if (expandedCount > 0) {\n delete config.provider[PROVIDER_ID]\n }\n\n return expandedCount > 0\n}\n\nconst server: OpenCodePlugin = async (input) => {\n cleanupStaleUnscopedInstall()\n\n const opencodeVersion = pickOpencodeVersion(input)\n\n // Capture the SDK client so the language model can query opencode's\n // in-memory MCP state per-turn for the runtime overlay. `input` is\n // `unknown` here (kept loose since opencode adds fields over time);\n // narrow defensively.\n if (input && typeof input === \"object\" && \"client\" in input) {\n setOpencodeClient((input as { client?: unknown }).client)\n }\n\n // Capture opencode's project-aware directory as a *fallback* used at\n // Claude CLI spawn time only when `process.cwd()` is unusable. Rescues\n // macOS GUI launches at `/` without freezing the value into provider\n // config, so opencode workspace switches mid-session still take effect.\n // See `resolveSpawnCwd` in runtime-status.ts and issue #4.\n setOpencodeProjectDirectory(pickOpencodeDirectory(input))\n\n return {\n config: async (config) => {\n config.provider ??= {}\n\n const expanded = await expandAccountProviders(config)\n if (expanded) {\n logStartupDiagnostics(\n claudeCodeProviders(config.provider),\n opencodeVersion,\n )\n return\n }\n\n const existing = config.provider[PROVIDER_ID]\n config.provider[PROVIDER_ID] = {\n ...existing,\n ...(await providerConfig(existing)),\n models: configModelsForProvider(\n (existing?.models ?? {}) as OpenCodeProvider[\"models\"],\n PROVIDER_ID,\n ),\n }\n logStartupDiagnostics(\n claudeCodeProviders(config.provider),\n opencodeVersion,\n )\n },\n // No `event` hook: MCP config drift is detected at turn start by the\n // hot-reload check in `claude-code-language-model.ts`, which respawns\n // claude safely between turns. Eviction on `global.disposed` would kill\n // an in-flight stream and abort the user's current turn.\n provider: {\n id: PROVIDER_ID,\n models: async (provider) => defaultModelsForProvider(provider.models),\n },\n // Inject opencode's agent name into providerOptions so the language\n // model can distinguish /compact (and title) calls from normal turns.\n // Without this, every no-tools call looks like a title request and\n // gets short-circuited to a synthetic stub.\n \"chat.params\": async (input, output) => {\n const providerID = input.model?.providerID ?? input.provider?.info?.id\n // The hook fires for every provider opencode is configured with, not\n // just ours — keep this at debug to avoid log spam on non-claude-code\n // calls.\n log.debug(\"chat.params hook fired\", {\n agent: input.agent,\n providerID,\n sessionID: input.sessionID,\n })\n if (typeof providerID !== \"string\") return\n if (providerID !== PROVIDER_ID && !providerID.startsWith(`${PROVIDER_ID}-`)) return\n\n // Inject sessionID BEFORE the agent guard so session isolation works\n // even when input.agent is absent (older opencode, provider-switch\n // edge paths). resolveSessionAffinity reads this as a fallback when\n // the x-session-affinity header is missing.\n if (typeof input.sessionID === \"string\" && input.sessionID.length > 0) {\n output.options ??= {}\n ;(output.options as Record<string, unknown>).opencodeSessionID = input.sessionID\n }\n\n if (!input.agent) return\n // opencode wraps the entire `output.options` bag under the providerID\n // via ProviderTransform.providerOptions(model, options) → { [providerID]: options }\n // before handing it to the language model as `providerOptions`. So we\n // write fields at the TOP LEVEL of output.options, not nested under\n // providerID — otherwise the model sees providerOptions[id][id].opencodeAgent.\n output.options ??= {}\n ;(output.options as Record<string, unknown>).opencodeAgent = input.agent\n log.debug(\"chat.params tagged providerOptions\", {\n agent: input.agent,\n sessionID: input.sessionID,\n providerID,\n })\n },\n }\n}\n\nexport default {\n id: \"@khalilgharbaoui/opencode-claude-code-plugin\",\n server,\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport { ClaudeCodeLanguageModel } from \"./claude-code-language-model.js\"\nexport { bridgeOpencodeMcp } from \"./mcp-bridge.js\"\nexport { defaultModels } from \"./models.js\"\nexport type {\n ClaudeCodeConfig,\n ClaudeCodeProviderSettings,\n ClaudeStreamMessage,\n} from \"./types.js\"\nexport type { OpenCodeHooks, OpenCodeModel, OpenCodePlugin } from \"./opencode-types.js\"\n"],"mappings":"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","names":["sessionKey","fs","path","os","resolve","sessionKey","EventEmitter","unlink","os","fs","path","EventEmitter","unlink","sessionKey","fs","path","crypto","EventEmitter","EventEmitter","server","resolve","EventEmitter","EventEmitter","sessionKey","readFileSync","writeFileSync","unlink","homedir","tmpdir","randomUUID","dirname","join","content","path","spawn","createInterface","resolve","stream","completeResult","planId","path","path","existsSync","readFileSync","rmSync","writeFileSync","homedir","join","resolve","join","homedir","existsSync","readFileSync","resolve","rmSync","writeFileSync","execFile","fs","path","promisify","fileURLToPath","fileURLToPath","execFileAsync","promisify","execFile","PROVIDER_ID","input"]}
|