@khalilgharbaoui/opencode-claude-code-plugin 0.11.2 → 0.12.1

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 CHANGED
@@ -70,17 +70,17 @@ The plugin auto-registers the following. They appear in the model picker without
70
70
 
71
71
  | ID | Display name | Context | Output | Reasoning variants | Price × |
72
72
  |---|---|---|---|---|---|
73
- | `claude-haiku-4-5` | Claude Haiku 4.5 | 200k | 8,192 | – | 1× |
74
- | `claude-sonnet-4-5` | Claude Sonnet 4.5 | 1M | 16,384 | low/medium/high/xhigh/max | 3× |
75
- | `claude-sonnet-4-6` | Claude Sonnet 4.6 | 1M | 16,384 | low/medium/high/xhigh/max | 3× |
73
+ | `claude-haiku-4-5` | Claude Haiku 4.5 | 200k | 64,000 | – | 1× |
74
+ | `claude-sonnet-4-5` | Claude Sonnet 4.5 | 200k | 64,000 | low/medium/high/xhigh/max | 3× |
75
+ | `claude-sonnet-4-6` | Claude Sonnet 4.6 | 1M | 128,000 | low/medium/high/xhigh/max | 3× |
76
76
  | `claude-sonnet-5` | Claude Sonnet 5 | 1M | 128,000 | low/medium/high/xhigh/max | 2×* |
77
- | `claude-opus-4-5` | Claude Opus 4.5 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
78
- | `claude-opus-4-6` | Claude Opus 4.6 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
79
- | `claude-opus-4-7` | Claude Opus 4.7 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
80
- | `claude-opus-4-8` | Claude Opus 4.8 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
77
+ | `claude-opus-4-5` | Claude Opus 4.5 | 200k | 64,000 | low/medium/high/xhigh/max | 5× |
78
+ | `claude-opus-4-6` | Claude Opus 4.6 | 1M | 128,000 | low/medium/high/xhigh/max | 5× |
79
+ | `claude-opus-4-7` | Claude Opus 4.7 | 1M | 128,000 | low/medium/high/xhigh/max | 5× |
80
+ | `claude-opus-4-8` | Claude Opus 4.8 | 1M | 128,000 | low/medium/high/xhigh/max | 5× |
81
81
  | `claude-opus-5` | Claude Opus 5 | 1M | 128,000 | low/medium/high/xhigh/max | 5× |
82
- | `claude-fable-5` | Claude Fable 5 | 1M | 16,384 | low/medium/high/xhigh/max | 10× |
83
- | `claude-mythos-5` | Claude Mythos 5 | 1M | 16,384 | low/medium/high/xhigh/max | 10× |
82
+ | `claude-fable-5` | Claude Fable 5 | 1M | 128,000 | low/medium/high/xhigh/max | 10× |
83
+ | `claude-mythos-5` | Claude Mythos 5 | 1M | 128,000 | low/medium/high/xhigh/max | 10× |
84
84
 
