@astralyn/pi 0.82.6 → 0.82.7

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 (183) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +1 -1
  3. package/dist/cli/session-picker.d.ts.map +1 -1
  4. package/dist/cli/session-picker.js +11 -13
  5. package/dist/cli/session-picker.js.map +1 -1
  6. package/dist/core/extensions/types.d.ts +4 -0
  7. package/dist/core/extensions/types.d.ts.map +1 -1
  8. package/dist/core/extensions/types.js.map +1 -1
  9. package/dist/core/session-manager.d.ts.map +1 -1
  10. package/dist/core/session-manager.js +2 -2
  11. package/dist/core/session-manager.js.map +1 -1
  12. package/dist/core/tools/bash.d.ts +1 -5
  13. package/dist/core/tools/bash.d.ts.map +1 -1
  14. package/dist/core/tools/bash.js +16 -41
  15. package/dist/core/tools/bash.js.map +1 -1
  16. package/dist/core/tools/edit.d.ts.map +1 -1
  17. package/dist/core/tools/edit.js +42 -11
  18. package/dist/core/tools/edit.js.map +1 -1
  19. package/dist/core/tools/find.d.ts.map +1 -1
  20. package/dist/core/tools/find.js +6 -7
  21. package/dist/core/tools/find.js.map +1 -1
  22. package/dist/core/tools/grep.d.ts.map +1 -1
  23. package/dist/core/tools/grep.js +17 -8
  24. package/dist/core/tools/grep.js.map +1 -1
  25. package/dist/core/tools/ls.d.ts.map +1 -1
  26. package/dist/core/tools/ls.js +3 -3
  27. package/dist/core/tools/ls.js.map +1 -1
  28. package/dist/core/tools/read.d.ts.map +1 -1
  29. package/dist/core/tools/read.js +4 -4
  30. package/dist/core/tools/read.js.map +1 -1
  31. package/dist/core/tools/render-utils.d.ts +7 -0
  32. package/dist/core/tools/render-utils.d.ts.map +1 -1
  33. package/dist/core/tools/render-utils.js +11 -0
  34. package/dist/core/tools/render-utils.js.map +1 -1
  35. package/dist/core/tools/write.d.ts.map +1 -1
  36. package/dist/core/tools/write.js +2 -3
  37. package/dist/core/tools/write.js.map +1 -1
  38. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  39. package/dist/extensions/deepwiki/render.js +34 -22
  40. package/dist/extensions/deepwiki/render.js.map +1 -1
  41. package/dist/extensions/plan/constants.d.ts +32 -4
  42. package/dist/extensions/plan/constants.d.ts.map +1 -1
  43. package/dist/extensions/plan/constants.js +37 -6
  44. package/dist/extensions/plan/constants.js.map +1 -1
  45. package/dist/extensions/plan/index.d.ts +27 -0
  46. package/dist/extensions/plan/index.d.ts.map +1 -1
  47. package/dist/extensions/plan/index.js +150 -44
  48. package/dist/extensions/plan/index.js.map +1 -1
  49. package/dist/extensions/plan/schema.d.ts +5 -0
  50. package/dist/extensions/plan/schema.d.ts.map +1 -1
  51. package/dist/extensions/plan/schema.js.map +1 -1
  52. package/dist/extensions/plan/state.d.ts +11 -2
  53. package/dist/extensions/plan/state.d.ts.map +1 -1
  54. package/dist/extensions/plan/state.js +31 -9
  55. package/dist/extensions/plan/state.js.map +1 -1
  56. package/dist/extensions/plan/storage.d.ts +11 -3
  57. package/dist/extensions/plan/storage.d.ts.map +1 -1
  58. package/dist/extensions/plan/storage.js +45 -20
  59. package/dist/extensions/plan/storage.js.map +1 -1
  60. package/dist/extensions/plan/view.d.ts +15 -7
  61. package/dist/extensions/plan/view.d.ts.map +1 -1
  62. package/dist/extensions/plan/view.js +91 -16
  63. package/dist/extensions/plan/view.js.map +1 -1
  64. package/dist/extensions/question/dialog.d.ts.map +1 -1
  65. package/dist/extensions/question/dialog.js +29 -10
  66. package/dist/extensions/question/dialog.js.map +1 -1
  67. package/dist/extensions/question/index.d.ts.map +1 -1
  68. package/dist/extensions/question/index.js +7 -2
  69. package/dist/extensions/question/index.js.map +1 -1
  70. package/dist/extensions/question/render.d.ts +4 -8
  71. package/dist/extensions/question/render.d.ts.map +1 -1
  72. package/dist/extensions/question/render.js +202 -29
  73. package/dist/extensions/question/render.js.map +1 -1
  74. package/dist/extensions/question/results.d.ts.map +1 -1
  75. package/dist/extensions/question/results.js +1 -0
  76. package/dist/extensions/question/results.js.map +1 -1
  77. package/dist/extensions/question/schema.d.ts.map +1 -1
  78. package/dist/extensions/question/schema.js +2 -2
  79. package/dist/extensions/question/schema.js.map +1 -1
  80. package/dist/extensions/question/types.d.ts +1 -0
  81. package/dist/extensions/question/types.d.ts.map +1 -1
  82. package/dist/extensions/question/types.js +1 -1
  83. package/dist/extensions/question/types.js.map +1 -1
  84. package/dist/extensions/router/stream.d.ts +1 -0
  85. package/dist/extensions/router/stream.d.ts.map +1 -1
  86. package/dist/extensions/router/stream.js +44 -13
  87. package/dist/extensions/router/stream.js.map +1 -1
  88. package/dist/extensions/subagent/constants.d.ts +1 -0
  89. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  90. package/dist/extensions/subagent/constants.js +1 -0
  91. package/dist/extensions/subagent/constants.js.map +1 -1
  92. package/dist/extensions/subagent/index.d.ts.map +1 -1
  93. package/dist/extensions/subagent/index.js +2 -0
  94. package/dist/extensions/subagent/index.js.map +1 -1
  95. package/dist/extensions/subagent/render.d.ts.map +1 -1
  96. package/dist/extensions/subagent/render.js +121 -48
  97. package/dist/extensions/subagent/render.js.map +1 -1
  98. package/dist/extensions/subagent/retry.d.ts +17 -0
  99. package/dist/extensions/subagent/retry.d.ts.map +1 -0
  100. package/dist/extensions/subagent/retry.js +41 -0
  101. package/dist/extensions/subagent/retry.js.map +1 -0
  102. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  103. package/dist/extensions/subagent/runner.js +33 -5
  104. package/dist/extensions/subagent/runner.js.map +1 -1
  105. package/dist/extensions/subagent/sdk-runner.d.ts +6 -0
  106. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  107. package/dist/extensions/subagent/sdk-runner.js +46 -24
  108. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  109. package/dist/extensions/subagent/types.d.ts +7 -0
  110. package/dist/extensions/subagent/types.d.ts.map +1 -1
  111. package/dist/extensions/subagent/types.js.map +1 -1
  112. package/dist/extensions/todo/index.d.ts.map +1 -1
  113. package/dist/extensions/todo/index.js +1 -1
  114. package/dist/extensions/todo/index.js.map +1 -1
  115. package/dist/extensions/todo/state.d.ts.map +1 -1
  116. package/dist/extensions/todo/state.js +10 -2
  117. package/dist/extensions/todo/state.js.map +1 -1
  118. package/dist/extensions/todo/view.d.ts +1 -1
  119. package/dist/extensions/todo/view.d.ts.map +1 -1
  120. package/dist/extensions/todo/view.js +179 -34
  121. package/dist/extensions/todo/view.js.map +1 -1
  122. package/dist/migrations.d.ts.map +1 -1
  123. package/dist/migrations.js +2 -1
  124. package/dist/migrations.js.map +1 -1
  125. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/armin.js +5 -0
  127. package/dist/modes/interactive/components/armin.js.map +1 -1
  128. package/dist/modes/interactive/components/bash-execution.d.ts +1 -0
  129. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/bash-execution.js +4 -2
  131. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  132. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -6
  133. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  134. package/dist/modes/interactive/components/countdown-timer.js +54 -17
  135. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  136. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  137. package/dist/modes/interactive/components/extension-selector.js +10 -6
  138. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  139. package/dist/modes/interactive/components/keybinding-hints.d.ts +11 -1
  140. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  141. package/dist/modes/interactive/components/keybinding-hints.js +56 -0
  142. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  143. package/dist/modes/interactive/components/session-selector.d.ts +3 -0
  144. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/session-selector.js +52 -2
  146. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  147. package/dist/modes/interactive/components/tool-execution.d.ts +10 -0
  148. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/tool-execution.js +133 -18
  150. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  151. package/dist/modes/interactive/components/tool-group.d.ts +1 -0
  152. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  153. package/dist/modes/interactive/components/tool-group.js +5 -0
  154. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  155. package/dist/modes/interactive/components/tree-selector.d.ts +10 -1
  156. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  157. package/dist/modes/interactive/components/tree-selector.js +55 -2
  158. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  159. package/dist/modes/interactive/interactive-mode.d.ts +5 -0
  160. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  161. package/dist/modes/interactive/interactive-mode.js +72 -18
  162. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  163. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  164. package/dist/modes/interactive/theme/theme.js +3 -2
  165. package/dist/modes/interactive/theme/theme.js.map +1 -1
  166. package/dist/utils/paths.d.ts +6 -0
  167. package/dist/utils/paths.d.ts.map +1 -1
  168. package/dist/utils/paths.js +8 -0
  169. package/dist/utils/paths.js.map +1 -1
  170. package/docs/bundled/README.md +1 -0
  171. package/docs/bundled/extensions/deepwiki.md +1 -1
  172. package/docs/bundled/extensions/plan.md +10 -9
  173. package/docs/bundled/extensions/question.md +7 -5
  174. package/docs/bundled/extensions/router.md +3 -4
  175. package/docs/bundled/extensions/statusline.md +0 -1
  176. package/docs/bundled/extensions/subagent.md +4 -3
  177. package/docs/bundled/extensions/todo.md +1 -1
  178. package/docs/bundled/tool-presentation.md +17 -16
  179. package/docs/extensions.md +20 -5
  180. package/docs/rpc.md +1 -1
  181. package/docs/usage.md +1 -1
  182. package/npm-shrinkwrap.json +6 -6
  183. package/package.json +1 -1
