@oh-my-pi/pi-coding-agent 15.7.3 → 15.7.6

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.
Files changed (119) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/dist/types/config/settings-schema.d.ts +12 -22
  3. package/dist/types/eval/__tests__/heartbeat.test.d.ts +1 -0
  4. package/dist/types/eval/heartbeat.d.ts +45 -0
  5. package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
  6. package/dist/types/extensibility/extensions/loader.d.ts +2 -2
  7. package/dist/types/extensibility/extensions/runner.d.ts +2 -1
  8. package/dist/types/extensibility/extensions/types.d.ts +24 -5
  9. package/dist/types/extensibility/shared-events.d.ts +2 -2
  10. package/dist/types/internal-urls/local-protocol.d.ts +19 -9
  11. package/dist/types/internal-urls/types.d.ts +14 -0
  12. package/dist/types/lsp/client.d.ts +3 -0
  13. package/dist/types/lsp/diagnostics-ledger.d.ts +10 -0
  14. package/dist/types/lsp/index.d.ts +2 -0
  15. package/dist/types/lsp/utils.d.ts +4 -0
  16. package/dist/types/mcp/manager.d.ts +14 -5
  17. package/dist/types/modes/acp/acp-agent.d.ts +1 -1
  18. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  19. package/dist/types/modes/components/custom-editor.d.ts +0 -1
  20. package/dist/types/modes/components/hook-selector.d.ts +7 -1
  21. package/dist/types/modes/controllers/command-controller.d.ts +2 -3
  22. package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -2
  23. package/dist/types/modes/interactive-mode.d.ts +2 -2
  24. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -1
  25. package/dist/types/modes/theme/theme.d.ts +1 -1
  26. package/dist/types/modes/types.d.ts +2 -2
  27. package/dist/types/session/agent-session.d.ts +10 -7
  28. package/dist/types/session/shake-types.d.ts +3 -3
  29. package/dist/types/task/repair-args.d.ts +52 -0
  30. package/dist/types/tiny/models.d.ts +0 -14
  31. package/dist/types/tiny/title-client.d.ts +28 -2
  32. package/dist/types/tiny/title-protocol.d.ts +8 -9
  33. package/dist/types/tools/ask.d.ts +8 -6
  34. package/dist/types/tools/eval-backends.d.ts +12 -0
  35. package/dist/types/tools/eval-render.d.ts +52 -0
  36. package/dist/types/tools/eval.d.ts +2 -35
  37. package/dist/types/tools/find.d.ts +1 -1
  38. package/dist/types/tools/index.d.ts +4 -11
  39. package/dist/types/tools/path-utils.d.ts +7 -0
  40. package/dist/types/tui/output-block.d.ts +11 -10
  41. package/examples/extensions/README.md +1 -0
  42. package/examples/extensions/thinking-note.ts +13 -0
  43. package/package.json +9 -9
  44. package/scripts/build-binary.ts +0 -1
  45. package/src/cli.ts +59 -0
  46. package/src/config/model-registry.ts +33 -4
  47. package/src/config/settings-schema.ts +13 -24
  48. package/src/config/settings.ts +10 -0
  49. package/src/discovery/claude.ts +41 -22
  50. package/src/edit/index.ts +23 -3
  51. package/src/eval/__tests__/agent-bridge.test.ts +90 -0
  52. package/src/eval/__tests__/heartbeat.test.ts +84 -0
  53. package/src/eval/__tests__/llm-bridge.test.ts +30 -0
  54. package/src/eval/agent-bridge.ts +44 -38
  55. package/src/eval/heartbeat.ts +74 -0
  56. package/src/eval/js/executor.ts +13 -9
  57. package/src/eval/llm-bridge.ts +20 -14
  58. package/src/eval/py/executor.ts +14 -18
  59. package/src/exec/bash-executor.ts +31 -5
  60. package/src/extensibility/custom-tools/types.ts +2 -2
  61. package/src/extensibility/extensions/loader.ts +16 -18
  62. package/src/extensibility/extensions/runner.ts +22 -17
  63. package/src/extensibility/extensions/types.ts +39 -5
  64. package/src/extensibility/shared-events.ts +2 -2
  65. package/src/internal-urls/docs-index.generated.ts +5 -5
  66. package/src/internal-urls/local-protocol.ts +23 -11
  67. package/src/internal-urls/types.ts +15 -0
  68. package/src/lsp/client.ts +28 -5
  69. package/src/lsp/diagnostics-ledger.ts +51 -0
  70. package/src/lsp/index.ts +9 -22
  71. package/src/lsp/utils.ts +21 -0
  72. package/src/mcp/manager.ts +87 -4
  73. package/src/modes/acp/acp-agent.ts +8 -4
  74. package/src/modes/components/assistant-message.ts +28 -1
  75. package/src/modes/components/custom-editor.ts +9 -7
  76. package/src/modes/components/hook-selector.ts +159 -32
  77. package/src/modes/components/tool-execution.ts +20 -4
  78. package/src/modes/controllers/command-controller.ts +7 -39
  79. package/src/modes/controllers/event-controller.ts +38 -28
  80. package/src/modes/controllers/extension-ui-controller.ts +3 -2
  81. package/src/modes/controllers/input-controller.ts +0 -15
  82. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  83. package/src/modes/interactive-mode.ts +2 -1
  84. package/src/modes/rpc/rpc-mode.ts +17 -6
  85. package/src/modes/theme/theme-schema.json +30 -0
  86. package/src/modes/theme/theme.ts +39 -2
  87. package/src/modes/types.ts +2 -1
  88. package/src/modes/utils/ui-helpers.ts +5 -2
  89. package/src/prompts/system/project-prompt.md +3 -2
  90. package/src/prompts/system/subagent-system-prompt.md +12 -8
  91. package/src/prompts/system/system-prompt.md +8 -6
  92. package/src/prompts/tools/ask.md +2 -1
  93. package/src/prompts/tools/eval.md +1 -1
  94. package/src/session/agent-session.ts +75 -103
  95. package/src/session/shake-types.ts +4 -5
  96. package/src/slash-commands/builtin-registry.ts +2 -4
  97. package/src/task/executor.ts +14 -4
  98. package/src/task/index.ts +3 -2
  99. package/src/task/repair-args.ts +117 -0
  100. package/src/tiny/models.ts +0 -28
  101. package/src/tiny/title-client.ts +133 -43
  102. package/src/tiny/title-protocol.ts +11 -16
  103. package/src/tiny/worker.ts +6 -61
  104. package/src/tools/ask.ts +74 -32
  105. package/src/tools/ast-edit.ts +3 -0
  106. package/src/tools/ast-grep.ts +3 -0
  107. package/src/tools/eval-backends.ts +38 -0
  108. package/src/tools/eval-render.ts +750 -0
  109. package/src/tools/eval.ts +27 -754
  110. package/src/tools/find.ts +20 -6
  111. package/src/tools/gh.ts +1 -0
  112. package/src/tools/index.ts +7 -37
  113. package/src/tools/path-utils.ts +13 -2
  114. package/src/tools/read.ts +1 -0
  115. package/src/tools/renderers.ts +1 -1
  116. package/src/tools/search.ts +12 -1
  117. package/src/tools/write.ts +9 -1
  118. package/src/tui/output-block.ts +42 -79
  119. package/src/utils/git.ts +9 -3