85
85
  `claude-mythos-5` is Mythos-class like Fable 5 but without safety classifiers, and is **limited availability via [Project Glasswing](https://anthropic.com/glasswing)**. It's registered unconditionally; if your Claude account lacks access, `claude --model claude-mythos-5` just errors. Use `claude-fable-5` (generally available) otherwise.
86
86
 
@@ -183,6 +183,7 @@ The account model IDs are internally suffixed, for example `claude-sonnet-4-6@wo
183
183
  | `permissionMode` | `acceptEdits` \| `auto` \| `bypassPermissions` \| `default` \| `dontAsk` \| `plan` | – | Forwarded to `claude --permission-mode`. |
184
184
  | `proxyTools` | string[] | `["Bash", "Edit", "Write", "WebFetch", "Task"]` | Claude built-in tools to route through opencode's executor + permission UI. See [Selective tool proxy](#selective-tool-proxy). |
185
185
  | `proxyToolTimeoutMs` | `Record<string, number>` | – | Per-tool proxy call deadline in ms, keyed by proxy tool name (`bash`, `task`, …). Defaults: 10 min flat, `task` → 60 min. For `bash`, the call's own `input.timeout` is honoured on top (`max(resolved, input.timeout)`). See [Selective tool proxy](#selective-tool-proxy). |
186
+ | `planModeQuestion` | boolean | `false` | Route `ExitPlanMode` approval through opencode's native `question` tool instead of a text "(yes/no)" prompt. Off because opencode's question form is currently broken upstream. See [Plan mode](#plan-mode). |
186
187
  | `controlRequestBehavior` | `allow` \| `deny` | `allow` | Default response when `skipPermissions: false` and Claude sends a `can_use_tool` control request. |
187
188
  | `controlRequestToolBehaviors` | `Record<string, "allow" \| "deny">` | – | Per-tool override for `can_use_tool`. Example: `{ "Bash": "deny", "Read": "allow" }`. |
188
189
  | `controlRequestDenyMessage` | string | built-in message | Message returned to Claude on a deny. |
@@ -271,6 +272,7 @@ By default, the plugin proxies `Bash`, `Edit`, `Write`, `WebFetch`, and `Task`.
271
272
  | `"Write"` | `Write` | `mcp__opencode_proxy__write` |
272
273
  | `"WebFetch"` | `WebFetch` | `mcp__opencode_proxy__webfetch` |
273
274
  | `"Task"` | `Agent` | `mcp__opencode_proxy__task` |
275
+ | `"Question"` | `AskUserQuestion` | `mcp__opencode_proxy__question` |
274
276
 
275
277
  ### OpenCode-native subagents
276
278
 
@@ -295,7 +297,7 @@ recovery step for harnesses that defer MCP tool schemas. Both apply per Claude
295
297
  process at spawn, and provider options are read once at opencode startup, so
296
298
  `proxyTools` changes need a full opencode restart.
297
299
 
298
- Only those five values are actually proxied; anything else you put in `proxyTools` is ignored. Proxying `Edit` also disables `MultiEdit` — opencode has no batched-edit equivalent, so Claude is forced to fan out into single `Edit` calls that each flow through the permission UI.
300
+ Only those six values are actually proxied; anything else you put in `proxyTools` is ignored. Proxying `Edit` also disables `MultiEdit` — opencode has no batched-edit equivalent, so Claude is forced to fan out into single `Edit` calls that each flow through the permission UI. The `"Question"` proxy is version-gated on opencode's built-in `question` tool: on builds that lack the registry entry the def is silently dropped (a forwarded call would otherwise render as `⚙ invalid`), so add it only on opencode versions that ship the `question` tool.
299
301
 
300
302
  Without `"Task"` in `proxyTools`, Claude's built-in `Agent` tool stays enabled and Claude orchestrates subagents internally with no opencode child-session visibility. To opt out of all proxying, including Task, use an explicit empty list:
301
303
 
@@ -303,6 +305,48 @@ Without `"Task"` in `proxyTools`, Claude's built-in `Agent` tool stays enabled a
303
305
  "options": { "proxyTools": [] }
304
306
  ```
305
307
 
308
+ ### Subagent todos
309
+
310
+ When Claude works through a multi-step task it emits `TaskCreate` / `TaskUpdate` calls. The plugin translates those into opencode's full-list `todowrite` so the todo panel populates. Inside a **subagent** that translation is blocked unless you say otherwise: opencode's task tool injects `todowrite: false` into the tools dict for any subagent without an explicit rule, so the plugin's synthetic emissions surface as `⚙ invalid todowrite` rows instead of todos. The built-in `general` subagent denies it by default.
311
+
312
+ Grant it per subagent definition in `opencode.json`:
313
+
314
+ ```json
315
+ {
316
+ "agent": {
317
+ "multistep": {
318
+ "description": "Multi-step worker whose progress should be visible as todos",
319
+ "mode": "subagent",
320
+ "model": "claude-code-default/claude-opus-5",
321
+ "permission": {
322
+ "todowrite": "allow",
323
+ "todoread": "allow",
324
+ "task": "deny"
325
+ }
326
+ }
327
+ }
328
+ }
329
+ ```
330
+
331
+ Notes on that example:
332
+
333
+ - `todowrite: "allow"` is the load-bearing line. Without it you get `⚙ invalid` rows, not a broken run.
334
+ - `todoread` is worth allowing too so the subagent can re-read its own list across turns.
335
+ - `task: "deny"` is explicit rather than implied. Leave it denied unless this subagent should itself delegate, in which case set `"allow"` and raise the top-level `subagent_depth` (opencode defaults it to `1`, so a child cannot spawn a grandchild).
336
+ - Provider and agent config are read at startup, so restart opencode fully after editing.
337
+
338
+ The todos render in the **subagent's own session view**, not the parent's panel. Navigate to it in the TUI with `session.child.next` (and back with `session.parent`); run `opencode --print-logs` or check the keybindings if those actions are unbound in your setup.
339
+
340
+ To confirm the data actually landed rather than trusting the UI:
341
+
342
+ ```bash
343
+ sqlite3 ~/.local/share/opencode/opencode.db \
344
+ "select id, parent_id from session order by rowid desc limit 5;"
345
+ # then, with the child session id:
346
+ sqlite3 ~/.local/share/opencode/opencode.db \
347
+ "select tool, state from part where session_id='<child-id>' and tool='todowrite';"
348
+ ```
349
+
306
350
  ### What you get with proxying on
307
351
 
308
352
  - opencode's **permission prompts** for every Bash/Edit/Write/WebFetch call (the default `claude --dangerously-skip-permissions` is NOT applied to proxied tools).
@@ -407,11 +451,52 @@ Each chat keeps a long-lived `claude` subprocess so the model retains its native
407
451
 
408
452
  Set `permissionMode: "plan"` to forward `--permission-mode plan` to Claude. The plugin handles `ExitPlanMode` specially — instead of forwarding it as a tool call, it converts it to a confirmation prompt that flows through opencode normally.
409
453
 
454
+ By default that prompt is text: the plan is rendered as markdown, followed by `**Do you want to proceed with this plan?** (yes/no)`, and you answer in your next message.
455
+
456
+ ### Approval as a real form (`planModeQuestion`, opt-in)
457
+
458
+ Set `planModeQuestion: true` to route the approval through opencode's native `question` tool instead:
459
+
460
+ ```json
461
+ "options": {
462
+ "permissionMode": "plan",
463
+ "planModeQuestion": true
464
+ }
465
+ ```
466
+
467
+ The plan is still rendered, but the turn then ends on `tool-calls` and opencode runs its own `question` tool, so approval is a form rather than prose. Your answer is fed back to the CLI as the `tool_result` for the original `ExitPlanMode` call, which is what actually unlocks plan mode on the Claude side. A "yes" typed as ordinary text never does that. Anything other than picking `yes` (including custom text) comes back as rejection feedback the model is told to act on.
468
+
469
+ > **Leave this off for now.** It depends on the same opencode `question` form that is [broken upstream](#with-question-in-proxytools-currently-blocked-upstream--leave-it-off): with it on, a plan approval hangs until you interrupt the turn. On opencode builds with no `question` registry entry at all the plugin silently keeps the text path (look for `plan-mode question gate` in the log). Re-test when [anomalyco/opencode#36603](https://github.com/anomalyco/opencode/pull/36603) merges.
470
+
471
+ Approval bridge contributed by [@CollieIsCute](https://github.com/CollieIsCute).
472
+
410
473
  ---
411
474
 
412
475
  ## AskUserQuestion
413
476
 
414
- opencode has no native structured ask-question executor to proxy through (unlike `Bash`/`Task`), so the plugin handles `AskUserQuestion` specially:
477
+ opencode ships a built-in `question` tool (`packages/opencode/src/tool/question.ts`) that renders a real TUI form with options and a custom-answer field — near-identical to Claude Code's `AskUserQuestion` (`multiSelect` `multiple`). The plugin can route `AskUserQuestion` through it so the prompt becomes an actual form instead of plain text. Two modes:
478
+
479
+ ### With `"Question"` in `proxyTools` (currently blocked upstream — leave it off)
480
+
481
+ > **Known upstream breakage (opencode 1.15.x through at least 1.18.5).** opencode's `question` TUI form does not render, so the tool blocks until you interrupt the turn. This is not specific to this plugin: native providers hit it identically, and a `--pure` headless server drives the same question end to end successfully (`question.asked` → `GET /question` → `POST /question/{id}/reply` → tool completes), which isolates the fault to the TUI. Tracked upstream as [anomalyco/opencode#36604](https://github.com/anomalyco/opencode/issues/36604) with fix [PR #36603](https://github.com/anomalyco/opencode/pull/36603) (unmerged). Until that lands, enabling `"Question"` trades the working fallback below for a hang. The instructions here describe the intended behavior for when it is fixed.
482
+
483
+ Add `"Question"` to `proxyTools` and grant `permission.question: allow` to the calling agent. Claude's built-in `AskUserQuestion` is disabled via `--disallowedTools`, and the plugin exposes `mcp__opencode_proxy__question` in its place. The model calls the proxy, opencode renders the form, and the operator's answers come back as arrays of selected labels. On builds that lack the `question` registry entry the def is silently dropped at spawn (version gate), and the deny/markdown fallback below applies instead.
484
+
485
+ `proxyTools` replaces the default list rather than adding to it, so repeat the defaults you still want:
486
+
487
+ ```json
488
+ "options": {
489
+ "proxyTools": ["Bash", "Edit", "Write", "WebFetch", "Task", "Question"]
490
+ }
491
+ ```
492
+
493
+ To turn it back off, drop `"Question"` from the list. It is **not** in the default list, so no configuration means the deny/markdown fallback below stays in force.
494
+
495
+ The same spawn-time caveat as `"Task"` applies: provider options are read once at opencode startup, so restart opencode fully after adding it. Question calls get a 30-minute proxy deadline (raise it with `proxyToolTimeoutMs` if you expect to be AFK longer; an expired call comes back as an error, not an answer).
496
+
497
+ ### Without the proxy (default fallback)
498
+
499
+ When `"Question"` is not in `proxyTools` (or the opencode version lacks the `question` tool), the plugin handles `AskUserQuestion` as follows:
415
500
 
416
501
  1. **It renders the full question.** The tool's payload — every question, header, option label, and option description — is emitted as readable markdown into the assistant stream so the user actually sees the choices (same approach as `ExitPlanMode`).
417
502
  2. **It is never auto-allowed at the CLI gate.** Allowing it would let the headless Claude CLI resolve its own question (no TTY → fabricated/empty answer) and proceed on a guess. `controlRequestBehaviorForTool` hard-denies `AskUserQuestion` and returns a message telling the model to **stop and wait for the operator's answer** — end the turn, call no further tools, and never self-answer. (Before v0.7.0 this message also offered an "if the run is non-interactive, proceed with a reasonable guess" fallback. The model could not reliably tell interactive opencode from a headless run and routinely took it, so questions appeared to be skipped — [issue #8](https://github.com/khalilgharbaoui/opencode-claude-code-plugin/issues/8). For genuinely unattended runs, use the `controlRequestToolBehaviors` override below instead.)
@@ -483,7 +568,7 @@ The plugin respects the standard Claude Code thinking env vars. If you set them
483
568
 
484
569
  - **Empty text blocks are dropped.** Claude sometimes opens a `content_block_start` for text but never sends a delta. The plugin no longer emits the empty block (which was triggering Anthropic 400s like `cache_control cannot be set for empty text blocks`).
485
570
  - **Smart incomplete-turn continuation.** By default, the plugin keeps the current opencode stream open and feeds Claude CLI a small internal continuation message when Claude emits a `result` after reasoning/tool activity without a useful visible answer. It still stops normally on final-looking answers, questions, blockers, errors, aborts, or internal safety-budget exhaustion. Disable with `"autoContinueIncompleteTurns": false`.
486
- - **`AskUserQuestion`** from the CLI is converted into plain text content rather than forwarded as a tool call.
571
+ - **`AskUserQuestion`** from the CLI is converted into plain text content rather than forwarded as a tool call — unless `"Question"` is in `proxyTools`, in which case it is routed through opencode's native `question` tool (see [AskUserQuestion](#askuserquestion)).
487
572
  - **Wire-inactivity watchdog.** Once the CLI has produced any content, the stream closes gracefully if stdout goes silent for 60 seconds without a `result` message arriving. Resets on every line received, so long mid-turn pauses (Sonnet between text-end and the next tool_use, for example) are tolerated. On a user-initiated abort, the watchdog shortens to 5 seconds.
488
573
  - **Per-iteration usage.** When the CLI internally retries with tools, the plugin only counts the last iteration's usage so opencode's context accounting stays accurate.
489
574
  - **Lazy `cwd`.** The working directory is re-resolved at every request, so opencode's project-aware behavior works without restarting the plugin.
@@ -616,8 +701,8 @@ Workaround for autonomous compression: trigger it manually with `/dcp compress`
616
701
  - No streaming of tool inputs as they're being constructed (Anthropic's `input_json_delta`); the plugin emits them once complete.
617
702
  - Raw chain-of-thought is not available. Claude 4 family models ship summarized thinking only. See [Extended thinking](#extended-thinking) for the full picture.
618
703
  - Recommended Claude Code CLI: **2.1.142+**. Older CLIs work for everything else but skip the `--thinking-display` flag, so Claude Opus 4.7 turns may render empty Thinking rows. If something breaks after a Claude Code update, the CLI version is the first thing to check.
619
- - **Foreground Task calls have a 30-minute proxy timeout.** The same timeout is written into Claude's generated HTTP MCP configuration so long-running opencode subagents are not cut off by Claude's 60-second default. For independent longer work, use `background: true` after enabling opencode's experimental background-subagent flag.
620
- - **Subagent todos require explicit permission.** opencode's task tool gates `todowrite` per subagent: without a `permission: { todowrite: "allow" }` rule on the subagent definition, opencode injects `todowrite: false` into the tools dict and the plugin's synthetic `todowrite` emissions surface as `⚙ invalid todowrite` rows. The built-in `general` subagent denies `todowrite` by default; use a custom subagent for parallel work that needs todo visibility. Subagent todos render inline in the **subagent's** session view (navigate with the TUI's `session.child.next` / `session.parent` commands), not in the parent session's panel.
704
+ - **Foreground Task calls have a 60-minute proxy deadline** (configurable via [`proxyToolTimeoutMs`](#per-tool-proxy-timeouts)). A ceiling covering the longest configured deadline is written into Claude's generated HTTP MCP configuration so long-running opencode subagents are not cut off by Claude's 60-second default. For independent longer work, use `background: true` after enabling opencode's experimental background-subagent flag.
705
+ - **Subagent todos require explicit permission.** See [Subagent todos](#subagent-todos) for the rule and a working config.
621
706
 
622
707
  ---
623
708
 
package/dist/index.d.ts CHANGED
@@ -162,6 +162,14 @@ interface ClaudeCodeConfig {
162
162
  controlRequestDenyMessage?: string;
163
163
  proxyTools?: string[];
164
164
  proxyToolTimeoutMs?: Record<string, number>;
165
+ /**
166
+ * Route `ExitPlanMode` through opencode's native `question` tool so plan
167
+ * approval is a real form instead of a "(yes/no)" line the operator has to
168
+ * answer in prose. Off by default: opencode's question form is currently
169
+ * broken upstream, so enabling this trades a working text prompt for a
170
+ * silent hang. See the plan-mode gotcha in AGENTS.md.
171
+ */
172
+ planModeQuestion?: boolean;
165
173
  webSearch?: WebSearchRouting;
166
174
  hotReloadMcp?: boolean;
167
175
  proxyOpencodeMcpTools?: boolean;
@@ -258,16 +266,22 @@ interface ClaudeCodeProviderSettings {
258
266
  * opencode's tool executor (with its native permission UI) and returns
259
267
  * the result.
260
268
  *
261
- * Supported: `bash`, `write`, `edit`, `webfetch`, `task`. Leave empty or unset to disable proxying.
262
- *
263
- * `task` proxies Claude CLI's `Agent` (subagent dispatch) tool through
264
- * opencode's `task` tool, so subagent calls run under opencode's
265
- * configured subagent set (build/general/custom) with opencode's
266
- * permission and lifecycle handling, instead of Claude CLI's
267
- * internal-only general-purpose / Explore / Plan options. The calling
268
- * agent must have `permission.task: allow` for the target subagent
269
- * (see opencode's agent docs).
270
- */
269
+ * Supported: `bash`, `write`, `edit`, `webfetch`, `task`, `question`. Leave empty or unset to disable proxying.
270
+ *
271
+ * `task` proxies Claude CLI's `Agent` (subagent dispatch) tool through
272
+ * opencode's `task` tool, so subagent calls run under opencode's
273
+ * configured subagent set (build/general/custom) with opencode's
274
+ * permission and lifecycle handling, instead of Claude CLI's
275
+ * internal-only general-purpose / Explore / Plan options. The calling
276
+ * agent must have `permission.task: allow` for the target subagent
277
+ * (see opencode's agent docs).
278
+ *
279
+ * `question` proxies Claude CLI's `AskUserQuestion` through opencode's
280
+ * native `question` tool (TUI form with options + custom answer). The
281
+ * calling agent must have `permission.question: allow`. Version-gated:
282
+ * silently dropped on opencode builds that lack the `question` registry
283
+ * entry, in which case the deny/markdown fallback applies.
284
+ */
271
285
  proxyTools?: string[];
272
286
  /**
273
287
  * Per-tool proxy call timeouts in milliseconds, keyed by the proxy tool
@@ -286,6 +300,23 @@ interface ClaudeCodeProviderSettings {
286
300
  * long build the caller explicitly asked to run is never undercut.
287
301
  */
288
302
  proxyToolTimeoutMs?: Record<string, number>;
303
+ /**
304
+ * Route Claude's `ExitPlanMode` through opencode's native `question` tool.
305
+ *
306
+ * Off (default): the plan is rendered as markdown followed by
307
+ * `**Do you want to proceed with this plan?** (yes/no)` and the operator
308
+ * answers in prose. On: the plan is rendered, the turn ends on
309
+ * `tool-calls`, and opencode runs its own `question` tool so approval is a
310
+ * real form; the answer is fed back to the CLI as the `tool_result` for
311
+ * the original `ExitPlanMode` call, which is what unlocks plan mode.
312
+ *
313
+ * Two reasons it is opt-in. opencode's `question` form does not currently
314
+ * render (upstream anomalyco/opencode#36604), so an enabled bridge hangs
315
+ * the turn until the operator interrupts; and older opencode builds have
316
+ * no `question` registry entry at all, in which case the plugin silently
317
+ * keeps the text path. See the plan-mode gotcha in AGENTS.md.
318
+ */
319
+ planModeQuestion?: boolean;
289
320
  /**
290
321
  * Strip `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` from the environment of
291
322
  * every spawned `claude` process. When an API key is present, Claude Code
@@ -506,16 +537,33 @@ declare class ClaudeCodeLanguageModel implements LanguageModelV3 {
506
537
  */
507
538
  private resolvedProxyMcpTools;
508
539
  /**
509
- * Live description of opencode's `task` tool for the current
510
- * provider/model, exactly as opencode's registry renders it for native
511
- * models including the "Available agent types" list (built from the
512
- * default agent's permissions). Overlaid onto the static `task` proxy
513
- * def so Claude sees the same subagent catalog native opencode models
514
- * see, instead of hunting through config files. Returns undefined when
515
- * the SDK client is unavailable (direct AI-SDK use, tests) so the
516
- * static def stands.
540
+ * Live tool info derived from a single `client.tool.list()` fetch:
541
+ *
542
+ * - `taskDescription`: opencode's `task` tool description exactly as the
543
+ * registry renders it for native models, including the "Available
544
+ * agent types" list. Overlaid onto the static `task` proxy def so
545
+ * Claude sees the same subagent catalog native models see, instead
546
+ * of hunting through config files.
547
+ * - `questionDescription` / `hasQuestion`: opencode's `question` tool
548
+ * description and whether the registry has the entry at all. Older
549
+ * builds lack it, in which case a `mcp__opencode_proxy__question`
550
+ * call resolves to `⚙ invalid`; the version gate drops the def.
551
+ *
552
+ * Returns undefined/false when the SDK client is unavailable (direct
553
+ * AI-SDK use, tests) so the static defs stand. `resolved` distinguishes
554
+ * "the registry answered and has no `question` entry" from "nobody
555
+ * answered": only the former is a real version-gate signal.
556
+ */
557
+ private fetchLiveToolInfo;
558
+ /** Share one lazy registry request within a turn without making it stale. */
559
+ private createLiveToolInfoLoader;
560
+ /**
561
+ * Whether the ExitPlanMode approval bridge is live for this turn: the
562
+ * operator opted in AND opencode's registry actually has the `question`
563
+ * tool. Without the registry entry the emitted tool-call would render as
564
+ * `⚙ invalid` and wedge the turn, so the plugin keeps the text path.
517
565
  */
518
- private fetchLiveTaskDescription;
566
+ private resolvePlanModeQuestion;
519
567
  /**
520
568
  * Create a proxy MCP server for a single active Claude process/session.
521
569
  * The process lifecycle owns the server lifecycle via session-manager.