@@ -10,9 +10,9 @@ Adds a `question` tool for asking one to four multiple-choice questions when the
10
10
  - Options are numbered; pressing `1`–`9` jumps to the matching option — selecting it in single-select, toggling it in multi-select. The custom-answer row's number opens its input.
11
11
  - `←` / `→` switch between adjacent questions without wrapping. The tab bar marks answered questions and the Review state.
12
12
  - `Chat about this` is available after the choices. It returns a `needs_clarification` outcome so the model explains or reformulates instead of treating the user as having declined.
13
- - `Type something.` is appended automatically for custom answers. Authored options may not use reserved labels (`Other`, `Type something.`, `Chat about this`); the comparison is case-insensitive and ignores surrounding whitespace.
13
+ - `Type something` is appended automatically for custom answers. Authored options may not use reserved labels (`Other`, `Type something`, the legacy `Type something.`, or `Chat about this`); the comparison is case-insensitive and ignores surrounding whitespace.
14
14
  - `Tab` opens a note editor for the focused option; in multi-select, the option must be selected first. In single-select it also selects the option, and cancelling the note editor with `Esc` restores the previous selection. On the custom-answer row, it opens custom-answer input.
15
- - Multi-select custom answers stay on the `Type something.` row, are selected when saved, and can be toggled with `Space` without losing text. Enter on that row opens the input while no custom answer exists yet.
15
+ - Multi-select custom answers stay on the `Type something` row, are selected when saved, and can be toggled with `Space` without losing text. Enter on that row opens the input while no custom answer exists yet.
16
16
  - `preview` shows focused single-select content beside the choices on wide terminals and beneath them on narrow terminals. Preview height is capped and reports hidden lines. Previews on multi-select questions are rejected with a `preview_multiselect` error.
