@oh-my-pi/pi-coding-agent 15.8.2 → 15.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +82 -29
  2. package/dist/types/capability/skill.d.ts +7 -0
  3. package/dist/types/config/settings-schema.d.ts +36 -22
  4. package/dist/types/debug/protocol-probe.d.ts +38 -0
  5. package/dist/types/debug/terminal-info.d.ts +34 -0
  6. package/dist/types/export/html/template.generated.d.ts +1 -1
  7. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  8. package/dist/types/extensibility/extensions/types.d.ts +11 -0
  9. package/dist/types/extensibility/shared-events.d.ts +1 -1
  10. package/dist/types/index.d.ts +1 -0
  11. package/dist/types/mcp/transports/stdio.d.ts +16 -7
  12. package/dist/types/modes/components/assistant-message.d.ts +3 -2
  13. package/dist/types/modes/components/hook-selector.d.ts +11 -0
  14. package/dist/types/modes/components/todo-reminder.d.ts +1 -1
  15. package/dist/types/modes/components/transcript-container.d.ts +36 -0
  16. package/dist/types/modes/interactive-mode.d.ts +2 -1
  17. package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
  18. package/dist/types/modes/theme/theme.d.ts +20 -1
  19. package/dist/types/plan-mode/plan-handoff.d.ts +20 -0
  20. package/dist/types/plan-mode/plan-protection.d.ts +12 -0
  21. package/dist/types/session/agent-session.d.ts +1 -1
  22. package/dist/types/session/indexed-session-storage.d.ts +59 -0
  23. package/dist/types/session/redis-session-storage.d.ts +12 -85
  24. package/dist/types/session/session-manager.d.ts +20 -0
  25. package/dist/types/session/session-storage.d.ts +5 -7
  26. package/dist/types/session/sql-session-storage.d.ts +16 -85
  27. package/dist/types/task/executor.d.ts +9 -0
  28. package/dist/types/task/index.d.ts +3 -1
  29. package/dist/types/telemetry-export.d.ts +19 -0
  30. package/dist/types/tiny/compiled-runtime.d.ts +35 -0
  31. package/dist/types/tools/ask.d.ts +1 -0
  32. package/dist/types/tools/index.d.ts +4 -2
  33. package/dist/types/tools/path-utils.d.ts +1 -1
  34. package/dist/types/tools/search.d.ts +2 -2
  35. package/dist/types/tools/{todo-write.d.ts → todo.d.ts} +18 -18
  36. package/dist/types/utils/jj.d.ts +1 -1
  37. package/dist/types/utils/session-color.d.ts +7 -2
  38. package/dist/types/web/search/index.d.ts +1 -1
  39. package/dist/types/web/search/provider.d.ts +2 -2
  40. package/dist/types/web/search/types.d.ts +65 -1
  41. package/package.json +15 -9
  42. package/scripts/build-binary.ts +12 -0
  43. package/src/capability/skill.ts +7 -0
  44. package/src/cli/args.ts +1 -1
  45. package/src/config/settings-schema.ts +22 -55
  46. package/src/debug/index.ts +67 -1
  47. package/src/debug/protocol-probe.ts +267 -0
  48. package/src/debug/terminal-info.ts +127 -0
  49. package/src/export/html/template.generated.ts +1 -1
  50. package/src/export/html/template.js +3 -3
  51. package/src/extensibility/custom-tools/types.ts +1 -1
  52. package/src/extensibility/extensions/types.ts +11 -0
  53. package/src/extensibility/shared-events.ts +1 -1
  54. package/src/extensibility/skills.ts +3 -3
  55. package/src/index.ts +1 -0
  56. package/src/internal-urls/docs-index.generated.ts +7 -7
  57. package/src/main.ts +12 -0
  58. package/src/mcp/transports/stdio.ts +37 -12
  59. package/src/modes/acp/acp-event-mapper.ts +7 -7
  60. package/src/modes/components/assistant-message.ts +3 -2
  61. package/src/modes/components/hook-selector.ts +149 -14
  62. package/src/modes/components/session-selector.ts +36 -5
  63. package/src/modes/components/status-line/segments.ts +2 -1
  64. package/src/modes/components/status-line.ts +1 -1
  65. package/src/modes/components/tips.txt +1 -1
  66. package/src/modes/components/todo-reminder.ts +1 -1
  67. package/src/modes/components/tool-execution.ts +9 -4
  68. package/src/modes/components/transcript-container.ts +91 -0
  69. package/src/modes/controllers/event-controller.ts +12 -7
  70. package/src/modes/controllers/extension-ui-controller.ts +3 -0
  71. package/src/modes/controllers/todo-command-controller.ts +1 -1
  72. package/src/modes/interactive-mode.ts +18 -6
  73. package/src/modes/print-mode.ts +5 -0
  74. package/src/modes/rpc/rpc-types.ts +1 -1
  75. package/src/modes/theme/theme.ts +48 -8
  76. package/src/modes/utils/ui-helpers.ts +1 -0
  77. package/src/plan-mode/plan-handoff.ts +37 -0
  78. package/src/plan-mode/plan-protection.ts +31 -0
  79. package/src/priority.json +4 -0
  80. package/src/prompts/goals/goal-continuation.md +1 -1
  81. package/src/prompts/system/eager-todo.md +3 -3
  82. package/src/prompts/system/orchestrate-notice.md +5 -5
  83. package/src/prompts/system/plan-mode-approved.md +14 -17
  84. package/src/prompts/system/plan-mode-reference.md +3 -6
  85. package/src/prompts/system/subagent-system-prompt.md +11 -0
  86. package/src/prompts/system/workflow-notice.md +1 -1
  87. package/src/prompts/tools/browser.md +5 -2
  88. package/src/prompts/tools/search.md +1 -1
  89. package/src/prompts/tools/task.md +3 -1
  90. package/src/prompts/tools/{todo-write.md → todo.md} +8 -0
  91. package/src/sdk.ts +1 -0
  92. package/src/session/agent-session.ts +29 -16
  93. package/src/session/indexed-session-storage.ts +430 -0
  94. package/src/session/redis-session-storage.ts +66 -377
  95. package/src/session/session-manager.ts +102 -22
  96. package/src/session/session-storage.ts +148 -68
  97. package/src/session/sql-session-storage.ts +131 -382
  98. package/src/slash-commands/helpers/todo.ts +2 -2
  99. package/src/task/executor.ts +9 -1
  100. package/src/task/index.ts +51 -1
  101. package/src/telemetry-export.ts +126 -0
  102. package/src/tiny/compiled-runtime.ts +179 -0
  103. package/src/tiny/worker.ts +24 -2
  104. package/src/tools/ask.ts +133 -87
  105. package/src/tools/fetch.ts +17 -4
  106. package/src/tools/find.ts +2 -2
  107. package/src/tools/index.ts +6 -4
  108. package/src/tools/path-utils.ts +16 -7
  109. package/src/tools/renderers.ts +2 -2
  110. package/src/tools/search.ts +6 -3
  111. package/src/tools/{todo-write.ts → todo.ts} +32 -35
  112. package/src/utils/jj.ts +28 -5
  113. package/src/utils/session-color.ts +39 -14
  114. package/src/web/search/index.ts +1 -1
  115. package/src/web/search/provider.ts +18 -34
  116. package/src/web/search/types.ts +73 -32
