@oh-my-pi/pi-coding-agent 15.10.0 → 15.10.2

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 (238) hide show
  1. package/CHANGELOG.md +142 -1
  2. package/dist/types/cli/dry-balance-cli.d.ts +15 -1
  3. package/dist/types/cli/startup-cwd.d.ts +2 -0
  4. package/dist/types/commands/launch.d.ts +3 -0
  5. package/dist/types/commit/analysis/conventional.d.ts +2 -2
  6. package/dist/types/commit/analysis/summary.d.ts +2 -2
  7. package/dist/types/commit/changelog/generate.d.ts +2 -2
  8. package/dist/types/commit/changelog/index.d.ts +2 -2
  9. package/dist/types/commit/map-reduce/index.d.ts +3 -3
  10. package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
  11. package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
  12. package/dist/types/commit/model-selection.d.ts +10 -4
  13. package/dist/types/config/api-key-resolver.d.ts +34 -0
  14. package/dist/types/config/keybindings.d.ts +2 -2
  15. package/dist/types/config/model-provider-priority.d.ts +1 -0
  16. package/dist/types/config/model-registry.d.ts +17 -1
  17. package/dist/types/config/model-resolver.d.ts +4 -1
  18. package/dist/types/config/settings-schema.d.ts +9 -0
  19. package/dist/types/config/settings.d.ts +7 -2
  20. package/dist/types/dap/config.d.ts +14 -1
  21. package/dist/types/dap/types.d.ts +10 -0
  22. package/dist/types/debug/report-bundle.d.ts +3 -0
  23. package/dist/types/edit/file-snapshot-store.d.ts +18 -10
  24. package/dist/types/eval/py/__tests__/prelude.test.d.ts +1 -0
  25. package/dist/types/extensibility/extensions/types.d.ts +4 -1
  26. package/dist/types/lsp/client.d.ts +10 -0
  27. package/dist/types/lsp/utils.d.ts +3 -2
  28. package/dist/types/main.d.ts +3 -9
  29. package/dist/types/mcp/tool-bridge.d.ts +2 -0
  30. package/dist/types/modes/components/chat-block.d.ts +64 -0
  31. package/dist/types/modes/components/custom-editor.d.ts +4 -1
  32. package/dist/types/modes/components/overlay-box.d.ts +17 -0
  33. package/dist/types/modes/components/plan-review-overlay.d.ts +59 -0
  34. package/dist/types/modes/components/plan-toc.d.ts +41 -0
  35. package/dist/types/modes/components/read-tool-group.d.ts +2 -0
  36. package/dist/types/modes/components/status-line.d.ts +2 -0
  37. package/dist/types/modes/components/transcript-container.d.ts +11 -0
  38. package/dist/types/modes/controllers/command-controller.d.ts +1 -0
  39. package/dist/types/modes/controllers/event-controller.d.ts +17 -1
  40. package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
  41. package/dist/types/modes/controllers/input-controller.d.ts +1 -1
  42. package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
  43. package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
  44. package/dist/types/modes/interactive-mode.d.ts +16 -5
  45. package/dist/types/modes/magic-keywords.d.ts +1 -1
  46. package/dist/types/modes/markdown-prose.d.ts +1 -1
  47. package/dist/types/modes/theme/theme.d.ts +1 -1
  48. package/dist/types/modes/types.d.ts +21 -5
  49. package/dist/types/modes/utils/copy-targets.d.ts +21 -1
  50. package/dist/types/modes/workflow.d.ts +3 -3
  51. package/dist/types/plan-mode/approved-plan.d.ts +27 -8
  52. package/dist/types/plan-mode/plan-protection.d.ts +4 -4
  53. package/dist/types/sdk.d.ts +2 -0
  54. package/dist/types/session/agent-session.d.ts +21 -0
  55. package/dist/types/session/auth-storage.d.ts +1 -1
  56. package/dist/types/session/messages.d.ts +12 -0
  57. package/dist/types/session/session-manager.d.ts +8 -3
  58. package/dist/types/slash-commands/types.d.ts +4 -6
  59. package/dist/types/task/executor.d.ts +17 -0
  60. package/dist/types/task/index.d.ts +1 -0
  61. package/dist/types/task/render.d.ts +3 -2
  62. package/dist/types/tools/archive-reader.d.ts +5 -0
  63. package/dist/types/tools/ast-edit.d.ts +3 -0
  64. package/dist/types/tools/ast-grep.d.ts +3 -0
  65. package/dist/types/tools/bash.d.ts +1 -0
  66. package/dist/types/tools/eval.d.ts +8 -0
  67. package/dist/types/tools/find.d.ts +8 -4
  68. package/dist/types/tools/gh-cache-invalidation.d.ts +6 -0
  69. package/dist/types/tools/github-cache.d.ts +12 -0
  70. package/dist/types/tools/grouped-file-output.d.ts +95 -12
  71. package/dist/types/tools/memory-render.d.ts +4 -1
  72. package/dist/types/tools/path-utils.d.ts +8 -0
  73. package/dist/types/tools/plan-mode-guard.d.ts +8 -9
  74. package/dist/types/tools/render-utils.d.ts +5 -9
  75. package/dist/types/tools/search.d.ts +6 -2
  76. package/dist/types/tools/sqlite-reader.d.ts +1 -0
  77. package/dist/types/tools/todo.d.ts +3 -2
  78. package/dist/types/tools/write.d.ts +3 -0
  79. package/dist/types/tools/yield.d.ts +8 -0
  80. package/dist/types/tui/output-block.d.ts +16 -4
  81. package/dist/types/tui/status-line.d.ts +3 -0
  82. package/dist/types/utils/enhanced-paste.d.ts +20 -0
  83. package/dist/types/web/search/providers/kimi.d.ts +1 -1
  84. package/package.json +9 -9
  85. package/src/auto-thinking/classifier.ts +5 -1
  86. package/src/cli/args.ts +3 -1
  87. package/src/cli/dry-balance-cli.ts +54 -21
  88. package/src/cli/gallery-cli.ts +4 -1
  89. package/src/cli/gallery-fixtures/misc.ts +29 -0
  90. package/src/cli/startup-cwd.ts +68 -0
  91. package/src/commands/launch.ts +3 -0
  92. package/src/commit/analysis/conventional.ts +2 -2
  93. package/src/commit/analysis/summary.ts +2 -2
  94. package/src/commit/changelog/generate.ts +2 -2
  95. package/src/commit/changelog/index.ts +2 -2
  96. package/src/commit/map-reduce/index.ts +3 -3
  97. package/src/commit/map-reduce/map-phase.ts +2 -2
  98. package/src/commit/map-reduce/reduce-phase.ts +2 -2
  99. package/src/commit/model-selection.ts +36 -11
  100. package/src/commit/pipeline.ts +4 -4
  101. package/src/config/api-key-resolver.ts +58 -0
  102. package/src/config/model-provider-priority.ts +55 -0
  103. package/src/config/model-registry.ts +29 -24
  104. package/src/config/model-resolver.ts +39 -7
  105. package/src/config/settings-schema.ts +10 -0
  106. package/src/config/settings.ts +106 -43
  107. package/src/dap/config.ts +41 -2
  108. package/src/dap/defaults.json +1 -0
  109. package/src/dap/session.ts +1 -0
  110. package/src/dap/types.ts +10 -0
  111. package/src/debug/index.ts +47 -53
  112. package/src/debug/raw-sse-buffer.ts +7 -4
  113. package/src/debug/report-bundle.ts +9 -0
  114. package/src/edit/file-snapshot-store.ts +33 -1
  115. package/src/edit/hashline/filesystem.ts +2 -1
  116. package/src/edit/renderer.ts +82 -78
  117. package/src/eval/__tests__/llm-bridge.test.ts +110 -31
  118. package/src/eval/js/context-manager.ts +32 -15
  119. package/src/eval/llm-bridge.ts +22 -6
  120. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  121. package/src/eval/py/executor.ts +23 -11
  122. package/src/eval/py/prelude.py +1 -1
  123. package/src/extensibility/extensions/types.ts +10 -1
  124. package/src/goals/tools/goal-tool.ts +36 -26
  125. package/src/internal-urls/docs-index.generated.ts +8 -8
  126. package/src/lsp/client.ts +23 -11
  127. package/src/lsp/config.ts +11 -1
  128. package/src/lsp/index.ts +61 -9
  129. package/src/lsp/utils.ts +3 -2
  130. package/src/main.ts +100 -72
  131. package/src/mcp/tool-bridge.ts +2 -0
  132. package/src/memories/index.ts +14 -7
  133. package/src/mnemopi/backend.ts +5 -1
  134. package/src/modes/acp/acp-agent.ts +33 -26
  135. package/src/modes/components/assistant-message.ts +2 -9
  136. package/src/modes/components/chat-block.ts +111 -0
  137. package/src/modes/components/copy-selector.ts +1 -44
  138. package/src/modes/components/custom-editor.ts +164 -109
  139. package/src/modes/components/custom-message.ts +1 -3
  140. package/src/modes/components/execution-shared.ts +1 -2
  141. package/src/modes/components/hook-message.ts +1 -3
  142. package/src/modes/components/model-selector.ts +59 -13
  143. package/src/modes/components/oauth-selector.ts +33 -7
  144. package/src/modes/components/overlay-box.ts +108 -0
  145. package/src/modes/components/plan-review-overlay.ts +799 -0
  146. package/src/modes/components/plan-toc.ts +138 -0
  147. package/src/modes/components/read-tool-group.ts +20 -4
  148. package/src/modes/components/skill-message.ts +0 -1
  149. package/src/modes/components/status-line.ts +19 -4
  150. package/src/modes/components/tips.txt +2 -1
  151. package/src/modes/components/todo-reminder.ts +0 -2
  152. package/src/modes/components/tool-execution.ts +68 -88
  153. package/src/modes/components/transcript-container.ts +84 -24
  154. package/src/modes/components/user-message.ts +2 -3
  155. package/src/modes/controllers/command-controller-shared.ts +7 -6
  156. package/src/modes/controllers/command-controller.ts +57 -55
  157. package/src/modes/controllers/event-controller.ts +67 -40
  158. package/src/modes/controllers/extension-ui-controller.ts +10 -73
  159. package/src/modes/controllers/input-controller.ts +170 -126
  160. package/src/modes/controllers/mcp-command-controller.ts +69 -60
  161. package/src/modes/controllers/selector-controller.ts +23 -25
  162. package/src/modes/controllers/streaming-reveal.ts +212 -0
  163. package/src/modes/controllers/tan-command-controller.ts +173 -0
  164. package/src/modes/interactive-mode.ts +274 -112
  165. package/src/modes/magic-keywords.ts +1 -1
  166. package/src/modes/markdown-prose.ts +1 -1
  167. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  168. package/src/modes/theme/shimmer.ts +20 -9
  169. package/src/modes/theme/theme-schema.json +1 -1
  170. package/src/modes/theme/theme.ts +8 -4
  171. package/src/modes/types.ts +21 -7
  172. package/src/modes/utils/copy-targets.ts +133 -27
  173. package/src/modes/utils/ui-helpers.ts +44 -46
  174. package/src/modes/workflow.ts +10 -10
  175. package/src/plan-mode/approved-plan.ts +66 -43
  176. package/src/plan-mode/plan-protection.ts +4 -4
  177. package/src/prompts/system/background-tan-dispatch.md +8 -0
  178. package/src/prompts/system/plan-mode-active.md +67 -58
  179. package/src/prompts/system/plan-mode-approved.md +1 -1
  180. package/src/prompts/system/workflow-notice.md +1 -1
  181. package/src/prompts/tools/bash.md +9 -0
  182. package/src/prompts/tools/browser.md +1 -1
  183. package/src/prompts/tools/eval.md +2 -1
  184. package/src/prompts/tools/read.md +2 -2
  185. package/src/sdk.ts +37 -46
  186. package/src/session/agent-session.ts +119 -18
  187. package/src/session/auth-storage.ts +2 -0
  188. package/src/session/messages.ts +26 -0
  189. package/src/session/session-manager.ts +109 -28
  190. package/src/slash-commands/builtin-registry.ts +36 -9
  191. package/src/slash-commands/types.ts +4 -6
  192. package/src/task/executor.ts +76 -38
  193. package/src/task/index.ts +4 -0
  194. package/src/task/render.ts +211 -147
  195. package/src/tools/archive-reader.ts +64 -0
  196. package/src/tools/ask.ts +119 -164
  197. package/src/tools/ast-edit.ts +98 -71
  198. package/src/tools/ast-grep.ts +37 -43
  199. package/src/tools/bash.ts +57 -6
  200. package/src/tools/browser/tab-supervisor.ts +13 -1
  201. package/src/tools/browser/tab-worker.ts +33 -4
  202. package/src/tools/debug.ts +20 -8
  203. package/src/tools/eval.ts +13 -2
  204. package/src/tools/fetch.ts +297 -7
  205. package/src/tools/find.ts +51 -30
  206. package/src/tools/gh-cache-invalidation.ts +200 -0
  207. package/src/tools/gh-renderer.ts +81 -42
  208. package/src/tools/github-cache.ts +25 -0
  209. package/src/tools/grouped-file-output.ts +272 -48
  210. package/src/tools/image-gen.ts +150 -103
  211. package/src/tools/inspect-image-renderer.ts +63 -41
  212. package/src/tools/inspect-image.ts +10 -3
  213. package/src/tools/job.ts +3 -4
  214. package/src/tools/memory-render.ts +4 -1
  215. package/src/tools/path-utils.ts +28 -2
  216. package/src/tools/plan-mode-guard.ts +66 -39
  217. package/src/tools/read.ts +48 -28
  218. package/src/tools/render-utils.ts +21 -37
  219. package/src/tools/resolve.ts +14 -0
  220. package/src/tools/search-tool-bm25.ts +36 -23
  221. package/src/tools/search.ts +118 -81
  222. package/src/tools/sqlite-reader.ts +9 -12
  223. package/src/tools/todo.ts +118 -52
  224. package/src/tools/write.ts +83 -64
  225. package/src/tools/yield.ts +10 -1
  226. package/src/tui/output-block.ts +60 -13
  227. package/src/tui/status-line.ts +5 -1
  228. package/src/utils/commit-message-generator.ts +11 -3
  229. package/src/utils/enhanced-paste.ts +230 -0
  230. package/src/utils/title-generator.ts +2 -1
  231. package/src/web/search/providers/anthropic.ts +25 -19
  232. package/src/web/search/providers/codex.ts +37 -8
  233. package/src/web/search/providers/exa.ts +11 -3
  234. package/src/web/search/providers/kimi.ts +28 -17
  235. package/src/web/search/providers/parallel.ts +35 -24
  236. package/src/web/search/providers/synthetic.ts +8 -6
  237. package/src/web/search/providers/tavily.ts +9 -8
  238. package/src/web/search/providers/zai.ts +8 -6