17
17
  - The dialog is available only in TUI mode. RPC, JSON, and print calls return a structured `no_ui` error rather than attempting a custom component.
18
18
  - Aborting the turn closes the dialog and resolves the call as cancelled with the answers given so far.
@@ -27,12 +27,15 @@ Adds a `question` tool for asking one to four multiple-choice questions when the
27
27
  outcome: "answered" | "cancelled" | "needs_clarification" | "error",
28
28
  cancelled,
29
29
  error?,
30
+ message?, // human-readable rendering text for error outcomes
30
31
  }
31
32
  ```
32
33
 
33
34
  Only `content` reaches the model. Successful results are numbered, clearly identify single/custom/multi answers, retain notes, and state when a preview was selected without echoing its full source. Cancelling — via `Esc` or a turn abort — lists any answers already given as partial answers alongside the decline message. Model-facing output is capped at 12,000 characters; if it is truncated, the result instructs the model to ask a focused follow-up question. Notes and custom answers are capped at 4,000 characters in the dialog.
34
35
 
35
- The transcript uses a private `renderCall` / `renderResult` only to replace raw question JSON and model-oriented result text with concise user summaries. Pi retains its native tool shell, pending/error state, and collapsed/expanded behavior.
36
+ The transcript uses a private `renderCall` / `renderResult` only to replace raw question JSON and model-oriented result text with concise user summaries. The collapsed call keeps a bounded header; expanding lists every question in full and marks multi-select prompts. Cancelled and clarification outcomes report `answered N of M`, and the expanded result preserves partial decisions and notes. Human-readable validation errors are shown instead of machine codes, while older or malformed session details fall back defensively to bounded content. Schema-level argument failures show only the first bounded error (plus any remaining count) when collapsed and reveal the bounded validator report with received arguments only when expanded. Pi retains its native tool shell and pending/error state.
37
+
38
+ Dialog footers use configured keybindings where Pi exposes them, format compact labels such as `↑/↓ navigate • Enter select • Esc cancel`, and show `1-N select/toggle`. Unbound actions are omitted rather than advertising a key that does not work.
36
39
 
37
40
  ## Limits
38
41
 
@@ -46,5 +49,4 @@ The transcript uses a private `renderCall` / `renderResult` only to replace raw
46
49
  - Uses Pi's native `ctx.ui.custom()` lifecycle; no state is shared with another extension.
47
50
  - The render cache is keyed by terminal width **and height**, because preview height depends on available rows and Pi resize only requests a render. Preview markdown rendering is additionally memoized per text and dimensions so editor keystrokes don't re-parse previews.
48
51
  - `validateQuestions` enforces only what the JSON schema cannot express: case-insensitive uniqueness, reserved-label rejection, and the preview/multi-select conflict. Length and count limits are enforced against the schema before the tool executes.
49
- - Dialog navigation follows Pi's injected select/input keybindings where applicable; custom actions such as Space-to-toggle remain explicit in the footer.
50
-
52
+ - Dialog navigation follows Pi's injected select/input keybindings where applicable; compact footer labels show the first configured binding in a human-readable form. Custom actions such as Space-to-toggle remain explicit in the footer.
@@ -109,18 +109,17 @@ There is **no migration** from any older models-manager config. Add relays with
109
109
  - Catalog probe expects OpenAI-style `{ data: [{ id }] }` response format.
110
110
  - Empty model list → provider is not registered (nothing appears in `/model`).
111
111
  - Body is Codex-oriented for transparent gateways; auth and URL remain Platform Responses (`sk-` + `/responses`).
112
+ - Replayed optional top-level `ResponseItem.id` identity fields are omitted from stateless requests, matching Codex CLI 0.145's default `store: false` wire behavior. Required semantic references such as `item_reference.id`, plus `call_id` and encrypted reasoning content, remain intact.
112
113
  - Same relay + same model: tool/reasoning multi-turn matches Codex-style Responses. Switching model or provider mid-session may normalize tool-call ids more strictly (upstream allow-list); this is not worked around here.
113
114
  - Interactive `/router` requires a TUI (`ctx.hasUI`); otherwise a warning is shown and no dialog opens.
114
115
  - Catalog multi-select and thinking editor are apply-on-Ctrl+S screens; only those screens can be discarded with double Esc.
115
116
 
116
117
  ## Implementation notes
117
118
 
118
- **Request shape.** `stream.ts` calls `openAIResponsesApi().streamSimple` with a model configured as Platform Responses (`api: "openai-responses"`). The `onPayload` callback reshapes the body toward Pi's built-in `openai-codex-responses` format, with `store: false`, system prompt as `instructions`, `parallel_tool_calls: true`, and rejected fields such as `prompt_cache_retention` and `temperature` dropped.
119
+ **Request shape.** `stream.ts` calls `openAIResponsesApi().streamSimple` with a model configured as Platform Responses (`api: "openai-responses"`). The `onPayload` callback reshapes the body toward Pi's built-in `openai-codex-responses` format, with `store: false`, system prompt as `instructions`, `parallel_tool_calls: true`, and rejected fields such as `prompt_cache_retention` and `temperature` dropped. Before sending, it omits each recognized ResponseItem variant's optional top-level identity `id`, matching the released Codex CLI 0.145 default for non-Azure `store: false` requests; this prevents a relay-supplied generic `item_*` id from later being validated as a reasoning (`rs_*`), message (`msg_*`), or function-call (`fc_*`) id. IDs that are required semantic references on other input variants are not removed.
119
120
 
120
121
  Session affinity headers use hyphenated form (`session-id`, `x-client-request-id`). Compat settings: `sessionAffinityFormat: "openai-nosession"`, `supportsLongCacheRetention: false`. Originator header: `codex`.
121
122
 
122
123
  **Differences from ChatGPT Codex OAuth.** Auth uses Bearer `sk-…` (not OAuth JWT), endpoint is `{baseUrl}/responses` (not `/codex/responses`), transport is SSE only (no WebSocket or zstd), and `OpenAI-Beta` is not set. These match **sk- relays**, not the official ChatGPT backend.
123
124
 
124
- **Multi-turn tool calls.** On a fixed relay + fixed model, tool-call ids preserve the Responses form and replay like Codex. Pi only rewrites ids across model boundaries. Staying on one model for long tool + reasoning sessions avoids id sanitization.
125
-
126
-
125
+ **Multi-turn tool calls.** `call_id` remains the stable tool-call/result join key, while optional replay-only ResponseItem identity IDs are omitted. Encrypted reasoning content and required semantic reference IDs are still replayed, so fixed-relay, fixed-model sessions retain stateless reasoning continuity without depending on a relay's item-ID namespace. Switching models or providers can still trigger pi-ai's stricter tool-call normalization.
@@ -106,4 +106,3 @@ Footer paint is hot (every TUI render). The extension caches:
106
106
  - **Branch stats** (thinking level + cumulative usage) by branch length, leaf entry identity, and a leaf usage fingerprint.
107
107
 
108
108
  Both caches clear on footer `invalidate()`.
109
-
@@ -84,12 +84,13 @@ They apply only to future subagent runs and never change the parent session's `/
84
84
  - The parent tool call waits until every worker reaches a terminal state.