package/CHANGELOG.md CHANGED
@@ -2,6 +2,59 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.9.0] - 2026-06-04
6
+
7
+ ### Breaking Changes
8
+
9
+ - Removed synchronous `readTextSync` from `SessionStorage` and core implementations (`MemorySessionStorage`, `FileSessionStorage`, `RedisSessionStorage`, `SqlSessionStorage`), requiring callers to use async text reads
10
+ - Replaced the public `SessionStorage` `readTextPrefix(path, maxBytes)` and `readTextSuffix(path, maxBytes)` methods with `readTextSlices(path, prefixBytes, suffixBytes): Promise<[string, string]>`; custom session storage backends must implement the new combined slice API.
11
+
12
+ ### Added
13
+
14
+ - Added env-driven OpenTelemetry trace export. When `OTEL_EXPORTER_OTLP_ENDPOINT` (or `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`) is set, `omp` registers a global OTLP/proto trace exporter and switches on the agent loop's telemetry, so the `invoke_agent` / `chat` / `execute_tool` spans actually reach a collector instead of a no-op tracer. Honors the standard `OTEL_*` env contract (endpoint, headers, `OTEL_SERVICE_NAME`, `OTEL_SDK_DISABLED` and `OTEL_TRACES_EXPORTER=none` parsed case-insensitively) and the `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` capture toggle; it is a no-op when no endpoint is configured. Only the `http/protobuf` transport is supported — a `grpc` or `http/json` `OTEL_EXPORTER_OTLP*_PROTOCOL` declines rather than misrouting spans. This makes the existing telemetry usable from headless hosts that run `omp` as a spawned child process, where an in-process `TracerProvider` registered by the parent can't reach the child. Uses the `@opentelemetry/exporter-trace-otlp-proto` 2.x line, which exports cleanly under Bun.
15
+ ## Fixed
16
+
17
+ - Fixed the status line session name (and the editor border / status-line gap fill) being nearly illegible on light themes.
18
+ - Added `IndexedSessionStorage` and `SessionStorageBackend` exports to support shared metadata-indexed session backends
19
+ - Added the `tui.maxInlineImages` setting (default `8`) capping how many inline images render as live terminal graphics. Once a new image pushes the count past the cap, the oldest images are hidden via a full redraw — replaced by their `[Image: …]` text placeholder and purged from the terminal's graphics store — so long sessions with many screenshots/diagrams stop piling up images (and, on Kitty, stop leaving scrollback ghosts). Set to `0` to keep every image inline.
20
+ - Added a "View: terminal state" item to the `/debug` menu that prints the detected terminal, live geometry and cell size, multiplexer, and the negotiated subprotocols actually in use — graphics (Kitty/iTerm2/Sixel), desktop notifications (BEL/OSC 9/OSC 99, plus whether OSC 99 was confirmed via a device-attributes probe), OSC 8 hyperlinks, 24-bit color, DECCARA rectangular-SGR background fills, and DEC 2026 synchronized output — alongside the scrollback-clear strategy (`CSI 22 J` vs `CSI 2 J` redraw / ED3 eager-erase risk) and the raw `TERM`/`TERM_PROGRAM`/`COLORTERM` detection signals.
21
+ - Added a "Test: terminal protocols" item to the `/debug` menu that renders one live sample of every special escape protocol the renderer can emit — SGR text attributes (bold/italic/underline/strikethrough/inverse/dim), themed and 24-bit truecolor, OSC 8 hyperlinks, OSC 66 text sizing (large text), and an inline graphics swatch via the active image protocol (Kitty/iTerm2/Sixel, with a text fallback) — and fires a desktop notification, so you can eyeball which protocols the current terminal actually honors. The sample image is a gradient PNG generated in-process, so the graphics test needs no asset on disk.
22
+ - Added the `tui.textSizing` setting (default off) that renders Markdown H1 headings at 2x scale via Kitty's OSC 66 text-sizing protocol. It replaces the undocumented `PI_TUI_TEXT_SIZING` env var with a real setting, and only takes effect on Kitty terminals (where OSC 66 is implemented) — it is ignored everywhere else so headings never emit raw escape bytes.
23
+ - Added a lifecycle status to the `/resume` session picker. Each session's tail (last 32 KiB) is now read alongside the existing header window in a single pass, and its final message classified as `done` (the agent ended its turn and yielded control back), `interrupted` (a trailing tool call or tool result the loop never continued from), `aborted`, `error`, or `pending` (a trailing user message with no reply). The status renders as a colored segment on each session's metadata line. When the final message is larger than the tail window the status is omitted rather than guessed.
24
+ - Added support for `disable-model-invocation: true` frontmatter field from the [Agent Skills standard](https://agentskills.io/specification). Skills using this field are now hidden from the system prompt listing, matching the behavior of `hide: true`.
25
+
26
+ ### Changed
27
+
28
+ - Changed the `task` tool description to tag read-only agents and explicitly forbid assigning them file edits/commands or offloading reasoning to `quick_task`/`explore`.
29
+ - Changed Redis and SQL session storage initialization to load only indexed metadata (`size`, `mtimeMs`) instead of full session content
30
+ - Changed `SessionStorage` read paths to rely on backend-backed metadata/indexed storage, so session content is fetched on demand rather than cached as full in-memory mirrors
31
+ - Changed session-list slice reads to go through `SessionStorage.readTextSlices` across all backends, removing the file-only single-open branch and caller-managed buffers. `FileSessionStorage` now reads both windows via `peekFileEnds`, while Redis and SQL backends encode session content once per combined read.
32
+ - Changed the `ask` tool transcript renderer to mark single-choice questions with circular radio glyphs (`○`/`◉`) instead of the rectangular checkbox glyphs (`☐`/`☑`) it shares with multi-select questions, so a "pick one" combo box visually reads as a radio group rather than a checklist. Multi-select questions keep checkboxes. Added a `radio.selected`/`radio.unselected` symbol pair across the unicode, nerd-font, and ASCII presets.
33
+ - Changed the `ask` tool transcript renderer to mark the chosen answer inside the question form rather than re-listing the questions in a detached summary block below it. Once a question is answered, the standalone prompt preview is dropped and the result redraws the same form — every offered option still shown, with the selected one(s) filled in (`◉`/`☑`, highlighted) and the rest dimmed (`○`/`☐`); custom free-text answers and cancellations render in place as the final entry. This removes the duplicate question/option listing that previously appeared once as the call preview and again as the result.
34
+ - Changed task-completion and `ask` desktop notifications to structured terminal notifications (title, body, type, and a focus-on-click action). On Kitty these render through OSC 99 as a proper title/body with click-to-focus; terminals without confirmed OSC 99 support collapse them to the previous single-line message (BEL/OSC 9).
35
+ - Updated the "each kitty/tmux split" tip to include cmux.
36
+
37
+ ### Fixed
38
+
39
+ - Fixed tiny-model startup in compiled binaries by resolving `@huggingface/transformers` and its runtime dependencies from the installed cache using `package.json` `exports`/`main` metadata, preventing module-resolution failures when launching models
40
+ - Fixed tiny runtime installation flow in compiled binaries by using the build-time resolved `@huggingface/transformers` version and ensuring the runtime lock directory’s parent exists before acquiring the install lock, preventing mismatch and setup failures on fresh installs
41
+ - Fixed the terminal protocol debug probe reusing one stable Kitty graphics id across repeated panels, which could move/replace an earlier swatch instead of rendering a new one.
42
+ - Fixed selector dialogs (the `ask` tool, hook prompts) collapsing to a single visible option on shorter terminals when options carried long descriptions: the highlighted option's wrapped description consumed the entire row budget, hiding every other option and making the menu feel unnavigable (down moved the lone visible entry, left/right did nothing). When the fully-expanded list overflows, `HookSelectorComponent` now renders a compact list — every option label stays on screen and only the highlighted option expands its description, truncated to the remaining rows — so the whole menu is always visible and the detail pane follows the cursor.
43
+ - Fixed `read` failing with "Path not found" on web URLs whose scheme `//` collapsed to a single `/` (e.g. `https:/github.com/...`), which happens when a URL is routed through Node's `path.normalize`/`path.resolve`. The fetch URL recognizer now accepts a single-slash scheme and repairs it back to `//` before fetching, so collapsed URLs resolve instead of falling through to filesystem lookup.
44
+ - Fixed subagent slow-model priority falling through to older Claude Opus aliases when Opus 4.8 is available by adding Opus 4.8 and 4.7 aliases ahead of older Opus fallbacks ([#1753](https://github.com/can1357/oh-my-pi/issues/1753)).
45
+ - Fixed the web-search provider selectors in TUI settings/setup to derive from the shared provider metadata, so newly added providers cannot be omitted from the preference list.
46
+
47
+ ## [15.8.3] - 2026-06-03
48
+
49
+ ### Fixed
50
+
51
+ - Fixed Jujutsu workspace detection failing in non-default workspaces created by `jj workspace add`, whose `.jj/repo` is a FILE pointing at the shared repo dir rather than a directory. Detection now matches jj's own criterion (`.jj/repo` present, file or dir) instead of requiring a `.jj/repo/store` directory, and `jj.repo.resolve`'s `storeDir` follows the file indirection to the shared store.
52
+
53
+ ### Changed
54
+
55
+ - Changed the `todo` prompt to require initializing every item from a user-supplied multi-step plan as an individual todo task before execution
56
+ - Changed context compaction (prune/shake) to protect reads of the active plan file the same way it already protects `skill://` reads, so the plan stays intact through automatic and manual compaction. Both the canonical `local://PLAN.md` alias and the session's current plan reference path (e.g. a titled `local://<title>.md` after approval) are kept, tolerating read selectors and `local:/` scheme spelling.
57
+
5
58
  ## [15.8.2] - 2026-06-03
6
59
 
7
60
  ### Added
@@ -235,7 +288,7 @@
235
288
  - Changed the `task` tool's streaming call preview to list each dispatched agent's `id` and UI description as a tree instead of a bare `N agents` count, so the individual agents are visible while the tool-call arguments are still streaming. The collapsed view caps at 12 entries (`… N more agents`); the expanded view shows all.
236
289
  - Changed Mnemopi `recall` tool output to include memory ids for explicit recall results so agents can target `memory_edit`; auto-injected memory context and `reflect` remain id-free.
237
290
  - Changed the system prompt to advertise `memory://root` only when the local memory backend is active.
238
- - Changed `todo_write` result rendering to animate completed items in place: the checkbox flips checked first, then the strikethrough reveals across the task text.
291
+ - Changed `todo` result rendering to animate completed items in place: the checkbox flips checked first, then the strikethrough reveals across the task text.
239
292
 
240
293
  ### Fixed
241
294
 
@@ -315,7 +368,7 @@
315
368
 
316
369
  ### Changed
317
370
 
318
- - Changed the sticky `Todos` panel above the editor to advance as tasks close, instead of pinning to the first 5 tasks of the active phase. `selectStickyTodoWindow` now shows up to 5 open (pending / in_progress) tasks in original phase order and reports the count of remaining open tasks for the `+N more` hint, so every `todo_write` flip produces a visible row shift. Closed-phase tail falls back to the last 5 tasks (with the `+N more` line suppressed) until `getActivePhase` walks to the next phase.
371
+ - Changed the sticky `Todos` panel above the editor to advance as tasks close, instead of pinning to the first 5 tasks of the active phase. `selectStickyTodoWindow` now shows up to 5 open (pending / in_progress) tasks in original phase order and reports the count of remaining open tasks for the `+N more` hint, so every `todo` flip produces a visible row shift. Closed-phase tail falls back to the last 5 tasks (with the `+N more` line suppressed) until `getActivePhase` walks to the next phase.
319
372
  - Linked the sticky `Todos` panel to the live `SessionObserverRegistry` so pending todos that have an in-flight subagent doing their work light up green with an animated spinner — the same `theme.spinnerFrames` ("status" preset) the `task` tool uses for its agent rows — instead of staying greyed out as if nothing is happening. A new exported `todoMatchesAnyDescription(content, descriptions)` does case- and whitespace-insensitive equality first with a 6-char minimum-overlap substring fallback in either direction, so "Sonnet #2: shallow bug scan" and a subagent description of "Sonnet #2" still link up. Completed todos now render with `theme.status.success` (✔ / `\uf00c` / `[ok]` per symbol preset, still wrapped in the `success` colour so themed palettes can keep their purple/green/whatever) and in_progress rows render with `theme.status.running`, matching the `task` tool's icon vocabulary. The spinner interval only ticks while at least one visible open todo has a matched active subagent, and self-stops once subagents finish, so plain in_progress todos do not animate forever in the absence of subagent activity.
320
373
  - Extracted the top-level CLI command table from `src/cli.ts` into a side-effect-free `src/cli-commands.ts` so test code can introspect the registered subcommands without triggering the entrypoint's top-level await.
321
374
 
@@ -1716,9 +1769,9 @@
1716
1769
 
1717
1770
  ### Breaking Changes
1718
1771
 
1719
- - `todo_write`: renamed `replace` op to `init` and reshaped its input to `list: [{phase: string, items: string[]}]`. Tasks no longer accept a `status` field; all start `pending` and the first auto-promotes to `in_progress`. The `append` op's `items` is now `string[]` (was `{id, label}[]`)
1720
- - `todo_write`: removed the synthetic `task-N` / `phase-N` ids — task identity is now its `content` and phase identity is its `name`. The `task` field on `start`/`done`/`drop`/`note` and the `phase` field on `done`/`drop`/`rm`/`append` take those values directly
1721
- - `todo_write`: phase names no longer accept a numeric/roman prefix (`I.`, `1.`, `Phase 1:`, …). The renderer numbers phases visually (Ⅰ. Ⅱ. Ⅲ. …) and the model-facing state stores the bare noun phrase
1772
+ - `todo`: renamed `replace` op to `init` and reshaped its input to `list: [{phase: string, items: string[]}]`. Tasks no longer accept a `status` field; all start `pending` and the first auto-promotes to `in_progress`. The `append` op's `items` is now `string[]` (was `{id, label}[]`)
1773
+ - `todo`: removed the synthetic `task-N` / `phase-N` ids — task identity is now its `content` and phase identity is its `name`. The `task` field on `start`/`done`/`drop`/`note` and the `phase` field on `done`/`drop`/`rm`/`append` take those values directly
1774
+ - `todo`: phase names no longer accept a numeric/roman prefix (`I.`, `1.`, `Phase 1:`, …). The renderer numbers phases visually (Ⅰ. Ⅱ. Ⅲ. …) and the model-facing state stores the bare noun phrase
1722
1775
 
1723
1776
  ### Changed
1724
1777
 
@@ -1944,7 +1997,7 @@
1944
1997
 
1945
1998
  ### Added
1946
1999
 
1947
- - Added `note` to todo-write operations so you can append follow-up text notes to a task via `op: "note"` and `text`
2000
+ - Added `note` to todo operations so you can append follow-up text notes to a task via `op: "note"` and `text`
1948
2001
  - Added markdown note-block support to `/todo export` and `/todo import` so task notes are written as blockquote lines and reloaded with the todo list
1949
2002
  - Added `/todo export <path>` to write the current todo list as Markdown to a file, defaulting to `TODO.md` when no path is provided
1950
2003
  - Added `/todo import <path>` to replace the current todo list from a Markdown file, defaulting to `TODO.md` when no path is provided
@@ -2008,7 +2061,7 @@
2008
2061
  - Removed multi-pattern array input from `ast_grep` by changing `pat` to a single pattern string, so call sites using `pat: [...]` must be updated to send one query per invocation
2009
2062
  - Removed `lang`, `glob`, and `sel` options from `ast_edit` and `ast_grep`, and moved those behaviors into the required `path` argument
2010
2063
  - Required `path` for `ast_edit` and `ast_grep`, so invocations that relied on implicit repo-root searching are no longer valid
2011
- - Changed `todo_write` from multi-field verb payloads to an ordered array of flat operations, while retaining `replace` for harness bootstrap compatibility
2064
+ - Changed `todo` from multi-field verb payloads to an ordered array of flat operations, while retaining `replace` for harness bootstrap compatibility
2012
2065
  - Renamed atom edit operations from `before` and `after` to `pre` and `post`, so existing `atom` payloads using the old operation keys must be updated
2013
2066
  - Changed the hashline anchor format from `LINE#ID:content` to `LINEID:content` (no `#` separator, colon between anchor and content, no padding on line numbers); expanded the bigram alphabet from 40 hand-picked English bigrams to the full 647 single-token 2-letter bigrams — invalidates every previously captured `LINE#ID` reference
2014
2067
  - Renamed the subagent completion contract from `submit_result` to `yield`, so subagent sessions must now finish with the `yield` tool and the `requireYieldTool` option; `submit_result`/`requireSubmitResultTool` and old completion calls are no longer recognized
@@ -2027,10 +2080,10 @@
2027
2080
 
2028
2081
  - Updated `atom` and `hashline` edit anchor validation to auto-rebase a stale anchor within ±2 lines when the same hash matches a unique nearby line, continuing the edit with a warning instead of immediate failure
2029
2082
  - Changed bash command output labels from `[full result: artifact://…]` to `[raw output: artifact://…]` for artifact references produced from large command output
2030
- - Changed `todo_write` `done`, `rm`, and `drop` operations to target all tasks when neither `task` nor `phase` is provided, and made `append` create the target phase automatically when missing
2083
+ - Changed `todo` `done`, `rm`, and `drop` operations to target all tasks when neither `task` nor `phase` is provided, and made `append` create the target phase automatically when missing
2031
2084
  - Updated `ast_edit` and `ast_grep` to pass file-selection intent through `path` (including inline globs and comma/space-separated path lists) instead of separate `glob` filters
2032
2085
  - Changed `ast_grep` pagination API from `offset` to `skip`
2033
- - Flattened `todo_write` operation arguments to `{ op, task?, phase?, items? }[]` and removed task details from the persisted todo shape
2086
+ - Flattened `todo` operation arguments to `{ op, task?, phase?, items? }[]` and removed task details from the persisted todo shape
2034
2087
  - Changed `grep` truncation output to report `Result limit reached; narrow path.` and label match/result caps as `first N`
2035
2088
  - Changed JSON tree output to truncate inline argument pairs by available width and add an ellipsis when values no longer fit in the display
2036
2089
  - Changed JSON tree rendering to hide harness-internal `intent` and `__partialJson` fields from top-level tool output
@@ -2053,12 +2106,12 @@
2053
2106
 
2054
2107
  - Removed line-range support from `atom` mode selectors, including `loc` values like `160sr-170ab`, so edits must target a single anchor (`160sr`, `^`, or `$`) per entry
2055
2108
  - Removed the atom `del` verb and now require anchored-line deletion to be requested with `set: []`
2056
- - Removed `todo_write` task details and the `add_notes` operation
2109
+ - Removed `todo` task details and the `add_notes` operation
2057
2110
 
2058
2111
  ### Fixed
2059
2112
 
2060
2113
  - Improved no-op edit diagnostics for `atom` and `hashline` operations so edits that leave content unchanged now fail with contextual details (edit index, locator, and reason), including guidance for `replace_range` no-op cases
2061
- - Wrapped `todo_write` operations in an `ops` object so Codex/OpenAI function schemas always use a JSON Schema object.
2114
+ - Wrapped `todo` operations in an `ops` object so Codex/OpenAI function schemas always use a JSON Schema object.
2062
2115
  - Fixed JSON tree rendering for tool arguments by excluding injected internal keys from displayed root records
2063
2116
  - Printed assistant `errorMessage` text in print mode output to stderr so message-level errors are visible during non-interactive runs
2064
2117
  - Displayed assistant `errorMessage` text in the assistant message component for completed tool responses with non-terminal stop reasons
@@ -2159,14 +2212,14 @@
2159
2212
 
2160
2213
  ### Breaking Changes
2161
2214
 
2162
- - Replaced the legacy `todo_write` `ops`-based API (`replace`, `update`, `add_task`, and `remove_task`) with direct top-level fields, requiring migration of any callers using the old request shape
2163
- - Removed in-place updates to existing task `content`, `details`, and `notes` via `todo_write`; note changes now append through `add_notes`
2164
- - Phased task definitions in `todo_write` now reject `notes` on initial creation, so notes must be added later with `add_notes`
2215
+ - Replaced the legacy `todo` `ops`-based API (`replace`, `update`, `add_task`, and `remove_task`) with direct top-level fields, requiring migration of any callers using the old request shape
2216
+ - Removed in-place updates to existing task `content`, `details`, and `notes` via `todo`; note changes now append through `add_notes`
2217
+ - Phased task definitions in `todo` now reject `notes` on initial creation, so notes must be added later with `add_notes`
2165
2218
 
2166
2219
  ### Added
2167
2220
 
2168
- - Added `complete`, `start`, `abandon`, `remove`, `add_notes`, and `add_tasks` parameters to `todo_write` so callers can complete, jump to, drop, and annotate tasks without op wrappers
2169
- - Added direct `add_phase` support as a top-level argument for inserting a new phase in `todo_write`
2221
+ - Added `complete`, `start`, `abandon`, `remove`, `add_notes`, and `add_tasks` parameters to `todo` so callers can complete, jump to, drop, and annotate tasks without op wrappers
2222
+ - Added direct `add_phase` support as a top-level argument for inserting a new phase in `todo`
2170
2223
  - Added `task.simple` with `default`, `schema-free`, and `independent` modes so the task tool can disable task-call `schema` and shared `context` inputs while preserving agent-defined and inherited subagent schemas
2171
2224
 
2172
2225
  ### Changed
@@ -3991,7 +4044,7 @@
3991
4044
  - Fixed workspace symbol search to query all configured LSP servers and filter out non-matching results
3992
4045
  - Fixed `references`/`rename`/`hover` symbol targeting to error when `symbol` is missing on the line or `occurrence` is out of bounds
3993
4046
  - Fixed `reload` without a file to reload all active configured language servers instead of only the first server
3994
- - Fixed `todo_write` task normalization to auto-activate the first remaining task and include explicit remaining-items output in tool results, removing the need for an immediate follow-up start update
4047
+ - Fixed `todo` task normalization to auto-activate the first remaining task and include explicit remaining-items output in tool results, removing the need for an immediate follow-up start update
3995
4048
 
3996
4049
  ## [13.3.7] - 2026-02-27
3997
4050
 
@@ -4190,7 +4243,7 @@
4190
4243
 
4191
4244
  - Changed todo state management from file-based (`todos.json`) to in-memory session cache for improved performance and consistency
4192
4245
  - Changed todo phases to sync from session branch history when branching or rewriting entries
4193
- - Changed `TodoWriteTool` to update session cache instead of writing to disk, with automatic persistence through session entries
4246
+ - Changed `TodoTool` to update session cache instead of writing to disk, with automatic persistence through session entries
4194
4247
  - Changed XML tag from `<swarm-context>` to `<context>` in subagent prompts and task rendering
4195
4248
  - Changed system reminder XML tags from underscore to kebab-case format (`<system-reminder>`)
4196
4249
  - Changed plan storage from `plan://` protocol to `local://PLAN.md` for draft plans and `local://<title>.md` for finalized approved plans
@@ -5251,7 +5304,7 @@
5251
5304
  ### Fixed
5252
5305
 
5253
5306
  - Fixed TUI crash when ask tool renders long user input exceeding terminal width by using Text component for word wrapping instead of raw line output
5254
- - Fixed TUI crash when todo_write tool renders long todo content exceeding terminal width by using Text component for word wrapping instead of truncation
5307
+ - Fixed TUI crash when todo tool renders long todo content exceeding terminal width by using Text component for word wrapping instead of truncation
5255
5308
 
5256
5309
  ## [11.5.0] - 2026-02-06
5257
5310
 
@@ -5495,7 +5548,7 @@
5495
5548
  - Added new subcommands to help text: `commit` for AI-assisted git commits, `stats` for AI usage statistics dashboard, and `jupyter` for managing the shared Jupyter gateway
5496
5549
  - Added `grep` subcommand to help text for testing the grep tool
5497
5550
  - Added `browser` tool documentation for browser automation using Puppeteer
5498
- - Added `todo_write` tool documentation for managing todo and task lists
5551
+ - Added `todo` tool documentation for managing todo and task lists
5499
5552
  - Added documentation for additional LLM provider API keys (Groq, Cerebras, xAI, OpenRouter, Mistral, z.ai, MiniMax, OpenCode, Cursor, Vercel AI Gateway) in environment variables reference
5500
5553
  - Added documentation for cloud provider configuration (AWS Bedrock, Google Vertex AI) in environment variables reference
5501
5554
  - Added documentation for search provider API keys (Perplexity, Anthropic Search) in environment variables reference
@@ -5647,7 +5700,7 @@
5647
5700
  - Tightened `ask` tool conditions to require multiple approaches with significantly different tradeoffs before prompting user
5648
5701
  - Strengthened `ask` tool guidance to default to action and only ask when genuinely blocked by decisions with materially different outcomes
5649
5702
  - Changed refactor workflow to automatically remove now-unused elements and note removals instead of asking for confirmation
5650
- - Enforced exclusive concurrency mode for all file-modifying tools (edit, write, bash, python, ssh, todo-write) to prevent concurrent execution conflicts
5703
+ - Enforced exclusive concurrency mode for all file-modifying tools (edit, write, bash, python, ssh, todo) to prevent concurrent execution conflicts
5651
5704
  - Updated `ask` tool guidance to prioritize proactive problem-solving and default to action, asking only when truly blocked by decisions that materially change scope or behavior
5652
5705
  - Changed Python kernel initialization to require shared gateway mode; local gateway startup has been removed
5653
5706
  - Changed shared gateway error handling to retry on server errors (5xx status codes) before failing
@@ -5688,7 +5741,7 @@
5688
5741
 
5689
5742
  - Added `find.enabled`, `grep.enabled`, `ls.enabled`, `notebook.enabled`, `fetch.enabled`, `web_search.enabled`, `lsp.enabled`, and `calc.enabled` settings to control availability of individual tools
5690
5743
  - Added conditional tool documentation in system prompt that dynamically lists only enabled specialized tools
5691
- - Added `todos.enabled` setting to control availability of the todo_write tool for task tracking
5744
+ - Added `todos.enabled` setting to control availability of the todo tool for task tracking
5692
5745
  - Added `tools` field to agent frontmatter for declaring agent-specific tool capabilities
5693
5746
 
5694
5747
  ### Changed
@@ -6252,10 +6305,10 @@
6252
6305
  - Changed Web Search result rendering to use renderOutputBlock with answer, sources, related questions, and metadata sections
6253
6306
  - Changed Find, Grep, and Ls tools to use renderFileList and renderTreeList for consistent file/item listing
6254
6307
  - Changed Calculator tool result rendering to use renderTreeList for result item display
6255
- - Changed Notebook and TodoWrite tools to use new TUI rendering components for consistent output format
6308
+ - Changed Notebook and Todo tools to use new TUI rendering components for consistent output format
6256
6309
  - Refactored render-utils to move tree-related utilities to TUI module (getTreeBranch, getTreeContinuePrefix)
6257
6310
  - Changed import organization in sdk.ts for consistency
6258
- - Changed tool result rendering to merge call and result displays, showing tool arguments (command, pattern, query, path) in result headers for Bash, Calculator, Fetch, Find, Grep, Ls, LSP, Notebook, Read, SSH, TodoWrite, Web Search, and Write tools
6311
+ - Changed tool result rendering to merge call and result displays, showing tool arguments (command, pattern, query, path) in result headers for Bash, Calculator, Fetch, Find, Grep, Ls, LSP, Notebook, Read, SSH, Todo, Web Search, and Write tools
6259
6312
  - Changed Read tool title to display line range when offset or limit arguments are provided
6260
6313
  - Changed worker instantiation to use direct URL import instead of pre-bundled worker files
6261
6314
  - Changed `omp commit` to use agentic mode by default with tool-based git inspection
@@ -6269,7 +6322,7 @@
6269
6322
  - Changed Calculator tool result display to show both expression and output (e.g., `2+2 = 4`) instead of just the result
6270
6323
  - Changed Python tool output to group status information under a labeled section for clearer organization
6271
6324
  - Changed SSH tool output to apply consistent styling to non-ANSI output lines
6272
- - Changed Todo Write tool to respect expanded/collapsed state and use standard preview limits
6325
+ - Changed Todo tool to respect expanded/collapsed state and use standard preview limits
6273
6326
  - Changed Web Search related questions to respect expanded/collapsed state instead of always showing all items
6274
6327
  - Changed empty and error state rendering across multiple tools (Find, Grep, Ls, Notebook, Calculator, Ask) to include consistent status headers
6275
6328
  - Changed split commit to support hunk selectors (all, indices, or line ranges) instead of whole-file staging
@@ -6373,10 +6426,10 @@
6373
6426
  - Enhanced bash and python executors to save full output as artifacts when truncated
6374
6427
  - Improved abort signal handling across <caution>ith consistent ToolAbortError
6375
6428
  - Renamed task parameter from `vars` to `args` throughout task tool interface and updated template rendering to support built-in `{{id}}` and `{{description}}` placeholders
6376
- - Simplified todo-write tool by removing active_form parameter, using single content field for task descriptions
6429
+ - Simplified todo tool by removing active_form parameter, using single content field for task descriptions
6377
6430
  - Updated system prompt structure with `<important>` and `<avoid>` tags, clearer critical sections, and standardized whitespace handling
6378
6431
  - Renamed web_fetch tool to fetch and removed internal URL handling (use read tool instead)
6379
- - Standardized tool parameter names from camelCase to snake_case across edit, grep, python, and todo-write tools
6432
+ - Standardized tool parameter names from camelCase to snake_case across edit, grep, python, and todo tools
6380
6433
  - Unified timeout parameters across all tools with auto-conversion from milliseconds and reasonable clamping (1s-3600s for bash/ssh, 1s-600s for python/gemini-image)
6381
6434
  - Simplified web-search tool by removing advanced parameters (`max_tokens`, `model`, `search_domain_filter`, `search_context_size`, `return_related_questions`) and using `recency` instead of `search_recency_filter`
6382
6435
  - Restructured tool documentation with standardized `<instruction>`, `<output>`, `<critical>`, and `<avoid>` sections across all 18 tools
@@ -6985,11 +7038,11 @@
6985
7038
 
6986
7039
  ### Added
6987
7040
 
6988
- - Added `todo_write` tool for creating and managing structured task lists during coding sessions
7041
+ - Added `todo` tool for creating and managing structured task lists during coding sessions
6989
7042
  - Added persistent todo panel above the editor that displays task progress
6990
7043
  - Added `Ctrl+T` keybinding to toggle todo list expansion
6991
7044
  - Added grouped display for consecutive Read tool calls, showing multiple file reads in a compact tree view
6992
- - Added `todo_write` tool and persistent todo panel above the editor
7045
+ - Added `todo` tool and persistent todo panel above the editor
6993
7046
 
6994
7047
  ### Changed
6995
7048
 
@@ -14,6 +14,13 @@ export interface SkillFrontmatter {
14
14
  * rather than ones the model should auto-discover.
15
15
  */
16
16
  hide?: boolean;
17
+ /**
18
+ * Agent Skills standard equivalent of `hide`.
19
+ * When `true`, the skill is excluded from the system prompt listing.
20
+ * Normalized from kebab-case `disable-model-invocation` in YAML frontmatter.
21
+ * @see https://agentskills.io/specification
22
+ */
23
+ disableModelInvocation?: boolean;
17
24
  [key: string]: unknown;
18
25
  }
19
26
  /**
@@ -638,6 +638,20 @@ export declare const SETTINGS_SCHEMA: {
638
638
  readonly default: 20;
639
639
  readonly description: "Maximum height in terminal rows for inline images (default 20). Set to 0 to use only the viewport-based limit (60% of terminal height).";
640
640
  };
641
+ readonly "tui.maxInlineImages": {
642
+ readonly type: "number";
643
+ readonly default: 8;
644
+ readonly description: "Maximum number of inline images kept as live terminal graphics (default 8). Older images fall back to a text placeholder via a full redraw once the limit is exceeded. Set to 0 to keep every image (no limit).";
645
+ };
646
+ readonly "tui.textSizing": {
647
+ readonly type: "boolean";
648
+ readonly default: false;
649
+ readonly ui: {
650
+ readonly tab: "appearance";
651
+ readonly label: "Large Headings (Kitty)";
652
+ readonly description: "Render Markdown H1 headings at 2x scale using Kitty's OSC 66 text-sizing protocol. Only takes effect on Kitty terminals; ignored everywhere else. Off by default.";
653
+ };
654
+ };
641
655
  readonly "tui.hyperlinks": {
642
656
  readonly type: "enum";
643
657
  readonly values: readonly ["off", "auto", "always"];
@@ -2421,7 +2435,7 @@ export declare const SETTINGS_SCHEMA: {
2421
2435
  readonly ui: {
2422
2436
  readonly tab: "tools";
2423
2437
  readonly label: "Todos";
2424
- readonly description: "Enable the todo_write tool for task tracking";
2438
+ readonly description: "Enable the todo tool for task tracking";
2425
2439
  };
2426
2440
  };
2427
2441
  readonly "todo.reminders": {
@@ -3268,7 +3282,7 @@ export declare const SETTINGS_SCHEMA: {
3268
3282
  };
3269
3283
  readonly "providers.webSearch": {
3270
3284
  readonly type: "enum";
3271
- readonly values: readonly ["auto", "exa", "brave", "jina", "kimi", "zai", "perplexity", "anthropic", "gemini", "codex", "tavily", "kagi", "synthetic", "parallel", "searxng"];
3285
+ readonly values: readonly ["auto", "tavily", "perplexity", "brave", "jina", "kimi", "anthropic", "gemini", "codex", "zai", "exa", "parallel", "kagi", "synthetic", "searxng"];
3272
3286
  readonly default: "auto";
3273
3287
  readonly ui: {
3274
3288
  readonly tab: "providers";
@@ -3277,11 +3291,15 @@ export declare const SETTINGS_SCHEMA: {
3277
3291
  readonly options: readonly [{
3278
3292
  readonly value: "auto";
3279
3293
  readonly label: "Auto";
3280
- readonly description: "Preferred web-search provider";
3294
+ readonly description: "Automatically uses the first configured web-search provider";
3281
3295
  }, {
3282
- readonly value: "exa";
3283
- readonly label: "Exa";
3284
- readonly description: "Requires EXA_API_KEY";
3296
+ readonly value: "tavily";
3297
+ readonly label: "Tavily";
3298
+ readonly description: "Requires TAVILY_API_KEY";
3299
+ }, {
3300
+ readonly value: "perplexity";
3301
+ readonly label: "Perplexity";
3302
+ readonly description: "Requires PERPLEXITY_COOKIES or PERPLEXITY_API_KEY";
3285
3303
  }, {
3286
3304
  readonly value: "brave";
3287
3305
  readonly label: "Brave";
@@ -3294,42 +3312,38 @@ export declare const SETTINGS_SCHEMA: {
3294
3312
  readonly value: "kimi";
3295
3313
  readonly label: "Kimi";
3296
3314
  readonly description: "Requires MOONSHOT_SEARCH_API_KEY or MOONSHOT_API_KEY";
3297
- }, {
3298
- readonly value: "perplexity";
3299
- readonly label: "Perplexity";
3300
- readonly description: "Requires PERPLEXITY_COOKIES or PERPLEXITY_API_KEY";
3301
3315
  }, {
3302
3316
  readonly value: "anthropic";
3303
3317
  readonly label: "Anthropic";
3304
3318
  readonly description: "Claude's native web_search tool (uses Anthropic OAuth or ANTHROPIC_API_KEY)";
3305
- }, {
3306
- readonly value: "codex";
3307
- readonly label: "OpenAI";
3308
- readonly description: "OpenAI's native web_search (uses ChatGPT OAuth via /login openai-codex)";
3309
3319
  }, {
3310
3320
  readonly value: "gemini";
3311
3321
  readonly label: "Gemini";
3312
3322
  readonly description: "Google Search grounding via Gemini (uses google-gemini-cli or google-antigravity OAuth)";
3323
+ }, {
3324
+ readonly value: "codex";
3325
+ readonly label: "OpenAI";
3326
+ readonly description: "OpenAI's native web_search (uses ChatGPT OAuth via /login openai-codex)";
3313
3327
  }, {
3314
3328
  readonly value: "zai";
3315
3329
  readonly label: "Z.AI";
3316
3330
  readonly description: "Calls Z.AI webSearchPrime MCP";
3317
3331
  }, {
3318
- readonly value: "tavily";
3319
- readonly label: "Tavily";
3320
- readonly description: "Requires TAVILY_API_KEY";
3332
+ readonly value: "exa";
3333
+ readonly label: "Exa";
3334
+ readonly description: "Requires EXA_API_KEY";
3335
+ }, {
3336
+ readonly value: "parallel";
3337
+ readonly label: "Parallel";
3338
+ readonly description: "Requires PARALLEL_API_KEY";
3321
3339
  }, {
3322
3340
  readonly value: "kagi";
3323
3341
  readonly label: "Kagi";
3324
- readonly description: "Requires KAGI_API_KEY (Kagi V1 Search API)";
3342
+ readonly description: "Requires KAGI_API_KEY and Kagi Search API beta access";
3325
3343
  }, {
3326
3344
  readonly value: "synthetic";
3327
3345
  readonly label: "Synthetic";
3328
3346
  readonly description: "Requires SYNTHETIC_API_KEY";
3329
- }, {
3330
- readonly value: "parallel";
3331
- readonly label: "Parallel";
3332
- readonly description: "Requires PARALLEL_API_KEY";
3333
3347
  }, {
3334
3348
  readonly value: "searxng";
3335
3349
  readonly label: "SearXNG";
@@ -0,0 +1,38 @@
1
+ import { Container, type ImageBudget, type TextSizingScale } from "@oh-my-pi/pi-tui";
2
+ /**
3
+ * Encode raw 8-bit RGB pixels (`width * height * 3` bytes, row-major) as a PNG
4
+ * (color type 2, no interlacing). The IDAT payload is a real zlib stream from
5
+ * {@link zlib.deflateSync}, so the output is a fully valid PNG that every image
6
+ * protocol — including Sixel, which decodes the bytes natively — accepts.
7
+ */
8
+ export declare function encodeRgbPng(width: number, height: number, rgb: Uint8Array): Uint8Array;
9
+ export interface SampleImage {
10
+ base64: string;
11
+ mimeType: string;
12
+ dimensions: {
13
+ widthPx: number;
14
+ heightPx: number;
15
+ };
16
+ }
17
+ /** Build a deterministic RGB gradient PNG (red across, green down, constant blue). */
18
+ export declare function buildSampleImage(width?: number, height?: number): SampleImage;
19
+ /**
20
+ * OSC 66 text-sizing sample lines, one scaled span per requested scale. Each
21
+ * scaled row is followed by `scale - 1` blank rows that reserve the vertical
22
+ * cells its multi-cell glyphs occupy — mirroring the markdown H1 renderer so
23
+ * the next line does not paint over the bottom of the glyphs.
24
+ */
25
+ export declare function buildLargeTextLines(scales?: readonly TextSizingScale[]): string[];
26
+ export interface ProtocolProbeOptions {
27
+ image: SampleImage;
28
+ imageBudget: ImageBudget;
29
+ /** Whether the desktop notification was suppressed (e.g. `PI_NOTIFICATIONS=off`). */
30
+ notificationSuppressed: boolean;
31
+ }
32
+ /**
33
+ * Self-contained panel that renders one sample of every special terminal
34
+ * protocol into the chat transcript.
35
+ */
36
+ export declare class ProtocolProbeComponent extends Container {
37
+ constructor(options: ProtocolProbeOptions);
38
+ }
@@ -0,0 +1,34 @@
1
+ /** Live values the debug view reads off the running TUI, not the static capability table. */
2
+ export interface TerminalRuntimeState {
3
+ columns: number;
4
+ rows: number;
5
+ /** Whether DEC 2026 synchronized-output wrappers are currently emitted. */
6
+ synchronizedOutput: boolean;
7
+ }
8
+ export interface TerminalStateInfo {
9
+ detectedId: string;
10
+ columns: number;
11
+ rows: number;
12
+ cellWidthPx: number;
13
+ cellHeightPx: number;
14
+ trueColor: boolean;
15
+ imageProtocol: string;
16
+ notifyProtocol: string;
17
+ osc99Confirmed: boolean;
18
+ hyperlinks: boolean;
19
+ deccara: boolean;
20
+ screenToScrollback: boolean;
21
+ eagerEraseScrollbackRisk: boolean;
22
+ synchronizedOutput: boolean;
23
+ multiplexer: string | null;
24
+ env: {
25
+ TERM?: string;
26
+ TERM_PROGRAM?: string;
27
+ TERM_PROGRAM_VERSION?: string;
28
+ COLORTERM?: string;
29
+ };
30
+ }
31
+ /** Snapshot the active terminal capabilities and the live runtime geometry. */
32
+ export declare function collectTerminalState(runtime: TerminalRuntimeState): TerminalStateInfo;
33
+ /** Format terminal state for display in the debug menu. */
34
+ export declare function formatTerminalState(info: TerminalStateInfo): string;