package/CHANGELOG.md CHANGED
@@ -2,6 +2,147 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.2] - 2026-06-08
6
+ ### Added
7
+
8
+ - Added `raw-sse.txt` to debug report bundles, exporting recent raw provider SSE diagnostics when captured
9
+ - Added `/model` visibility for auto-selected role defaults: inferred `pi/smol`/`pi/slow`/designer choices now show as compact `[ROLE auto]` badges, while explicitly configured roles keep the existing solid badges and thinking labels.
10
+ - Added credential provenance to the `/login` and `/logout` provider picker: each authenticated provider now shows where its credential comes from — `(login)`, `(api key)`, `(env: VAR_NAME)`, `(config)`, `(--api-key)`, or `(custom provider)` — so a real OAuth login is distinguishable from an env var that merely aliases the provider (e.g. `COPILOT_GITHUB_TOKEN`). The origin is also matched by the picker's type-to-search filter.
11
+
12
+ ### Changed
13
+
14
+ - Changed raw SSE debug export output to prepend dropped-record metadata so truncated sessions in debug bundles now report dropped record and character counts
15
+ - Changed settings reads to cache pre-split schema paths and resolved values, with coarse invalidation on source/cwd changes.
16
+ - Changed status-line rendering to cache merged effective settings until `updateSettings()` changes the configuration.
17
+ - Changed `CustomEditor` app shortcut dispatch to parse each input packet once and match against precomputed canonical key sets, preserving the existing shortcut precedence while avoiding repeated key reparses.
18
+ - Changed `lsp references` to retry only when no references or only the queried declaration are returned, using two fixed 250ms retries for project-aware servers
19
+ - Changed `read` handling of `https://github.com/<owner>/<repo>:raw` to use raw page rendering only, removing the GitHub API README fallback
20
+ - Changed model resolution to apply provider-priority ordering when selecting models for roles and ambiguous patterns, using `modelProviderOrder` settings and built-in provider priority so first-party providers are preferred over relays in tie cases
21
+ - Changed model canonical variant selection to use the same provider-priority ordering instead of candidate order when deduplicating equivalent upstream models
22
+ - Changed the working-message shimmer to sweep at a fixed velocity (cells/second) instead of a fixed sweep duration divided by the message length. The band now advances ≤1 cell per 30fps redraw frame and stays equally smooth on short and long messages — previously a longer message swept proportionally faster and stepped visibly because it outran the redraw cadence. Sweep/round-trip duration now scales with length. Additionally, when `display.shimmer = disabled` the working line is static, so the loader no longer schedules 30fps redraws for it and falls back to the spinner-only ~12.5fps cadence.
23
+ - Changed the eval fan-out trigger keyword from `workflow`/`workflows` to `workflowz`.
24
+
25
+ ### Fixed
26
+
27
+ - Fixed working-message loader session accents so spinner/message color math is cached per session name, session-accent setting, and theme luminance while still updating immediately on renames, setting toggles, and theme changes.
28
+ - Fixed startup model fallback selection so sessions now prefer each provider’s configured default model before choosing the first available authenticated model
29
+ - Fixed implicit model selection path for tools and sessions by honoring persisted model-provider order when no explicit pattern is provided
30
+ - Fixed the working spinner appearing to ignore Esc for 2-3 seconds when an interrupt lands mid-tool. Esc fires the abort synchronously, but the agent loop only stops the loader at `agent_end`, which it cannot reach until every in-flight tool settles in `executeToolCalls`' `await Promise.allSettled(...)` — and process/subagent/kernel-owning tools tear down gracefully (SIGTERM, 2-3s grace, SIGKILL), so the loader kept showing the unchanged "Working…/<intent>" line and read as a dropped keypress. The loader now switches to "Interrupting…" the instant Esc requests the abort and freezes intent-driven label updates until the turn unwinds (`EventController.notifyInterrupting`), so the interrupt is acknowledged immediately even while teardown completes.
31
+ - Fixed a flaky JS eval worker startup that intermittently failed unrelated CI runs. The worker-ready wait reused Bun's 5s default per-test timeout as its floor, so a slow cold-start under `--isolate` + high concurrency was aborted mid-init; terminating a still-initializing Bun worker is the documented SIGILL/SIGTRAP crash trigger, which took down the whole test file. Worker init now floors at a fixed 15s infrastructure budget (independent of, and still dominated by, a larger per-cell `timeout`), and the JS eval test suites set a 20s file-local timeout so cold starts complete instead of being torn down.
32
+ - Fixed reviewer-style subagent yields crashing the calling eval cell when a caller-supplied output schema declares `additionalProperties: false` without a `findings` property. `normalizeCompleteData` now consults the active validator before splicing collected `report_finding` entries onto the yielded payload, so injection is suppressed when the schema would reject it — keeping the executor's post-mortem validation in lockstep with the in-tool `yield` validation that already accepted the same raw payload ([#2070](https://github.com/can1357/oh-my-pi/issues/2070))
33
+ - Fixed Anthropic empty `toolUse` stops without tool calls corrupting session history by retrying them and removing orphaned turns even at the retry cap.
34
+ - Fixed MCP tools hanging in non-yolo modes by declaring `approval = "write"` on `MCPTool` and `DeferredMCPTool`, and propagating the `approval` property through `customToolToDefinition()` in `sdk.ts`
35
+ - Fixed session resumption after a working directory is moved/renamed (e.g. `git worktree move`): `--continue` now re-roots the terminal's last session into the new directory when its original directory no longer exists, explicit `--resume <id> --session-dir <dir>` local matches re-root instead of reopening with the stale cwd, and cross-project `--resume <id>` offers to move (re-root) the session rather than only forking a duplicate copy when the source directory is gone
36
+ - Fixed Kitty OSC 5522 paste rejecting plain text as "no supported text or image data": the listing parser now decodes the `mime="."` DATA payload (whitespace-separated MIME list) Kitty actually sends, in addition to the per-type DATA packets described by the ancillary 5522-mode spec, and per-type spec listings now request the selected payload with `type=read:mime=...` instead of Kitty's dot-payload request shape ([#2051](https://github.com/can1357/oh-my-pi/issues/2051))
37
+ - Fixed follow-up shortcut submission of builtin slash commands so `/goal set ...` applies goal mode instead of queueing as plain text.
38
+ - Fixed Ctrl+Z crashing the agent on Windows with `TypeError: Unknown signal: SIGTSTP`. `InputController.handleCtrlZ` called `process.kill(0, "SIGTSTP")` unconditionally, but `SIGTSTP` is POSIX job-control and Bun/Node on Windows rejects the signal name from the JS side; the throw propagated out of the TUI input dispatcher as an uncaught exception. The handler now no-ops with a "Suspend (Ctrl+Z) is not supported on this platform" status on Windows, and on POSIX wraps `process.kill` in a try/catch that detaches the registered SIGCONT resume hook and re-`start()`s the TUI on failure so a rejected signal can never leave the UI stranded with a leaked listener ([#2036](https://github.com/can1357/oh-my-pi/issues/2036)).
39
+ - Fixed a relative `--cwd` target (e.g. `omp --cwd repo` launched from `/tmp`) leaking the raw relative string into the session config. `applyStartupCwd` chdired into the resolved directory via `setProjectDir` but left `parsed.cwd` as `"repo"`, so `buildSessionOptions` (which prefers `parsed.cwd` over `getProjectDir()`) handed downstream settings/discovery/session creation a value that re-resolved against the new process cwd (`/tmp/repo/repo`) or persisted a relative session cwd. `parsed.cwd` is now re-synced to the resolved absolute project dir after the chdir.
40
+ - Fixed the `--cwd` launch flag so it is parsed and can override the startup directory instead of always falling back to the current process directory or home auto-switch target.
41
+ - Fixed session auto-retry for generic `upstream_error: Upstream request failed` gateway failures.
42
+ - Stripped read-output line-number prefixes (`N:`) from auto-piped bare body rows in the hashline edit parser, so pasting `3:text` without a `+` prefix no longer injects `3:` as literal content. Uses single-pass stripping to avoid corrupting content whose own text starts with `digits:` ([#1492](https://github.com/can1357/oh-my-pi/issues/1492)).
43
+ - Fixed `eval` `llm()` returning HTTP 400 "Instructions are required" when called without a `system` prompt against providers (notably `openai-codex`) whose Responses transformer drops the `instructions` field on an empty system prompt. `runEvalLlm` now sends a minimal default system prompt ("You are a helpful assistant.") when no `system` is supplied, so `llm("question")` works against every provider; an explicit `system=` still wins.
44
+ - Fixed the Python `read(path, offset, limit)` prelude helper rejecting documented positional arguments with `TypeError: read() takes 1 positional argument but 3 were given`. The signature was keyword-only (`def read(path, *, offset=1, limit=None)`) while the eval helper table advertises positional optional args; agents that called `read("file.py", 10, 20)` literally crashed. The `*` is removed so both `read("f", 10, 20)` and `read("f", offset=10, limit=20)` work.
45
+ - Fixed `eval` reset cells failing with `"Python kernel reset already in progress"` / `"JS context reset already in progress"` when two cells happened to overlap on the same session (e.g. a rapid resubmit, or a parallel-cell race). The executor now coalesces concurrent resets — additional callers wait for the in-flight reset to finish and then run on the freshly restarted kernel — instead of throwing a user-visible error for what is purely an internal coordination state.
46
+ - Fixed the `eval` tool description advertising the `agent()` helper unconditionally even in subagent sessions whose parent forbids spawning. When `getSessionSpawns()` returns `""`, the prelude doc now omits `agent()` so the model is not promised a helper that can only ever throw "Cannot spawn 'task'. Allowed: none (spawns disabled for this agent)".
47
+ - Fixed plan mode rejecting `local://` plan-artifact edits when addressed via the absolute path the `read` tool echoes back in the `[path#tag]` header. `enforcePlanModeWrite` previously only matched the literal `local://` scheme; it now also accepts any absolute path whose realpath resolves inside the session's local sandbox root, so the absolute spelling and the `local://` spelling are interchangeable in plan mode.
48
+ - Fixed snapshot tags freshly minted by `read` being rejected as stale by a subsequent `edit` against the same file when the two sides reached the file via symlink-equivalent spellings (e.g. macOS `/tmp/…` vs `/private/tmp/…`, or `read local://foo.md` recording under the file's `fs.realpath` while `edit local://foo.md` looked up under the raw `path.resolve(localRoot, …)` form). The file snapshot store now keys every record/lookup through a `realpath`-canonicalized key (`canonicalSnapshotKey`), fusing all spellings of the same on-disk file onto one snapshot entry.
49
+ - Fixed `read` of a `github.com/<owner>/<repo>` URL with `:raw` returning the full JS-rendered HTML shell. Repo roots now resolve to the decoded README via the GitHub API (`/repos/<owner>/<repo>/readme`), falling back to the raw HTML only when the API returns no usable payload.
50
+ - Fixed `issue://` and `pr://` reads returning stale OPEN/CLOSED state after a successful `gh issue close` / `gh pr merge` (or any other state-changing `gh` invocation) in the same session. The `bash` tool now invalidates the matching `github-cache` rows before executing any `gh (issue|pr) <close|reopen|merge|delete|edit|comment|lock|unlock|pin|unpin|transfer|develop|ready|review>` command.
51
+ - Fixed line-range selectors on PDF/DOCX/PPTX/XLSX/RTF/EPUB reads being ignored. The markit-converted markdown body now flows through the same in-memory range slicer used for plain text, so `file.pdf:50-100` and `file.pdf:5-16,40-80` slice the converted body instead of returning the whole document.
52
+ - Fixed the `read` selector cheatsheet incorrectly promising "exactly one line" for `:N+1` while the implementation pads single-line reads with ≤1 leading and ≤3 trailing context; documented that multi-range selectors do not pad, giving callers a way to request exact bounds.
53
+ - Documented the `bash.autoBackground.enabled` behavior in the `bash` tool prompt so the `Background job <id> started: …` notice for foreground commands that exceed `autoBackgroundThresholdSeconds` no longer reads as a tool malfunction.
54
+ - Fixed `task` subagents whose in-tool `yield` validator had already accepted a payload after exhausting `MAX_SCHEMA_RETRIES` being rejected a second time by the post-mortem executor validator. The override now propagates through the yield tool's `details.schemaOverridden` flag, and the executor surfaces a `SUBAGENT_WARNING_SCHEMA_OVERRIDDEN` stderr line instead of re-emitting `schema_violation` for data the subagent already had to ship. Finalize also degrades to no validation (matching the yield tool's `looseRecordSchema` fallback) when the caller-supplied output schema fails to normalize.
55
+ - Fixed the `web_search` `codex` provider returning `(see attached image)` / `[Attached image]` / `See image above` and similar non-informational image-placeholder strings as the answer. Detection broadened to a small regex set, and when annotations did produce sources we now drop the placeholder prose from `answer` (returning sources only); when neither annotations nor a real answer materialize, we throw 502 to advance the provider chain.
56
+ - Fixed `search`, `find`, `ast_grep`, and `ast_edit` rejecting bracket-containing file paths (Next.js routes like `apps/[id]/page.tsx`) as glob patterns when the literal path exists on disk. `parseSearchPathPreferringLiteral` now prefers the literal interpretation for paths that resolve on disk and only falls back to glob expansion when the literal does not exist.
57
+ - Fixed `search` with an external `http(s)/ftp/ws/file://` URL in `paths` surfacing a misleading "Path not found" error. The tool now rejects external URLs with a clear "use `read` for URLs" message.
58
+ - Fixed `search` rejecting `skip: null` at the schema layer; `null` now normalizes to `0` alongside the omitted case, matching how callers serialize default pagination state.
59
+ - Fixed `search` returning zero matches with no explanation when explicit file targets exceed the native grep cap (4 MB). The tool now surfaces a `Skipped oversized files (>4MB grep limit; …)` notice listing the truncated paths.
60
+ - Fixed the archive-extraction error message in `search` recommending `grep` — which the system prompt forbids — instead of pointing to `read <archive>:<member>`.
61
+ - Fixed `browser` `tab.open(name, { viewport })` on an existing tab not applying the new viewport: `acquireTab`'s reuse path now resizes the page in addition to navigating.
62
+ - Fixed `browser` tab metadata leaking `user:pass@` basic-auth credentials in the URL surfaced to transcripts and observe snapshots; URLs are now redacted via `redactUrlCredentials()`.
63
+ - Fixed `browser` `tab.extract(format)` returning a `ReadableResult | null` shape that the tool prompt advertised as plain content. The helper now returns the markdown/text string directly (or throws a clear `ToolError` when extraction is empty), and the prompt matches.
64
+ - Fixed `lsp` requests timing out at a hard-coded 30 s ceiling when the caller supplied an explicit abort signal (e.g. the tool wall-clock). The signal is now the deadline; the 30 s default still applies when neither a signal nor an explicit `timeoutMs` is provided.
65
+ - Fixed `lsp status` reporting servers as `Active language servers: …` when the binary resolves on PATH but never spawns (rustup wrapper, missing toolchain component, etc.). Status now labels each entry as `(ready)` or `(configured, not started)`.
66
+ - Fixed `lsp rename_file` fanning `willRenameFiles` requests across every configured server (including ones with no jurisdiction over the file type) and burning the wall-clock timeout. The action now pre-filters configured LSPs to those whose `fileTypes` cover the source or destination path, falling back to a plain filesystem rename when no server claims the type.
67
+ - Fixed `lsp references` returning only the queried declaration (or only in-file results) on project-aware servers that had not finished indexing. The retry budget is raised from 2 → 3 with 250 / 500 / 1000 ms backoff, and the retry trigger now also fires when all results live in the queried file.
68
+ - Fixed `lsp config` accepting `fileTypes` entries with or without a leading dot inconsistently across actions; both `.ts` and `ts` are now normalized so a missing-dot entry no longer silently excludes a server from extension-based routing.
69
+ - Fixed `lsp request` error path swallowing the params that were sent, making shape/coercion bugs on raw LSP calls impossible to diagnose in one round-trip; the error now echoes a truncated copy of the request params.
70
+ - Fixed `find` with a single-star segment like `dir/*` recursing into subdirectories and returning nested matches. `parseFindPattern` already prepends `**/` for top-level globs (`*.ts` → `**/*.ts`), so anything reaching native without `**/` was deliberately scoped by the user; `recursive: false` is now passed to `natives.glob` to honor that scope.
71
+
72
+ ## [15.10.1] - 2026-06-07
73
+
74
+ ### Added
75
+
76
+ - Added `display.smoothStreaming` setting (default `true`) to let users enable or disable smooth assistant-stream text reveal
77
+ - Added `/tan <work>` slash command to fork the current conversation into a background agent so tangential work can continue asynchronously while your main session stays active
78
+ - Added a background `/tan` dispatch message that records the handoff in the transcript and marks the delegated work as non-blocking
79
+ - Added `providerPromptCacheKey` support to `CreateAgentSessionOptions` so `/tan` background sessions can reuse the parent session’s prompt-cache lineage
80
+ - Added session cloning for `/tan` runs with copied artifacts and shared MCP proxy tools
81
+ - Added `SessionManager.forkFrom`’s optional `suppressBreadcrumb` mode to avoid breadcrumb updates when forking background `/tan` sessions
82
+ - Added OSC 5522 enhanced paste handling in `InputController`, so terminal clipboard events are decoded as image or text payloads and inserted without passing raw paste sequences to the editor
83
+ - Added bracketed image-path paste support in `CustomEditor` so a single pasted image file path (PNG/JPEG/GIF/WEBP) is loaded from disk and inserted as an image candidate
84
+ - Added direct support for `Image #N` insertion from pasted local image paths by routing successful image-path pastes through the same image normalization and resize flow as clipboard image pastes
85
+ - Added `/fresh` to rotate the provider-facing session id and clear in-memory provider stream/cache state without changing the local session file.
86
+ - Added a `ChatBlock` transcript primitive (`modes/components/chat-block.ts`) and a single `ctx.present(...)` sink (with `ctx.resetTranscript()`) so chat output is mounted in one place instead of the repeated `chatContainer.addChild(...)` + `ui.requestRender()` pattern scattered across controllers. `ChatBlock` carries a React/Svelte-style lifecycle — `onMount` starts effects, `onCleanup` registers teardown, `finish()` self-completes (stops timers and freezes the block at its final content), and `dispose()`/`resetTranscript()` tears everything down — so animated blocks own their own resources instead of leaking `setInterval`/`requestRender` bookkeeping into callers. The MCP "Connecting…" spinner is now such a block.
87
+ - Added a `framedBlock` output-block helper (`tui/output-block.ts`) plus a `borderColor` override and `applyBg: false` (no background fill) on output blocks, a `renderStatusLine` `iconOverride`, and an `icon.search` (magnifier) theme symbol — so tool renderers can draw self-contained muted-outline frames and search-family tools can show a magnifier instead of a checkmark.
88
+
89
+ ### Changed
90
+
91
+ - Changed the bash tool frame to use a plain top rule instead of repeating "Bash" in the title bar, and folded minimizer raw-output artifact links into the status footer as `Artifact: <id>`.
92
+
93
+ - Changed grouped `read` output to use a white filled-circle mark for the group/single-read success state and omit duplicate per-file success marks inside multi-read groups.
94
+
95
+ - Changed assistant streaming output to reveal text incrementally at 30 FPS with grapheme-safe adaptive catch-up, instead of replacing the whole message chunk-by-chunk
96
+ - Changed shimmer-driven TUI animations (working text, pending bash/eval borders, and theme activity-spinner documentation) to render at 30fps instead of 60fps.
97
+ - Changed running `task` tool agent rows to use a static `•` marker and shimmer only the subagent name, leaving descriptions, stats, and nested tool detail text solid while removing the rotating status glyph from those rows.
98
+ - Changed settings singleton method access to reuse bound methods for the active instance instead of allocating a new bound function on every `settings.get` lookup.
99
+ - Changed plan-mode approval to keep the drafted `local://<slug>-plan.md` file at its original name as the canonical plan path, so approved plans are no longer renamed when leaving plan mode
100
+ - Changed plan-mode write enforcement so only `local://` artifact files are writable during planning, blocking working-tree edits and allowing scratch or draft plan files in the local artifact area
101
+ - Changed the `todo` tool result renderer to stop redrawing every phase's full task list on each update: when a multi-phase list is rendered collapsed (the default, not manually expanded), only phases the latest update touched — the phase holding the in_progress task, any phase with a just-completed task, and phases named by the ops that ran (`init` counts as touching all) — render their tasks; untouched phases collapse to a one-line `N. Name done/total` summary. When call args are unavailable (e.g. transcript rebuilds) it falls back to the in_progress/completed-transition signals, and the manual expand toggle still shows every task. Also dropped the blank separator line previously inserted between phases.
102
+ - Changed non-agent API operations (title and commit-message generation, image generation, web search, eval `llm()`, auto-thinking classifier, memory consolidation) to use session-aware API key resolution with auth retries via `registry.resolver()` / `authStorage.resolver()`, refreshing the active credential before rotating to another account
103
+ - Changed image generation to wrap every provider fetch branch in `withAuth`, so 401 / usage-limit errors trigger credential force-refresh and rotation for authStorage-backed providers (OpenAI-hosted, antigravity, xai-oauth) while env-only providers (openrouter, gemini) stay single-attempt
104
+ - Changed web-search providers using `authStorage.getApiKey` (anthropic, exa, tavily, parallel, synthetic, zai, kimi) to wrap HTTP calls in `withAuth` for automatic credential rotation on 401 / usage-limit errors
105
+ - Changed the directory grouping for `find`, `search`, `ast_grep`, `ast_edit`, and `lsp` diagnostics from a single flat `# dir/` heading per immediate directory to a multi-level tree that folds the common path prefix into one heading. Previously every group repeated the full directory path — so results rooted outside cwd printed the absolute prefix (e.g. `/Users/me/proj/`) on every heading and nested directories were never collapsed. Now a single-child directory chain folds into one heading (`# packages/pkg/src/`, including an absolute root for out-of-cwd results), subdirectories nest one `#` deeper (`## nested/` → `### child.ts`), and each directory's own files are listed before its subdirectories. TUI hyperlink reconstruction tracks the nested directory stack across the whole output so file and code-frame links keep resolving to the correct absolute paths.
106
+ - Changed the plan-mode approval surface from an inline transcript block plus a separate bottom selector into a single fullscreen overlay (like `/copy`) and overhauled its navigation. The overlay now renders the plan per-section through `ScrollView` (line-level ↑/↓ scroll, Shift+↑/↓ to scroll faster, PgUp/PgDn, g/G) with no stray per-line `…`, and — when the terminal is wide enough and the plan has ≥2 headings — shows a compact VS Code-style section sidebar (the redundant plan-title heading and any "Contents" label are omitted). Focus moves between regions with Tab/Shift+Tab (and flows at the edges: Down past the last section or the bottom of the body drops into the approval options; Up steps back), while the sidebar glows to track the scrolled section. The sidebar can fast-jump between sections, delete a section (with `u` undo), and annotate sections with feedback (`a`); deletions and annotations are collected into refinement feedback that is submitted back to the model when the operator picks "Refine plan". Mouse works too: clicking an approval option activates it, clicking a sidebar section jumps to it, and the wheel scrolls the plan. ←/→ always drive the model-tier slider, Enter confirms, the external-editor key opens the plan, and Esc cancels. The overlay borrows the terminal's alternate screen buffer for its lifetime (`fullscreen` overlay), so the transcript stays put on the normal screen instead of bleeding through scrollback behind the modal.
107
+ - Changed the interactive controllers (command, MCP, selector, extension-UI, event), debug panels, and the status/error/warning helpers to render chat output through `ctx.present(...)` instead of appending to `chatContainer` and calling `ui.requestRender()` directly; transcript rebuilds dispose live blocks via `ctx.resetTranscript()` so animated blocks' timers stop on reset.
108
+ - Changed tool-execution block rendering so the container (`ToolExecutionComponent`) is a transparent passthrough — it no longer inserts a top/bottom blank line, adds left/right padding, or paints a state-colored background behind tool output. Tools with substantial body now self-frame with a muted outline and the tool title in the frame's top bar (`edit`/`apply_patch`, `write`, `ask`, `todo`, `github`, `goal`, `inspect_image`, `search_tool_bm25`, `task`), matching the already-framed `bash`/`read`/`eval`/`debug`/`web_search`/`lsp` blocks, while streaming/in-progress and trivial results collapse to a clean status line. The search-family list tools (`find`, `search`, `ast_grep`) and `job` render frameless/minimal; `find`/`search`/`ast_grep` show a magnifier on success instead of a checkmark, and `job` drops its `Job:` label prefix (the per-job rows are self-describing). The `search_tool_bm25`, `github`, and `inspect_image` frames draw with no background fill, and `inspect_image`'s label was shortened to `Inspect`.
109
+ - Changed the plan-mode active prompt (`prompts/system/plan-mode-active.md`) to make plans decision-complete and cut filler. Added an Objective framing ("another engineer can execute end-to-end without making a single design decision"), a shared "Resolving Unknowns" section (explore discoverable facts before asking; reserve `ask` for non-derivable preferences/tradeoffs with 2–4 options + a recommended default), and a single shared "The Plan" structure (Context / Approach grouped by behavior not file-by-file / ≤5 Critical files / Verification / Assumptions) that replaces the per-branch structure guidance previously duplicated across the iterative and parallel workflows. Added explicit prohibitions on sections that decide nothing (Non-Goals, Out of Scope, Alternatives Considered, Risks/Mitigations boilerplate, Future Work), on enumerating every file/line, and on inventing schema/validation/precedence policy the request never established.
110
+ - Changed completion notifications (`completion.notify`) to fire whenever the agent yields its turn, including in the foreground. The `agent_end` notification was previously gated behind background mode (`isBackgrounded`), so an ordinary foreground turn never emitted one; the gate is gone and the desktop toast now fires on every normal turn completion (still skipped for aborted/error turns and when `completion.notify` is `off`).
111
+ - Changed the in-progress `task` tool block to keep the shared `context` brief (`# Goal` / `# Constraints` background) visible after the first progress snapshot arrives, instead of dropping it the moment the streaming call view was replaced by the result frame, and to stop animating a spinner/clock next to the `Task` frame header while running — the per-agent body lines already carry their own running spinner, so the header now shows a static state icon (matching the completed/failed header icons). The context is rendered through a shared `buildContextSection` helper that also undoes per-field double-encoding, so the brief reads cleanly in the result frame even though `renderResult` receives the raw (un-repaired) tool args.
112
+ - Changed the messaging shown when you press Esc to interrupt a streaming turn from the ambiguous `Operation aborted` / `Tool execution was aborted: Request was aborted` to `Interrupted by user`, so a deliberate user interrupt no longer reads like an internal failure. Every Esc/flush interrupt path (`onEscape` while streaming, the queued-message restore-and-abort path, and the empty-submit queue flush) threads the reason through `AgentSession.abort({ reason })` → `Agent.abort(reason)` so it rides the `AbortController` onto the aborted assistant message's `errorMessage`; the turn label renders it verbatim on both the live and replay paths, and the synthetic placeholder results paired with in-flight tool calls now read `Tool execution was aborted: Interrupted by user`. Aborts that carry no reason still fall back to the retry-aware `Operation aborted` generic. Transcript label resolution is centralized in `resolveAbortLabel` (`session/messages.ts`).
113
+
114
+ ### Removed
115
+
116
+ - Removed the `/background` (and `/bg`) slash command and the background-mode subsystem it was the sole entry point for — `InteractiveMode.isBackgrounded`, `createBackgroundUiContext`, `handleBackgroundEvent`, and every `isBackgrounded` guard across the input/event/extension-UI controllers and UI helpers. The command suspended the whole process group via `SIGTSTP` (a leftover testing shortcut) instead of detaching the running agent, which is not the expected workflow — use terminal panes or a multiplexer instead.
117
+
118
+ ### Fixed
119
+
120
+ - Fixed inline `find` and `search` result blocks to align with grouped `read` output and render their success headers with the normal tool-title color instead of accent blue.
121
+
122
+ - Fixed the working-status shimmer to opt into the loader's 30fps animated-message repaint path while keeping both the status spinner and pending bash/eval tool spinners on their normal 80 ms glyph cadence.
123
+ - Fixed consecutive `read` tool calls failing to collapse into a single grouped block when a reasoning model emits one read per completion (`[thinking, read]`). The read group was reset on every assistant `message_start`, so each read rendered as its own one-entry `Read …` line; now a read run accretes across completions and is broken only by a rendered non-empty text/thinking block, a non-read tool, or a user/IRC message — matching the transcript-rebuild path. `ReadToolGroupComponent` now reports its live/finalized state so the growing `Read (N)` header repaints correctly on native-scrollback (risk) terminals.
124
+ - Fixed the `task` tool shared-context brief rendering raw Markdown headings (`# Goal`, `# Constraints`) inside framed call/result blocks instead of using the normal Markdown renderer.
125
+ - Fixed the animated pending border on `bash`/`eval` blocks leaving a frozen dark "bar" segment behind after a backgrounded command finalized through the async update path. Once a command is auto-backgrounded (`details.async.state === "running"`) the block stays "partial" in the TUI until the async job-manager delivers the final result, but it also gets committed to native scrollback — so a mid-sweep shimmer frame baked a stray darkened border segment into the committed copy. The border now stops animating (and the 60fps redraw loop stops) the moment a block enters the backgrounded state, so the committed frame is a clean static border.
126
+ - Fixed cold `omp` launch to clear native terminal history on the first paint, avoiding a once-per-launch duplicate welcome/transcript copy before the normal session replay.
127
+ - Fixed plan approval resolution so `resolve` with `action: "apply"` can still find the plan file when `extra.title` is missing or stale by falling back to the current plan path and most-recent local plan artifacts
128
+ - Fixed the search-family tool magnifier glyph (`find`, `search`, `ast_grep`, `search_tool_bm25`) to use the `accent` title color instead of `success` green, so the icon matches the tool title in the status header instead of standing out
129
+ - Fixed TTSR stream interrupts to pass the matched rule name through the abort reason, so aborted in-flight tool placeholders say why they were stopped instead of `Request was aborted`.
130
+ - Fixed URL reads for binary/special payloads to reuse local readers: remote archives list their root entries, SQLite databases show their table overview, notebooks render as editable cells, and unrenderable binary returns a metadata notice instead of decoded byte garbage.
131
+ - Fixed pasted image-file paths that cannot be loaded to fall back to normal text paste with status feedback instead of disappearing.
132
+ - Fixed tool-output file paths not being clickable OSC 8 `file://` hyperlinks in several renderers. `read` titles for plain text and image files (the common case) emitted no link at all because the renderer only linked when a `resolvedPath` was recorded — which the ordinary file/image read paths never set, keeping the absolute path only in `meta.source`; the renderer now falls back to that source path. `write` headers were never wrapped in a hyperlink and now link to the absolute path written (file, archive entry, SQLite, and conflict resolutions). `edit`/`apply_patch` headers wrapped the model-supplied (often cwd-relative) argument path, producing a root-anchored `file:///rel/path` URI; they now link the absolute `details.path` instead. Finally, `search`, `ast_grep`, and `ast_edit` produced doubled link targets (`/proj/src/src/file.ts`) for searches scoped to a subdirectory, because the renderer resolved the cwd-relative display paths against the scope directory rather than cwd — the scoped-search base is now the session cwd (with the scoped file's absolute path still seeding single-file body lines).
133
+ - Fixed `omp dry-balance --bench` to recover from 401 token failures by re-minting the failing OAuth credential in place before switching accounts
134
+ - Fixed the bash tool corrupting commands that embed multi-byte UTF-8 (e.g. `✓`/`×` inside a `grep -E` pattern) ahead of a trailing `| head`/`| tail`. The `bash.stripTrailingHeadTail` rewrite cut at char-offset positions reported by `brush-parser` while slicing the command by byte offset, so the trailing-pipe strip landed mid-pattern and dropped the closing quote — turning `… |✓|×|XCTAssert" | tail -80` into `… |✓|×-80` and making execution fail with `pi-natives:command: unterminated double quote`. Fixed in `pi_shell::fixup` (`@oh-my-pi/pi-natives`).
135
+ - Fixed `omp dry-balance --bench` to recover from 401 token failures by re-minting the failing OAuth credential in place before switching accounts
136
+ - Fixed duplicate file entries in grouped outputs for `find`, `search`, `ast_grep`, `ast_edit`, and `lsp` diagnostics when the same path appeared multiple times
137
+ - Fixed search, grep, and edit output rendering so repeated directory group blank-line boundaries no longer break nested path/link reconstruction
138
+ - Fixed `omp dry-balance --bench` flooding the terminal with staircased, duplicated spinner/status lines (and an indented summary) when the tty has ONLCR/OPOST disabled (raw mode). The interactive progress region separated rows with a bare LF and repositioned with a column-preserving `\x1b[<n>A` cursor-up, both of which only land at column 0 when the terminal translates LF→CRLF; with that translation off, every 80 ms redraw cascaded down and to the right into scrollback. The live region now carriage-returns before every cleared row, terminates each row with CRLF, and caps each row to the terminal width so a wrapped line cannot desync the cursor-up from the logical line count.
139
+ - Fixed inconsistent vertical spacing between transcript blocks: some blocks (tool results from `search`/`find` and other renderer-backed tools) rendered with a doubled gap (a leading `Spacer` plus the content box's own `paddingY`), while others (the grouped `read` card, file-mention lists, IRC cards) rendered with no gap at all. Vertical spacing is now owned entirely by the chat renderer: `TranscriptContainer` strips each block's plain-blank top/bottom edges and inserts exactly one blank line between consecutive blocks, so every block is separated by a single consistent gap regardless of which component produced it. Individual components (assistant/user/tool/read-group/bash/eval/skill/custom/hook/compaction/branch/todo-reminder/plan-review messages) no longer emit their own leading `Spacer`/`paddingY` for separation, and multi-row groups (IRC cards, file-mention lists, completed-job batches, and the bordered command/`/changelog`/`/context`/version/OAuth/debug panels) are wrapped as single `TranscriptBlock` children so the renderer spaces them as one unit. Background-colored box padding is preserved as block-internal design.
140
+ - Fixed `resolve` with `action: "discard"` surfacing a hard `isError` "No pending action to resolve" failure to the model when the agent asked to cancel a staged action (e.g. an `ast_edit` preview) but nothing was pending. A discard is a request to reach the "no staged change" end-state, which already holds in that case, so it is now honored as a successful cancellation (`"Nothing to discard; no pending action remains."` with `details.action: "discard"`) instead of an error. `action: "apply"` with no pending action still errors.
141
+ - Fixed the collapsed tool-output expand hint rendering double brackets (e.g. `((Ctrl+O for more))`) — the `EXPAND_HINT` text already carried its own parentheses and then `formatExpandHint` wrapped it again with the theme's bracket glyphs. The hint now resolves the key actually bound to `app.tools.expand` at render time and reads `⟨<key>: Expand⟩` (e.g. `⟨Ctrl+O: Expand⟩`), so a single bracket pair surrounds it and a user remap of the expand keybinding is reflected instead of a hard-coded `Ctrl+O`.
142
+ - Fixed the `edit`/`apply_patch` tool dropping its outlined frame while streaming/in-progress (only the final result was framed); the in-progress diff preview now renders inside the same muted frame as the completed result.
143
+ - Fixed the `todo` and `job` tools rendering a success icon and success styling on a failed/error result; error results now show the error icon and a red frame border.
144
+ - Fixed `debug` tool refusing every `dlv` launch on Go modules. The launch handler ran `validateLaunchProgram` before adapter selection and rejected any directory program with `launch program resolves to a directory`, while dlv's default `mode=debug` requires a Go package path (a directory or `.go` source file). Adapter resolution now precedes validation, directory programs prefer adapters that advertise `acceptsDirectoryProgram` before falling back to native extensionless debuggers, the rejection only fires when the resolved adapter does not advertise that flag (set on `dlv` in `dap/defaults.json`), and dlv's `mode` is derived from the program shape — directories and `.go` files launch as `mode=debug`, other files as `mode=exec` — so `omp` can debug both Go packages and pre-built binaries ([#2020](https://github.com/can1357/oh-my-pi/issues/2020)).
145
+
5
146
  ## [15.10.0] - 2026-06-06
6
147
 
7
148
  ### Breaking Changes
@@ -9496,4 +9637,4 @@ Initial public release.
9496
9637
  - Git branch display in footer
9497
9638
  - Message queueing during streaming responses
9498
9639
  - OAuth integration for Gmail and Google Calendar access
9499
- - HTML export with syntax highlighting and collapsible sections
9640
+ - HTML export with syntax highlighting and collapsible sections
@@ -1,4 +1,4 @@
1
- import type { Api, AssistantMessageEventStream, Context, Model, OAuthAccess, OAuthAccessResolution, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
1
+ import type { Api, AssistantMessageEventStream, AuthCredentialSnapshotEntry, Context, Model, OAuthAccess, OAuthAccessResolution, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
2
2
  import type { CanonicalModelVariant } from "../config/model-equivalence";
3
3
  import { type CanonicalModelQueryOptions } from "../config/model-registry";
4
4
  import { Settings } from "../config/settings";
@@ -20,6 +20,12 @@ export interface DryBalanceAuthOptions {
20
20
  export interface DryBalanceAuthStorage {
21
21
  getOAuthAccess(provider: string, sessionId?: string, options?: DryBalanceAuthOptions): Promise<OAuthAccess | undefined>;
22
22
  getOAuthAccesses?(provider: string, options?: DryBalanceAuthOptions): Promise<OAuthAccessResolution[]>;
23
+ /**
24
+ * Force-refresh a single credential by id (step (b) of the auth-retry
25
+ * policy). The bench re-mints the failing account's token in place on a
26
+ * 401 rather than rotating accounts — it is measuring each account.
27
+ */
28
+ forceRefreshCredentialById?(id: number, signal?: AbortSignal): Promise<AuthCredentialSnapshotEntry>;
23
29
  }
24
30
  export interface DryBalanceModelRegistry {
25
31
  authStorage: DryBalanceAuthStorage;
@@ -98,7 +104,15 @@ export interface DryBalanceDependencies {
98
104
  now?: () => number;
99
105
  stdoutIsTTY?: boolean;
100
106
  stderrIsTTY?: boolean;
107
+ stdoutColumns?: number;
108
+ stderrColumns?: number;
101
109
  }
110
+ interface DryBalanceBenchProgressSink {
111
+ markRunning(index: number, account: string): void;
112
+ complete(index: number, result: DryBalanceBenchResult): void;
113
+ close(): void;
114
+ }
115
+ export declare function createBenchProgressSink(total: number, write: (text: string) => void, interactive: boolean, columns: number): DryBalanceBenchProgressSink;
102
116
  export declare function formatDryBalanceText(summary: DryBalanceSummary): string;
103
117
  export declare function runDryBalanceCommand(command: DryBalanceCommandArgs, deps?: DryBalanceDependencies): Promise<DryBalanceSummary>;
104
118
  export {};
@@ -0,0 +1,2 @@
1
+ import type { Args } from "./args";
2
+ export declare function applyStartupCwd(parsed: Args): Promise<void>;
@@ -40,6 +40,9 @@ export default class Index extends Command {
40
40
  "allow-home": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
41
41
  description: string;
42
42
  };
43
+ cwd: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
44
+ description: string;
45
+ };
43
46
  mode: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
44
47
  description: string;
45
48
  options: string[];
@@ -1,9 +1,9 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { ConventionalAnalysis } from "../../commit/types";
4
4
  export interface ConventionalAnalysisInput {
5
5
  model: Model<Api>;
6
- apiKey: string;
6
+ apiKey: ApiKey;
7
7
  thinkingLevel?: ThinkingLevel;
8
8
  contextFiles?: Array<{
9
9
  path: string;
@@ -1,9 +1,9 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { CommitSummary } from "../../commit/types";
4
4
  export interface SummaryInput {
5
5
  model: Model<Api>;
6
- apiKey: string;
6
+ apiKey: ApiKey;
7
7
  thinkingLevel?: ThinkingLevel;
8
8
  commitType: string;
9
9
  scope: string | null;
@@ -1,5 +1,5 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import * as z from "zod/v4";
4
4
  import { type ChangelogGenerationResult } from "../../commit/types";
5
5
  export declare const changelogTool: {
@@ -19,7 +19,7 @@ export declare const changelogTool: {
19
19
  };
20
20
  export interface ChangelogPromptInput {
21
21
  model: Model<Api>;
22
- apiKey: string;
22
+ apiKey: ApiKey;
23
23
  thinkingLevel?: ThinkingLevel;
24
24
  changelogPath: string;
25
25
  isPackageChangelog: boolean;
@@ -1,9 +1,9 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  export interface ChangelogFlowInput {
4
4
  cwd: string;
5
5
  model: Model<Api>;
6
- apiKey: string;
6
+ apiKey: ApiKey;
7
7
  thinkingLevel?: ThinkingLevel;
8
8
  stagedFiles: string[];
9
9
  dryRun: boolean;
@@ -1,5 +1,5 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { ConventionalAnalysis } from "../../commit/types";
4
4
  export interface MapReduceSettings {
5
5
  enabled?: boolean;
@@ -10,10 +10,10 @@ export interface MapReduceSettings {
10
10
  }
11
11
  export interface MapReduceInput {
12
12
  model: Model<Api>;
13
- apiKey: string;
13
+ apiKey: ApiKey;
14
14
  thinkingLevel?: ThinkingLevel;
15
15
  smolModel: Model<Api>;
16
- smolApiKey: string;
16
+ smolApiKey: ApiKey;
17
17
  smolThinkingLevel?: ThinkingLevel;
18
18
  diff: string;
19
19
  stat: string;
@@ -1,9 +1,9 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { FileDiff, FileObservation } from "../../commit/types";
4
4
  export interface MapPhaseInput {
5
5
  model: Model<Api>;
6
- apiKey: string;
6
+ apiKey: ApiKey;
7
7
  thinkingLevel?: ThinkingLevel;
8
8
  files: FileDiff[];
9
9
  config?: {
@@ -1,9 +1,9 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { ConventionalAnalysis, FileObservation } from "../../commit/types";
4
4
  export interface ReducePhaseInput {
5
5
  model: Model<Api>;
6
- apiKey: string;
6
+ apiKey: ApiKey;
7
7
  thinkingLevel?: ThinkingLevel;
8
8
  observations: FileObservation[];
9
9
  stat: string;
@@ -1,15 +1,21 @@
1
1
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
3
+ import type { ApiKeyResolverRegistry } from "../config/api-key-resolver";
3
4
  import { type ModelLookupRegistry } from "../config/model-resolver";
4
5
  import type { Settings } from "../config/settings";
5
6
  export interface ResolvedCommitModel {
6
7
  model: Model<Api>;
7
- apiKey: string;
8
+ /**
9
+ * Resolver for the model's bearer: re-resolves on 401 / usage-limit so the
10
+ * whole commit pipeline (analysis, map/reduce, changelog) inherits the
11
+ * central force-refresh + account-rotation policy.
12
+ */
13
+ apiKey: ApiKey;
8
14
  thinkingLevel?: ThinkingLevel;
9
15
  }
10
- type CommitModelRegistry = ModelLookupRegistry & {
16
+ type CommitModelRegistry = ModelLookupRegistry & ApiKeyResolverRegistry & {
11
17
  getApiKey: (model: Model<Api>) => Promise<string | undefined>;
12
18
  };
13
19
  export declare function resolvePrimaryModel(override: string | undefined, settings: Settings, modelRegistry: CommitModelRegistry): Promise<ResolvedCommitModel>;
14
- export declare function resolveSmolModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey: string): Promise<ResolvedCommitModel>;
20
+ export declare function resolveSmolModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey: ApiKey): Promise<ResolvedCommitModel>;
15
21
  export {};
@@ -0,0 +1,34 @@
1
+ import type { ApiKeyResolver, AuthStorage } from "@oh-my-pi/pi-ai";
2
+ export interface ApiKeyResolverOptions {
3
+ /** Session id for credential stickiness; read at resolve time by the caller. */
4
+ sessionId?: string;
5
+ /** Provider base URL hint forwarded to the auth-storage cascade. */
6
+ baseUrl?: string;
7
+ }
8
+ /**
9
+ * Minimal slice of `ModelRegistry` the resolver needs. Typed structurally so
10
+ * narrower registry shells (e.g. the commit pipeline's `CommitModelRegistry`)
11
+ * can build resolvers without depending on the full class.
12
+ */
13
+ export interface ApiKeyResolverRegistry {
14
+ getApiKeyForProvider(provider: string, sessionId?: string, options?: {
15
+ baseUrl?: string;
16
+ forceRefresh?: boolean;
17
+ signal?: AbortSignal;
18
+ }): Promise<string | undefined>;
19
+ authStorage: Pick<AuthStorage, "rotateSessionCredential">;
20
+ /**
21
+ * Build an {@link ApiKeyResolver} implementing the central a/b/c auth-retry
22
+ * policy: initial → resolve; step (b) → force-refresh same account; step (c)
23
+ * → rotate to a sibling credential, then re-resolve.
24
+ *
25
+ * The resolver is stateless (safe to reuse across requests). Callers that
26
+ * need the initial key for a guard can call `resolveApiKeyOnce(resolver)`.
27
+ */
28
+ resolver(provider: string, options?: ApiKeyResolverOptions): ApiKeyResolver;
29
+ }
30
+ /**
31
+ * Default implementation of {@link ApiKeyResolverRegistry.resolver}.
32
+ * Also usable standalone for structural registries that don't carry the method.
33
+ */
34
+ export declare function createApiKeyResolver(registry: Pick<ApiKeyResolverRegistry, "getApiKeyForProvider" | "authStorage">, provider: string, options?: ApiKeyResolverOptions): ApiKeyResolver;
@@ -109,11 +109,11 @@ export declare const KEYBINDINGS: {
109
109
  readonly description: "Delete character forward";
110
110
  };
111
111
  readonly "tui.editor.deleteWordBackward": {
112
- readonly defaultKeys: ["ctrl+w", "alt+backspace", "ctrl+backspace"];
112
+ readonly defaultKeys: ["ctrl+w", "alt+backspace", "ctrl+backspace", "super+alt+backspace"];
113
113
  readonly description: "Delete word backward";
114
114
  };
115
115
  readonly "tui.editor.deleteWordForward": {
116
- readonly defaultKeys: ["alt+delete", "alt+d"];
116
+ readonly defaultKeys: ["alt+delete", "alt+d", "super+alt+delete", "super+alt+d"];
117
117
  readonly description: "Delete word forward";
118
118
  };
119
119
  readonly "tui.editor.deleteToLineStart": {
@@ -0,0 +1 @@
1
+ export declare function buildModelProviderPriorityRank(configuredProviderOrder?: readonly string[]): Map<string, number>;
@@ -1,9 +1,11 @@
1
1
  import { type ModelRefreshStrategy } from "@oh-my-pi/pi-ai/model-manager";
2
2
  import type { Api, Context, Model, SimpleStreamOptions, ThinkingConfig } from "@oh-my-pi/pi-ai/types";
3
3
  import type { AssistantMessageEventStream } from "@oh-my-pi/pi-ai/utils/event-stream";
4
+ import type { ApiKeyResolver } from "@oh-my-pi/pi-ai";
4
5
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types";
5
6
  import { type ThemeColor } from "../modes/theme/theme";
6
7
  import type { AuthStorage } from "../session/auth-storage";
8
+ import { type ApiKeyResolverOptions } from "./api-key-resolver";
7
9
  import { type ConfigError, ConfigFile } from "./config-file";
8
10
  import { type CanonicalModelIndex, type CanonicalModelRecord, type CanonicalModelVariant, type ModelEquivalenceConfig } from "./model-equivalence";
9
11
  import { type Settings } from "./settings";
@@ -326,8 +328,22 @@ export declare class ModelRegistry {
326
328
  getApiKey(model: Model<Api>, sessionId?: string): Promise<string | undefined>;
327
329
  /**
328
330
  * Get API key for a provider (e.g., "openai").
331
+ *
332
+ * `options.forceRefresh` powers step (b) of the auth-retry policy — it
333
+ * re-mints the session-sticky OAuth token even when the cached copy still
334
+ * looks valid. `options.signal` is threaded into any broker-bound refresh.
335
+ */
336
+ getApiKeyForProvider(provider: string, sessionId?: string, options?: {
337
+ baseUrl?: string;
338
+ forceRefresh?: boolean;
339
+ signal?: AbortSignal;
340
+ }): Promise<string | undefined>;
341
+ /**
342
+ * Build an {@link ApiKeyResolver} for this provider, implementing the
343
+ * central a/b/c auth-retry policy. Callers that need the initial key for
344
+ * a guard can call `resolveApiKeyOnce(resolver)`.
329
345
  */
330
- getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string): Promise<string | undefined>;
346
+ resolver(provider: string, options?: ApiKeyResolverOptions): ApiKeyResolver;
331
347
  /**
332
348
  * Check if a model is using OAuth credentials (subscription).
333
349
  */
@@ -30,7 +30,9 @@ export declare function resolveProviderModelReference(provider: string, modelId:
30
30
  export interface ModelMatchPreferences {
31
31
  /** Most-recently-used model keys (provider/modelId) to prefer when ambiguous. */
32
32
  usageOrder?: string[];
33
- /** Providers to deprioritize when no recent usage is available. */
33
+ /** Provider precedence used for ambiguous unqualified model patterns. */
34
+ providerOrder?: readonly string[];
35
+ /** Providers to deprioritize when no recent usage or provider priority is available. */
34
36
  deprioritizeProviders?: string[];
35
37
  }
36
38
  export type CanonicalModelRegistry = Partial<Pick<ModelRegistry, "resolveCanonicalModel" | "getCanonicalVariants" | "getCanonicalId">>;
@@ -38,6 +40,7 @@ export type ModelLookupRegistry = Pick<ModelRegistry, "getAvailable"> & Partial<
38
40
  type CliModelRegistry = Pick<ModelRegistry, "getAll"> & Partial<CanonicalModelRegistry>;
39
41
  type InitialModelRegistry = Pick<ModelRegistry, "getAvailable" | "find">;
40
42
  type RestorableModelRegistry = Pick<ModelRegistry, "getAvailable" | "find" | "getApiKey">;
43
+ export declare function getModelMatchPreferences(settings?: Partial<Pick<Settings, "get" | "getStorage">>): ModelMatchPreferences;
41
44
  /**
42
45
  * Find an exact explicit provider/model match.
43
46
  * Bare model ids are handled separately so canonical ids can coalesce variants.
@@ -689,6 +689,15 @@ export declare const SETTINGS_SCHEMA: {
689
689
  }];
690
690
  };
691
691
  };
692
+ readonly "display.smoothStreaming": {
693
+ readonly type: "boolean";
694
+ readonly default: true;
695
+ readonly ui: {
696
+ readonly tab: "appearance";
697
+ readonly label: "Smooth Streaming";
698
+ readonly description: "Reveal assistant text smoothly while streamed chunks arrive";
699
+ };
700
+ };
692
701
  readonly "display.showTokenUsage": {
693
702
  readonly type: "boolean";
694
703
  readonly default: false;
@@ -131,7 +131,12 @@ export declare class Settings {
131
131
  * Returns an unsubscribe function. Multiple sessions (main + subagents)
132
132
  * can register independently without overwriting each other.
133
133
  */
134
- export declare function onAppendOnlyModeChanged(cb: (value: string) => void): () => void;
134
+ export declare const onAppendOnlyModeChanged: (cb: (value: string) => void) => () => void;
135
+ /**
136
+ * Subscribe to session-accent setting changes.
137
+ * Returns an unsubscribe function. Callers should re-read settings in the callback.
138
+ */
139
+ export declare const onStatusLineSessionAccentChanged: (cb: () => void) => () => void;
135
140
  /**
136
141
  * Subscribe to changes in the Hindsight bank-scoping settings. Lets the
137
142
  * Hindsight backend rebuild the active `HindsightSessionState` when the
@@ -142,7 +147,7 @@ export declare function onAppendOnlyModeChanged(cb: (value: string) => void): ()
142
147
  * Returns an unsubscribe function. The callback receives no arguments — the
143
148
  * caller is expected to re-read the relevant settings via `Settings.get`.
144
149
  */
145
- export declare function onHindsightScopeChanged(cb: () => void): () => void;
150
+ export declare const onHindsightScopeChanged: (cb: () => void) => () => void;
146
151
  export declare function isSettingsInitialized(): boolean;
147
152
  /**
148
153
  * Reset the global singleton for testing.
@@ -2,5 +2,18 @@ import type { DapAdapterConfig, DapResolvedAdapter } from "./types";
2
2
  export declare function getAdapterConfigs(): Record<string, DapAdapterConfig>;
3
3
  export declare function resolveAdapter(adapterName: string, cwd: string): DapResolvedAdapter | null;
4
4
  export declare function getAvailableAdapters(cwd: string): DapResolvedAdapter[];
5
- export declare function selectLaunchAdapter(program: string, cwd: string, adapterName?: string): DapResolvedAdapter | null;
5
+ export declare function selectLaunchAdapter(program: string, cwd: string, adapterName?: string, programKind?: LaunchProgramKind): DapResolvedAdapter | null;
6
6
  export declare function selectAttachAdapter(cwd: string, adapterName?: string, port?: number): DapResolvedAdapter | null;
7
+ /** How the launch `program` resolves on disk. `"missing"` is reserved for
8
+ * programs the adapter creates on demand (rare); we treat them like files. */
9
+ export type LaunchProgramKind = "file" | "directory" | "missing";
10
+ /** Compute adapter-specific launch arguments that depend on the resolved
11
+ * program. Returned values are spread over `adapter.launchDefaults` so they
12
+ * take precedence over the static defaults but can still be overridden by
13
+ * the fields `DapSessionManager.launch` sets explicitly (program, cwd, args).
14
+ *
15
+ * Currently scoped to dlv, where `mode` selects how the program path is
16
+ * interpreted: directories and `.go` source files debug as a Go package
17
+ * (`mode=debug`), anything else is treated as a compiled binary (`mode=exec`).
18
+ */
19
+ export declare function resolveLaunchOverrides(adapter: DapResolvedAdapter, program: string, programKind: LaunchProgramKind): Record<string, unknown>;
@@ -422,6 +422,10 @@ export interface DapAdapterConfig {
422
422
  * On Linux, connects via a unix domain socket.
423
423
  * On macOS, the adapter dials into a local TCP listener (--client-addr). */
424
424
  connectMode?: "stdio" | "socket";
425
+ /** When true, the adapter accepts a directory as the launch `program`
426
+ * (e.g. dlv treats it as a Go package path). When false/undefined, the
427
+ * debug tool rejects directory programs upfront. */
428
+ acceptsDirectoryProgram?: boolean;
425
429
  }
426
430
  export interface DapResolvedAdapter {
427
431
  name: string;
@@ -434,6 +438,7 @@ export interface DapResolvedAdapter {
434
438
  launchDefaults: Record<string, unknown>;
435
439
  attachDefaults: Record<string, unknown>;
436
440
  connectMode: "stdio" | "socket";
441
+ acceptsDirectoryProgram: boolean;
437
442
  }
438
443
  export interface DapBreakpointRecord {
439
444
  id?: number;
@@ -514,6 +519,11 @@ export interface DapLaunchSessionOptions {
514
519
  program: string;
515
520
  args?: string[];
516
521
  cwd: string;
522
+ /** Per-launch overrides merged over `adapter.launchDefaults`. Used to
523
+ * inject adapter-specific values that depend on the resolved program
524
+ * (e.g. dlv's `mode` switches between `debug` and `exec` based on
525
+ * whether `program` is a Go package path or a compiled binary). */
526
+ extraLaunchArguments?: Record<string, unknown>;
517
527
  }
518
528
  export interface DapAttachSessionOptions {
519
529
  adapter: DapResolvedAdapter;
@@ -11,6 +11,8 @@ export interface ReportBundleOptions {
11
11
  heapSnapshot?: HeapSnapshot;
12
12
  /** Work profile (for work scheduling reports) */
13
13
  workProfile?: WorkProfile;
14
+ /** Raw provider SSE diagnostics captured by the session buffer */
15
+ rawSseText?: string;
14
16
  }
15
17
  export interface ReportBundleResult {
16
18
  path: string;
@@ -33,6 +35,7 @@ export interface DebugLogSource {
33
35
  * - env.json: Sanitized environment variables
34
36
  * - config.json: Resolved settings
35
37
  * - profile.cpuprofile: CPU profile (performance report only)
38
+ * - raw-sse.txt: Recent raw provider SSE diagnostics (when captured)
36
39
  * - profile.md: Markdown CPU profile (performance report only)
37
40
  * - heap.heapsnapshot: Heap snapshot (memory report only)
38
41
  * - work.folded: Work profile folded stacks (work report only)