85
85
  - Parent abort, `/reload`, `/new`, `/resume`, `/fork`, and session shutdown abort active child sessions. Queued workers do not survive the call.
86
86
  - Parallel worker failures do not cancel other independent workers.
87
- - Transient provider errors auto-retry: the worker session retries retryable stream errors with backoff (visible as `Retrying (n/m) in Xs…`), and a failure that produced no work (for example a preflight auth throw) is rerun at the task level up to two more times. Runs with partial work behind them are never rerun.
88
- - Progress is rendered in Pi's native tool transcript. The collapsed view stays lean in both phases: while running, one intent line (for example `Verifying changes`) carries tool uses, the `ctx:` context watermark, cost, and elapsed time above the current tool marked with `›` and the live output tail; once settled, the excerpted result is followed by a single metrics line (`tok · $ · duration`, plus tool uses and `ctx:` for single runs) and the configured expand hint. Live lines never quote token totals — mid-run totals are cache-inflated. The call-level status dot belongs to the tool shell; run and activity rows only use `›`, `○`, `✓`, `×`, and `■`, and parallel run rows carry stable dim ordinals that match the expanded section numbers. `Ctrl+O` expands each run into a report cover sheet: a status line, a metrics line, a fixed two-line `Prompt` preview (`… continues, N more lines`, honest about the 1KB bound), an `Activity · last n of N` digest whose successful rows are quiet one-liners, a `Working` tail while streaming, and the full `Report` (or `Error`, with `Report · partial` for salvaged output) rendered as Markdown. Expanded batches start with a numbered contents list whose numbers match the `──` section headers.
87
+ - Transient provider errors auto-retry: the worker session retries retryable stream errors with backoff (visible as a live `Retrying (n/m) in Xs…` countdown), and a failure that produced no work (for example a preflight auth throw) is rerun at the task level up to two more times. Provider and task retries share one absolute-deadline state; at zero it reads `Retrying now…`, and parent abort/session shutdown interrupts backoff immediately. Runs with partial work behind them are never rerun.
88
+ - Progress is rendered in Pi's native tool transcript. While a call is running, the native shell rebuilds the Subagent renderer once per second, independently of worker output and the main Working spinner. Silent single and parallel runs therefore keep advancing their own elapsed clocks in collapsed and expanded views, and queued retries keep counting down; the generic shell `Running…` row stays hidden to avoid duplicate progress. Once settled, the final duration is fixed and refresh stops.
89
+ - The collapsed view stays lean in both phases: while running, one bounded intent line (for example `Verifying changes`) carries tool uses, the `ctx:` context watermark, cost, and elapsed time above the current tool marked with `›` and the live output tail; once settled, the sentence-aware result excerpt is followed by a single metrics line (`tok · $ · duration`, plus tool uses and `ctx:` for single runs) and the configured expand hint. Live lines never quote token totals — mid-run totals are cache-inflated. The call-level status dot belongs to the tool shell; run and activity rows only use `›`, `○`, `✓`, `×`, and `■`, and parallel run rows carry stable dim ordinals that match the expanded section numbers. `Ctrl+O` expands each run into a report cover sheet: a status line, a metrics line, a fixed two-line `Prompt` preview (`… continues, N more lines`, honest about the 1KB bound), an `Activity · last n of N` digest whose successful rows are quiet aligned one-liners, a `Working` tail while streaming, and the full `Report` (or `Error`, with `Report · partial` for salvaged output) rendered as Markdown. Expanded batches start with a numbered contents list whose numbers match the `── N · ✓ Agent` section headers.
90
+ - Failed and aborted batch runs place their bounded reason on a separate error-colored line below the run headline instead of cutting it into the status row. Reasons are capped at 200 characters and keep their hanging indent when wrapped; successful settled excerpts prefer complete leading sentences within their 96-character budget. Rounded durations switch to minute form at 60 seconds without producing `1m 60s`.
89
91
  - Full child transcripts are not stored separately. Bounded run details remain in the parent tool result, so completed calls restore naturally in the parent session tree.