package/CHANGELOG.md CHANGED
@@ -2,6 +2,66 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Fixed
6
+
7
+ - Fixed a module-load crash (`ReferenceError: Cannot access 'evalToolRenderer' before initialization`) triggered whenever `tools/eval` was imported before `tools/renderers`. The eval JS backend statically pulls the agent/task/sdk/extension chain, which re-enters the root barrel → `modes/components` → `tool-execution` → `renderers` while `eval.ts` was still initializing, so `renderers.ts` read `evalToolRenderer` in its TDZ. The eval TUI renderer is now split into a dependency-light `tools/eval-render.ts` that `renderers.ts` imports directly (decoupling pure rendering from the eval runtime); `eval.ts` re-exports `evalToolRenderer`/`EVAL_DEFAULT_PREVIEW_LINES` for compatibility.
8
+
9
+ ## [15.7.6] - 2026-06-01
10
+ ### Added
11
+
12
+ - Added `ask` option descriptions so agents can keep short labels and render explanatory text as separate muted rows in the selector.
13
+ - Added an extension API for rendering supplemental UI below visible assistant thinking blocks.
14
+ - Added default-on `lsp.diagnosticsDeduplicate` support so post-edit LSP diagnostics already shown for a file are suppressed within the session and only new or changed diagnostics are surfaced.
15
+
16
+ ### Fixed
17
+
18
+ - Fixed a single ESC press both dismissing the @/slash autocomplete popup and aborting the running agent operation. ESC now drains the popup first; only when no popup is visible does it route to the global interrupt handler (matching the standard TUI/IDE pattern). The `shouldBypassAutocompleteOnEscape` editor hook is removed — it had become the trigger for this bug ([#1655](https://github.com/can1357/oh-my-pi/issues/1655)).
19
+ - Fixed Claude Code slash command discovery to load subdirectory commands recursively while preserving basename commands (e.g. `/apply`) and adding namespace aliases (e.g. `/opsx:apply`) for tools that install colon-namespaced workflows ([#1523](https://github.com/can1357/oh-my-pi/issues/1523)).
20
+ - Fixed the `eval` tool's per-cell `timeout` killing cells that were not stalled. The timeout is now a plain wall-clock budget on the cell's **own** work that is **paused only while a host-side `agent()`/`parallel()`/`llm()` bridge call is in flight** — those calls pump a heartbeat that re-arms the watchdog, so a long fanout or a slow (e.g. reasoning-tier) completion runs to completion instead of being aborted mid-flight (a subagent's time-to-first-token, a long quiet nested tool, or an entire oneshot `llm()` request no longer trip it). Nothing else re-arms the budget: ordinary compute, `print`/stdout, `log()`/`phase()`, and non-agent tool calls all count against it, so a cell that is not delegating to an agent/llm is bounded by the regular wall-clock timeout (and the timeout message no longer says "of inactivity"). The heartbeat is a pure keepalive — never persisted or rendered.
21
+
22
+ ## [15.7.5] - 2026-06-01
23
+ ### Fixed
24
+
25
+ - Fixed streaming assistant responses leaving duplicated tail rows in WSL/Windows Terminal scrollback by enabling eager native-scrollback rebuilds while assistant text is actively streaming ([#1615](https://github.com/can1357/oh-my-pi/issues/1615)).
26
+
27
+ ### Fixed
28
+
29
+ - Fixed the `task` tool mangling subagent prompts when a model double-JSON-encodes a string argument: `context` and each task's `assignment`/`description` are now repaired when they arrive uniformly double-escaped (literal `\n`, `\"`, `\uXXXX`), so the subagent receives the intended prose and the call preview renders real newlines. The repair is guarded by a JSON-string round-trip and a double-encode signature, so legitimate backslashes/quotes (Windows paths, regexes, embedded quotes) are left untouched, and it is scoped to these natural-language fields only (never code-bearing tools).
30
+
31
+ ### Fixed
32
+
33
+ - Fixed `pr://` PR views omitting formal review submissions and approvals when comments are enabled ([#1600](https://github.com/can1357/oh-my-pi/issues/1600)).
34
+
35
+ ### Fixed
36
+
37
+ - Fixed subagent yield-reminder loop logging benign user/compaction aborts as `ERROR`. The catch around `session.prompt`/`waitForIdle` in `task/executor.ts` now demotes `ToolAbortError` and signal-aborted exits to `debug` and keeps `ERROR` for genuine prompt failures only ([#1623](https://github.com/can1357/oh-my-pi/issues/1623)).
38
+
39
+ ### Fixed
40
+
41
+ - Fixed `read local://<file>` resolving to the wrong session's artifacts directory in multi-session ACP hosts (e.g. cmux). `LocalProtocolHandler.resolve` now honors `context.localProtocolOptions` supplied by the calling tool before falling back to the process-wide override or the first `main`-kind session in the global `AgentRegistry`; `read`, `find`, `search`, `ast_grep`, and `ast_edit` thread their session's options through so a `local://PLAN.md` lookup hits the calling session's `local` root instead of a sibling session's ([#1608](https://github.com/can1357/oh-my-pi/issues/1608)).
42
+
43
+ ### Fixed
44
+
45
+ - Fixed `omp` segfaulting on exit on Windows after the tiny title/memory model loaded `onnxruntime-node` (issue [#1606](https://github.com/can1357/oh-my-pi/issues/1606)). The tiny model now runs in a Bun subprocess instead of a Worker thread, so the NAPI finalizer that crashes during shutdown never executes in the agent's address space; the subprocess is `SIGKILL`'d on dispose to skip every native destructor on every platform.
46
+
47
+ ### Fixed
48
+
49
+ - Fixed unbounded MCP reconnect loop that could fork-bomb the host when a stdio MCP server completes the `initialize`/`tools/list` handshake and then exits. `MCPManager` now enforces a per-server crash circuit breaker (5 reconnects per 30 s window) on the automatic `transport.onClose` path; manual `/mcp reconnect` resets the window so users can recover after fixing the misconfiguration ([#1592](https://github.com/can1357/oh-my-pi/issues/1592)).
50
+
51
+ ### Fixed
52
+
53
+ - Fixed auto context maintenance to include the pending prompt in the pre-send token estimate, so large user turns compact history before the provider rejects an over-limit request ([#1618](https://github.com/can1357/oh-my-pi/issues/1618)).
54
+
55
+ ## [15.7.4] - 2026-05-31
56
+
57
+ ### Removed
58
+
59
+ - Removed `/shake summary`, the `shake-summary` auto-compaction strategy, and the `providers.shakeSummaryModel` setting. Use `/shake` or `compaction.strategy: shake` for mechanical artifact-backed elision without local-model CPU.
60
+
61
+ ### Fixed
62
+
63
+ - Fixed plugin install failing for sources pinned to a SHA: `git.clone()` no longer adds `--depth 1` when `options.sha` is set, so the checkout of arbitrary commits succeeds instead of bailing out with "shallow clone may not contain this commit" ([#1589](https://github.com/can1357/oh-my-pi/issues/1589)).
64
+
5
65
  ## [15.7.3] - 2026-05-31
6
66
  ### Added
7
67
 
@@ -39,6 +99,10 @@
39
99
 
40
100
  ### Removed
41
101
 
102
+ ### Fixed
103
+
104
+ - Fixed auto-discovered OpenAI-compatible / Ollama / llama.cpp / new-api proxy models defaulting to `maxTokens: 8192`, which made providers drop the streaming connection mid-response on large `write`/`edit` tool calls and surfaced as Bun's opaque `socket connection was closed unexpectedly`. The discovery cap is now `32_768` (`DISCOVERY_DEFAULT_MAX_TOKENS` in `packages/coding-agent/src/config/model-registry.ts`) and `min(contextWindow, …)` still honors smaller advertised context windows ([#1528](https://github.com/can1357/oh-my-pi/issues/1528)).
105
+
42
106
  - Removed the `/drop-images` slash command; use `/shake images`, which strips every image from the session through the same `dropImages()` path.
43
107
 
44
108
  ### Fixed
@@ -112,6 +176,10 @@
112
176
 
113
177
  - Removed the `recipe` tool and its `recipe.enabled` setting. Task-runner targets (just/package.json/Cargo/make/Taskfile) are invoked directly through `bash`.
114
178
 
179
+ ### Added
180
+
181
+ - Added a `symbols.spinnerFrames` field to custom theme JSON so themes can override the loader/tool-execution spinner. Accepts either a flat `string[]` (used for both spinner types) or `{ "status"?: string[], "activity"?: string[] }` to override each independently; anything not specified falls back to the symbol preset. Documented in `docs/theme.md` and validated by `theme-schema.json`. ([#1553](https://github.com/can1357/oh-my-pi/issues/1553))
182
+
115
183
  ## [15.6.0] - 2026-05-30
116
184
  ### Added
117
185
 
@@ -9199,4 +9267,4 @@ Initial public release.
9199
9267
  - Git branch display in footer
9200
9268
  - Message queueing during streaming responses
9201
9269
  - OAuth integration for Gmail and Google Calendar access
9202
- - HTML export with syntax highlighting and collapsible sections
9270
+ - HTML export with syntax highlighting and collapsible sections
@@ -1298,12 +1298,12 @@ export declare const SETTINGS_SCHEMA: {
1298
1298
  };
1299
1299
  readonly "compaction.strategy": {
1300
1300
  readonly type: "enum";
1301
- readonly values: readonly ["context-full", "handoff", "shake", "shake-summary", "off"];
1301
+ readonly values: readonly ["context-full", "handoff", "shake", "off"];
1302
1302
  readonly default: "context-full";
1303
1303
  readonly ui: {
1304
1304
  readonly tab: "context";
1305
1305
  readonly label: "Compaction Strategy";
1306
- readonly description: "Choose in-place context-full maintenance, auto-handoff, surgical shake (drop heavy content), shake with local-model summaries, or disable auto maintenance (off)";
1306
+ readonly description: "Choose in-place context-full maintenance, auto-handoff, surgical shake (drop heavy content), or disable auto maintenance (off)";
1307
1307
  readonly options: readonly [{
1308
1308
  readonly value: "context-full";
1309
1309
  readonly label: "Context-full";
@@ -1316,10 +1316,6 @@ export declare const SETTINGS_SCHEMA: {
1316
1316
  readonly value: "shake";
1317
1317
  readonly label: "Shake";
1318
1318
  readonly description: "Drop heavy content (tool results + large blocks) in place; recover via artifact";
1319
- }, {
1320
- readonly value: "shake-summary";
1321
- readonly label: "Shake (summary)";
1322
- readonly description: "Shake, but compress heavy regions with a local on-device model instead of dropping";
1323
1319
  }, {
1324
1320
  readonly value: "off";
1325
1321
  readonly label: "Off";
@@ -2303,6 +2299,15 @@ export declare const SETTINGS_SCHEMA: {
2303
2299
  readonly description: "Return LSP diagnostics after editing code files";
2304
2300
  };
2305
2301
  };
2302
+ readonly "lsp.diagnosticsDeduplicate": {
2303
+ readonly type: "boolean";
2304
+ readonly default: true;
2305
+ readonly ui: {
2306
+ readonly tab: "editing";
2307
+ readonly label: "Deduplicate Diagnostics";
2308
+ readonly description: "Suppress post-edit LSP diagnostics already shown for a file; only surface new or changed ones";
2309
+ };
2310
+ };
2306
2311
  readonly "bashInterceptor.enabled": {
2307
2312
  readonly type: "boolean";
2308
2313
  readonly default: false;
@@ -3560,21 +3565,6 @@ export declare const SETTINGS_SCHEMA: {
3560
3565
  })[];
3561
3566
  };
3562
3567
  };
3563
- readonly "providers.shakeSummaryModel": {
3564
- readonly type: "enum";
3565
- readonly values: readonly ["qwen3-1.7b", "gemma-3-1b", "qwen2.5-1.5b", "lfm2-1.2b"];
3566
- readonly default: "gemma-3-1b" | "lfm2-1.2b" | "qwen2.5-1.5b" | "qwen3-1.7b";
3567
- readonly ui: {
3568
- readonly tab: "context";
3569
- readonly label: "Shake Summary Model";
3570
- readonly description: "Local on-device model used by /shake summary and the shake-summary compaction strategy to compress heavy regions. Runs entirely on-device; downloads on first use. Falls back to plain elide when unavailable.";
3571
- readonly options: {
3572
- value: "gemma-3-1b" | "lfm2-1.2b" | "qwen2.5-1.5b" | "qwen3-1.7b";
3573
- label: "Gemma 3 1B" | "LFM2 1.2B" | "Qwen2.5 1.5B" | "Qwen3 1.7B";
3574
- description: "Best consolidation/dedup; lighter footprint, but leaks small talk during extraction." | "Best extraction granularity (atomic facts); weaker consolidation." | "Fastest load; solid all-rounder, slightly noisier extraction labels." | "Recommended; most disciplined extraction (ignores chit-chat), good consolidation, about 1.1 GB cached.";
3575
- }[];
3576
- };
3577
- };
3578
3568
  readonly "providers.kimiApiFormat": {
3579
3569
  readonly type: "enum";
3580
3570
  readonly values: readonly ["openai", "anthropic"];
@@ -3868,7 +3858,7 @@ export type StatusLineSeparatorStyle = SettingValue<"statusLine.separator">;
3868
3858
  export type TreeFilterMode = SettingValue<"treeFilterMode">;
3869
3859
  export interface CompactionSettings {
3870
3860
  enabled: boolean;
3871
- strategy: "context-full" | "handoff" | "shake" | "shake-summary" | "off";
3861
+ strategy: "context-full" | "handoff" | "shake" | "off";
3872
3862
  thresholdPercent: number;
3873
3863
  thresholdTokens: number;
3874
3864
  reserveTokens: number;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Keepalive for in-flight host-side eval bridge calls.
3
+ *
4
+ * The eval watchdog ({@link ../tools/eval IdleTimeout}) caps a cell's `timeout`
5
+ * as a wall-clock budget on the cell's *own* work, but pauses that budget while
6
+ * a host-side `agent()`/`parallel()` (via `runSubprocess`) or `llm()` (a single
7
+ * completion) call is in flight. Those calls are the only thing that re-arms the
8
+ * watchdog — and they can run for long stretches with **no** status of their own
9
+ * (a subagent's time-to-first-token on a reasoning model, a long quiet nested
10
+ * tool, or the entire body of a oneshot `llm()` call). Without a keepalive the
11
+ * watchdog would mistake that delegated work for the cell stalling and abort it
12
+ * mid-flight, killing the subagent.
13
+ *
14
+ * {@link withBridgeHeartbeat} bridges that gap by emitting a synthetic
15
+ * {@link EVAL_HEARTBEAT_OP} status event immediately when the call begins and
16
+ * then on a fixed cadence until it settles. The event rides the same
17
+ * `emitStatus → onStatus` channel both runtimes already forward, so it re-arms
18
+ * the watchdog without any new plumbing. The heartbeat is the *sole* signal that
19
+ * extends the budget: consumers MUST treat it as a pure keepalive — bump the
20
+ * watchdog and drop it (never persist or render it) — see the executor display
21
+ * sinks and the eval tool's `onStatus` handler. Every other status event
22
+ * (compute helpers, `log()`/`phase()`, tool results) counts against the budget.
23
+ */
24
+ import type { JsStatusEvent } from "./js/shared/types";
25
+ /**
26
+ * Synthetic status op emitted purely to keep the eval idle watchdog alive while
27
+ * a host-side bridge call is in flight. Carries no payload.
28
+ */
29
+ export declare const EVAL_HEARTBEAT_OP = "heartbeat";
30
+ /**
31
+ * Test seam: override the heartbeat cadence so integration tests can exercise
32
+ * the keepalive within a sub-second idle budget. Pass no value to restore the
33
+ * production default.
34
+ */
35
+ export declare function setBridgeHeartbeatIntervalMs(ms?: number): void;
36
+ /**
37
+ * Run {@link operation}, pumping {@link EVAL_HEARTBEAT_OP} status events through
38
+ * {@link emitStatus} — one immediately, then on a fixed cadence — until it
39
+ * settles. The immediate beat pauses the watchdog the instant the call begins,
40
+ * so a bridge call that starts close to the budget edge (after the cell already
41
+ * spent most of it computing) is not aborted before the first interval tick. A
42
+ * no-op wrapper when no `emitStatus` sink is wired (the heartbeat would reach
43
+ * nobody).
44
+ */
45
+ export declare function withBridgeHeartbeat<T>(emitStatus: ((event: JsStatusEvent) => void) | undefined, operation: () => Promise<T>): Promise<T>;
@@ -86,10 +86,10 @@ export type CustomToolSessionEvent = {
86
86
  } | {
87
87
  reason: "auto_compaction_start";
88
88
  trigger: "threshold" | "overflow" | "idle" | "incomplete";
89
- action: "context-full" | "handoff" | "shake" | "shake-summary";
89
+ action: "context-full" | "handoff" | "shake";
90
90
  } | {
91
91
  reason: "auto_compaction_end";
92
- action: "context-full" | "handoff" | "shake" | "shake-summary";
92
+ action: "context-full" | "handoff" | "shake";
93
93
  result: CompactionResult | undefined;
94
94
  aborted: boolean;
95
95
  willRetry: boolean;
@@ -1,6 +1,6 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
2
  import { EventBus } from "../../utils/event-bus";
3
- import type { Extension, ExtensionFactory, ExtensionRuntime as IExtensionRuntime, LoadExtensionsResult } from "./types";
3
+ import type { Extension, ExtensionFactory, ExtensionRuntime as IExtensionRuntime, LoadExtensionsResult, ProviderConfig } from "./types";
4
4
  export declare class ExtensionRuntimeNotInitializedError extends Error {
5
5
  constructor();
6
6
  }
@@ -12,7 +12,7 @@ export declare class ExtensionRuntime implements IExtensionRuntime {
12
12
  flagValues: Map<string, string | boolean>;
13
13
  pendingProviderRegistrations: Array<{
14
14
  name: string;
15
- config: import("./types").ProviderConfig;
15
+ config: ProviderConfig;
16
16
  sourceId: string;
17
17
  }>;
18
18
  sendMessage(): void;
@@ -6,7 +6,7 @@ import type { CredentialDisabledEvent, ImageContent, Model, ProviderResponseMeta
6
6
  import type { KeyId } from "@oh-my-pi/pi-tui";
7
7
  import type { ModelRegistry } from "../../config/model-registry";
8
8
  import type { SessionManager } from "../../session/session-manager";
9
- import type { AfterProviderResponseEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
9
+ import type { AfterProviderResponseEvent, AssistantThinkingRenderer, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
10
10
  /** Combined result from all before_agent_start handlers */
11
11
  interface BeforeAgentStartCombinedResult {
12
12
  messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
@@ -98,6 +98,7 @@ export declare class ExtensionRunner {
98
98
  emitError(error: ExtensionError): void;
99
99
  hasHandlers(eventType: string): boolean;
100
100
  getMessageRenderer(customType: string): MessageRenderer | undefined;
101
+ getAssistantThinkingRenderers(): AssistantThinkingRenderer[];
101
102
  getRegisteredCommands(reserved?: Set<string>): RegisteredCommand[];
102
103
  getCommandDiagnostics(): Array<{
103
104
  type: string;
@@ -13,6 +13,8 @@ import type { Api, AssistantMessageEvent, AssistantMessageEventStream, Context,
13
13
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
14
14
  import type * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
15
15
  import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
16
+ import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
17
+ import type * as Zod from "zod/v4";
16
18
  import type { KeybindingsManager } from "../../config/keybindings";
17
19
  import type { ModelRegistry } from "../../config/model-registry";
18
20
  import type { EditToolDetails } from "../../edit";
@@ -27,9 +29,16 @@ import type { BashToolDetails, BashToolInput, FindToolDetails, FindToolInput, Re
27
29
  import type { EventBus } from "../../utils/event-bus";
28
30
  import type { AgentEndEvent, AgentStartEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, GoalUpdatedEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionSwitchEvent, SessionTreeEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
29
31
  import type { SlashCommandInfo } from "../slash-commands";
32
+ import type * as TypeBox from "../typebox";
30
33
  export type { AppKeybinding, KeybindingsManager } from "../../config/keybindings";
31
34
  export type { ExecOptions, ExecResult } from "../../exec/exec";
32
35
  export type { AgentToolResult, AgentToolUpdateCallback };
36
+ export interface ExtensionUISelectOption {
37
+ label: string;
38
+ description?: string;
39
+ }
40
+ export type ExtensionUISelectItem = string | ExtensionUISelectOption;
41
+ export declare function getExtensionUISelectOptionLabel(option: ExtensionUISelectItem): string;
33
42
  /**
34
43
  * UI dialog options for extensions.
35
44
  */
@@ -70,8 +79,8 @@ export type ExtensionWidgetContent = string[] | ExtensionUiComponentFactory | un
70
79
  * Each mode (interactive, RPC, print) provides its own implementation.
71
80
  */
72
81
  export interface ExtensionUIContext {
73
- /** Show a selector and return the user's choice. */
74
- select(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
82
+ /** Show a selector and return the selected label, even when an option also includes a description. */
83
+ select(title: string, options: ExtensionUISelectItem[], dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
75
84
  /** Show a confirmation dialog. */
76
85
  confirm(title: string, message: string, dialogOptions?: ExtensionUIDialogOptions): Promise<boolean>;
77
86
  /** Show a text input dialog. */
@@ -508,6 +517,13 @@ export interface MessageRenderOptions {
508
517
  expanded: boolean;
509
518
  }
510
519
  export type MessageRenderer<T = unknown> = (message: CustomMessage<T>, options: MessageRenderOptions, theme: Theme) => Component | undefined;
520
+ export interface AssistantThinkingRenderContext {
521
+ contentIndex: number;
522
+ thinkingIndex: number;
523
+ text: string;
524
+ requestRender(): void;
525
+ }
526
+ export type AssistantThinkingRenderer = (context: AssistantThinkingRenderContext, theme: Theme) => Component | undefined;
511
527
  export interface RegisteredCommand {
512
528
  name: string;
513
529
  description?: string;
@@ -521,11 +537,11 @@ export type ExtensionHandler<E, R = undefined> = (event: E, ctx: ExtensionContex
521
537
  */
522
538
  export interface ExtensionAPI {
523
539
  /** File logger for error/warning/debug messages */
524
- logger: typeof import("@oh-my-pi/pi-utils").logger;
540
+ logger: typeof PiLogger;
525
541
  /** Injected zod-backed typebox shim for legacy `Type.Object(...)` parameter authoring. */
526
- typebox: typeof import("../typebox");
542
+ typebox: typeof TypeBox;
527
543
  /** Injected zod module for Zod-authored extension tools (canonical going forward). */
528
- zod: typeof import("zod/v4");
544
+ zod: typeof Zod;
529
545
  /** Injected pi-coding-agent exports for accessing SDK utilities */
530
546
  pi: typeof piCodingAgent;
531
547
  on(event: "resources_discover", handler: ExtensionHandler<ResourcesDiscoverEvent, ResourcesDiscoverResult>): void;
@@ -592,6 +608,8 @@ export interface ExtensionAPI {
592
608
  getFlag(name: string): boolean | string | undefined;
593
609
  /** Register a custom renderer for CustomMessageEntry. */
594
610
  registerMessageRenderer<T = unknown>(customType: string, renderer: MessageRenderer<T>): void;
611
+ /** Register a renderer for assistant thinking blocks. Rendered after the original thinking text. */
612
+ registerAssistantThinkingRenderer(renderer: AssistantThinkingRenderer): void;
595
613
  /**
596
614
  * Send a custom message to the session.
597
615
  *
@@ -840,6 +858,7 @@ export interface Extension {
840
858
  label?: string;
841
859
  handlers: Map<string, HandlerFn[]>;
842
860
  tools: Map<string, RegisteredTool<any, any>>;
861
+ assistantThinkingRenderers: AssistantThinkingRenderer[];
843
862
  messageRenderers: Map<string, MessageRenderer>;
844
863
  commands: Map<string, RegisteredCommand>;
845
864
  flags: Map<string, ExtensionFlag>;
@@ -160,12 +160,12 @@ export interface TurnEndEvent {
160
160
  export interface AutoCompactionStartEvent {
161
161
  type: "auto_compaction_start";
162
162
  reason: "threshold" | "overflow" | "idle" | "incomplete";
163
- action: "context-full" | "handoff" | "shake" | "shake-summary";
163
+ action: "context-full" | "handoff" | "shake";
164
164
  }
165
165
  /** Fired when auto-compaction ends */
166
166
  export interface AutoCompactionEndEvent {
167
167
  type: "auto_compaction_end";
168
- action: "context-full" | "handoff" | "shake" | "shake-summary";
168
+ action: "context-full" | "handoff" | "shake";
169
169
  result: CompactionResult | undefined;
170
170
  aborted: boolean;
171
171
  willRetry: boolean;
@@ -1,4 +1,4 @@
1
- import type { InternalResource, InternalUrl, ProtocolHandler, UrlCompletion } from "./types";
1
+ import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
2
2
  export interface LocalProtocolOptions {
3
3
  getArtifactsDir?: () => string | null;
4
4
  getSessionId?: () => string | null;
@@ -28,13 +28,23 @@ export declare class LocalProtocolHandler implements ProtocolHandler {
28
28
  * Returns the active local-protocol options.
29
29
  *
30
30
  * Resolution order:
31
- * 1. Explicit override installed via {@link setOverride} (used by subagents
32
- * that share their parent's root and by SDK consumers with a custom
33
- * artifacts/session id mapping).
34
- * 2. The main session in `AgentRegistry.global()`. Its `SessionManager`
35
- * supplies both `getArtifactsDir` and `getSessionId`.
31
+ * 1. **Caller-supplied** `context.localProtocolOptions` (the actual session
32
+ * that initiated the `read`/`find`/`search`/`router.resolve` call). This
33
+ * is what keeps `local://` reads pinned to the calling session in
34
+ * multi-session hosts (cmux/ACP, embedded SDK consumers) where every
35
+ * session registers as `kind: "main"` and "first one wins" would route
36
+ * to the wrong artifacts directory.
37
+ * 2. Explicit process-global override installed via {@link setOverride}
38
+ * (used by SDK consumers with a custom artifacts/session-id mapping and
39
+ * by code paths that do not have a calling session, e.g. TUI hyperlink
40
+ * resolution).
41
+ * 3. The first `main`-kind session in `AgentRegistry.global()`. Its
42
+ * `SessionManager` supplies both `getArtifactsDir` and `getSessionId`.
43
+ * Last-resort fallback — every caller that has a session reference
44
+ * SHOULD thread it through `context` so this branch is never taken in
45
+ * multi-session setups.
36
46
  */
37
- static resolveOptions(): LocalProtocolOptions | undefined;
38
- resolve(url: InternalUrl): Promise<InternalResource>;
39
- complete(): Promise<UrlCompletion[]>;
47
+ static resolveOptions(context?: ResolveContext): LocalProtocolOptions | undefined;
48
+ resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource>;
49
+ complete(_query?: string, context?: ResolveContext): Promise<UrlCompletion[]>;
40
50
  }
@@ -4,6 +4,7 @@
4
4
  * Internal URLs (agent://, artifact://, memory://, skill://, rule://, mcp://, omp://, local://) are resolved by tools like read,
5
5
  * providing access to agent outputs and server resources without exposing filesystem paths.
6
6
  */
7
+ import type { LocalProtocolOptions } from "./local-protocol";
7
8
  /**
8
9
  * Raw resource payload returned by protocol handlers. The `immutable` flag is
9
10
  * applied by the router from {@link ProtocolHandler.immutable}, so handlers do
@@ -73,6 +74,17 @@ export interface ResolveContext {
73
74
  settings?: unknown;
74
75
  /** Caller's abort signal. */
75
76
  signal?: AbortSignal;
77
+ /**
78
+ * Calling session's `local://` root mapping. When present, the local-protocol
79
+ * handler resolves the URL against THIS session's artifacts dir instead of
80
+ * picking the first `main`-kind session from the global `AgentRegistry`.
81
+ *
82
+ * Required for correctness in multi-session hosts (cmux/ACP, embedded SDK
83
+ * consumers) where multiple sessions are registered as `main` and the
84
+ * "first one wins" lookup picks the wrong artifacts directory — see
85
+ * [#1608](https://github.com/can1357/oh-my-pi/issues/1608).
86
+ */
87
+ localProtocolOptions?: LocalProtocolOptions;
76
88
  }
77
89
  /**
78
90
  * Caller context for write operations dispatched to host-owned URI handlers.
@@ -84,6 +96,8 @@ export interface WriteContext {
84
96
  cwd?: string;
85
97
  /** Caller's abort signal. */
86
98
  signal?: AbortSignal;
99
+ /** Calling session's `local://` root mapping — see {@link ResolveContext.localProtocolOptions}. */
100
+ localProtocolOptions?: LocalProtocolOptions;
87
101
  }
88
102
  /**
89
103
  * Handler for a specific internal URL scheme (e.g., agent://, memory://, skill://, mcp://).
@@ -39,6 +39,9 @@ export declare function notifySaved(client: LspClient, filePath: string, signal?
39
39
  * Increments version, sends didChange and didSave notifications.
40
40
  */
41
41
  export declare function refreshFile(client: LspClient, filePath: string, signal?: AbortSignal): Promise<void>;
42
+ /**
43
+ * Shutdown a specific client by key.
44
+ */
42
45
  export declare function shutdownClient(key: string): Promise<void>;
43
46
  /**
44
47
  * Send an LSP request and wait for response.
@@ -0,0 +1,10 @@
1
+ import type { FileDiagnosticsResult } from "./index";
2
+ export declare function diagnosticIdentity(message: string): string;
3
+ export declare class DiagnosticsLedger {
4
+ #private;
5
+ reduce(absPath: string, result: FileDiagnosticsResult): FileDiagnosticsResult;
6
+ }
7
+ export interface DiagnosticsLedgerOwner {
8
+ diagnosticsLedger?: DiagnosticsLedger;
9
+ }
10
+ export declare function getDiagnosticsLedger(owner: DiagnosticsLedgerOwner): DiagnosticsLedger;
@@ -71,6 +71,8 @@ export interface WritethroughOptions {
71
71
  onDeferredDiagnostics?: (diagnostics: FileDiagnosticsResult) => void;
72
72
  /** Signal to cancel a pending deferred diagnostics fetch. */
73
73
  deferredSignal?: AbortSignal;
74
+ /** Transform diagnostics before surfacing them after a successful fetch. */
75
+ transformDiagnostics?: (absPath: string, result: FileDiagnosticsResult) => FileDiagnosticsResult;
74
76
  }
75
77
  /** Per-file deferred LSP diagnostics wiring for {@link WritethroughCallback}. */
76
78
  export type WritethroughDeferredHandle = {
@@ -39,6 +39,10 @@ export declare function formatGroupedDiagnosticMessages(messages: string[]): str
39
39
  * Format diagnostics grouped by severity.
40
40
  */
41
41
  export declare function formatDiagnosticsSummary(diagnostics: Diagnostic[]): string;
42
+ export declare function summarizeDiagnosticMessages(messages: string[]): {
43
+ summary: string;
44
+ errored: boolean;
45
+ };
42
46
  /**
43
47
  * Format a location as file:line:col relative to cwd.
44
48
  */
@@ -130,12 +130,21 @@ export declare class MCPManager {
130
130
  disconnectAll(): Promise<void>;
131
131
  /**
132
132
  * Reconnect to a server after a connection failure.
133
+ *
133
134
  * Tears down the stale connection, re-resolves auth, establishes a new
134
- * connection, reloads tools, and notifies consumers.
135
- * Concurrent calls for the same server share one reconnection attempt.
136
- * Returns the new connection, or null if reconnection failed.
137
- */
138
- reconnectServer(name: string): Promise<MCPServerConnection | null>;
135
+ * connection, reloads tools, and notifies consumers. Concurrent calls for
136
+ * the same server share one reconnection attempt. Returns the new
137
+ * connection, or `null` if reconnection failed or the per-server crash
138
+ * burst limit (see {@link RECONNECT_BURST_LIMIT}) is exceeded.
139
+ *
140
+ * @param options.manual - When `true`, resets the crash-burst window so a
141
+ * user-driven retry (e.g. `/mcp reconnect`) is never blocked by an
142
+ * earlier storm. Defaults to `false`; the transport `onClose` callback
143
+ * and the per-tool-call retry path in `tool-bridge` MUST NOT set it.
144
+ */
145
+ reconnectServer(name: string, options?: {
146
+ manual?: boolean;
147
+ }): Promise<MCPServerConnection | null>;
139
148
  /**
140
149
  * Refresh tools from a specific server.
141
150
  */
@@ -1,5 +1,5 @@
1
1
  import { type Agent, type AgentSideConnection, type AuthenticateRequest, type AuthenticateResponse, type ClientCapabilities, type CloseSessionRequest, type CloseSessionResponse, type ForkSessionRequest, type ForkSessionResponse, type InitializeRequest, type InitializeResponse, type ListSessionsRequest, type ListSessionsResponse, type LoadSessionRequest, type LoadSessionResponse, type NewSessionRequest, type NewSessionResponse, type PromptRequest, type PromptResponse, type ResumeSessionRequest, type ResumeSessionResponse, type SetSessionConfigOptionRequest, type SetSessionConfigOptionResponse, type SetSessionModelRequest, type SetSessionModelResponse, type SetSessionModeRequest, type SetSessionModeResponse } from "@agentclientprotocol/sdk";
2
- import type { ExtensionUIContext } from "../../extensibility/extensions";
2
+ import { type ExtensionUIContext } from "../../extensibility/extensions";
3
3
  import type { AgentSession } from "../../session/agent-session";
4
4
  /**
5
5
  * Delay between `session/new` (or `session/load` / `session/resume` /
@@ -1,5 +1,6 @@
1
1
  import type { AssistantMessage, ImageContent, Usage } from "@oh-my-pi/pi-ai";
2
2
  import { Container } from "@oh-my-pi/pi-tui";
3
+ import type { AssistantThinkingRenderer } from "../../extensibility/extensions/types";
3
4
  /**
4
5
  * Component that renders a complete assistant message
5
6
  */
@@ -7,7 +8,8 @@ export declare class AssistantMessageComponent extends Container {
7
8
  #private;
8
9
  private hideThinkingBlock;
9
10
  private readonly onImageUpdate?;
10
- constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: (() => void) | undefined);
11
+ private readonly thinkingRenderers;
12
+ constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: (() => void) | undefined, thinkingRenderers?: readonly AssistantThinkingRenderer[]);
11
13
  invalidate(): void;
12
14
  setHideThinkingBlock(hide: boolean): void;
13
15
  setToolResultImages(toolCallId: string, images: ImageContent[]): void;
@@ -10,7 +10,6 @@ export declare class CustomEditor extends Editor {
10
10
  * them, skipping any occurrence inside code spans, fenced blocks, or XML sections. */
11
11
  decorateText: (text: string) => string;
12
12
  onEscape?: () => void;
13
- shouldBypassAutocompleteOnEscape?: () => boolean;
14
13
  onClear?: () => void;
15
14
  onExit?: () => void;
16
15
  onCycleThinkingLevel?: () => void;
@@ -42,9 +42,15 @@ export interface HookSelectorOptions {
42
42
  helpText?: string;
43
43
  slider?: HookSelectorSlider;
44
44
  }
45
+ export interface HookSelectorOption {
46
+ label: string;
47
+ description?: string;
48
+ }
49
+ export type HookSelectorOptionInput = string | HookSelectorOption;
45
50
  export declare class HookSelectorComponent extends Container {
46
51
  #private;
47
- constructor(title: string, options: string[], onSelect: (option: string) => void, onCancel: () => void, opts?: HookSelectorOptions);
52
+ constructor(title: string, options: HookSelectorOptionInput[], onSelect: (option: string) => void, onCancel: () => void, opts?: HookSelectorOptions);
48
53
  handleInput(keyData: string): void;
54
+ render(width: number): string[];
49
55
  dispose(): void;
50
56
  }
@@ -31,9 +31,8 @@ export declare class CommandController {
31
31
  handlePythonCommand(code: string, excludeFromContext?: boolean): Promise<void>;
32
32
  handleCompactCommand(customInstructions?: string): Promise<CompactionOutcome>;
33
33
  /**
34
- * TUI handler for `/shake`. `elide`/`images` are instant structural drops;
35
- * `summary` runs the local on-device compressor behind a cancelable loader
36
- * (Esc aborts via `abortCompaction`). Rebuilds the chat and reports counts.
34
+ * TUI handler for `/shake`. `elide` drops heavy structural content and
35
+ * `images` strips image blocks. Rebuilds the chat and reports counts.
37
36
  */
38
37
  handleShakeCommand(mode: ShakeMode): Promise<void>;
39
38
  handleSkillCommand(skillPath: string, args: string): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
2
2
  import { KeybindingsManager } from "../../config/keybindings";
3
- import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetContent, ExtensionWidgetOptions, TerminalInputHandler } from "../../extensibility/extensions";
3
+ import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions, TerminalInputHandler } from "../../extensibility/extensions";
4
4
  import { type HookSelectorSlider } from "../../modes/components/hook-selector";
5
5
  import { type Theme } from "../../modes/theme/theme";
6
6
  import type { InteractiveModeContext } from "../../modes/types";
@@ -30,7 +30,7 @@ export declare class ExtensionUiController {
30
30
  /**
31
31
  * Show a selector for hooks.
32
32
  */
33
- showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
33
+ showHookSelector(title: string, options: ExtensionUISelectItem[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
34
34
  slider?: HookSelectorSlider;
35
35
  }): Promise<string | undefined>;
36
36
  /**
@@ -5,7 +5,7 @@ import type { Component, EditorTheme } from "@oh-my-pi/pi-tui";
5
5
  import { Container, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
6
6
  import { KeybindingsManager } from "../config/keybindings";
7
7
  import { Settings } from "../config/settings";
8
- import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
8
+ import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
9
9
  import type { CompactOptions } from "../extensibility/extensions/types";
10
10
  import { type PlanApprovalDetails } from "../plan-mode/approved-plan";
11
11
  import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
@@ -253,7 +253,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
253
253
  emitCustomToolSessionEvent(reason: "start" | "switch" | "branch" | "tree" | "shutdown", previousSessionFile?: string): Promise<void>;
254
254
  setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
255
255
  setHookStatus(key: string, text: string | undefined): void;
256
- showHookSelector(title: string, options: string[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
256
+ showHookSelector(title: string, options: ExtensionUISelectItem[], dialogOptions?: ExtensionUIDialogOptions, extra?: {
257
257
  slider?: HookSelectorSlider;
258
258
  }): Promise<string | undefined>;
259
259
  hideHookSelector(): void;
@@ -1,4 +1,4 @@
1
- import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../../extensibility/extensions";
1
+ import { type ExtensionUIContext, type ExtensionUIDialogOptions } from "../../extensibility/extensions";
2
2
  import type { AgentSession } from "../../session/agent-session";
3
3
  import type { RpcExtensionUIRequest, RpcExtensionUIResponse, RpcHostToolCallRequest, RpcHostToolCancelRequest, RpcHostUriCancelRequest, RpcHostUriRequest, RpcResponse } from "./rpc-types";
4
4
  export type * from "./rpc-types";