@linxiraos/pi-tui 1.2.1 → 1.3.1
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 +245 -224
- package/README.md +36 -0
- package/THIRD-PARTY-NOTICES.txt +55 -5
- package/dist/types/app-keybindings.d.ts +18 -8
- package/dist/types/apps/git/diff-pane.d.ts +5 -0
- package/dist/types/apps/git/git-tui.d.ts +16 -2
- package/dist/types/apps/git/state.d.ts +11 -0
- package/dist/types/autocomplete.d.ts +2 -0
- package/dist/types/charts/chart-svg.d.ts +7 -13
- package/dist/types/chat/advisor-message.d.ts +4 -1
- package/dist/types/chat/assistant-message.d.ts +9 -4
- package/dist/types/chat/figure-markdown.d.ts +7 -2
- package/dist/types/chat/messages.d.ts +3 -1
- package/dist/types/chat/read-tool-group.d.ts +2 -2
- package/dist/types/chat/table-chart.d.ts +11 -15
- package/dist/types/chat/tool-execution.d.ts +32 -20
- package/dist/types/chat/user-message.d.ts +3 -2
- package/dist/types/chrome/countdown-timer.d.ts +3 -2
- package/dist/types/chrome/diff.d.ts +2 -3
- package/dist/types/chrome/status-notice.d.ts +2 -0
- package/dist/types/chrome/transcript-container.d.ts +2 -0
- package/dist/types/components/image.d.ts +2 -0
- package/dist/types/components/markdown.d.ts +49 -3
- package/dist/types/components/text.d.ts +2 -0
- package/dist/types/debug-server.d.ts +2 -0
- package/dist/types/keybinding-matchers.d.ts +6 -0
- package/dist/types/multiplexers/tmux.d.ts +1 -0
- package/dist/types/multiplexers/types.d.ts +6 -0
- package/dist/types/native/backend.d.ts +5 -4
- package/dist/types/native/blobs.d.ts +24 -12
- package/dist/types/overlays/agent-hub-projection.d.ts +10 -5
- package/dist/types/overlays/annotation-overlay.d.ts +19 -0
- package/dist/types/overlays/approval-dialog.d.ts +79 -0
- package/dist/types/overlays/ask-dialog.d.ts +11 -6
- package/dist/types/overlays/btw-history-panel.d.ts +2 -6
- package/dist/types/overlays/hook-editor.d.ts +7 -2
- package/dist/types/overlays/hook-input.d.ts +12 -4
- package/dist/types/overlays/job-tree.d.ts +50 -0
- package/dist/types/overlays/jobs-panel.d.ts +25 -11
- package/dist/types/overlays/login-dialog.d.ts +8 -3
- package/dist/types/overlays/mcp-add-wizard.d.ts +9 -1
- package/dist/types/overlays/model-browser.d.ts +6 -1
- package/dist/types/overlays/model-picker.d.ts +2 -0
- package/dist/types/overlays/pause-screen.d.ts +5 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +4 -0
- package/dist/types/overlays/report-panel.d.ts +5 -1
- package/dist/types/overlays/reset-usage-selector.d.ts +7 -5
- package/dist/types/overlays/session-account-selector.d.ts +4 -0
- package/dist/types/overlays/session-info-overlay.d.ts +7 -3
- package/dist/types/overlays/session-selector.d.ts +3 -1
- package/dist/types/overlays/usage-dashboard.d.ts +6 -6
- package/dist/types/prompt/composer.d.ts +23 -20
- package/dist/types/prompt/custom-editor.d.ts +20 -10
- package/dist/types/prompt/image-references.d.ts +22 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +1 -0
- package/dist/types/prompt/macos-spelling.d.ts +2 -1
- package/dist/types/prompt/prose-gate.d.ts +3 -0
- package/dist/types/prompt/queued-messages.d.ts +1 -1
- package/dist/types/prompt/typing-word.d.ts +25 -0
- package/dist/types/prompt/welcome.d.ts +26 -6
- package/dist/types/render/hanging-wrap.d.ts +7 -0
- package/dist/types/render/hyperlink.d.ts +2 -0
- package/dist/types/render/render-utils.d.ts +9 -1
- package/dist/types/render/utils.d.ts +1 -1
- package/dist/types/setup/scenes/splash.d.ts +6 -5
- package/dist/types/status-line/context-usage.d.ts +4 -1
- package/dist/types/status-line/host.d.ts +6 -4
- package/dist/types/status-line/startup.d.ts +6 -6
- package/dist/types/status-line/types.d.ts +3 -0
- package/dist/types/stdin-buffer.d.ts +7 -0
- package/dist/types/terminal-capabilities.d.ts +16 -1
- package/dist/types/terminal-multiplexer.d.ts +7 -0
- package/dist/types/terminal.d.ts +8 -4
- package/dist/types/theme/symbols.d.ts +1 -1
- package/dist/types/theme/theme.d.ts +11 -0
- package/dist/types/thinking.d.ts +5 -0
- package/dist/types/tmux.d.ts +39 -4
- package/dist/types/tools/ast-edit.d.ts +2 -2
- package/dist/types/tools/ast-grep.d.ts +2 -2
- package/dist/types/tools/bash.d.ts +6 -1
- package/dist/types/tools/edit.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +53 -4
- package/dist/types/tools/find.d.ts +14 -4
- package/dist/types/tools/glob.d.ts +3 -3
- package/dist/types/tools/grep.d.ts +2 -2
- package/dist/types/tools/grouped-file-output.d.ts +9 -4
- package/dist/types/tools/native-view.d.ts +1 -1
- package/dist/types/tools/read.d.ts +32 -10
- package/dist/types/tools/renderer.d.ts +2 -0
- package/dist/types/tools/task.d.ts +31 -0
- package/dist/types/tools/web-search-types.d.ts +1 -0
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/tui.d.ts +20 -3
- package/package.json +10 -10
- package/src/app-keybindings.d.ts +18 -8
- package/src/app-keybindings.ts +20 -8
- package/src/apps/autoresearch-dashboard.ts +444 -27
- package/src/apps/debug/raw-sse.ts +2 -2
- package/src/apps/git/diff-pane.ts +39 -41
- package/src/apps/git/git-tui.ts +80 -14
- package/src/apps/git/sidebar.ts +10 -1
- package/src/apps/git/state.ts +12 -0
- package/src/autocomplete.d.ts +2 -0
- package/src/autocomplete.ts +21 -19
- package/src/bracketed-paste.ts +9 -2
- package/src/charts/chart-svg.d.ts +7 -13
- package/src/charts/chart-svg.ts +19 -22
- package/src/charts/table-data.ts +17 -6
- package/src/chat/advisor-message.d.ts +4 -1
- package/src/chat/advisor-message.ts +77 -24
- package/src/chat/assistant-message.d.ts +9 -4
- package/src/chat/assistant-message.ts +127 -31
- package/src/chat/bash-execution.ts +7 -2
- package/src/chat/figure-markdown.d.ts +7 -2
- package/src/chat/figure-markdown.ts +10 -3
- package/src/chat/image-loading.ts +9 -6
- package/src/chat/messages.d.ts +3 -1
- package/src/chat/messages.ts +4 -1
- package/src/chat/read-tool-group.d.ts +2 -2
- package/src/chat/read-tool-group.ts +97 -42
- package/src/chat/svg-figure.ts +3 -1
- package/src/chat/svg-source.ts +6 -3
- package/src/chat/table-chart.d.ts +11 -15
- package/src/chat/table-chart.ts +24 -57
- package/src/chat/tool-execution.d.ts +32 -20
- package/src/chat/tool-execution.ts +103 -36
- package/src/chat/user-message.d.ts +3 -2
- package/src/chat/user-message.ts +54 -34
- package/src/chrome/countdown-timer.ts +3 -3
- package/src/chrome/diff.d.ts +2 -3
- package/src/chrome/diff.ts +4 -9
- package/src/chrome/status-notice.ts +5 -0
- package/src/chrome/transcript-container.d.ts +2 -0
- package/src/chrome/transcript-container.ts +212 -28
- package/src/components/editor.ts +12 -12
- package/src/components/image.d.ts +2 -0
- package/src/components/image.ts +54 -20
- package/src/components/markdown.d.ts +49 -3
- package/src/components/markdown.ts +482 -12
- package/src/components/settings-list.ts +2 -4
- package/src/components/text.d.ts +2 -0
- package/src/components/text.ts +11 -1
- package/src/debug-server.d.ts +2 -0
- package/src/debug-server.ts +51 -69
- package/src/hotkeys-markdown.ts +2 -0
- package/src/keybinding-matchers.d.ts +6 -0
- package/src/keybinding-matchers.ts +19 -0
- package/src/multiplexers/tmux.d.ts +1 -0
- package/src/multiplexers/tmux.ts +3 -0
- package/src/multiplexers/types.d.ts +6 -0
- package/src/multiplexers/types.ts +6 -0
- package/src/native/backend.d.ts +5 -4
- package/src/native/backend.ts +13 -5
- package/src/native/blobs.d.ts +24 -12
- package/src/native/blobs.ts +56 -7
- package/src/native/reconcile.ts +43 -21
- package/src/overlays/advisor-config.ts +259 -8
- package/src/overlays/agent-hub-projection.d.ts +10 -5
- package/src/overlays/agent-hub-projection.ts +63 -12
- package/src/overlays/annotation-overlay.ts +422 -168
- package/src/overlays/approval-dialog.ts +389 -0
- package/src/overlays/ask-dialog.ts +244 -105
- package/src/overlays/btw-history-panel.ts +208 -147
- package/src/overlays/extensions/extension-list.ts +4 -6
- package/src/overlays/hook-editor.ts +90 -32
- package/src/overlays/hook-input.ts +105 -19
- package/src/overlays/job-tree.ts +177 -0
- package/src/overlays/jobs-panel.ts +222 -142
- package/src/overlays/login-dialog.ts +201 -91
- package/src/overlays/mcp-add-wizard.ts +562 -279
- package/src/overlays/model-browser.ts +32 -7
- package/src/overlays/model-hub.ts +4 -10
- package/src/overlays/model-picker.ts +58 -21
- package/src/overlays/pause-screen.ts +81 -23
- package/src/overlays/plan-review-overlay.ts +16 -0
- package/src/overlays/plugin-selector.ts +17 -1
- package/src/overlays/queue-mode-selector.ts +10 -0
- package/src/overlays/report-panel.ts +6 -2
- package/src/overlays/reset-usage-selector.ts +130 -21
- package/src/overlays/session-account-selector.ts +36 -0
- package/src/overlays/session-info-overlay.ts +199 -76
- package/src/overlays/session-selector.ts +15 -10
- package/src/overlays/settings-selector.ts +3 -0
- package/src/overlays/show-images-selector.ts +1 -0
- package/src/overlays/snapcompact-shape-preview.ts +13 -6
- package/src/overlays/theme-selector.ts +6 -1
- package/src/overlays/thinking-selector.ts +8 -4
- package/src/overlays/tree-selector.ts +117 -2
- package/src/overlays/usage-dashboard.ts +498 -144
- package/src/prompt/composer-cache.ts +4 -1
- package/src/prompt/composer.ts +200 -74
- package/src/prompt/custom-editor.ts +168 -65
- package/src/prompt/image-references.d.ts +22 -0
- package/src/prompt/image-references.ts +79 -2
- package/src/prompt/internal-url-autocomplete.ts +1 -0
- package/src/prompt/macos-spelling.ts +28 -5
- package/src/prompt/prose-gate.ts +3 -0
- package/src/prompt/queued-messages.ts +9 -2
- package/src/prompt/tips.txt +1 -2
- package/src/prompt/typing-word.ts +59 -0
- package/src/prompt/welcome.ts +97 -45
- package/src/render/code-cell.ts +18 -5
- package/src/render/hanging-wrap.d.ts +7 -0
- package/src/render/hanging-wrap.ts +58 -0
- package/src/render/hyperlink.d.ts +2 -0
- package/src/render/hyperlink.ts +5 -0
- package/src/render/render-utils.d.ts +9 -1
- package/src/render/render-utils.ts +16 -2
- package/src/render/utils.d.ts +1 -1
- package/src/render/utils.ts +1 -1
- package/src/render/width-aware-text.ts +6 -5
- package/src/setup/scenes/splash.ts +22 -8
- package/src/status-line/component.ts +79 -11
- package/src/status-line/context-usage.ts +176 -73
- package/src/status-line/footer.ts +18 -35
- package/src/status-line/host.ts +6 -1
- package/src/status-line/segments.ts +16 -5
- package/src/status-line/startup.ts +6 -6
- package/src/status-line/types.ts +1 -0
- package/src/stdin-buffer.d.ts +7 -0
- package/src/stdin-buffer.ts +300 -62
- package/src/terminal-capabilities.d.ts +16 -1
- package/src/terminal-capabilities.ts +66 -28
- package/src/terminal-multiplexer.d.ts +7 -0
- package/src/terminal-multiplexer.ts +14 -0
- package/src/terminal.d.ts +8 -4
- package/src/terminal.ts +190 -63
- package/src/theme/symbols.d.ts +1 -1
- package/src/theme/symbols.ts +1 -0
- package/src/theme/theme-class.ts +1 -0
- package/src/theme/theme.d.ts +11 -0
- package/src/theme/theme.ts +46 -14
- package/src/thinking.d.ts +5 -0
- package/src/thinking.ts +9 -1
- package/src/tmux.d.ts +39 -4
- package/src/tmux.ts +110 -16
- package/src/tools/ask.ts +20 -9
- package/src/tools/ast-edit.d.ts +2 -2
- package/src/tools/ast-edit.ts +30 -7
- package/src/tools/ast-grep.d.ts +2 -2
- package/src/tools/ast-grep.ts +39 -35
- package/src/tools/bash.d.ts +6 -1
- package/src/tools/bash.ts +15 -9
- package/src/tools/debug.ts +2 -1
- package/src/tools/default-renderer.ts +3 -2
- package/src/tools/edit.d.ts +2 -0
- package/src/tools/edit.ts +100 -21
- package/src/tools/eval.d.ts +53 -4
- package/src/tools/eval.ts +173 -137
- package/src/tools/find.d.ts +14 -4
- package/src/tools/find.ts +71 -18
- package/src/tools/glob.d.ts +3 -3
- package/src/tools/glob.ts +51 -17
- package/src/tools/grep.d.ts +2 -2
- package/src/tools/grep.ts +99 -22
- package/src/tools/grouped-file-output.d.ts +9 -4
- package/src/tools/grouped-file-output.ts +21 -6
- package/src/tools/lsp.ts +30 -18
- package/src/tools/mcp.ts +2 -2
- package/src/tools/native-view.d.ts +1 -1
- package/src/tools/native-view.ts +2 -2
- package/src/tools/read.d.ts +32 -10
- package/src/tools/read.ts +89 -43
- package/src/tools/renderer.d.ts +2 -0
- package/src/tools/renderer.ts +2 -0
- package/src/tools/task.d.ts +31 -0
- package/src/tools/task.ts +40 -7
- package/src/tools/todo.ts +3 -2
- package/src/tools/wait.ts +16 -30
- package/src/tools/web-search-types.d.ts +1 -0
- package/src/tools/web-search-types.ts +1 -0
- package/src/tools/web-search.ts +2 -1
- package/src/tools/write.d.ts +2 -0
- package/src/tools/write.ts +36 -12
- package/src/tools/yield.ts +2 -2
- package/src/tui.d.ts +20 -3
- package/src/tui.ts +160 -43
- package/src/utils.ts +5 -3
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +0 -5
- package/src/tools/eval-format/code-mode-declarations.ts +0 -61
package/src/tools/task.ts
CHANGED
|
@@ -29,6 +29,8 @@ import {
|
|
|
29
29
|
isFeedModelBadgeEnabled,
|
|
30
30
|
pluralize,
|
|
31
31
|
previewLine,
|
|
32
|
+
clipCollapsed,
|
|
33
|
+
flattenLine,
|
|
32
34
|
previewWindowRows,
|
|
33
35
|
replaceTabs,
|
|
34
36
|
shortenEmbeddedPaths,
|
|
@@ -347,7 +349,7 @@ function renderOutputSection(
|
|
|
347
349
|
lines.push(
|
|
348
350
|
`${continuePrefix} ${theme.fg("warning", theme.status.warning)} ${theme.fg(
|
|
349
351
|
"dim",
|
|
350
|
-
|
|
352
|
+
clipCollapsed(sanitizeText(warning), 80, expanded),
|
|
351
353
|
)}`,
|
|
352
354
|
);
|
|
353
355
|
|
|
@@ -391,7 +393,7 @@ function renderOutputSection(
|
|
|
391
393
|
const outputLines = trimmedOutput.split("\n");
|
|
392
394
|
const previewCount = expanded ? maxExpanded : maxCollapsed;
|
|
393
395
|
for (const line of outputLines.slice(0, previewCount)) {
|
|
394
|
-
lines.push(`${continuePrefix} ${theme.fg("dim",
|
|
396
|
+
lines.push(`${continuePrefix} ${theme.fg("dim", clipCollapsed(replaceTabs(line), 70, expanded))}`);
|
|
395
397
|
}
|
|
396
398
|
|
|
397
399
|
if (outputLines.length > previewCount) {
|
|
@@ -444,7 +446,7 @@ function renderOutputSection(
|
|
|
444
446
|
const outputLines = trimmedOutput.split("\n");
|
|
445
447
|
const previewCount = expanded ? maxExpanded : maxCollapsed;
|
|
446
448
|
for (const line of outputLines.slice(0, previewCount)) {
|
|
447
|
-
lines.push(`${continuePrefix} ${theme.fg("dim",
|
|
449
|
+
lines.push(`${continuePrefix} ${theme.fg("dim", clipCollapsed(replaceTabs(line), 70, expanded))}`);
|
|
448
450
|
}
|
|
449
451
|
|
|
450
452
|
if (outputLines.length > previewCount) {
|
|
@@ -468,7 +470,7 @@ function renderTaskSection(
|
|
|
468
470
|
lines.push(`${continuePrefix}${theme.fg("dim", "Task")}`);
|
|
469
471
|
const taskLines = trimmed.split("\n");
|
|
470
472
|
for (const line of taskLines.slice(0, maxExpanded)) {
|
|
471
|
-
lines.push(`${continuePrefix} ${theme.fg("dim",
|
|
473
|
+
lines.push(`${continuePrefix} ${theme.fg("dim", replaceTabs(line))}`);
|
|
472
474
|
}
|
|
473
475
|
if (taskLines.length > maxExpanded) {
|
|
474
476
|
lines.push(`${continuePrefix} ${theme.fg("dim", formatMoreItems(taskLines.length - maxExpanded, "line"))}`);
|
|
@@ -1119,7 +1121,7 @@ function renderAgentResult(
|
|
|
1119
1121
|
lines.push(
|
|
1120
1122
|
`${continuePrefix}${theme.fg("error", theme.status.aborted)} ${theme.fg(
|
|
1121
1123
|
"dim",
|
|
1122
|
-
|
|
1124
|
+
clipCollapsed(flattenLine(sanitizeText(result.abortReason)), 80, expanded),
|
|
1123
1125
|
)}`,
|
|
1124
1126
|
);
|
|
1125
1127
|
}
|
|
@@ -1211,7 +1213,7 @@ function renderAgentResult(
|
|
|
1211
1213
|
lines.push(
|
|
1212
1214
|
`${continuePrefix}${theme.fg("warning", theme.status.warning)} ${theme.fg(
|
|
1213
1215
|
"dim",
|
|
1214
|
-
|
|
1216
|
+
clipCollapsed(sanitizeText(missingCompleteWarning), 80, expanded),
|
|
1215
1217
|
)}`,
|
|
1216
1218
|
);
|
|
1217
1219
|
}
|
|
@@ -1251,7 +1253,7 @@ function renderAgentResult(
|
|
|
1251
1253
|
// Error message
|
|
1252
1254
|
if (result.error && (!success || mergeFailed) && (!aborted || result.error !== result.abortReason)) {
|
|
1253
1255
|
lines.push(
|
|
1254
|
-
`${continuePrefix}${theme.fg(mergeFailed ? "warning" : "error",
|
|
1256
|
+
`${continuePrefix}${theme.fg(mergeFailed ? "warning" : "error", clipCollapsed(flattenLine(sanitizeText(result.error)), 70, expanded))}`,
|
|
1255
1257
|
);
|
|
1256
1258
|
}
|
|
1257
1259
|
|
|
@@ -2200,6 +2202,10 @@ export interface TaskItem {
|
|
|
2200
2202
|
name?: string;
|
|
2201
2203
|
/** Agent type to run this item (e.g. "scout"). Defaults to the spawn policy's default agent. */
|
|
2202
2204
|
agent?: string;
|
|
2205
|
+
/** Historical source session selected by the bundled consult agent. */
|
|
2206
|
+
sourceSession?: string;
|
|
2207
|
+
/** Optional model selector override for the historical source session. */
|
|
2208
|
+
model?: string | string[];
|
|
2203
2209
|
/** The work; required by the schema. */
|
|
2204
2210
|
task?: string;
|
|
2205
2211
|
/** How open-ended the work is; required by the schema and the child's sole `auto` thinking classification input. */
|
|
@@ -2227,6 +2233,10 @@ export interface TaskParams {
|
|
|
2227
2233
|
name?: string;
|
|
2228
2234
|
/** Agent type to spawn (flat form); omitted values resolve from the session spawn policy. */
|
|
2229
2235
|
agent?: string;
|
|
2236
|
+
/** Historical source session selected by the bundled consult agent. */
|
|
2237
|
+
sourceSession?: string;
|
|
2238
|
+
/** Optional model selector override for the historical source session. */
|
|
2239
|
+
model?: string | string[];
|
|
2230
2240
|
/** The work (flat form). */
|
|
2231
2241
|
task?: string;
|
|
2232
2242
|
/** How open-ended the work is (flat form); see {@link TaskItem.solutionSpace}. */
|
|
@@ -2497,6 +2507,29 @@ export interface SingleResult {
|
|
|
2497
2507
|
attempt: number;
|
|
2498
2508
|
errorMessage: string;
|
|
2499
2509
|
};
|
|
2510
|
+
/**
|
|
2511
|
+
* Coarse category of a non-zero exit — `usage-limit`, `auth`,
|
|
2512
|
+
* `account-policy`, `context-overflow`, `transient`, `aborted`, or
|
|
2513
|
+
* `unknown`. A parent agent reads this to tell "swap the model" (the first
|
|
2514
|
+
* three) from "fix the request" instead of parsing provider prose.
|
|
2515
|
+
*/
|
|
2516
|
+
failureClass?: "usage-limit" | "auth" | "account-policy" | "context-overflow" | "transient" | "aborted" | "unknown";
|
|
2517
|
+
/**
|
|
2518
|
+
* Other models this session could run instead (selectors accepted by the
|
|
2519
|
+
* task `model` parameter, including `@role` aliases). Empty when nothing
|
|
2520
|
+
* else is configured or every alternative is already in cooldown.
|
|
2521
|
+
*/
|
|
2522
|
+
fallbackCandidates?: string[];
|
|
2523
|
+
/**
|
|
2524
|
+
* Set when a caller-supplied `model` replaced the model this run would
|
|
2525
|
+
* otherwise have used — the audit trail of an agent-driven switch.
|
|
2526
|
+
*/
|
|
2527
|
+
modelChange?: {
|
|
2528
|
+
source: "spawn-param" | "wake-param";
|
|
2529
|
+
/** The model the run would have used without the override, when resolvable. */
|
|
2530
|
+
from?: string;
|
|
2531
|
+
to: string;
|
|
2532
|
+
};
|
|
2500
2533
|
/** Output metadata for agent:// URL integration */
|
|
2501
2534
|
outputMeta?: { lineCount: number; charCount: number };
|
|
2502
2535
|
}
|
package/src/tools/todo.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { RenderResultOptions } from "./renderer";
|
|
|
8
8
|
import type { Theme } from "../theme/theme";
|
|
9
9
|
|
|
10
10
|
import { renderStatusLine, renderTreeList } from "../render";
|
|
11
|
+
import { wrapTreeLine } from "../render/hanging-wrap";
|
|
11
12
|
import { framedToolCard } from "../render/tool-card";
|
|
12
13
|
|
|
13
14
|
import { formatErrorDetail, formatMoreItems, PREVIEW_LIMITS, pluralize, replaceTabs } from "../render/render-utils";
|
|
@@ -657,7 +658,7 @@ export const todoToolRenderer = {
|
|
|
657
658
|
matchByContent.clear();
|
|
658
659
|
};
|
|
659
660
|
|
|
660
|
-
return framedToolCard(uiTheme, () => {
|
|
661
|
+
return framedToolCard(uiTheme, ({ contentWidth }) => {
|
|
661
662
|
const { expanded, spinnerFrame } = options;
|
|
662
663
|
const multiPhase = phases.length > 1;
|
|
663
664
|
const indent = multiPhase ? " " : "";
|
|
@@ -738,7 +739,7 @@ export const todoToolRenderer = {
|
|
|
738
739
|
);
|
|
739
740
|
})();
|
|
740
741
|
for (const line of treeLines) {
|
|
741
|
-
bodyLines.push(`${indent}${line}`);
|
|
742
|
+
bodyLines.push(...(wrapTreeLine(`${indent}${line}`, contentWidth, uiTheme) ?? [`${indent}${line}`]));
|
|
742
743
|
}
|
|
743
744
|
}
|
|
744
745
|
while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
|
package/src/tools/wait.ts
CHANGED
|
@@ -589,7 +589,11 @@ export function createIrcMessageCard(
|
|
|
589
589
|
return Object.assign(component, { describe: () => described });
|
|
590
590
|
}
|
|
591
591
|
|
|
592
|
-
/**
|
|
592
|
+
/**
|
|
593
|
+
* One job row on one line: type badge, id + label, terminal-clocked duration
|
|
594
|
+
* (live while running). The job's output and errors fill the card of the call
|
|
595
|
+
* that started it (`parksAsBackground`), so the row carries no preview.
|
|
596
|
+
*/
|
|
593
597
|
function describeJob(job: JobSnapshot, isPartial: boolean): NativeNode {
|
|
594
598
|
const running = job.status === "running" && isPartial;
|
|
595
599
|
const label = job.label.trim() !== job.id ? plainText(job.label.split(/\r?\n/)[0] ?? "") : "";
|
|
@@ -606,39 +610,21 @@ function describeJob(job: JobSnapshot, isPartial: boolean): NativeNode {
|
|
|
606
610
|
: job.status === "cancelled"
|
|
607
611
|
? "warning"
|
|
608
612
|
: "accent";
|
|
609
|
-
const artifactError = job.meta?.artifactError ?? job.artifactError;
|
|
610
|
-
const preview = flattenStructuredPreview(
|
|
611
|
-
stripTaskResultEnvelope(
|
|
612
|
-
stripOutputNotice(job.errorText?.trim() || job.resultText?.trim() || "", job.meta).trim(),
|
|
613
|
-
),
|
|
614
|
-
);
|
|
615
613
|
return node(
|
|
616
|
-
"
|
|
617
|
-
{ role: "zeta.wait.job", tone },
|
|
614
|
+
"row",
|
|
615
|
+
{ role: "zeta.wait.job", tone, gap: "sm" },
|
|
618
616
|
compact([
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
tone: "accent",
|
|
628
|
-
title: "Agent's own completion estimate",
|
|
629
|
-
})
|
|
630
|
-
: undefined,
|
|
631
|
-
elapsed(job.durationMs, !running),
|
|
632
|
-
]),
|
|
633
|
-
{ gap: "sm" },
|
|
634
|
-
),
|
|
635
|
-
artifactError && text([span(formatArtifactErrorNotice(artifactError), "warning")], { wrap: "word" }),
|
|
636
|
-
preview
|
|
637
|
-
? text([span(plainText(preview), job.errorText ? "error" : "dim")], {
|
|
638
|
-
wrap: "word",
|
|
639
|
-
lines: PREVIEW_LINES_EXPANDED,
|
|
617
|
+
node("badge", { text: job.type, tone }),
|
|
618
|
+
text(spans, { truncate: "end", grow: 1 }),
|
|
619
|
+
job.status === "running" && job.completionPercent !== undefined
|
|
620
|
+
? node("progress", {
|
|
621
|
+
value: job.completionPercent / 100,
|
|
622
|
+
label: `${job.completionPercent}%`,
|
|
623
|
+
tone: "accent",
|
|
624
|
+
title: "Agent's own completion estimate",
|
|
640
625
|
})
|
|
641
626
|
: undefined,
|
|
627
|
+
elapsed(job.durationMs, !running),
|
|
642
628
|
]),
|
|
643
629
|
job.id,
|
|
644
630
|
);
|
|
@@ -25,6 +25,7 @@ export declare const SEARCH_PROVIDER_LABELS: {
|
|
|
25
25
|
readonly tavily: "Tavily";
|
|
26
26
|
readonly firecrawl: "Firecrawl";
|
|
27
27
|
readonly brave: "Brave";
|
|
28
|
+
readonly deepseek: "DeepSeek";
|
|
28
29
|
readonly kimi: "Kimi";
|
|
29
30
|
readonly synthetic: "Synthetic";
|
|
30
31
|
readonly ollama: "Ollama";
|
package/src/tools/web-search.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
PREVIEW_LIMITS,
|
|
20
20
|
replaceTabs,
|
|
21
21
|
truncateToWidth,
|
|
22
|
+
clipCollapsed,
|
|
22
23
|
} from "../render/render-utils";
|
|
23
24
|
import { tuiText, tuiTextFmt } from "../i18n";
|
|
24
25
|
import { renderStatusLine, renderTreeList, urlHyperlink } from "../render";
|
|
@@ -35,7 +36,7 @@ const MAX_COLLAPSED_ITEMS = PREVIEW_LIMITS.COLLAPSED_ITEMS;
|
|
|
35
36
|
function renderFallbackText(contentText: string, expanded: boolean, theme: Theme): Component {
|
|
36
37
|
const lines = contentText.split("\n").filter(line => line.trim());
|
|
37
38
|
const maxLines = expanded ? lines.length : 6;
|
|
38
|
-
const displayLines = lines.slice(0, maxLines).map(line =>
|
|
39
|
+
const displayLines = lines.slice(0, maxLines).map(line => clipCollapsed(line.trim(), 110, expanded));
|
|
39
40
|
const remaining = lines.length - displayLines.length;
|
|
40
41
|
|
|
41
42
|
const headerIcon = formatStatusIcon("warning", theme);
|
package/src/tools/write.d.ts
CHANGED
|
@@ -73,6 +73,8 @@ interface WriteStreamingPreviewStateCarrier {
|
|
|
73
73
|
/** Render context for the write tool: resolves an `xd://`-mounted tool so its live renderer drives device dispatch previews. */
|
|
74
74
|
export interface WriteRenderContext {
|
|
75
75
|
resolveXdevMounted?: (name: string) => XdevMountedRenderer | undefined;
|
|
76
|
+
/** Original result metadata used only for filesystem link targets. */
|
|
77
|
+
rawDetails?: unknown;
|
|
76
78
|
}
|
|
77
79
|
/** Render file writes and delegated tool-device calls. */
|
|
78
80
|
export declare const writeToolRenderer: {
|
package/src/tools/write.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { sanitizeText } from "@linxiraos/pi-utils";
|
|
2
3
|
import type { HighlightStream } from "@linxiraos/pi-natives";
|
|
3
4
|
import type { Component } from "../tui";
|
|
4
5
|
import { fencedCode } from "../components/markdown";
|
|
@@ -7,6 +8,7 @@ import { getLanguageFromPath } from "../lang-from-path";
|
|
|
7
8
|
import { createHighlightStream, highlightCode, type Theme } from "../theme/theme";
|
|
8
9
|
import { fileHyperlink, renderStatusLine } from "../render";
|
|
9
10
|
import { framedToolCard } from "../render/tool-card";
|
|
11
|
+
import { wrapPrefixedLine } from "../render/hanging-wrap";
|
|
10
12
|
import {
|
|
11
13
|
cachedRenderedString,
|
|
12
14
|
createRenderedStringCache,
|
|
@@ -162,10 +164,12 @@ function describeFigure(figure: ToolFigure | undefined): NativeNode | undefined
|
|
|
162
164
|
return { ...md(text, { role: "zeta.tool.write.figure", stream: !figure.closed }), key: "figure" };
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
/**
|
|
167
|
+
/**
|
|
168
|
+
* The written content as numbered code, highlighted by Tern from the file's path,
|
|
169
|
+
* keyed so it keeps its node as the figure above it comes and goes.
|
|
170
|
+
*/
|
|
166
171
|
function describeSource(rawPath: string, content: string): NativeNode {
|
|
167
|
-
|
|
168
|
-
return { ...code(content, { lang, numbers: true }), key: "source" };
|
|
172
|
+
return { ...code(content, { path: rawPath || undefined, numbers: true, wrap: true }), key: "source" };
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
function countLines(text: string): number {
|
|
@@ -388,6 +392,15 @@ function formatStreamingContent(
|
|
|
388
392
|
return `${bodyText}${spinner}${uiTheme.fg("dim", `… (streaming)`)}`;
|
|
389
393
|
}
|
|
390
394
|
|
|
395
|
+
function wrapWritePreviewRows(lines: string[], width: number): string[] {
|
|
396
|
+
return lines.flatMap(line => {
|
|
397
|
+
const gutter = /^(\x1b\[[0-9;]*m)( *\d+ )(\x1b\[[0-9;]*m)(.*)$/.exec(line);
|
|
398
|
+
if (!gutter) return line;
|
|
399
|
+
const prefix = `${gutter[1]}${gutter[2]}${gutter[3]}`;
|
|
400
|
+
return wrapPrefixedLine(prefix, " ".repeat(Bun.stringWidth(gutter[2]!)), gutter[4] ?? "", width);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
391
404
|
function renderContentPreview(
|
|
392
405
|
content: string,
|
|
393
406
|
expanded: boolean,
|
|
@@ -424,6 +437,8 @@ function renderContentPreview(
|
|
|
424
437
|
/** Render context for the write tool: resolves an `xd://`-mounted tool so its live renderer drives device dispatch previews. */
|
|
425
438
|
export interface WriteRenderContext {
|
|
426
439
|
resolveXdevMounted?: (name: string) => XdevMountedRenderer | undefined;
|
|
440
|
+
/** Original result metadata used only for filesystem link targets. */
|
|
441
|
+
rawDetails?: unknown;
|
|
427
442
|
}
|
|
428
443
|
|
|
429
444
|
/** Process id and operation named by the text after `proc://`. */
|
|
@@ -540,6 +555,15 @@ function describeWriteUrl(
|
|
|
540
555
|
}
|
|
541
556
|
}
|
|
542
557
|
|
|
558
|
+
function writeResolvedPath(rawDetails: unknown, fallback: string | undefined): string | undefined {
|
|
559
|
+
return rawDetails !== null &&
|
|
560
|
+
typeof rawDetails === "object" &&
|
|
561
|
+
"resolvedPath" in rawDetails &&
|
|
562
|
+
typeof rawDetails.resolvedPath === "string"
|
|
563
|
+
? rawDetails.resolvedPath
|
|
564
|
+
: fallback;
|
|
565
|
+
}
|
|
566
|
+
|
|
543
567
|
/** Native write head shared by the call and result: `Write · path · 22 lines`, executable/diagnostics chips. */
|
|
544
568
|
function writeToolHead(
|
|
545
569
|
rawPath: string,
|
|
@@ -553,7 +577,7 @@ function writeToolHead(
|
|
|
553
577
|
if (diagnostics) badges.push(diagnostics);
|
|
554
578
|
return {
|
|
555
579
|
title: "Write",
|
|
556
|
-
target: rawPath ? displayPath(rawPath) : undefined,
|
|
580
|
+
target: rawPath ? sanitizeText(displayPath(rawPath)) : undefined,
|
|
557
581
|
targetKind: "path",
|
|
558
582
|
href: fileHref(details?.resolvedPath),
|
|
559
583
|
meta: lineCount > 0 ? [`${lineCount} line${lineCount === 1 ? "" : "s"}`] : undefined,
|
|
@@ -611,7 +635,7 @@ export const writeToolRenderer = {
|
|
|
611
635
|
if (xdev.name === REPORT_ISSUE_DEVICE_NAME) return renderReportIssueDeviceCall(args.content, uiTheme);
|
|
612
636
|
return renderXdevCall(xdev.name, args.content, options, uiTheme, options.renderContext?.resolveXdevMounted);
|
|
613
637
|
}
|
|
614
|
-
const filePath = shortenPath(rawPath);
|
|
638
|
+
const filePath = sanitizeText(shortenPath(rawPath));
|
|
615
639
|
const lang = rawPath ? (getLanguageFromPath(rawPath) ?? "text") : "text";
|
|
616
640
|
const langIcon = uiTheme.fg("muted", uiTheme.getLangIcon(lang));
|
|
617
641
|
const styledPath = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
@@ -639,7 +663,7 @@ export const writeToolRenderer = {
|
|
|
639
663
|
const streamingCache = createRenderedStringCache();
|
|
640
664
|
return framedToolCard(
|
|
641
665
|
uiTheme,
|
|
642
|
-
() => {
|
|
666
|
+
({ contentWidth }) => {
|
|
643
667
|
const body = content
|
|
644
668
|
? formatStreamingContent(
|
|
645
669
|
content,
|
|
@@ -660,7 +684,7 @@ export const writeToolRenderer = {
|
|
|
660
684
|
while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
|
|
661
685
|
return {
|
|
662
686
|
header,
|
|
663
|
-
sections: bodyLines.length > 0 ? [{ content: bodyLines }] : [],
|
|
687
|
+
sections: bodyLines.length > 0 ? [{ content: wrapWritePreviewRows(bodyLines, contentWidth) }] : [],
|
|
664
688
|
phase: "pending",
|
|
665
689
|
borderColor: "borderMuted",
|
|
666
690
|
};
|
|
@@ -695,14 +719,14 @@ export const writeToolRenderer = {
|
|
|
695
719
|
}
|
|
696
720
|
const rawPath =
|
|
697
721
|
typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
698
|
-
const filePath = shortenPath(rawPath);
|
|
722
|
+
const filePath = sanitizeText(shortenPath(rawPath));
|
|
699
723
|
const fileContent = normalizeDisplayText(args?.content);
|
|
700
724
|
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
701
725
|
const langIcon = uiTheme.fg("muted", uiTheme.getLangIcon(lang));
|
|
702
726
|
// The header shows the cwd-relative path but links to the absolute path the
|
|
703
727
|
// write resolved to (args.path may be relative, which would yield a broken
|
|
704
728
|
// `file://` URI). Falls back to plain text when the result lacks a path.
|
|
705
|
-
const linkTarget = result.details?.resolvedPath;
|
|
729
|
+
const linkTarget = writeResolvedPath(options.renderContext?.rawDetails, result.details?.resolvedPath);
|
|
706
730
|
const styledPath = filePath ? uiTheme.fg("accent", filePath) : uiTheme.fg("toolOutput", "…");
|
|
707
731
|
const pathDisplay = filePath && linkTarget ? fileHyperlink(linkTarget, styledPath) : styledPath;
|
|
708
732
|
|
|
@@ -743,7 +767,7 @@ export const writeToolRenderer = {
|
|
|
743
767
|
const previewCache = createRenderedStringCache();
|
|
744
768
|
return framedToolCard(
|
|
745
769
|
uiTheme,
|
|
746
|
-
() => {
|
|
770
|
+
({ contentWidth }) => {
|
|
747
771
|
const { expanded } = options;
|
|
748
772
|
let body = renderContentPreview(fileContent, expanded, lang, uiTheme, previewCache);
|
|
749
773
|
if (isPartial && progressText) {
|
|
@@ -768,7 +792,7 @@ export const writeToolRenderer = {
|
|
|
768
792
|
while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
|
|
769
793
|
return {
|
|
770
794
|
header,
|
|
771
|
-
sections: bodyLines.length > 0 ? [{ content: bodyLines }] : [],
|
|
795
|
+
sections: bodyLines.length > 0 ? [{ content: wrapWritePreviewRows(bodyLines, contentWidth) }] : [],
|
|
772
796
|
phase: isPartial ? "partial" : "success",
|
|
773
797
|
borderColor: "borderMuted",
|
|
774
798
|
};
|
|
@@ -825,7 +849,7 @@ export const writeToolRenderer = {
|
|
|
825
849
|
const diagnostics = isPartial ? undefined : result.details?.diagnostics;
|
|
826
850
|
const tool = writeToolHead(rawPath, fileContent, {
|
|
827
851
|
madeExecutable: !isPartial && result.details?.madeExecutable === true,
|
|
828
|
-
resolvedPath: result.details?.resolvedPath,
|
|
852
|
+
resolvedPath: writeResolvedPath(options.renderContext?.rawDetails, result.details?.resolvedPath),
|
|
829
853
|
diagnostics,
|
|
830
854
|
});
|
|
831
855
|
if (result.isError) return { tool, tone: "error", body: [errorText(resultText(result))] };
|
package/src/tools/yield.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { compact, md } from "../native/describe";
|
|
|
9
9
|
import { OwnerMemo } from "../native/memo";
|
|
10
10
|
import type { NativeChild } from "../native/node";
|
|
11
11
|
import { formatOutputPaneLines, styleToolOutputLine } from "../render/output-pane";
|
|
12
|
-
import { formatExpandHint, sanitizeDisplayLines
|
|
12
|
+
import { clipCollapsed, formatExpandHint, sanitizeDisplayLines } from "../render/render-utils";
|
|
13
13
|
import type { StatusLineOptions } from "../render/status-line";
|
|
14
14
|
import { plainToolCard, type ToolCardPhase } from "../render/tool-card";
|
|
15
15
|
import type { Theme } from "../theme/theme";
|
|
@@ -134,7 +134,7 @@ function dataLines(data: unknown, expanded: boolean, width: number, theme: Theme
|
|
|
134
134
|
lines: sanitizeText(data).trimEnd().split("\n"),
|
|
135
135
|
expanded,
|
|
136
136
|
collapsedMaxLines: TEXT_ROWS_COLLAPSED,
|
|
137
|
-
styleLine: line =>
|
|
137
|
+
styleLine: line => clipCollapsed(styleToolOutputLine(line, theme), width, expanded),
|
|
138
138
|
},
|
|
139
139
|
theme,
|
|
140
140
|
).lines,
|
package/src/tui.d.ts
CHANGED
|
@@ -115,9 +115,6 @@ export interface Component {
|
|
|
115
115
|
* last time.
|
|
116
116
|
*/
|
|
117
117
|
render(width: number): readonly string[];
|
|
118
|
-
/** Inline decision panels must keep displaced settled transcript rows in
|
|
119
|
-
* native scrollback even when mounted inside a transient editor container. */
|
|
120
|
-
readonly retireDisplacedTranscript?: boolean;
|
|
121
118
|
/**
|
|
122
119
|
* Describe the component semantically for a Tern Surface Protocol
|
|
123
120
|
* terminal (see `native/node.ts`). Called instead of `render()` when the
|
|
@@ -351,6 +348,7 @@ export declare class TUI extends Container {
|
|
|
351
348
|
overlayStack: {
|
|
352
349
|
component: Component;
|
|
353
350
|
options?: OverlayOptions;
|
|
351
|
+
/** Focus restored after closing; tracks live focus changes beneath an input-less key holder. */
|
|
354
352
|
preFocus: Component | null;
|
|
355
353
|
hidden: boolean;
|
|
356
354
|
/**
|
|
@@ -458,6 +456,16 @@ export declare class TUI extends Container {
|
|
|
458
456
|
top: number;
|
|
459
457
|
length: number;
|
|
460
458
|
};
|
|
459
|
+
/**
|
|
460
|
+
* Rows of native history the last paint left on screen above a mutable
|
|
461
|
+
* viewport that reached the bottom row, or `undefined` when that paint left
|
|
462
|
+
* rows free below it (or none happened, or a destructive reset will repaint
|
|
463
|
+
* from row zero). Rows above a bottom-reaching viewport may already sit in
|
|
464
|
+
* native scrollback, which a later shrink cannot pull back down.
|
|
465
|
+
*/
|
|
466
|
+
getFilledHistoryRows(): number | undefined;
|
|
467
|
+
/** Whether native history holds rows the frame provider committed since the last destructive reset. */
|
|
468
|
+
hasProviderHistory(): boolean;
|
|
461
469
|
/**
|
|
462
470
|
* Probe for opt-in normal-buffer click capture. The provider is read every
|
|
463
471
|
* frame; while it returns true (and no fullscreen overlay owns the
|
|
@@ -507,6 +515,13 @@ export declare class TUI extends Container {
|
|
|
507
515
|
* overtaking them. No-op unless `previous` owns the held keys.
|
|
508
516
|
*/
|
|
509
517
|
replaceHeldFocus(previous: Component, next: Component): void;
|
|
518
|
+
/**
|
|
519
|
+
* Register a hook that re-enables terminal modes on every start(). A hook
|
|
520
|
+
* added while the TUI is already running (a prepaint composer starts it
|
|
521
|
+
* before the interactive mode wires its controllers) missed that start, so
|
|
522
|
+
* it runs immediately instead of waiting for a stop/start cycle that may
|
|
523
|
+
* never come.
|
|
524
|
+
*/
|
|
510
525
|
addStartListener(listener: StartListener): () => void;
|
|
511
526
|
addInputListener(listener: InputListener): () => void;
|
|
512
527
|
removeInputListener(listener: InputListener): void;
|
|
@@ -519,6 +534,8 @@ export declare class TUI extends Container {
|
|
|
519
534
|
*/
|
|
520
535
|
resetDisplay(): void;
|
|
521
536
|
requestRender(force?: boolean, options?: RenderRequestOptions): void;
|
|
537
|
+
/** Run `callback` after `delayMs` on the render scheduler's clock, unless the TUI has stopped. */
|
|
538
|
+
scheduleAfter(delayMs: number, callback: () => void): RenderTimer;
|
|
522
539
|
/**
|
|
523
540
|
* Paint a forced frame synchronously when startup must hand off an already
|
|
524
541
|
* visible component tree before further async initialization. Same as
|