90
92
  - Nested usage is returned with the tool result and included in parent session accounting.
91
93
 
92
94
  ## Deliberate non-features
93
95
 
94
96
  There are no background agents, persistent worker IDs, unread state, fleet panel, statusline widget, send/stop/resume control plane, completion notifications, swarm/coordinator, worktree isolation, nested agents, MCP, hooks, or agent memory.
95
-
@@ -12,6 +12,7 @@ Adds a `todo` tool plus `/todos` for multi-step work, with a live overlay above
12
12
  - Deletion — via `delete` or `update` with `status: "deleted"` — leaves an immutable tombstone for branch history, removes that task from every dependent `blockedBy` list, and therefore releases dependents; the tool result names pending dependents that ended up fully unblocked. A deletion cannot be combined with other field edits in the same call. `clear` requires `confirm: true` and an `expectedCount` equal to the current task count, then empties the list without reusing ids.
13
13
  - Newly completed tasks remain visible for 30 seconds, then drop from the overlay; historical completions loaded by `/reload` or `/tree` stay hidden so live work remains prominent.
14
14
  - **Exactly one `in_progress`.** Moving a task to `in_progress` auto-demotes any other `in_progress` tasks to `pending`; the tool result lists demoted ids so the model sees the side effect.
15
+ - **Transcript presentation.** Consecutive calls collapse into one `todo` group. A `create_many` headline reports the correct `task`/`tasks` count and previews the first two subjects; expanding shows every valid batch item, its description preview, and dependency edges, bounded by the tool's batch and dependency limits. Settled create summaries preserve subjects and use the real task IDs; delete summaries preserve the tombstoned subject. The model-facing `create_many` result likewise lists each `#id: subject (pending)` instead of returning IDs alone.
15
16
  - **Verification soft nudge.** When a completion leaves the list fully done with 3+ completed tasks and no subject/description matching `verif|test|check|review`, the tool result appends a short NOTE (text only — `details` schema unchanged).
