@astralyn/pi 0.87.4 → 0.87.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/bundle/chunks/{chunk-CUDKRZ2V.js → chunk-4W4Q2H6W.js} +58 -57
- package/dist/bundle/chunks/{chunk-ANT4TSUE.js → chunk-IORR2FW4.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-Y2YZRMU3.js → virtual-modules-KUEIEAZN.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +8 -24
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +54 -109
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background/session.d.ts +11 -7
- package/dist/core/background/session.d.ts.map +1 -1
- package/dist/core/background/session.js +42 -16
- package/dist/core/background/session.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +17 -4
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +48 -50
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/extensions/distribution-api.d.ts +0 -7
- package/dist/core/extensions/distribution-api.d.ts.map +1 -1
- package/dist/core/extensions/distribution-api.js +6 -6
- package/dist/core/extensions/distribution-api.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +3 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +59 -7
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -3
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +0 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +0 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +0 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +0 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +0 -7
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +0 -11
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +59 -5
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.d.ts.map +1 -1
- package/dist/core/tools/renderers/edit.js +4 -22
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/core/tools/renderers/find.d.ts.map +1 -1
- package/dist/core/tools/renderers/find.js +7 -6
- package/dist/core/tools/renderers/find.js.map +1 -1
- package/dist/core/tools/renderers/grep.d.ts.map +1 -1
- package/dist/core/tools/renderers/grep.js +8 -7
- package/dist/core/tools/renderers/grep.js.map +1 -1
- package/dist/core/tools/renderers/ls.d.ts.map +1 -1
- package/dist/core/tools/renderers/ls.js +3 -2
- package/dist/core/tools/renderers/ls.js.map +1 -1
- package/dist/core/tools/renderers/read.d.ts.map +1 -1
- package/dist/core/tools/renderers/read.js +7 -12
- package/dist/core/tools/renderers/read.js.map +1 -1
- package/dist/core/tools/renderers/write.d.ts.map +1 -1
- package/dist/core/tools/renderers/write.js +3 -2
- package/dist/core/tools/renderers/write.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +2 -6
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +5 -4
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/background/completion-render.d.ts.map +1 -1
- package/dist/extensions/background/completion-render.js +3 -4
- package/dist/extensions/background/completion-render.js.map +1 -1
- package/dist/extensions/background/constants.d.ts +2 -0
- package/dist/extensions/background/constants.d.ts.map +1 -1
- package/dist/extensions/background/constants.js +2 -0
- package/dist/extensions/background/constants.js.map +1 -1
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +31 -5
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/question/detail-pane.d.ts +12 -0
- package/dist/extensions/question/detail-pane.d.ts.map +1 -0
- package/dist/extensions/question/detail-pane.js +42 -0
- package/dist/extensions/question/detail-pane.js.map +1 -0
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +175 -105
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/option-window.d.ts +26 -0
- package/dist/extensions/question/option-window.d.ts.map +1 -0
- package/dist/extensions/question/option-window.js +53 -0
- package/dist/extensions/question/option-window.js.map +1 -0
- package/dist/extensions/question/render-cache.d.ts +4 -4
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +10 -11
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts +1 -1
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +2 -2
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +12 -8
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +1 -0
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +1 -1
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +15 -5
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +4 -4
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +11 -30
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/status-marker.d.ts +2 -2
- package/dist/modes/interactive/components/status-marker.js +2 -2
- package/dist/modes/interactive/components/status-marker.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +20 -0
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/chat.js +46 -0
- package/dist/modes/interactive/tool-view/chat.js.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts +14 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.js +52 -0
- package/dist/modes/interactive/tool-view/fallback.js.map +1 -0
- package/dist/modes/interactive/tool-view/style.d.ts +63 -0
- package/dist/modes/interactive/tool-view/style.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/style.js +83 -0
- package/dist/modes/interactive/tool-view/style.js.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.d.ts +17 -24
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.js +42 -116
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -0
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/background.md +1 -1
- package/docs/bundled/extensions/question.md +6 -5
- package/docs/bundled/extensions/todo.md +5 -5
- package/docs/bundled/tool-presentation.md +41 -31
- package/docs/extensions.md +1 -4
- package/docs/keybindings.md +11 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/core/model-stream-options.d.ts +0 -6
- package/dist/core/model-stream-options.d.ts.map +0 -1
- package/dist/core/model-stream-options.js +0 -20
- package/dist/core/model-stream-options.js.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts +0 -28
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.js +0 -84
- package/dist/modes/interactive/components/tool-chrome.js.map +0 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-execution.js.map +0 -1
- package/dist/modes/interactive/components/tool-group.d.ts +0 -17
- package/dist/modes/interactive/components/tool-group.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-group.js +0 -78
- package/dist/modes/interactive/components/tool-group.js.map +0 -1
- package/dist/modes/interactive/tool-chat.d.ts +0 -21
- package/dist/modes/interactive/tool-chat.d.ts.map +0 -1
- package/dist/modes/interactive/tool-chat.js +0 -58
- package/dist/modes/interactive/tool-chat.js.map +0 -1
|
@@ -9,14 +9,15 @@ Adds a `question` tool for asking one to four multiple-choice questions when the
|
|
|
9
9
|
- A single single-select question submits as soon as the user selects an option.
|
|
10
10
|
- A multi-question flow advances after each single-select answer; multi-select uses `Space` to toggle choices and Enter to continue. Once every question is answered, a **Review answers** view requires explicit submission.
|
|
11
11
|
- 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.
|
|
12
|
-
- `←` / `→` switch between adjacent questions without wrapping. The tab bar marks answered questions and the Review state.
|
|
12
|
+
- `←` / `→` switch between adjacent questions without wrapping. The tab bar uses the question headers and marks answered questions and the Review state. The question body displays only the question text, without repeating its header.
|
|
13
13
|
- `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.
|
|
14
14
|
- `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.
|
|
15
15
|
- `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.
|
|
16
16
|
- 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.
|
|
17
|
-
- `preview`
|
|
17
|
+
- Options form a compact list with one row per choice. The focused row is highlighted; its full label, description, saved note, and optional Markdown `preview` appear in a separate reading area. At 72 columns and up the areas sit side by side: the list fits the longest option label, with a 24-column minimum and a cap of half the usable width; the remaining width goes to details. Its width stays stable when moving focus or saving answers. Narrower terminals stack the details under a window of choices. Long labels are shortened only in the list, and remain readable in full in the details.
|
|
18
|
+
- `Alt+↑` / `Alt+↓` page through the details without changing the focused choice. A clipped reading area shows the visible line range and total, such as `8–15/36`, plus the configured paging keys. Changing choices starts the new details at the top; resizing reflows the content and keeps its end visible if you were already there. Rebind these actions with `app.question.pageUp` / `app.question.pageDown`. Plain Page Up/Down continue to scroll the transcript in fullscreen mode. Previews on multi-select questions are rejected with a `preview_multiselect` error.
|
|
18
19
|
- 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.
|
|
19
|
-
-
|
|
20
|
+
- The dialog takes at most half of the terminal height (16 rows minimum, capped by the terminal height) so the assistant reply above it stays readable. The tab bar, the question, `Chat about this`, and the key hints stay pinned when space permits. The options scroll as whole rows, with `↑ N more options` and `↓ N more options` hints on the sides that have more. Narrow layouts reserve space for reading details while keeping the focused choice visible. Notes and custom-answer input follow the cursor when clipped. Long Review answers can be scrolled with the configured up/down bindings while Enter still submits and Esc returns to editing.
|
|
20
21
|
- Aborting the turn closes the dialog and resolves the call as cancelled with the answers given so far.
|
|
21
22
|
|
|
22
23
|
## Result contract
|
|
@@ -37,7 +38,7 @@ Only `content` reaches the model. Successful results are numbered, clearly ident
|
|
|
37
38
|
|
|
38
39
|
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.
|
|
39
40
|
|
|
40
|
-
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`.
|
|
41
|
+
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`. Hints wrap between actions so each key stays beside its meaning. Question-switching hints appear only in multi-question flows, and unbound actions are omitted.
|
|
41
42
|
|
|
42
43
|
## Limits
|
|
43
44
|
|
|
@@ -49,7 +50,7 @@ Dialog footers use configured keybindings where Pi exposes them, format compact
|
|
|
49
50
|
## Implementation notes
|
|
50
51
|
|
|
51
52
|
- Uses Pi's native `ctx.ui.custom()` lifecycle; no state is shared with another extension.
|
|
52
|
-
- The render cache is keyed by terminal width **and height**, because preview
|
|
53
|
+
- The render cache is keyed by terminal width **and height**, because the option area and preview heights depend on available rows and Pi resize only requests a render. Preview markdown rendering is additionally memoized per text and width so editor keystrokes and option scrolling don't re-parse previews. `option-window.ts` picks the choices around the focused one; `detail-pane.ts` independently pages the reading area with one overlapping line for continuity.
|
|
53
54
|
- `validateQuestions` defensively trims every visible text field and rejects whitespace-only content, then enforces case-insensitive uniqueness, reserved-label rejection, and the preview/multi-select conflict. The JSON schema separately carries non-empty, length, and count constraints before execution.
|
|
54
55
|
- `prepareArguments` normalizes the three unambiguous argument shapes models actually emit — a lone question written flat at the root wraps into `questions[0]`, a root-level `question` string fills a `questions[0]` object that lost its own `question` field, and a stringified `questions` array parses back into an array. The schema itself keeps a single object shape because strict constrained sampling (which the tool opts into) does not support object unions.
|
|
55
56
|
- 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.
|
|
@@ -36,7 +36,7 @@ Omit or leave empty any group the call does not need; calling with `{}` lists ev
|
|
|
36
36
|
{ "delete": [3] }
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Tasks have three statuses: `pending`, `in_progress`, and `completed`.
|
|
39
|
+
Tasks have three statuses: `pending`, `in_progress`, and `completed`. At most one task may be `in_progress`; one activation per call returns every other active task to `pending` and reports that side effect, while a call that tries to activate two tasks is rejected. Zero active tasks is valid when waiting, before work starts, or after everything is done. Any status can be reopened or corrected. Listing includes every task, ordered as active, pending by ID, then completed by ID.
|
|
40
40
|
|
|
41
41
|
Todo intentionally has no action discriminator, dependency graph, owner, metadata, active-form label, tombstone, filtering, pagination, `get`, or `clear`. Keep tasks in intended execution order. When work is blocked, return it to `pending`, create a task that resolves the blocker, and activate that task instead.
|
|
42
42
|
|
|
@@ -47,10 +47,10 @@ The whole patch is validated before anything is applied: invalid input leaves th
|
|
|
47
47
|
The persistent widget displays only subjects:
|
|
48
48
|
|
|
49
49
|
```text
|
|
50
|
-
Todos 2/6 · [>] #4 Fix login redirect [ ] #5 Add regression tests +
|
|
50
|
+
Todos 2/6 · [>] #4 Fix login redirect [ ] #5 Add regression tests +2 more
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
`2/6` means completed tasks over total tasks. The active task is shown first, followed by pending tasks in ID order.
|
|
53
|
+
`2/6` means completed tasks over total tasks. The active task is shown first, followed by pending tasks in ID order. `+N more` counts only unfinished tasks that do not fit; it disappears when all unfinished tasks are visible. Completed tasks appear only in the header count. As width shrinks, whole pending segments move into `+N more`; only the active subject may be truncated. The renderer always returns at most one terminal-width-safe line.
|
|
54
54
|
|
|
55
55
|
The widget is registered only while a `pending` or `in_progress` task exists. It disappears immediately for an empty or fully completed list; there is no completion timer or visibility cache.
|
|
56
56
|
|
|
@@ -68,7 +68,7 @@ Consecutive tool calls collapse into the native `todo` transcript group. Collaps
|
|
|
68
68
|
|
|
69
69
|
## Limits
|
|
70
70
|
|
|
71
|
-
- At most 20 current tasks. When a call would push the list past 20, the oldest completed tasks are removed automatically to make room
|
|
71
|
+
- At most 20 current tasks. When a call would push the list past 20, the oldest completed tasks are removed automatically to make room, except tasks that same call created or updated. If too few tasks can be reclaimed, the call is rejected without changes. The error lists previously completed IDs: retry with those IDs in `delete` instead of `update` to free space in the same patch, or complete tasks in a separate call before creating more.
|
|
72
72
|
- At most 20 items in one `create`, `update`, or `delete` group.
|
|
73
73
|
- Subjects are limited to 160 characters.
|
|
74
74
|
- Descriptions are limited to 500 characters.
|
|
@@ -97,7 +97,7 @@ Todo state is conversation-backed rather than stored in a separate database. Eve
|
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
The assistant tool call already stores the arguments, so result details do not duplicate the patch parameters. The extension keeps one closure-scoped store for its runtime and replays the latest valid v3 snapshot from the current conversation branch on session start and `/tree` navigation. `/reload`, resume, and session replacement create a fresh extension runtime and replay that branch. Compaction does not require a separate replay handler because it does not change the live branch state.
|
|
100
|
+
For explicitly updated tasks, `from` is the status before the call and `to` is the final snapshot status, including any automatic demotion. The assistant tool call already stores the arguments, so result details do not duplicate the patch parameters. The extension keeps one closure-scoped store for its runtime and replays the latest valid v3 snapshot from the current conversation branch on session start and `/tree` navigation. `/reload`, resume, and session replacement create a fresh extension runtime and replay that branch. Compaction does not require a separate replay handler because it does not change the live branch state.
|
|
101
101
|
|
|
102
102
|
Replay scans tail to head, validates the bounded state, and can fall back past a malformed v3 snapshot. Snapshots from older schema versions (v1/v2) are intentionally ignored and are not migrated: restoring a conversation written before v3 starts with an empty list, while the historical tool-result text remains in the session transcript.
|
|
103
103
|
|
|
@@ -1,45 +1,58 @@
|
|
|
1
1
|
# Native tool presentation
|
|
2
2
|
|
|
3
|
-
The `@astralyn/pi` package
|
|
3
|
+
The `@astralyn/pi` package draws every tool call in the interactive transcript as one compact block: a status dot and a rail. Tools in the transcript are not cards, have no background color, and show no timers of their own.
|
|
4
4
|
|
|
5
5
|
## Visual language
|
|
6
6
|
|
|
7
7
|
```text
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
I'll look at the code.
|
|
9
|
+
|
|
10
|
+
● read src/app.ts:1-80
|
|
11
|
+
● grep /useState/ in src
|
|
12
|
+
● edit src/app.ts
|
|
13
|
+
│ 1 const a = 0
|
|
14
|
+
│ -2 const b = 1
|
|
15
|
+
│ +2 const b = 2
|
|
16
|
+
● $ npm test
|
|
17
|
+
│ ... (14 earlier lines, ctrl+o to expand)
|
|
18
|
+
│ FAIL a.test.ts
|
|
11
19
|
│
|
|
12
|
-
│
|
|
20
|
+
│ Command exited with code 1
|
|
21
|
+
│
|
|
22
|
+
│ Took 4.2s
|
|
23
|
+
|
|
24
|
+
The tests failed.
|
|
13
25
|
```
|
|
14
26
|
|
|
15
|
-
The
|
|
27
|
+
- The dot is the tool's state: the warning color while the call is pending or running, green after success, and red after failure.
|
|
28
|
+
- The rail continues through every visual line that belongs to the same tool. A blank output line renders as a bare `│`.
|
|
29
|
+
- Tool blocks sit directly under each other with no blank line. Text before or after a run of tools keeps one blank line.
|
|
30
|
+
- `read`, `grep`, `find`, and `ls` show only their header until expanded. A failed call always shows its error.
|
|
31
|
+
- Consecutive calls never merge into a group. Every call keeps its own row, and the configured expand-tools key (`Ctrl+O` by default) or a click on the row shows its complete result.
|
|
16
32
|
|
|
17
|
-
|
|
33
|
+
The bash renderer shows its own `Elapsed` line while a command runs and a fixed `Took` line after it settles. The shell adds no progress row, and other renderers that refresh over time schedule their own repaints: they arm a timer in renderer state, call the render context's `invalidate()`, and clear the timer on the first settled render. The shell calls `state.dispose()` when a row is disposed, so a timer never outlives its row.
|
|
18
34
|
|
|
19
|
-
|
|
35
|
+
The `Ctrl+B` background hint is not part of a tool row. Once a foreground Bash or Subagent execution has run for ten seconds and can still move, the Background extension shows `Ctrl+B to background` in the statusline, next to the `bg N active` count.
|
|
20
36
|
|
|
21
|
-
|
|
37
|
+
## Implementation boundary
|
|
22
38
|
|
|
23
|
-
- the
|
|
24
|
-
- pending, success, and error states;
|
|
25
|
-
- call titles and generic argument summaries;
|
|
26
|
-
- collapsed and expanded result behavior;
|
|
27
|
-
- generic fallback rendering;
|
|
28
|
-
- image placement and conversion.
|
|
39
|
+
The look is defined in one place, `src/modes/interactive/tool-view/style.ts`: the marker and rail glyphs, their colors, the spacing between blocks, and which tools fold their result. `FramedComponent` in the same file hangs a component's lines off the marker or the rail and derives the gutter width from the glyphs.
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
`tool-view/tool-execution.ts` owns one call's lifecycle: pending, success and error states, expansion, image placement and Kitty conversion, and renderer disposal. `tool-view/chat.ts` owns the chat container that removes the blank line between consecutive tool rows and disposes rows when the chat clears. Extension tools and built-in tools use the same shell, so a third-party tool gets the same dot and rail without any change.
|
|
31
42
|
|
|
32
|
-
|
|
43
|
+
Built-in renderers remain responsible for semantic content such as file paths, syntax highlighting, search results, Diff previews, and command output. They return plain components; the shell frames them.
|
|
33
44
|
|
|
34
45
|
## Renderer inheritance
|
|
35
46
|
|
|
36
47
|
| Tool definition | Behavior |
|
|
37
48
|
|---|---|
|
|
38
|
-
| No `renderCall`/`renderResult` | Uses the
|
|
49
|
+
| No `renderCall`/`renderResult` | Uses the native call and result fallback. |
|
|
39
50
|
| Custom renderer with the default shell | Uses the native shell around the custom content. |
|
|
40
51
|
| `renderShell: "self"` | Keeps complete ownership of the tool's layout. |
|
|
41
52
|
|
|
42
|
-
Built-in tool definitions are also used when an extension overrides only one renderer slot. A custom call renderer can inherit the built-in result renderer, and vice versa.
|
|
53
|
+
Built-in tool definitions are also used when an extension overrides only one renderer slot. A custom call renderer can inherit the built-in result renderer, and vice versa. An extension that overrides a built-in tool with its own result renderer controls what that row shows, including when it is collapsed.
|
|
54
|
+
|
|
55
|
+
The inherited Bash result renderer keeps its elapsed time even with a custom call renderer. Call and result renderers share `state`; a renderer that adds a `dispose()` callback must also call the previous callback so both renderers can release their resources.
|
|
43
56
|
|
|
44
57
|
Renderer failures fall back to native generic output rather than breaking the transcript.
|
|
45
58
|
|
|
@@ -49,29 +62,25 @@ When no semantic renderer is available:
|
|
|
49
62
|
|
|
50
63
|
- arguments are serialized into a bounded one-line summary;
|
|
51
64
|
- output is collapsed to the most recent ten visual lines;
|
|
52
|
-
- a
|
|
65
|
+
- a hint above the tail reports the number of hidden earlier lines and the configured expand key;
|
|
53
66
|
- expanding restores the complete output;
|
|
54
67
|
- historical tools that are no longer registered still receive the same shell;
|
|
55
|
-
- failed calls use the error-colored
|
|
68
|
+
- failed calls use the error-colored dot while result details keep the rail.
|
|
56
69
|
|
|
57
70
|
The fallback does not change tool schemas, execution logic, or result protocols.
|
|
58
71
|
|
|
59
72
|
## Built-in behavior preserved
|
|
60
73
|
|
|
61
|
-
The
|
|
74
|
+
The presentation continues to preserve:
|
|
62
75
|
|
|
63
76
|
- `read`, `bash`, `grep`, `find`, `ls`, `write`, and `edit` semantics;
|
|
64
77
|
- faithful width-aware raw command previews for Bash, with honest multi-line and width truncation markers;
|
|
65
|
-
-
|
|
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;
|
|
78
|
+
- a ten-line collapsed Diff preview for `edit`, with the complete Diff restored on expand;
|
|
68
79
|
- syntax highlighting;
|
|
69
80
|
- image output and Kitty conversion;
|
|
70
|
-
-
|
|
81
|
+
- click to expand and collapse;
|
|
71
82
|
- custom UI explicitly using `renderShell: "self"`;
|
|
72
|
-
- independently refreshed custom elapsed time and retry countdowns
|
|
73
|
-
|
|
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.
|
|
83
|
+
- independently refreshed custom elapsed time and retry countdowns.
|
|
75
84
|
|
|
76
85
|
## Deliberately rejected approaches
|
|
77
86
|
|
|
@@ -81,6 +90,7 @@ The package does not use:
|
|
|
81
90
|
- same-name re-registration to replace built-in tools;
|
|
82
91
|
- a global renderer registry exposed through Extension API;
|
|
83
92
|
- a restored `tools-view` extension;
|
|
84
|
-
- forced decoration of third-party tools that explicitly own their shell
|
|
93
|
+
- forced decoration of third-party tools that explicitly own their shell;
|
|
94
|
+
- merging consecutive calls into a collapsed group, or a shell-level progress row.
|
|
85
95
|
|
|
86
|
-
Those approaches either depend on private runtime internals, change execution ownership,
|
|
96
|
+
Those approaches either depend on private runtime internals, change execution ownership, cannot reliably cover independently loaded extensions, or add presentation that the compact block does not need.
|
package/docs/extensions.md
CHANGED
|
@@ -2277,8 +2277,6 @@ pi.registerTool(myTool);
|
|
|
2277
2277
|
|
|
2278
2278
|
**Constrained sampling:** `constrainedSampling: { type: "json_schema", strict: "prefer" }` requests provider-side schema enforcement when the active provider supports it, otherwise normal tool calling is used. Use `strict: "require"` only when the request should fail on unsupported providers. For provider-specific grammars, use `{ type: "grammar", variants: { openai_lark: "...", openai_regex: "..." } }`; each variant is optional, and unsupported providers fall back to normal function tools. `constrainedSampling: false` explicitly opts out (the same behavior as omitting it).
|
|
2279
2279
|
|
|
2280
|
-
**Tool groups:** `toolGroup: "my-group"` is a freeform display identifier. Adjacent default-shell tool rows with the same identifier collapse together in the interactive transcript; it does not change execution. In the collapsed group header, `renderCall` receives `context.toolGroupSummary === true`. Tools with `renderShell: "self"` are not grouped.
|
|
2281
|
-
|
|
2282
2280
|
**Usage accounting:** For unmanaged tools, if a tool makes nested LLM calls, return their combined `Usage` as `usage`. Pi persists it on the tool result and includes it in footer, `/session`, and RPC session totals. `tool_result` handlers can inspect or replace this value. Managed executions instead settle usage independently through [`ctx.background`](#ctxbackground); do not duplicate it on the handoff or managed foreground result.
|
|
2283
2281
|
|
|
2284
2282
|
**Signaling errors:** To mark a tool execution as failed (sets `isError: true` on the result and reports it to the LLM), throw an error from `execute`. Returning a value never sets the error flag regardless of what properties you include in the return object.
|
|
@@ -2500,7 +2498,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2500
2498
|
|
|
2501
2499
|
Tools can provide `renderCall` and `renderResult` for custom TUI display. See [tui.md](tui.md) for the full component API.
|
|
2502
2500
|
|
|
2503
|
-
By default, tool output is wrapped in Pi's native call/result shell, which owns the status dot, result rail,
|
|
2501
|
+
By default, tool output is wrapped in Pi's native call/result shell, which owns the status dot, result rail, spacing between consecutive tool rows, and fallback rendering. A defined `renderCall` or `renderResult` must return a `Component`. If a slot renderer is not defined, the shell uses fallback rendering for that slot. Return content without leading padding: the shell trims leading blank result lines and adds no blank line between consecutive tool rows.
|
|
2504
2502
|
|
|
2505
2503
|
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.
|
|
2506
2504
|
|
|
@@ -2531,7 +2529,6 @@ pi.registerTool({
|
|
|
2531
2529
|
- `invalidate()` - request a rerender of this tool row
|
|
2532
2530
|
- `toolCallId`, `cwd`, `executionStarted`, `argsComplete`, `isPartial`, `expanded`, `showImages`, `isError`
|
|
2533
2531
|
- `result` - the current partial or final result, if one has arrived
|
|
2534
|
-
- `toolGroupSummary` - true while `renderCall` builds a collapsed group header
|
|
2535
2532
|
|
|
2536
2533
|
Use `context.state` for cross-slot shared state. Keep slot-local caches on the returned component instance when you want to reuse and mutate the same component across renders.
|
|
2537
2534
|
|
package/docs/keybindings.md
CHANGED
|
@@ -137,6 +137,17 @@ In `/bg`, Up/Down and Page Up/Page Down target the focused pane: row selection/l
|
|
|
137
137
|
|
|
138
138
|
Ctrl+B also works while `/bg` owns focus. It does not restart execution, reset shell timeouts, detach individual workers, or affect user `!` commands. With no eligible work it only reports that nothing can be moved. See [Background tasks](bundled/extensions/background.md).
|
|
139
139
|
|
|
140
|
+
### Question Details
|
|
141
|
+
|
|
142
|
+
These actions apply while the [question dialog](bundled/extensions/question.md) is showing choices. Up/Down move between choices; the detail paging keys read the focused choice's description, notes, and preview without selecting it.
|
|
143
|
+
|
|
144
|
+
| Keybinding id | Default | Description |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| `app.question.pageUp` | `alt+up` | Page up in question details |
|
|
147
|
+
| `app.question.pageDown` | `alt+down` | Page down in question details |
|
|
148
|
+
|
|
149
|
+
In fullscreen mode, plain Page Up/Down still target the transcript. Notes and custom-answer editors use the ordinary editor bindings.
|
|
150
|
+
|
|
140
151
|
### BTW Side Questions
|
|
141
152
|
|
|
142
153
|
These actions apply while the [BTW panel](bundled/extensions/btw.md) is open and the editor has focus. Autocomplete and dialogs retain priority.
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astralyn/pi",
|
|
3
|
-
"version": "0.87.
|
|
3
|
+
"version": "0.87.6",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@astralyn/pi",
|
|
9
|
-
"version": "0.87.
|
|
9
|
+
"version": "0.87.6",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@earendil-works/chord": "0.87.1",
|
package/package.json
CHANGED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { Api, Model, ModelsSimpleStreamOptions, SimpleStreamOptions } from "@earendil-works/pi-ai";
|
|
2
|
-
import type { ExtensionRunner } from "./extensions/runner.ts";
|
|
3
|
-
import type { SettingsManager } from "./settings-manager.ts";
|
|
4
|
-
/** Resolve application defaults once, before authentication or network work begins. */
|
|
5
|
-
export declare function resolveModelStreamOptions(model: Model<Api>, settings: SettingsManager, runner: ExtensionRunner | undefined, options?: SimpleStreamOptions): ModelsSimpleStreamOptions;
|
|
6
|
-
//# sourceMappingURL=model-stream-options.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model-stream-options.d.ts","sourceRoot":"","sources":["../../src/core/model-stream-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACxG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,uFAAuF;AACvF,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,OAAO,GAAE,mBAAwB,GAC/B,yBAAyB,CAgB3B"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { mergeProviderAttributionHeaders } from "./provider-attribution.js";
|
|
2
|
-
/** Resolve application defaults once, before authentication or network work begins. */
|
|
3
|
-
export function resolveModelStreamOptions(model, settings, runner, options = {}) {
|
|
4
|
-
const retry = settings.getProviderRetrySettings();
|
|
5
|
-
const idleTimeout = settings.getHttpIdleTimeoutMs();
|
|
6
|
-
const attribution = mergeProviderAttributionHeaders(model, settings, options.sessionId);
|
|
7
|
-
return {
|
|
8
|
-
...options,
|
|
9
|
-
// Provider SDKs interpret zero as an immediate timeout, not an unlimited one.
|
|
10
|
-
timeoutMs: options.timeoutMs ?? retry.timeoutMs ?? (idleTimeout === 0 ? 2147483647 : idleTimeout),
|
|
11
|
-
websocketConnectTimeoutMs: options.websocketConnectTimeoutMs ?? settings.getWebSocketConnectTimeoutMs(),
|
|
12
|
-
maxRetries: options.maxRetries ?? retry.maxRetries,
|
|
13
|
-
maxRetryDelayMs: options.maxRetryDelayMs ?? retry.maxRetryDelayMs,
|
|
14
|
-
transformHeaders: async (requestHeaders) => {
|
|
15
|
-
const headers = { ...attribution, ...requestHeaders };
|
|
16
|
-
return runner?.hasHandlers("before_provider_headers") ? runner.emitBeforeProviderHeaders(headers) : headers;
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=model-stream-options.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model-stream-options.js","sourceRoot":"","sources":["../../src/core/model-stream-options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAG5E,uFAAuF;AACvF,MAAM,UAAU,yBAAyB,CACxC,KAAiB,EACjB,QAAyB,EACzB,MAAmC,EACnC,UAA+B,EAAE;IAEjC,MAAM,KAAK,GAAG,QAAQ,CAAC,wBAAwB,EAAE,CAAC;IAClD,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,EAAE,CAAC;IACpD,MAAM,WAAW,GAAG,+BAA+B,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxF,OAAO;QACN,GAAG,OAAO;QACV,8EAA8E;QAC9E,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;QACjG,yBAAyB,EAAE,OAAO,CAAC,yBAAyB,IAAI,QAAQ,CAAC,4BAA4B,EAAE;QACvG,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU;QAClD,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe;QACjE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;YAC1C,MAAM,OAAO,GAAG,EAAE,GAAG,WAAW,EAAE,GAAG,cAAc,EAAE,CAAC;YACtD,OAAO,MAAM,EAAE,WAAW,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7G,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import type { Api, Model, ModelsSimpleStreamOptions, SimpleStreamOptions } from \"@earendil-works/pi-ai\";\nimport type { ExtensionRunner } from \"./extensions/runner.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Resolve application defaults once, before authentication or network work begins. */\nexport function resolveModelStreamOptions(\n\tmodel: Model<Api>,\n\tsettings: SettingsManager,\n\trunner: ExtensionRunner | undefined,\n\toptions: SimpleStreamOptions = {},\n): ModelsSimpleStreamOptions {\n\tconst retry = settings.getProviderRetrySettings();\n\tconst idleTimeout = settings.getHttpIdleTimeoutMs();\n\tconst attribution = mergeProviderAttributionHeaders(model, settings, options.sessionId);\n\treturn {\n\t\t...options,\n\t\t// Provider SDKs interpret zero as an immediate timeout, not an unlimited one.\n\t\ttimeoutMs: options.timeoutMs ?? retry.timeoutMs ?? (idleTimeout === 0 ? 2147483647 : idleTimeout),\n\t\twebsocketConnectTimeoutMs: options.websocketConnectTimeoutMs ?? settings.getWebSocketConnectTimeoutMs(),\n\t\tmaxRetries: options.maxRetries ?? retry.maxRetries,\n\t\tmaxRetryDelayMs: options.maxRetryDelayMs ?? retry.maxRetryDelayMs,\n\t\ttransformHeaders: async (requestHeaders) => {\n\t\t\tconst headers = { ...attribution, ...requestHeaders };\n\t\t\treturn runner?.hasHandlers(\"before_provider_headers\") ? runner.emitBeforeProviderHeaders(headers) : headers;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { type Component } from "@earendil-works/pi-tui";
|
|
2
|
-
export declare const TOOL_CHROME_WIDTH = 2;
|
|
3
|
-
export declare function formatElapsed(ms: number): string;
|
|
4
|
-
/** Status dot / result rail prefix wrapper for a tool call or result slot. */
|
|
5
|
-
export declare class ToolChromeComponent implements Component {
|
|
6
|
-
private component;
|
|
7
|
-
private prefix;
|
|
8
|
-
private continuationPrefix;
|
|
9
|
-
private blankLinePrefix;
|
|
10
|
-
private trimLeadingBlankLines;
|
|
11
|
-
constructor(component: Component, prefix: string, options?: {
|
|
12
|
-
trimLeadingBlankLines?: boolean;
|
|
13
|
-
continuationPrefix?: string;
|
|
14
|
-
blankLinePrefix?: string;
|
|
15
|
-
});
|
|
16
|
-
render(width: number): string[];
|
|
17
|
-
invalidate(): void;
|
|
18
|
-
}
|
|
19
|
-
/** Bounded text fallback for tools without a result renderer. */
|
|
20
|
-
export declare class FallbackResultComponent implements Component {
|
|
21
|
-
private output;
|
|
22
|
-
private expanded;
|
|
23
|
-
constructor(output: string, expanded: boolean);
|
|
24
|
-
render(width: number): string[];
|
|
25
|
-
invalidate(): void;
|
|
26
|
-
}
|
|
27
|
-
export declare function formatFallbackArgs(args: unknown): string;
|
|
28
|
-
//# sourceMappingURL=tool-chrome.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-chrome.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,wBAAwB,CAAC;AAK/E,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAInC,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,8EAA8E;AAC9E,qBAAa,mBAAoB,YAAW,SAAS;IACpD,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,qBAAqB,CAAU;gBAGtC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAO;IASzG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAc/B,UAAU,IAAI,IAAI;CAGlB;AAED,iEAAiE;AACjE,qBAAa,uBAAwB,YAAW,SAAS;IACxD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAU;gBAEd,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO;IAK7C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAU/B,UAAU,IAAI,IAAI;CAClB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAexD"}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
2
|
-
import { collapsedLinesHint } from "../../../core/tools/render-utils.js";
|
|
3
|
-
import { theme } from "../theme/theme.js";
|
|
4
|
-
import { truncateToVisualLines } from "./visual-truncate.js";
|
|
5
|
-
export const TOOL_CHROME_WIDTH = 2;
|
|
6
|
-
const FALLBACK_ARGS_WIDTH = 120;
|
|
7
|
-
const FALLBACK_RESULT_LINES = 10;
|
|
8
|
-
export function formatElapsed(ms) {
|
|
9
|
-
const roundedTenths = Math.round(ms / 100) / 10;
|
|
10
|
-
if (roundedTenths < 60)
|
|
11
|
-
return `${roundedTenths.toFixed(1)}s`;
|
|
12
|
-
const roundedSeconds = Math.round(ms / 1000);
|
|
13
|
-
const minutes = Math.floor(roundedSeconds / 60);
|
|
14
|
-
if (minutes < 60)
|
|
15
|
-
return `${minutes}m ${roundedSeconds % 60}s`;
|
|
16
|
-
return `${Math.floor(minutes / 60)}h ${minutes % 60}m ${roundedSeconds % 60}s`;
|
|
17
|
-
}
|
|
18
|
-
/** Status dot / result rail prefix wrapper for a tool call or result slot. */
|
|
19
|
-
export class ToolChromeComponent {
|
|
20
|
-
constructor(component, prefix, options = {}) {
|
|
21
|
-
this.component = component;
|
|
22
|
-
this.prefix = prefix;
|
|
23
|
-
this.continuationPrefix = options.continuationPrefix ?? " ";
|
|
24
|
-
this.blankLinePrefix = options.blankLinePrefix ?? "";
|
|
25
|
-
this.trimLeadingBlankLines = options.trimLeadingBlankLines ?? false;
|
|
26
|
-
}
|
|
27
|
-
render(width) {
|
|
28
|
-
const renderedLines = this.component.render(Math.max(1, width - TOOL_CHROME_WIDTH));
|
|
29
|
-
let start = 0;
|
|
30
|
-
if (this.trimLeadingBlankLines) {
|
|
31
|
-
while (renderedLines[start] === "")
|
|
32
|
-
start++;
|
|
33
|
-
}
|
|
34
|
-
const lines = renderedLines.slice(start);
|
|
35
|
-
if (lines.length === 0)
|
|
36
|
-
return [];
|
|
37
|
-
return lines.map((line, index) => {
|
|
38
|
-
if (index === 0)
|
|
39
|
-
return `${this.prefix}${line}`;
|
|
40
|
-
return line ? `${this.continuationPrefix}${line}` : this.blankLinePrefix;
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
invalidate() {
|
|
44
|
-
this.component.invalidate();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/** Bounded text fallback for tools without a result renderer. */
|
|
48
|
-
export class FallbackResultComponent {
|
|
49
|
-
constructor(output, expanded) {
|
|
50
|
-
this.output = output;
|
|
51
|
-
this.expanded = expanded;
|
|
52
|
-
}
|
|
53
|
-
render(width) {
|
|
54
|
-
const styledOutput = theme.fg("toolOutput", this.output);
|
|
55
|
-
if (this.expanded)
|
|
56
|
-
return new Text(styledOutput, 0, 0).render(width);
|
|
57
|
-
const preview = truncateToVisualLines(styledOutput, FALLBACK_RESULT_LINES, width);
|
|
58
|
-
if (preview.skippedCount <= 0)
|
|
59
|
-
return preview.visualLines;
|
|
60
|
-
const hint = collapsedLinesHint(theme, preview.skippedCount, "earlier");
|
|
61
|
-
return [truncateToWidth(hint, width, "…"), ...preview.visualLines];
|
|
62
|
-
}
|
|
63
|
-
invalidate() { }
|
|
64
|
-
}
|
|
65
|
-
export function formatFallbackArgs(args) {
|
|
66
|
-
if (!args || typeof args !== "object")
|
|
67
|
-
return "";
|
|
68
|
-
const entries = Object.entries(args);
|
|
69
|
-
if (entries.length === 0)
|
|
70
|
-
return "";
|
|
71
|
-
const summary = entries
|
|
72
|
-
.map(([key, value]) => {
|
|
73
|
-
try {
|
|
74
|
-
return `${key}=${JSON.stringify(value) ?? String(value)}`;
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return `${key}=${String(value)}`;
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
.join(" ")
|
|
81
|
-
.replace(/\s+/g, " ");
|
|
82
|
-
return truncateToWidth(summary, FALLBACK_ARGS_WIDTH, "...");
|
|
83
|
-
}
|
|
84
|
-
//# sourceMappingURL=tool-chrome.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-chrome.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-chrome.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { collapsedLinesHint } from \"../../../core/tools/render-utils.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { truncateToVisualLines } from \"./visual-truncate.ts\";\n\nexport const TOOL_CHROME_WIDTH = 2;\nconst FALLBACK_ARGS_WIDTH = 120;\nconst FALLBACK_RESULT_LINES = 10;\n\nexport function formatElapsed(ms: number): string {\n\tconst roundedTenths = Math.round(ms / 100) / 10;\n\tif (roundedTenths < 60) return `${roundedTenths.toFixed(1)}s`;\n\tconst roundedSeconds = Math.round(ms / 1000);\n\tconst minutes = Math.floor(roundedSeconds / 60);\n\tif (minutes < 60) return `${minutes}m ${roundedSeconds % 60}s`;\n\treturn `${Math.floor(minutes / 60)}h ${minutes % 60}m ${roundedSeconds % 60}s`;\n}\n\n/** Status dot / result rail prefix wrapper for a tool call or result slot. */\nexport class ToolChromeComponent implements Component {\n\tprivate component: Component;\n\tprivate prefix: string;\n\tprivate continuationPrefix: string;\n\tprivate blankLinePrefix: string;\n\tprivate trimLeadingBlankLines: boolean;\n\n\tconstructor(\n\t\tcomponent: Component,\n\t\tprefix: string,\n\t\toptions: { trimLeadingBlankLines?: boolean; continuationPrefix?: string; blankLinePrefix?: string } = {},\n\t) {\n\t\tthis.component = component;\n\t\tthis.prefix = prefix;\n\t\tthis.continuationPrefix = options.continuationPrefix ?? \" \";\n\t\tthis.blankLinePrefix = options.blankLinePrefix ?? \"\";\n\t\tthis.trimLeadingBlankLines = options.trimLeadingBlankLines ?? false;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst renderedLines = this.component.render(Math.max(1, width - TOOL_CHROME_WIDTH));\n\t\tlet start = 0;\n\t\tif (this.trimLeadingBlankLines) {\n\t\t\twhile (renderedLines[start] === \"\") start++;\n\t\t}\n\t\tconst lines = renderedLines.slice(start);\n\t\tif (lines.length === 0) return [];\n\t\treturn lines.map((line, index) => {\n\t\t\tif (index === 0) return `${this.prefix}${line}`;\n\t\t\treturn line ? `${this.continuationPrefix}${line}` : this.blankLinePrefix;\n\t\t});\n\t}\n\n\tinvalidate(): void {\n\t\tthis.component.invalidate();\n\t}\n}\n\n/** Bounded text fallback for tools without a result renderer. */\nexport class FallbackResultComponent implements Component {\n\tprivate output: string;\n\tprivate expanded: boolean;\n\n\tconstructor(output: string, expanded: boolean) {\n\t\tthis.output = output;\n\t\tthis.expanded = expanded;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst styledOutput = theme.fg(\"toolOutput\", this.output);\n\t\tif (this.expanded) return new Text(styledOutput, 0, 0).render(width);\n\n\t\tconst preview = truncateToVisualLines(styledOutput, FALLBACK_RESULT_LINES, width);\n\t\tif (preview.skippedCount <= 0) return preview.visualLines;\n\t\tconst hint = collapsedLinesHint(theme, preview.skippedCount, \"earlier\");\n\t\treturn [truncateToWidth(hint, width, \"…\"), ...preview.visualLines];\n\t}\n\n\tinvalidate(): void {}\n}\n\nexport function formatFallbackArgs(args: unknown): string {\n\tif (!args || typeof args !== \"object\") return \"\";\n\tconst entries = Object.entries(args);\n\tif (entries.length === 0) return \"\";\n\tconst summary = entries\n\t\t.map(([key, value]) => {\n\t\t\ttry {\n\t\t\t\treturn `${key}=${JSON.stringify(value) ?? String(value)}`;\n\t\t\t} catch {\n\t\t\t\treturn `${key}=${String(value)}`;\n\t\t\t}\n\t\t})\n\t\t.join(\" \")\n\t\t.replace(/\\s+/g, \" \");\n\treturn truncateToWidth(summary, FALLBACK_ARGS_WIDTH, \"...\");\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype Component,\n\tContainer,\n\tgetCapabilities,\n\tImage,\n\tMouseRegion,\n\tSpacer,\n\tText,\n\ttype TUI,\n\ttype TuiMouseEvent,\n} from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext, ToolRenderResultOptions } from \"../../../core/extensions/types.ts\";\nimport type { Theme } from \"../theme/theme.ts\";\n\n/**\n * What this component needs from a tool: how to draw it. It neither executes tools nor reads their\n * parameter schemas, so a definition and a bare renderer pair are equally acceptable.\n *\n * The renderer parameters are `any` on purpose: a `ToolDefinition` types them from its schema, and\n * narrowing them here would make those definitions unassignable.\n */\nexport interface ToolRenderers {\n\trenderShell?: \"default\" | \"self\";\n\ttoolGroup?: string;\n\trenderCall?: (args: any, theme: Theme, context: ToolRenderContext<any, any>) => Component;\n\trenderResult?: (\n\t\tresult: AgentToolResult<any>,\n\t\toptions: ToolRenderResultOptions,\n\t\ttheme: Theme,\n\t\tcontext: ToolRenderContext<any, any>,\n\t) => Component;\n}\n\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { FallbackResultComponent, formatElapsed, formatFallbackArgs, ToolChromeComponent } from \"./tool-chrome.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n\t/** Long-running foreground cards advertise backgrounding. Absent means no hint (e.g. hosts without background execution). */\n\tdetachHint?: {\n\t\tisDetachable(toolName: string): boolean;\n\t\t/** Current key label; empty string means unbound and hides the hint. */\n\t\tkeyLabel(): string;\n\t};\n}\n\ninterface ConvertedImage {\n\tsourceData: string;\n\tsourceMimeType: string;\n\tdata: string;\n\tmimeType: string;\n}\n\ninterface PendingImageConversion {\n\tsourceData: string;\n\tsourceMimeType: string;\n}\n\nconst PROGRESS_THRESHOLD_MS = 2000;\nconst PROGRESS_REFRESH_INTERVAL_MS = 1000;\n/** Delay before a long-running detachable card advertises backgrounding. */\nconst DETACH_HINT_DELAY_MS = 10_000;\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate selfRenderContainer: Container;\n\tprivate selfRenderHeight = 0;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolRenderers;\n\treadonly toolGroup: string | undefined;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages = new Map<number, ConvertedImage>();\n\tprivate pendingImageConversions = new Map<number, PendingImageConversion>();\n\tprivate hideComponent = false;\n\tprivate progressStartedAt?: number;\n\tprivate refreshTimer?: NodeJS.Timeout;\n\tprivate readonly detachHint?: ToolExecutionOptions[\"detachHint\"];\n\tprivate disposed = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolRenderers | ToolDefinition<any, any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.toolGroup = this.getRenderShell() === \"self\" ? undefined : this.toolDefinition?.toolGroup;\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.detachHint = options.detachHint;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.contentContainer = new Container();\n\t\tthis.selfRenderContainer = new Container();\n\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentContainer);\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\treturn this.toolDefinition?.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\treturn this.toolDefinition?.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t}\n\n\tprivate shouldRenderGenericProgress(): boolean {\n\t\treturn this.toolName === \"bash\" && this.getRenderShell() !== \"self\";\n\t}\n\n\tprivate shouldRenderDetachHint(): boolean {\n\t\treturn this.getRenderShell() !== \"self\" && this.detachHint?.isDetachable(this.toolName) === true;\n\t}\n\n\t/** The hint label, or undefined when the hint is unavailable or the key is unbound. */\n\tprivate detachHintText(): string | undefined {\n\t\tif (!this.shouldRenderDetachHint()) return undefined;\n\t\tconst key = this.detachHint?.keyLabel();\n\t\treturn key ? `Press ${key} to run in background, /bg to manage` : undefined;\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined, toolGroupSummary = false): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tif (this.disposed) return;\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t\tresult: this.result\n\t\t\t\t? {\n\t\t\t\t\t\tcontent: this.result.content as AgentToolResult<unknown>[\"content\"],\n\t\t\t\t\t\tdetails: this.result.details,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\ttoolGroupSummary,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\tconst args = formatFallbackArgs(this.args);\n\t\tconst suffix = args ? theme.fg(\"dim\", `(${args})`) : \"\";\n\t\treturn new Text(`${theme.fg(\"toolTitle\", theme.bold(this.toolName))}${suffix}`, 0, 0);\n\t}\n\n\tprivate wrapCall(component: Component): Component {\n\t\tconst color = this.isPartial ? \"warning\" : this.result?.isError ? \"error\" : \"success\";\n\t\t// Continuation lines share the result rail so the whole block reads as one\n\t\t// unit hanging off the dot instead of an indented island above a lone rail.\n\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\treturn new ToolChromeComponent(component, `${theme.fg(color, \"●\")} `, {\n\t\t\tcontinuationPrefix: rail,\n\t\t\tblankLinePrefix: theme.fg(\"dim\", \"│\"),\n\t\t});\n\t}\n\n\tprivate wrapResult(component: Component): Component {\n\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\treturn new ToolChromeComponent(component, rail, {\n\t\t\ttrimLeadingBlankLines: true,\n\t\t\tcontinuationPrefix: rail,\n\t\t\tblankLinePrefix: theme.fg(\"dim\", \"│\"),\n\t\t});\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new FallbackResultComponent(output, this.expanded);\n\t}\n\n\tprivate createResultRegion(component: Component): MouseRegion {\n\t\treturn new MouseRegion(component, (event) => {\n\t\t\tif (!this.result || event.type !== \"click\" || event.button !== \"left\") return undefined;\n\t\t\tthis.setExpanded(!this.expanded);\n\t\t\treturn { handled: true };\n\t\t});\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tif (this.disposed) return;\n\t\tthis.executionStarted = true;\n\t\tif (this.shouldRenderGenericProgress() || this.shouldRenderDetachHint()) {\n\t\t\tif (this.progressStartedAt === undefined) {\n\t\t\t\tthis.progressStartedAt = Date.now();\n\t\t\t}\n\t\t\tif (this.refreshTimer === undefined) {\n\t\t\t\tthis.refreshTimer = setInterval(() => {\n\t\t\t\t\tif (this.disposed || !this.isPartial) {\n\t\t\t\t\t\tthis.clearRefreshTimer();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.invalidate();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}, PROGRESS_REFRESH_INTERVAL_MS);\n\t\t\t\tthis.refreshTimer.unref?.();\n\t\t\t}\n\t\t}\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tprivate clearRefreshTimer(): void {\n\t\tif (this.refreshTimer) {\n\t\t\tclearInterval(this.refreshTimer);\n\t\t\tthis.refreshTimer = undefined;\n\t\t}\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tif (!isPartial) this.clearRefreshTimer();\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((content) => content.type === \"image\");\n\t\tconst sourceMatches = (\n\t\t\timage: { data?: string; mimeType?: string } | undefined,\n\t\t\tentry: PendingImageConversion | undefined,\n\t\t): boolean => image?.data === entry?.sourceData && image?.mimeType === entry?.sourceMimeType;\n\t\tfor (const [index, converted] of this.convertedImages) {\n\t\t\tif (!sourceMatches(imageBlocks[index], converted)) this.convertedImages.delete(index);\n\t\t}\n\t\tfor (const [index, pending] of this.pendingImageConversions) {\n\t\t\tif (!sourceMatches(imageBlocks[index], pending)) this.pendingImageConversions.delete(index);\n\t\t}\n\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst image = imageBlocks[i];\n\t\t\tif (!image.data || !image.mimeType || image.mimeType === \"image/png\") continue;\n\t\t\tif (sourceMatches(image, this.convertedImages.get(i))) continue;\n\t\t\tif (sourceMatches(image, this.pendingImageConversions.get(i))) continue;\n\n\t\t\tconst index = i;\n\t\t\tconst sourceData = image.data;\n\t\t\tconst sourceMimeType = image.mimeType;\n\t\t\tthis.pendingImageConversions.set(index, { sourceData, sourceMimeType });\n\t\t\tvoid convertToPng(sourceData, sourceMimeType)\n\t\t\t\t.then((converted) => {\n\t\t\t\t\tconst pending = this.pendingImageConversions.get(index);\n\t\t\t\t\tif (pending?.sourceData !== sourceData || pending.sourceMimeType !== sourceMimeType) return;\n\t\t\t\t\tthis.pendingImageConversions.delete(index);\n\t\t\t\t\tif (this.disposed) return;\n\t\t\t\t\tconst currentImage = this.result?.content.filter((content) => content.type === \"image\")[index];\n\t\t\t\t\tif (currentImage?.data !== sourceData || currentImage.mimeType !== sourceMimeType) return;\n\t\t\t\t\tif (converted) {\n\t\t\t\t\t\tthis.convertedImages.set(index, { sourceData, sourceMimeType, ...converted });\n\t\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\tconst pending = this.pendingImageConversions.get(index);\n\t\t\t\t\tif (pending?.sourceData === sourceData && pending.sourceMimeType === sourceMimeType) {\n\t\t\t\t\t\tthis.pendingImageConversions.delete(index);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\tgetFinalErrorSummary(): string | undefined {\n\t\tif (this.isPartial || !this.result?.isError) return undefined;\n\t\tconst summary = this.getTextOutput().replace(/\\s+/gu, \" \").trim();\n\t\treturn summary || undefined;\n\t}\n\n\trenderCallSummary(width: number): string[] {\n\t\tconst callRenderer = this.getCallRenderer();\n\t\tlet component: Component;\n\t\tif (!callRenderer) {\n\t\t\tcomponent = this.createCallFallback();\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tcomponent = callRenderer(this.args, theme, this.getRenderContext(undefined, true));\n\t\t\t} catch {\n\t\t\t\tcomponent = this.createCallFallback();\n\t\t\t}\n\t\t}\n\t\treturn this.wrapCall(component).render(width);\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tthis.selfRenderHeight = contentLines.length;\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\toverride handleMouse(event: TuiMouseEvent): ReturnType<Container[\"handleMouse\"]> {\n\t\tif (!this.hasRendererDefinition() || this.getRenderShell() !== \"self\") return super.handleMouse(event);\n\t\tif (event.y <= 0 || event.y > this.selfRenderHeight) return undefined;\n\t\treturn this.selfRenderContainer.handleMouse({\n\t\t\t...event,\n\t\t\ty: event.y - 1,\n\t\t\theight: this.selfRenderHeight,\n\t\t});\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tconst selfRendered = this.getRenderShell() === \"self\";\n\t\tconst renderContainer = selfRendered ? this.selfRenderContainer : this.contentContainer;\n\t\trenderContainer.clear();\n\n\t\tconst addCall = (component: Component) => {\n\t\t\trenderContainer.addChild(selfRendered ? component : this.createResultRegion(this.wrapCall(component)));\n\t\t\thasContent = true;\n\t\t};\n\t\tconst addResult = (component: Component) => {\n\t\t\trenderContainer.addChild(selfRendered ? component : this.createResultRegion(this.wrapResult(component)));\n\t\t\thasContent = true;\n\t\t};\n\n\t\tconst callRenderer = this.getCallRenderer();\n\t\tif (!callRenderer) {\n\t\t\taddCall(this.createCallFallback());\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\taddCall(component);\n\t\t\t} catch {\n\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\taddCall(this.createCallFallback());\n\t\t\t}\n\t\t}\n\n\t\tif (this.result) {\n\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\tif (!resultRenderer) {\n\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\tif (component) addResult(component);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t);\n\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\taddResult(component);\n\t\t\t\t} catch {\n\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) addResult(component);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.executionStarted && this.isPartial && this.progressStartedAt !== undefined) {\n\t\t\tconst elapsedMs = Date.now() - this.progressStartedAt;\n\t\t\tif (this.shouldRenderGenericProgress() && elapsedMs >= PROGRESS_THRESHOLD_MS) {\n\t\t\t\taddResult(new Text(theme.fg(\"muted\", `Running… (${formatElapsed(elapsedMs)})`), 0, 0));\n\t\t\t}\n\t\t\tif (elapsedMs >= DETACH_HINT_DELAY_MS) {\n\t\t\t\tconst hint = this.detachHintText();\n\t\t\t\tif (hint) addResult(new Text(theme.fg(\"dim\", hint), 0, 0));\n\t\t\t}\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst cached = this.convertedImages.get(i);\n\t\t\t\t\tconst converted =\n\t\t\t\t\t\tcached?.sourceData === img.data && cached.sourceMimeType === img.mimeType ? cached : undefined;\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.clearRefreshTimer();\n\t\t(this.rendererState as { dispose?: () => void }).dispose?.();\n\t\tthis.pendingImageConversions.clear();\n\t}\n}\n"]}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type Component } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { ToolExecutionComponent } from "./tool-execution.ts";
|
|
3
|
-
export declare class ToolGroupComponent implements Component {
|
|
4
|
-
readonly toolGroup: string;
|
|
5
|
-
private readonly tools;
|
|
6
|
-
private expanded;
|
|
7
|
-
constructor(toolGroup: string, tools?: ToolExecutionComponent[]);
|
|
8
|
-
addTool(tool: ToolExecutionComponent): void;
|
|
9
|
-
setExpanded(expanded: boolean): void;
|
|
10
|
-
setShowImages(show: boolean): void;
|
|
11
|
-
setImageWidthCells(width: number): void;
|
|
12
|
-
invalidate(): void;
|
|
13
|
-
dispose(): void;
|
|
14
|
-
render(width: number): string[];
|
|
15
|
-
private renderCollapsed;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=tool-group.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-group.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,wBAAwB,CAAC;AAGvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAElE,qBAAa,kBAAmB,YAAW,SAAS;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAS;gBAEb,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,sBAAsB,EAAO;IAOnE,OAAO,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI;IAK3C,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAOpC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAMlC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMvC,UAAU,IAAI,IAAI;IAMlB,OAAO,IAAI,IAAI;IAMf,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAW/B,OAAO,CAAC,eAAe;CAyBvB"}
|