16
17
 
17
18
  ## Limits
@@ -29,4 +30,3 @@ Adds a `todo` tool plus `/todos` for multi-step work, with a live overlay above
29
30
  - **Status transitions are gated.** `completed` can be reopened to `in_progress` or `pending`, but a `deleted` tombstone is terminal. Single-active is enforced on demote (not hard-reject) so the model does not need a retry loop.
30
31
  - **Tool execution is sequential** (`executionMode: "sequential"`) so parallel tool calls cannot race on in-memory state. Validation failures **throw** so Pi marks `isError: true` and the branch replays the last good snapshot.
31
32
  - **Overlay paint is pure + width-cached.** Completion visibility bookkeeping runs in `update()` plus a disposable timeout, never during `render`. Same terminal width reuses the last line array.
32
-
@@ -6,17 +6,15 @@ The `@astralyn/pi` package uses Pi's native tool transcript presentation rather
6
6
 
7
7
  ```text
8
8
  ● ToolName(args)
9
- │ result
9
+ │ first result line
10
+ │ second result line
11
+ │
12
+ │ final result line
10
13
  ```
11
14
 
12
- States use the same shell:
15
+ The dim result rail continues through every visual line; an empty output line renders as a bare `│`. Calls keep their status in the leading dot: warning while pending or running, green after success, and red after failure. For default-shell tools that are still running after two seconds, the shell adds a live result row such as `Running… (2.1s)` and removes it when the call settles. Tools with purpose-built progress UI can opt out through `rendersOwnProgress`; tools using `renderShell: "self"` continue to own their entire presentation.
13
16
 
14
- ```text
15
- ● ToolName(args) completed call
16
- ● ToolName Working... pending call
17
- ● ToolName(args) failed call (error color)
18
- │ result successful or failed output
19
- ```
17
+ Time-driven renderers use `renderRefreshIntervalMs` separately from `rendersOwnProgress`. The former periodically rebuilds call/result components only during the partial lifecycle; the latter only hides the generic `Running…` row. The native shell shares the shortest needed interval, constrains explicit intervals to 250ms–60s, and stops refreshing on final result, abort, disposal, session replacement, chat rebuild, or shutdown. Renderers compute elapsed/countdown values from absolute timestamps or deadlines, so a delayed repaint never changes the underlying wall-clock meaning.
20
18
 
21
19
  ## Implementation boundary
22
20
 
@@ -31,7 +29,7 @@ The native tool presentation owns:
31
29
 
32
30
  Built-in renderers remain responsible for semantic content such as file paths, syntax highlighting, search results, Diff previews, and command output. The outer shell is native so built-in tools, bundled extensions, and compatible third-party tools share the same presentation.
33
31
 
34
- Consecutive tools may opt into a shared collapsed group through `toolGroup`. Built-in `read` and `find` calls use the `explore` group, and the bundled `todo` tool uses the `todo` group: their call rows render as one compact run with a single leading gap, while `Ctrl+O` restores each tool's complete call and result. Collapsed Todo rows are result-aware: successful current snapshots summarize the completed operation (created ids, update/get status, list counts, deletion, or clear) rather than only its arguments. Failures include a sanitized reason capped at 120 characters; missing or unrecognized result details fall back safely to the call summary.
32
+ Consecutive tools may opt into a shared collapsed group through `toolGroup`. Built-in `read`, `find`, `grep`, and `ls` calls use the `explore` group, and the bundled `todo` tool uses the `todo` group: their call rows render as one compact run with a single leading gap, while the configured expand-tools key (`Ctrl+O` by default) restores each tool's complete call and result. Collapsed Todo rows are result-aware: successful current snapshots summarize the completed operation, including task IDs and subjects for creation, rather than only its arguments. Failures include a sanitized reason capped at 120 characters; missing or unrecognized result details fall back safely to the call summary.
35
33
 
36
34
  ## Renderer inheritance
37
35
 
@@ -51,9 +49,10 @@ When no semantic renderer is available:
51
49
 
52
50
  - arguments are serialized into a bounded one-line summary;
53
51
  - output is collapsed to the most recent ten visual lines;
54
- - `Ctrl+O` expands the complete output;
52
+ - a shared hint above the tail reports the number of hidden earlier lines and the configured expand key;
53
+ - expanding restores the complete output;
55
54
  - historical tools that are no longer registered still receive the same shell;
56
- - failed calls use the error-colored bullet while result details keep the result bar.
55
+ - failed calls use the error-colored bullet while result details keep the result rail.
57
56
 
58
57
  The fallback does not change tool schemas, execution logic, or result protocols.
59
58
 
@@ -62,15 +61,17 @@ The fallback does not change tool schemas, execution logic, or result protocols.
62
61
  The native path continues to preserve:
63
62
 
64
63
  - `read`, `bash`, `grep`, `find`, `ls`, `write`, and `edit` semantics;
65
- - faithful width-aware raw command previews for Bash;
66
- - running Bash duration after the two-second progress threshold, without a permanent completion timer;
67
- - Diff previews and first-change-line metadata for `edit`;
64
+ - faithful width-aware raw command previews for Bash, with honest multi-line and width truncation markers;
65
+ - shell-wide running duration after the two-second progress threshold, with lifecycle-safe refresh disposal and no permanent completion timer;
66
+ - path links and consistent search flags/limits across built-in renderers;
67
+ - Diff statistics plus a ten-line collapsed Diff preview for `edit`, with the complete Diff restored on expand;
68
68
  - syntax highlighting;
69
69
  - image output and Kitty conversion;
70
70
  - native collapsed/expanded handling;
71
- - custom UI explicitly using `renderShell: "self"`.
71
+ - custom UI explicitly using `renderShell: "self"`;
72
+ - independently refreshed custom elapsed time and retry countdowns without a duplicate generic progress row.
72
73
 
73
- `edit` now uses the native outer shell while keeping its asynchronous Diff preview and final Diff result.
74
+ Built-in result truncation hints share the same `… (N earlier/more lines, … to expand)` language and correct singular/plural forms. `edit` uses the native outer shell while keeping its asynchronous Diff preview and final Diff result.
74
75
 
75
76
  ## Deliberately rejected approaches
76
77
 
@@ -1640,7 +1640,7 @@ const all = pi.getAllTools();
1640
1640
  const builtinTools = all.filter((t) => t.sourceInfo.source === "builtin");
1641
1641
  const extensionTools = all.filter((t) => t.sourceInfo.source !== "builtin" && t.sourceInfo.source !== "sdk");
1642
1642
  pi.setActiveTools([...new Set([...active, "my_custom_tool"])]); // Keep current tools and enable my_custom_tool
1643
- pi.setActiveTools(["read", "bash"]); // Switch to read-only
1643
+ pi.setActiveTools(["read", "bash"]); // Activate only read and bash
1644
1644
  ```
1645
1645
 
1646
1646
  `pi.getAllTools()` returns `name`, `description`, `parameters`, `promptGuidelines`, and `sourceInfo`.
@@ -1951,6 +1951,10 @@ pi.registerTool({
1951
1951
  },
1952
1952
 
1953
1953
  // Optional: Custom rendering
1954
+ // rendersOwnProgress suppresses only the shell's generic Running… row.
1955
+ rendersOwnProgress: true,
1956
+ // While the result is partial, rebuild renderCall/renderResult every second.
1957
+ renderRefreshIntervalMs: 1000,
1954
1958
  renderCall(args, theme, context) { ... },
1955
1959
  renderResult(result, options, theme, context) { ... },
1956
1960
  });
@@ -2184,9 +2188,18 @@ export default function (pi: ExtensionAPI) {
2184
2188
 
2185
2189
  Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API and [tool-execution.ts](https://github.com/ming-kang/pi/blob/main/src/modes/interactive/components/tool-execution.ts) for how tool rows are composed.
2186
2190
 
2187
- By default, tool output is wrapped in a `Box` that handles padding and background. A defined `renderCall` or `renderResult` must return a `Component`. If a slot renderer is not defined, `tool-execution.ts` uses fallback rendering for that slot.
2191
+ By default, tool output is wrapped in Pi's native call/result shell, which owns the status dot, result rail, padding, and fallback rendering. A defined `renderCall` or `renderResult` must return a `Component`. If a slot renderer is not defined, `tool-execution.ts` uses fallback rendering for that slot.
2188
2192
 
2189
- Set `renderShell: "self"` when the tool should render its own shell instead of using the default `Box`. This is useful for tools that need complete control over framing or background behavior, for example large previews that must stay visually stable after the tool settles.
2193
+ Set `renderShell: "self"` when the tool should render its own shell instead of using the native shell. This is useful for tools that need complete control over framing or background behavior, for example large previews that must stay visually stable after the tool settles.
2194
+
2195
+ Two independent options control live presentation:
2196
+
2197
+ - `rendersOwnProgress: true` suppresses only the native shell's generic `Running… (Ns)` row. It does not schedule renderer updates.
2198
+ - `renderRefreshIntervalMs` periodically rebuilds `renderCall` and `renderResult` while the tool result is partial. It does not suppress generic progress.
2199
+
2200
+ Use both when a tool renders its own elapsed time, retry countdown, or similar progress UI. Refresh intervals are rounded and constrained to 250–60,000ms. The shell may rebuild sooner when another native concern needs it, so the configured interval is the maximum refresh gap rather than an exclusive cadence. Refresh stops when the result settles or the row is disposed.
2201
+
2202
+ Derive displayed time from an absolute timestamp or deadline (`Date.now()`), not by decrementing a counter on every refresh. A refresh is only a repaint opportunity; event-loop stalls and machine sleep must not extend a wall-clock timeout.
2190
2203
 
2191
2204
  ```typescript
2192
2205
  pi.registerTool({
@@ -2289,15 +2302,17 @@ Custom editors and `ctx.ui.custom()` components receive `keybindings: Keybinding
2289
2302
 
2290
2303
  #### Best Practices
2291
2304
 
2292
- - Use `Text` with padding `(0, 0)`. The default Box handles padding.
2305
+ - Use `Text` with padding `(0, 0)`. The native shell handles padding.
2293
2306
  - Use `\n` for multi-line content.
2294
2307
  - Handle `isPartial` for streaming progress.
2308
+ - Use `renderRefreshIntervalMs` only for values that must change without a new partial result, and compute those values from absolute time.
2309
+ - Set `rendersOwnProgress` separately when the renderer replaces the native `Running…` row.
2295
2310
  - Support `expanded` for detail on demand.
2296
2311
  - Keep default view compact.
2297
2312
  - Read `context.args` in `renderResult` instead of copying args into `context.state`.
2298
2313
  - Use `context.state` only for data that must be shared across call and result slots.
2299
2314
  - Reuse `context.lastComponent` when the same component instance can be updated in place.
2300
- - Use `renderShell: "self"` only when the default boxed shell gets in the way. In self-shell mode the tool is responsible for its own framing, padding, and background.
2315
+ - Use `renderShell: "self"` only when the native shell gets in the way. In self-shell mode the tool is responsible for its own framing, padding, and background.
2301
2316
 
2302
2317
  #### Fallback
2303
2318
 
package/docs/rpc.md CHANGED
@@ -210,7 +210,7 @@ Response:
210
210
  }
211
211
  ```
212
212
 
213
- Messages are `AgentMessage` objects (see [Message Types](#message-types)).
213
+ Messages are `AgentMessage` objects (see [Types](#types)).
214
214
 
215
215
  ### Model
216
216
 
package/docs/usage.md CHANGED
@@ -293,6 +293,6 @@ pi --exclude-tools ask_question
293
293
 
294
294
  Pi keeps the core small and pushes workflow-specific behavior into extensions, skills, prompt templates, and packages.
295
295
 
296
- It intentionally does not include built-in MCP, sub-agents, permission popups, plan mode, to-dos, or background bash. You can build or install those workflows as extensions or packages, or use external tools such as containers and tmux.
296
+ This distribution ships selected workflows as hidden built-in extensions, including plan mode, sub-agents, and to-dos. It does not include built-in MCP, permission popups, or background bash. You can build or install additional workflows as extensions or packages, or use external tools such as containers and tmux.
297
297
 
298
298
  For the full rationale, read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/).
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.82.6",
3
+ "version": "0.82.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@astralyn/pi",
9
- "version": "0.82.6",
9
+ "version": "0.82.7",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@earendil-works/pi-agent-core": "0.82.1",
@@ -2476,15 +2476,15 @@
2476
2476
  "license": "MIT"
2477
2477
  },
2478
2478
  "node_modules/brace-expansion": {
2479
- "version": "5.0.7",
2480
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
2481
- "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
2479
+ "version": "5.0.8",
2480
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
2481
+ "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
2482
2482
  "license": "MIT",
2483
2483
  "dependencies": {
2484
2484
  "balanced-match": "^4.0.2"
2485
2485
  },
2486
2486
  "engines": {
2487
- "node": "18 || 20 || >=22"
2487
+ "node": "20 || >=22"
2488
2488
  }
2489
2489
  },
2490
2490
  "node_modules/braces": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.82.6",
3
+ "version": "0.82.7",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {