@astralyn/pi 0.84.10 → 0.84.12
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 +27 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session.d.ts +62 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +395 -78
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +19 -5
- package/dist/core/compaction/compaction.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.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +44 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +5 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/background/actions.d.ts +21 -0
- package/dist/extensions/background/actions.d.ts.map +1 -0
- package/dist/extensions/background/actions.js +264 -0
- package/dist/extensions/background/actions.js.map +1 -0
- package/dist/extensions/background/constants.d.ts +24 -0
- package/dist/extensions/background/constants.d.ts.map +1 -0
- package/dist/extensions/background/constants.js +24 -0
- package/dist/extensions/background/constants.js.map +1 -0
- package/dist/extensions/background/index.d.ts +6 -115
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +38 -509
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +2 -1
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +8 -10
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/notify.d.ts +16 -0
- package/dist/extensions/background/notify.d.ts.map +1 -0
- package/dist/extensions/background/notify.js +114 -0
- package/dist/extensions/background/notify.js.map +1 -0
- package/dist/extensions/background/output-file.d.ts +58 -0
- package/dist/extensions/background/output-file.d.ts.map +1 -0
- package/dist/extensions/background/output-file.js +122 -0
- package/dist/extensions/background/output-file.js.map +1 -0
- package/dist/extensions/background/registry.d.ts +40 -72
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +71 -184
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/render.d.ts +3 -10
- package/dist/extensions/background/render.d.ts.map +1 -1
- package/dist/extensions/background/render.js +20 -60
- package/dist/extensions/background/render.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +34 -0
- package/dist/extensions/background/schema.d.ts.map +1 -0
- package/dist/extensions/background/schema.js +89 -0
- package/dist/extensions/background/schema.js.map +1 -0
- package/dist/extensions/background/task-view.d.ts +48 -0
- package/dist/extensions/background/task-view.d.ts.map +1 -0
- package/dist/extensions/background/task-view.js +90 -0
- package/dist/extensions/background/task-view.js.map +1 -0
- package/dist/extensions/background/text.d.ts +15 -0
- package/dist/extensions/background/text.d.ts.map +1 -0
- package/dist/extensions/background/text.js +31 -0
- package/dist/extensions/background/text.js.map +1 -0
- package/dist/extensions/background/types.d.ts +74 -0
- package/dist/extensions/background/types.d.ts.map +1 -0
- package/dist/extensions/background/types.js +17 -0
- package/dist/extensions/background/types.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +6 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -0
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts +3 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +27 -6
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +5 -0
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +5 -0
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +6 -391
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/constants.js +2 -1
- package/dist/extensions/subagent/constants.js.map +1 -1
- package/dist/extensions/subagent/index.js +2 -2
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts +5 -5
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +106 -36
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +2 -4
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +1 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +8 -8
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +11 -0
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +90 -79
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts.map +1 -1
- package/dist/extensions/subagent/state.js +145 -126
- package/dist/extensions/subagent/state.js.map +1 -1
- package/dist/extensions/subagent/text.d.ts.map +1 -1
- package/dist/extensions/subagent/text.js +4 -0
- package/dist/extensions/subagent/text.js.map +1 -1
- package/dist/extensions/subagent/ui/agents-dialog.d.ts +4 -0
- package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/agents-dialog.js +84 -0
- package/dist/extensions/subagent/ui/agents-dialog.js.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts +39 -0
- package/dist/extensions/subagent/ui/choice-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choice-menu.js +93 -0
- package/dist/extensions/subagent/ui/choice-menu.js.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts +47 -0
- package/dist/extensions/subagent/ui/model-picker.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-picker.js +142 -0
- package/dist/extensions/subagent/ui/model-picker.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +41 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js +98 -0
- package/dist/extensions/subagent/ui/profile-settings-menu.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +71 -58
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +6 -4
- package/dist/utils/shell.js.map +1 -1
- package/docs/bundled/extensions/subagent.md +1 -1
- package/docs/compaction.md +5 -12
- package/docs/environment-variables.md +3 -0
- package/docs/extensions.md +21 -5
- package/docs/keybindings.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +23 -0
- package/docs/settings.md +7 -0
- package/docs/terminal-setup.md +12 -0
- package/docs/usage.md +4 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +6 -6
- package/dist/core/compaction-controller.d.ts +0 -90
- package/dist/core/compaction-controller.d.ts.map +0 -1
- package/dist/core/compaction-controller.js +0 -471
- package/dist/core/compaction-controller.js.map +0 -1
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
import { Container, Text, TruncatedText } from "@earendil-works/pi-tui";
|
|
8
8
|
import { formatSize } from "../../core/tools/truncate.js";
|
|
9
9
|
import { highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
10
|
-
import {
|
|
10
|
+
import { clampWaitMs } from "./schema.js";
|
|
11
|
+
import { commandLabel, exitSuffix, statusColor, statusGlyph } from "./task-view.js";
|
|
12
|
+
import { fileNameOf, firstCommandLine, formatDuration } from "./text.js";
|
|
11
13
|
const COMMAND_PREVIEW_LIMIT = 120;
|
|
14
|
+
/** Command budget inside a notification label that also carries a description. */
|
|
15
|
+
const LABELLED_COMMAND_LIMIT = 40;
|
|
12
16
|
const NOTIFY_TAIL_LIMIT = 4000;
|
|
13
17
|
/** Cap for expanded transcript views of tool-result text (already bounded at the source). */
|
|
14
18
|
const RESULT_EXPAND_LIMIT = 4000;
|
|
@@ -41,10 +45,6 @@ export function scheduleWaitRefresh(context, pending) {
|
|
|
41
45
|
state.waitStartedAt = undefined;
|
|
42
46
|
state.waitBaselineBytes = undefined;
|
|
43
47
|
}
|
|
44
|
-
/** Basename of a path, slash-normalized — compact display of output files. */
|
|
45
|
-
export function fileNameOf(path) {
|
|
46
|
-
return path.replace(/\\/g, "/").split("/").at(-1) ?? path;
|
|
47
|
-
}
|
|
48
48
|
function bgPrompt(theme) {
|
|
49
49
|
return theme.fg("toolTitle", theme.bold("$ "));
|
|
50
50
|
}
|
|
@@ -55,48 +55,16 @@ function timeoutSuffix(timeout, theme) {
|
|
|
55
55
|
function capForTranscript(text, limit) {
|
|
56
56
|
return text.length > limit ? `…${text.slice(-limit)}` : text;
|
|
57
57
|
}
|
|
58
|
-
export function statusGlyph(status, stalled) {
|
|
59
|
-
if (stalled)
|
|
60
|
-
return "…";
|
|
61
|
-
switch (status) {
|
|
62
|
-
case "completed":
|
|
63
|
-
return "✓";
|
|
64
|
-
case "failed":
|
|
65
|
-
case "timeout":
|
|
66
|
-
return "✗";
|
|
67
|
-
case "killed":
|
|
68
|
-
return "○";
|
|
69
|
-
default:
|
|
70
|
-
return "●";
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
export function statusColor(status, stalled) {
|
|
74
|
-
if (stalled)
|
|
75
|
-
return "warning";
|
|
76
|
-
switch (status) {
|
|
77
|
-
case "completed":
|
|
78
|
-
return "success";
|
|
79
|
-
case "failed":
|
|
80
|
-
return "error";
|
|
81
|
-
case "timeout":
|
|
82
|
-
case "killed":
|
|
83
|
-
return "warning";
|
|
84
|
-
default:
|
|
85
|
-
return "accent";
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/** First command line truncated to a visible-character budget with an ellipsis. */
|
|
89
|
-
export function commandLabel(command, width) {
|
|
90
|
-
const characters = [...firstCommandLine(command)];
|
|
91
|
-
return characters.length <= width ? characters.join("") : `${characters.slice(0, Math.max(0, width - 1)).join("")}…`;
|
|
92
|
-
}
|
|
93
58
|
// ── tool call ─────────────────────────────────────────────────────────────
|
|
94
59
|
export function renderBgCall(args, theme, context, getTaskLive) {
|
|
95
60
|
switch (args.action) {
|
|
96
|
-
case "create":
|
|
97
|
-
|
|
98
|
-
|
|
61
|
+
case "create": {
|
|
62
|
+
// Arguments stream in, so `command` may not have arrived yet.
|
|
63
|
+
const command = args.command;
|
|
64
|
+
return typeof command === "string"
|
|
65
|
+
? renderCreateCall(command, args, theme, context)
|
|
99
66
|
: new Text(theme.fg("toolTitle", theme.bold("bg create")), 0, 0);
|
|
67
|
+
}
|
|
100
68
|
case "read": {
|
|
101
69
|
const mode = args.mode ?? "tail";
|
|
102
70
|
const size = args.bytes !== undefined ? ` ${formatSize(args.bytes)}` : "";
|
|
@@ -116,10 +84,6 @@ export function renderBgCall(args, theme, context, getTaskLive) {
|
|
|
116
84
|
}
|
|
117
85
|
}
|
|
118
86
|
}
|
|
119
|
-
/** Mirror the execution-side clamp so the shown window matches the real one. */
|
|
120
|
-
export function clampWaitMs(waitMs) {
|
|
121
|
-
return Math.min(BG_WAIT_MAX_MS, Math.max(BG_WAIT_MIN_MS, Math.floor(waitMs ?? BG_WAIT_DEFAULT_MS)));
|
|
122
|
-
}
|
|
123
87
|
/**
|
|
124
88
|
* Pending wait call: elapsed/wait-window and the new-output delta since the
|
|
125
89
|
* wait began, refreshed once per second by scheduleWaitRefresh until the
|
|
@@ -157,15 +121,15 @@ function renderWaitCall(args, theme, context, getTaskLive) {
|
|
|
157
121
|
}
|
|
158
122
|
return new Text(`${theme.fg("toolTitle", theme.bold("bg wait "))}${theme.fg("accent", taskId)} ${theme.fg("muted", parts.join(" · "))}`, 0, 0);
|
|
159
123
|
}
|
|
160
|
-
function renderCreateCall(args, theme, context) {
|
|
161
|
-
const lines =
|
|
124
|
+
function renderCreateCall(command, args, theme, context) {
|
|
125
|
+
const lines = command.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
162
126
|
const label = args.description ? theme.fg("muted", ` · ${args.description}`) : "";
|
|
163
127
|
const suffix = theme.fg("muted", " &") + timeoutSuffix(args.timeout, theme) + label;
|
|
164
128
|
if (context.expanded && lines.length > 1) {
|
|
165
|
-
const body = highlightCode(
|
|
129
|
+
const body = highlightCode(command, "bash").join("\n");
|
|
166
130
|
return new Text(`${bgPrompt(theme)}${body}${suffix}`, 0, 0);
|
|
167
131
|
}
|
|
168
|
-
const body = highlightCode(firstCommandLine(
|
|
132
|
+
const body = highlightCode(firstCommandLine(command), "bash").join("\n");
|
|
169
133
|
if (lines.length > 1) {
|
|
170
134
|
const hidden = lines.length - 1;
|
|
171
135
|
const more = theme.fg("muted", ` (+${hidden} line${hidden === 1 ? "" : "s"})`);
|
|
@@ -209,7 +173,7 @@ function resultSummaryLine(details, theme) {
|
|
|
209
173
|
if (details.timedOut) {
|
|
210
174
|
return `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg("accent", details.taskId)}${theme.fg("muted", ` still running · waited ${formatDuration(details.waitedMs)} · ${formatSize(details.totalBytes)}`)}`;
|
|
211
175
|
}
|
|
212
|
-
const exit = details.exitCode
|
|
176
|
+
const exit = exitSuffix(details.exitCode, ", ");
|
|
213
177
|
return `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg("accent", details.taskId)}${theme.fg("muted", ` ${details.status}${exit} · waited ${formatDuration(details.waitedMs)} · +${formatSize(details.deltaBytes)}`)}`;
|
|
214
178
|
}
|
|
215
179
|
case "kill":
|
|
@@ -224,19 +188,15 @@ function resultSummaryLine(details, theme) {
|
|
|
224
188
|
/** One-line summary of a finished task, shared by the notification renderer. */
|
|
225
189
|
function taskSummaryLine(details, theme) {
|
|
226
190
|
const runtime = formatDuration(details.runtimeMs);
|
|
227
|
-
const
|
|
191
|
+
const label = details.description
|
|
192
|
+
? `${details.description} (${commandLabel(details.command, LABELLED_COMMAND_LIMIT)})`
|
|
193
|
+
: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);
|
|
228
194
|
if (details.stalled) {
|
|
229
195
|
const glyph = theme.fg("warning", "…");
|
|
230
|
-
const label = details.description
|
|
231
|
-
? `${details.description} (${commandLabel(details.command, 40)})`
|
|
232
|
-
: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);
|
|
233
196
|
return `${glyph} ${theme.fg("accent", details.taskId)} ${label} ${theme.fg("muted", `— waiting for input (${runtime})`)}`;
|
|
234
197
|
}
|
|
235
|
-
const outcome = theme.fg(statusColor(details.status), `${details.status}${
|
|
198
|
+
const outcome = theme.fg(statusColor(details.status), `${details.status}${exitSuffix(details.exitCode, ", ")} in ${runtime}`);
|
|
236
199
|
const glyph = theme.fg(statusColor(details.status), statusGlyph(details.status));
|
|
237
|
-
const label = details.description
|
|
238
|
-
? `${details.description} (${commandLabel(details.command, 40)})`
|
|
239
|
-
: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);
|
|
240
200
|
return `${glyph} ${theme.fg("accent", details.taskId)} ${label} ${theme.fg("muted", `— ${outcome}`)}`;
|
|
241
201
|
}
|
|
242
202
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/background/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Transcript rendering for the background extension: the single bg tool's\n * call/result rows (dispatched on action) and the completion-notification\n * message. Style follows the built-in bash presentation: a `$` prompt row\n * with an `&` marker for the background call.\n */\n\nimport { type Component, Container, Text, TruncatedText } from \"@earendil-works/pi-tui\";\nimport type {\n\tAgentToolResult,\n\tMessageRenderOptions,\n\tToolRenderContext,\n\tToolRenderResultOptions,\n} from \"../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../core/messages.ts\";\nimport { formatSize } from \"../../core/tools/truncate.ts\";\nimport { highlightCode, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { BgCreateInput, BgDetails, BgInput, BgNotificationDetails } from \"./index.ts\";\nimport {\n\tBG_WAIT_DEFAULT_MS,\n\tBG_WAIT_MAX_MS,\n\tBG_WAIT_MIN_MS,\n\ttype BgTaskStatus,\n\tfirstCommandLine,\n\tformatDuration,\n} from \"./registry.ts\";\n\nconst COMMAND_PREVIEW_LIMIT = 120;\nconst NOTIFY_TAIL_LIMIT = 4000;\n/** Cap for expanded transcript views of tool-result text (already bounded at the source). */\nconst RESULT_EXPAND_LIMIT = 4000;\n/** Live pending-wait line refresh cadence; the first settled render clears the timer. */\nconst WAIT_REFRESH_MS = 1000;\n\n/** Live peek at a waited-on task, fed from the registry by the call renderer. */\nexport interface BgTaskLive {\n\tstatus: BgTaskStatus;\n\toutputBytes: number;\n}\n\nexport type WaitLiveProbe = (taskId: string) => BgTaskLive | undefined;\n\n/** Per-call live-refresh state owned by the shell's render context. */\nexport interface BgRenderState {\n\trefreshTimer?: ReturnType<typeof setTimeout>;\n\t/** First pending render of a wait call; anchors the elapsed display. */\n\twaitStartedAt?: number;\n\t/** outputBytes snapshot at wait start; anchors the \"+new output\" display. */\n\twaitBaselineBytes?: number;\n}\n\n/**\n * Arm a one-shot 1s refresh while a wait call is pending, clear it once\n * settled. The timer fires → context.invalidate() → renderCall re-runs →\n * re-arms, so at most one armed timer exists per tool row. Unref'd: it can\n * never hold the process open.\n */\nexport function scheduleWaitRefresh(context: ToolRenderContext<BgRenderState>, pending: boolean): void {\n\tconst state = context.state;\n\tif (state === undefined) return; // Standalone render without shell state: nothing to schedule.\n\tif (pending) {\n\t\tif (state.refreshTimer === undefined) {\n\t\t\tstate.refreshTimer = setTimeout(() => {\n\t\t\t\tstate.refreshTimer = undefined;\n\t\t\t\tcontext.invalidate();\n\t\t\t}, WAIT_REFRESH_MS);\n\t\t\tstate.refreshTimer.unref?.();\n\t\t}\n\t\treturn;\n\t}\n\tif (state.refreshTimer !== undefined) {\n\t\tclearTimeout(state.refreshTimer);\n\t\tstate.refreshTimer = undefined;\n\t}\n\tstate.waitStartedAt = undefined;\n\tstate.waitBaselineBytes = undefined;\n}\n\n/** Basename of a path, slash-normalized — compact display of output files. */\nexport function fileNameOf(path: string): string {\n\treturn path.replace(/\\\\/g, \"/\").split(\"/\").at(-1) ?? path;\n}\n\nfunction bgPrompt(theme: Theme): string {\n\treturn theme.fg(\"toolTitle\", theme.bold(\"$ \"));\n}\n\nfunction timeoutSuffix(timeout: number | undefined, theme: Theme): string {\n\treturn timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n}\n\n/** Keep the END of oversized text — that is where the outcome lives. */\nfunction capForTranscript(text: string, limit: number): string {\n\treturn text.length > limit ? `…${text.slice(-limit)}` : text;\n}\n\nexport function statusGlyph(status: BgTaskStatus, stalled?: boolean): string {\n\tif (stalled) return \"…\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"✓\";\n\t\tcase \"failed\":\n\t\tcase \"timeout\":\n\t\t\treturn \"✗\";\n\t\tcase \"killed\":\n\t\t\treturn \"○\";\n\t\tdefault:\n\t\t\treturn \"●\";\n\t}\n}\n\nexport function statusColor(status: BgTaskStatus, stalled?: boolean): \"success\" | \"error\" | \"warning\" | \"accent\" {\n\tif (stalled) return \"warning\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"success\";\n\t\tcase \"failed\":\n\t\t\treturn \"error\";\n\t\tcase \"timeout\":\n\t\tcase \"killed\":\n\t\t\treturn \"warning\";\n\t\tdefault:\n\t\t\treturn \"accent\";\n\t}\n}\n\n/** First command line truncated to a visible-character budget with an ellipsis. */\nexport function commandLabel(command: string, width: number): string {\n\tconst characters = [...firstCommandLine(command)];\n\treturn characters.length <= width ? characters.join(\"\") : `${characters.slice(0, Math.max(0, width - 1)).join(\"\")}…`;\n}\n\n// ── tool call ─────────────────────────────────────────────────────────────\n\nexport function renderBgCall(\n\targs: BgInput,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n\tgetTaskLive?: WaitLiveProbe,\n): Component {\n\tswitch (args.action) {\n\t\tcase \"create\":\n\t\t\treturn typeof args.command === \"string\"\n\t\t\t\t? renderCreateCall(args as BgCreateInput, theme, context)\n\t\t\t\t: new Text(theme.fg(\"toolTitle\", theme.bold(\"bg create\")), 0, 0);\n\t\tcase \"read\": {\n\t\t\tconst mode = args.mode ?? \"tail\";\n\t\t\tconst size = args.bytes !== undefined ? ` ${formatSize(args.bytes)}` : \"\";\n\t\t\treturn new Text(\n\t\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg read \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}${theme.fg(\"muted\", ` ${mode}${size}`)}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\tcase \"wait\":\n\t\t\treturn renderWaitCall(args, theme, context, getTaskLive);\n\t\tcase \"kill\":\n\t\t\treturn new Text(\n\t\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg kill \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\tcase \"list\":\n\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(\"bg list\")), 0, 0);\n\t\tdefault: {\n\t\t\t// Tool arguments arrive incrementally while the model is still emitting\n\t\t\t// JSON. Keep the call row renderable until `action` becomes valid.\n\t\t\tconst action = typeof args.action === \"string\" ? ` ${theme.fg(\"dim\", args.action)}` : \"\";\n\t\t\treturn new Text(`${theme.fg(\"toolTitle\", theme.bold(\"bg\"))}${action}`, 0, 0);\n\t\t}\n\t}\n}\n\n/** Mirror the execution-side clamp so the shown window matches the real one. */\nexport function clampWaitMs(waitMs: number | undefined): number {\n\treturn Math.min(BG_WAIT_MAX_MS, Math.max(BG_WAIT_MIN_MS, Math.floor(waitMs ?? BG_WAIT_DEFAULT_MS)));\n}\n\n/**\n * Pending wait call: elapsed/wait-window and the new-output delta since the\n * wait began, refreshed once per second by scheduleWaitRefresh until the\n * result settles and takes over the row.\n */\nfunction renderWaitCall(\n\targs: BgInput,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n\tgetTaskLive: WaitLiveProbe | undefined,\n): Component {\n\tconst taskId = typeof args.taskId === \"string\" ? args.taskId.trim() : \"\";\n\tconst live = getTaskLive !== undefined && taskId ? getTaskLive(taskId) : undefined;\n\t// isPartial alone means \"not settled\", which also covers argument streaming\n\t// and replayed history rows that never settle; executionStarted narrows it to\n\t// a call that is actually running. The live display also needs shell-owned\n\t// state; without it (standalone renders) fall back to the static line.\n\tconst pending =\n\t\tcontext.executionStarted === true &&\n\t\tcontext.isPartial === true &&\n\t\tcontext.state !== undefined &&\n\t\ttaskId.length > 0;\n\tscheduleWaitRefresh(context, pending);\n\tif (!pending) {\n\t\tconst ms = args.waitMs !== undefined ? ` ${formatDuration(clampWaitMs(args.waitMs))}` : \"\";\n\t\treturn new Text(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg wait \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}${theme.fg(\"muted\", ms)}`,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t}\n\tconst state = context.state;\n\tif (state.waitStartedAt === undefined) state.waitStartedAt = Date.now();\n\tconst startedAt = state.waitStartedAt;\n\tlet liveBase: number | undefined;\n\tif (live) {\n\t\tif (state.waitBaselineBytes === undefined) state.waitBaselineBytes = live.outputBytes;\n\t\tliveBase = state.waitBaselineBytes;\n\t}\n\tconst parts = [`waiting ${formatDuration(Date.now() - startedAt)}/${formatDuration(clampWaitMs(args.waitMs))}`];\n\tif (live && live.status === \"running\" && liveBase !== undefined && live.outputBytes > liveBase) {\n\t\tparts.push(`+${formatSize(live.outputBytes - liveBase)} new output`);\n\t}\n\treturn new Text(\n\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg wait \"))}${theme.fg(\"accent\", taskId)} ${theme.fg(\"muted\", parts.join(\" · \"))}`,\n\t\t0,\n\t\t0,\n\t);\n}\n\nfunction renderCreateCall(args: BgCreateInput, theme: Theme, context: ToolRenderContext): Component {\n\tconst lines = args.command.split(/\\r?\\n/).filter((line) => line.trim().length > 0);\n\tconst label = args.description ? theme.fg(\"muted\", ` · ${args.description}`) : \"\";\n\tconst suffix = theme.fg(\"muted\", \" &\") + timeoutSuffix(args.timeout, theme) + label;\n\tif (context.expanded && lines.length > 1) {\n\t\tconst body = highlightCode(args.command, \"bash\").join(\"\\n\");\n\t\treturn new Text(`${bgPrompt(theme)}${body}${suffix}`, 0, 0);\n\t}\n\tconst body = highlightCode(firstCommandLine(args.command), \"bash\").join(\"\\n\");\n\tif (lines.length > 1) {\n\t\tconst hidden = lines.length - 1;\n\t\tconst more = theme.fg(\"muted\", ` (+${hidden} line${hidden === 1 ? \"\" : \"s\"})`);\n\t\treturn new Text(`${bgPrompt(theme)}${body}${suffix}${more}`, 0, 0);\n\t}\n\treturn new Text(`${bgPrompt(theme)}${body}${suffix}`, 0, 0);\n}\n\n// ── tool result ───────────────────────────────────────────────────────────\n\nexport function renderBgResult(\n\tresult: AgentToolResult<BgDetails | undefined>,\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n): Component {\n\t// bg results are always settled today; clear defensively so no live-refresh\n\t// timer can outlive its row if a host ever streams partial results.\n\tif (context.args?.action === \"wait\" && !options.isPartial) scheduleWaitRefresh(context, false);\n\tconst details = result.details;\n\tif (context.isError || !details) {\n\t\tconst text = result.content.find((part) => part.type === \"text\")?.text ?? \"\";\n\t\treturn new Text(theme.fg(\"toolOutput\", text.trimEnd()), 0, 0);\n\t}\n\n\tconst container = new Container();\n\tcontainer.addChild(new TruncatedText(resultSummaryLine(details, theme), 1, 0));\n\tif (options.expanded) {\n\t\tconst text = result.content.find((part) => part.type === \"text\")?.text ?? \"\";\n\t\tcontainer.addChild(new Text(\"\", 0, 0));\n\t\tcontainer.addChild(new Text(theme.fg(\"toolOutput\", capForTranscript(text, RESULT_EXPAND_LIMIT).trimEnd()), 1, 0));\n\t}\n\treturn container;\n}\n\nfunction resultSummaryLine(details: BgDetails, theme: Theme): string {\n\tswitch (details.action) {\n\t\tcase \"create\": {\n\t\t\tconst label = details.description ? ` (${details.description})` : \"\";\n\t\t\treturn `${theme.fg(\"muted\", \"→ task \")}${theme.fg(\"accent\", `${details.taskId}${label}`)}${theme.fg(\"muted\", ` started · ${details.outputPath}`)}`;\n\t\t}\n\t\tcase \"read\": {\n\t\t\tconst size =\n\t\t\t\tdetails.sliceBytes !== details.totalBytes\n\t\t\t\t\t? `${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`\n\t\t\t\t\t: formatSize(details.totalBytes);\n\t\t\treturn `${theme.fg(\"muted\", \"→ \")}${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` ${size} · ${details.outputPath}`)}`;\n\t\t}\n\t\tcase \"wait\": {\n\t\t\tif (details.timedOut) {\n\t\t\t\treturn `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` still running · waited ${formatDuration(details.waitedMs)} · ${formatSize(details.totalBytes)}`)}`;\n\t\t\t}\n\t\t\tconst exit = details.exitCode !== undefined && details.exitCode !== null ? `, exit ${details.exitCode}` : \"\";\n\t\t\treturn `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` ${details.status}${exit} · waited ${formatDuration(details.waitedMs)} · +${formatSize(details.deltaBytes)}`)}`;\n\t\t}\n\t\tcase \"kill\":\n\t\t\treturn `${theme.fg(statusColor(\"killed\"), statusGlyph(\"killed\"))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", \" stopped\")}`;\n\t\tcase \"list\": {\n\t\t\tconst hidden = details.hidden > 0 ? ` · ${details.hidden} more finished` : \"\";\n\t\t\treturn theme.fg(\"muted\", `${details.running} running · ${details.finished} finished${hidden}`);\n\t\t}\n\t}\n}\n\n// ── completion notification ───────────────────────────────────────────────\n\n/** One-line summary of a finished task, shared by the notification renderer. */\nfunction taskSummaryLine(details: BgNotificationDetails, theme: Theme): string {\n\tconst runtime = formatDuration(details.runtimeMs);\n\tconst exit = details.exitCode !== undefined && details.exitCode !== null ? `, exit ${details.exitCode}` : \"\";\n\tif (details.stalled) {\n\t\tconst glyph = theme.fg(\"warning\", \"…\");\n\t\tconst label = details.description\n\t\t\t? `${details.description} (${commandLabel(details.command, 40)})`\n\t\t\t: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);\n\t\treturn `${glyph} ${theme.fg(\"accent\", details.taskId)} ${label} ${theme.fg(\"muted\", `— waiting for input (${runtime})`)}`;\n\t}\n\tconst outcome = theme.fg(statusColor(details.status), `${details.status}${exit} in ${runtime}`);\n\tconst glyph = theme.fg(statusColor(details.status), statusGlyph(details.status));\n\tconst label = details.description\n\t\t? `${details.description} (${commandLabel(details.command, 40)})`\n\t\t: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);\n\treturn `${glyph} ${theme.fg(\"accent\", details.taskId)} ${label} ${theme.fg(\"muted\", `— ${outcome}`)}`;\n}\n\n/**\n * Collapsed: status glyph, task id, label, and outcome on one line, output\n * path below. Expanded adds the embedded output tail. Returns undefined for\n * malformed details so the default custom-message rendering takes over.\n */\nexport function renderBackgroundNotification(\n\tmessage: CustomMessage<BgNotificationDetails>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component | undefined {\n\tconst details = message.details;\n\tif (!details || typeof details.taskId !== \"string\") return undefined;\n\n\tconst container = new Container();\n\tcontainer.addChild(new TruncatedText(taskSummaryLine(details, theme), 1, 0));\n\t// Collapsed keeps the row compact with the file name; the full path\n\t// (model-relevant, human-rarely) shows when expanded.\n\tconst shownPath = options.expanded ? details.outputPath : fileNameOf(details.outputPath);\n\tcontainer.addChild(new Text(theme.fg(\"muted\", shownPath), 1, 0));\n\n\tif (details.tailError) {\n\t\tcontainer.addChild(new Text(theme.fg(\"error\", `Output unavailable: ${details.tailError}`), 1, 0));\n\t} else if (options.expanded && details.tailText) {\n\t\tcontainer.addChild(new Text(\"\", 0, 0));\n\t\tconst tail = capForTranscript(details.tailText, NOTIFY_TAIL_LIMIT);\n\t\tconst truncatedNote = details.tailTruncated\n\t\t\t? `\\n[showing tail of ${formatSize(details.totalBytes)} bytes; full output: ${details.outputPath}]`\n\t\t\t: \"\";\n\t\tcontainer.addChild(\n\t\t\tnew Text(`${theme.fg(\"toolOutput\", tail.trimEnd())}${theme.fg(\"muted\", truncatedNote)}`, 1, 0),\n\t\t);\n\t}\n\tif (details.stalled && options.expanded) {\n\t\tcontainer.addChild(\n\t\t\tnew Text(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"warning\",\n\t\t\t\t\t\"Blocked on interactive input — kill (bg action kill) and re-run with piped input or a non-interactive flag.\",\n\t\t\t\t),\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\treturn container;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/background/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Transcript rendering for the background extension: the single bg tool's\n * call/result rows (dispatched on action) and the completion-notification\n * message. Style follows the built-in bash presentation: a `$` prompt row\n * with an `&` marker for the background call.\n */\n\nimport { type Component, Container, Text, TruncatedText } from \"@earendil-works/pi-tui\";\nimport type {\n\tAgentToolResult,\n\tMessageRenderOptions,\n\tToolRenderContext,\n\tToolRenderResultOptions,\n} from \"../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../core/messages.ts\";\nimport { formatSize } from \"../../core/tools/truncate.ts\";\nimport { highlightCode, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { BgTaskStatus } from \"./registry.ts\";\nimport { type BgInput, clampWaitMs } from \"./schema.ts\";\nimport { commandLabel, exitSuffix, statusColor, statusGlyph } from \"./task-view.ts\";\nimport { fileNameOf, firstCommandLine, formatDuration } from \"./text.ts\";\nimport type { BgDetails, BgNotificationDetails } from \"./types.ts\";\n\nconst COMMAND_PREVIEW_LIMIT = 120;\n/** Command budget inside a notification label that also carries a description. */\nconst LABELLED_COMMAND_LIMIT = 40;\nconst NOTIFY_TAIL_LIMIT = 4000;\n/** Cap for expanded transcript views of tool-result text (already bounded at the source). */\nconst RESULT_EXPAND_LIMIT = 4000;\n/** Live pending-wait line refresh cadence; the first settled render clears the timer. */\nconst WAIT_REFRESH_MS = 1000;\n\n/** Live peek at a waited-on task, fed from the registry by the call renderer. */\nexport interface BgTaskLive {\n\tstatus: BgTaskStatus;\n\toutputBytes: number;\n}\n\nexport type WaitLiveProbe = (taskId: string) => BgTaskLive | undefined;\n\n/** Per-call live-refresh state owned by the shell's render context. */\nexport interface BgRenderState {\n\trefreshTimer?: ReturnType<typeof setTimeout>;\n\t/** First pending render of a wait call; anchors the elapsed display. */\n\twaitStartedAt?: number;\n\t/** outputBytes snapshot at wait start; anchors the \"+new output\" display. */\n\twaitBaselineBytes?: number;\n}\n\n/**\n * Arm a one-shot 1s refresh while a wait call is pending, clear it once\n * settled. The timer fires → context.invalidate() → renderCall re-runs →\n * re-arms, so at most one armed timer exists per tool row. Unref'd: it can\n * never hold the process open.\n */\nexport function scheduleWaitRefresh(context: ToolRenderContext<BgRenderState>, pending: boolean): void {\n\tconst state = context.state;\n\tif (state === undefined) return; // Standalone render without shell state: nothing to schedule.\n\tif (pending) {\n\t\tif (state.refreshTimer === undefined) {\n\t\t\tstate.refreshTimer = setTimeout(() => {\n\t\t\t\tstate.refreshTimer = undefined;\n\t\t\t\tcontext.invalidate();\n\t\t\t}, WAIT_REFRESH_MS);\n\t\t\tstate.refreshTimer.unref?.();\n\t\t}\n\t\treturn;\n\t}\n\tif (state.refreshTimer !== undefined) {\n\t\tclearTimeout(state.refreshTimer);\n\t\tstate.refreshTimer = undefined;\n\t}\n\tstate.waitStartedAt = undefined;\n\tstate.waitBaselineBytes = undefined;\n}\n\nfunction bgPrompt(theme: Theme): string {\n\treturn theme.fg(\"toolTitle\", theme.bold(\"$ \"));\n}\n\nfunction timeoutSuffix(timeout: number | undefined, theme: Theme): string {\n\treturn timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n}\n\n/** Keep the END of oversized text — that is where the outcome lives. */\nfunction capForTranscript(text: string, limit: number): string {\n\treturn text.length > limit ? `…${text.slice(-limit)}` : text;\n}\n\n// ── tool call ─────────────────────────────────────────────────────────────\n\nexport function renderBgCall(\n\targs: BgInput,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n\tgetTaskLive?: WaitLiveProbe,\n): Component {\n\tswitch (args.action) {\n\t\tcase \"create\": {\n\t\t\t// Arguments stream in, so `command` may not have arrived yet.\n\t\t\tconst command = args.command;\n\t\t\treturn typeof command === \"string\"\n\t\t\t\t? renderCreateCall(command, args, theme, context)\n\t\t\t\t: new Text(theme.fg(\"toolTitle\", theme.bold(\"bg create\")), 0, 0);\n\t\t}\n\t\tcase \"read\": {\n\t\t\tconst mode = args.mode ?? \"tail\";\n\t\t\tconst size = args.bytes !== undefined ? ` ${formatSize(args.bytes)}` : \"\";\n\t\t\treturn new Text(\n\t\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg read \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}${theme.fg(\"muted\", ` ${mode}${size}`)}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\tcase \"wait\":\n\t\t\treturn renderWaitCall(args, theme, context, getTaskLive);\n\t\tcase \"kill\":\n\t\t\treturn new Text(\n\t\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg kill \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\tcase \"list\":\n\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(\"bg list\")), 0, 0);\n\t\tdefault: {\n\t\t\t// Tool arguments arrive incrementally while the model is still emitting\n\t\t\t// JSON. Keep the call row renderable until `action` becomes valid.\n\t\t\tconst action = typeof args.action === \"string\" ? ` ${theme.fg(\"dim\", args.action)}` : \"\";\n\t\t\treturn new Text(`${theme.fg(\"toolTitle\", theme.bold(\"bg\"))}${action}`, 0, 0);\n\t\t}\n\t}\n}\n\n/**\n * Pending wait call: elapsed/wait-window and the new-output delta since the\n * wait began, refreshed once per second by scheduleWaitRefresh until the\n * result settles and takes over the row.\n */\nfunction renderWaitCall(\n\targs: BgInput,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n\tgetTaskLive: WaitLiveProbe | undefined,\n): Component {\n\tconst taskId = typeof args.taskId === \"string\" ? args.taskId.trim() : \"\";\n\tconst live = getTaskLive !== undefined && taskId ? getTaskLive(taskId) : undefined;\n\t// isPartial alone means \"not settled\", which also covers argument streaming\n\t// and replayed history rows that never settle; executionStarted narrows it to\n\t// a call that is actually running. The live display also needs shell-owned\n\t// state; without it (standalone renders) fall back to the static line.\n\tconst pending =\n\t\tcontext.executionStarted === true &&\n\t\tcontext.isPartial === true &&\n\t\tcontext.state !== undefined &&\n\t\ttaskId.length > 0;\n\tscheduleWaitRefresh(context, pending);\n\tif (!pending) {\n\t\tconst ms = args.waitMs !== undefined ? ` ${formatDuration(clampWaitMs(args.waitMs))}` : \"\";\n\t\treturn new Text(\n\t\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg wait \"))}${theme.fg(\"accent\", args.taskId ?? \"\")}${theme.fg(\"muted\", ms)}`,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t}\n\tconst state = context.state;\n\tif (state.waitStartedAt === undefined) state.waitStartedAt = Date.now();\n\tconst startedAt = state.waitStartedAt;\n\tlet liveBase: number | undefined;\n\tif (live) {\n\t\tif (state.waitBaselineBytes === undefined) state.waitBaselineBytes = live.outputBytes;\n\t\tliveBase = state.waitBaselineBytes;\n\t}\n\tconst parts = [`waiting ${formatDuration(Date.now() - startedAt)}/${formatDuration(clampWaitMs(args.waitMs))}`];\n\tif (live && live.status === \"running\" && liveBase !== undefined && live.outputBytes > liveBase) {\n\t\tparts.push(`+${formatSize(live.outputBytes - liveBase)} new output`);\n\t}\n\treturn new Text(\n\t\t`${theme.fg(\"toolTitle\", theme.bold(\"bg wait \"))}${theme.fg(\"accent\", taskId)} ${theme.fg(\"muted\", parts.join(\" · \"))}`,\n\t\t0,\n\t\t0,\n\t);\n}\n\nfunction renderCreateCall(command: string, args: BgInput, theme: Theme, context: ToolRenderContext): Component {\n\tconst lines = command.split(/\\r?\\n/).filter((line) => line.trim().length > 0);\n\tconst label = args.description ? theme.fg(\"muted\", ` · ${args.description}`) : \"\";\n\tconst suffix = theme.fg(\"muted\", \" &\") + timeoutSuffix(args.timeout, theme) + label;\n\tif (context.expanded && lines.length > 1) {\n\t\tconst body = highlightCode(command, \"bash\").join(\"\\n\");\n\t\treturn new Text(`${bgPrompt(theme)}${body}${suffix}`, 0, 0);\n\t}\n\tconst body = highlightCode(firstCommandLine(command), \"bash\").join(\"\\n\");\n\tif (lines.length > 1) {\n\t\tconst hidden = lines.length - 1;\n\t\tconst more = theme.fg(\"muted\", ` (+${hidden} line${hidden === 1 ? \"\" : \"s\"})`);\n\t\treturn new Text(`${bgPrompt(theme)}${body}${suffix}${more}`, 0, 0);\n\t}\n\treturn new Text(`${bgPrompt(theme)}${body}${suffix}`, 0, 0);\n}\n\n// ── tool result ───────────────────────────────────────────────────────────\n\nexport function renderBgResult(\n\tresult: AgentToolResult<BgDetails | undefined>,\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tcontext: ToolRenderContext<BgRenderState>,\n): Component {\n\t// bg results are always settled today; clear defensively so no live-refresh\n\t// timer can outlive its row if a host ever streams partial results.\n\tif (context.args?.action === \"wait\" && !options.isPartial) scheduleWaitRefresh(context, false);\n\tconst details = result.details;\n\tif (context.isError || !details) {\n\t\tconst text = result.content.find((part) => part.type === \"text\")?.text ?? \"\";\n\t\treturn new Text(theme.fg(\"toolOutput\", text.trimEnd()), 0, 0);\n\t}\n\n\tconst container = new Container();\n\tcontainer.addChild(new TruncatedText(resultSummaryLine(details, theme), 1, 0));\n\tif (options.expanded) {\n\t\tconst text = result.content.find((part) => part.type === \"text\")?.text ?? \"\";\n\t\tcontainer.addChild(new Text(\"\", 0, 0));\n\t\tcontainer.addChild(new Text(theme.fg(\"toolOutput\", capForTranscript(text, RESULT_EXPAND_LIMIT).trimEnd()), 1, 0));\n\t}\n\treturn container;\n}\n\nfunction resultSummaryLine(details: BgDetails, theme: Theme): string {\n\tswitch (details.action) {\n\t\tcase \"create\": {\n\t\t\tconst label = details.description ? ` (${details.description})` : \"\";\n\t\t\treturn `${theme.fg(\"muted\", \"→ task \")}${theme.fg(\"accent\", `${details.taskId}${label}`)}${theme.fg(\"muted\", ` started · ${details.outputPath}`)}`;\n\t\t}\n\t\tcase \"read\": {\n\t\t\tconst size =\n\t\t\t\tdetails.sliceBytes !== details.totalBytes\n\t\t\t\t\t? `${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`\n\t\t\t\t\t: formatSize(details.totalBytes);\n\t\t\treturn `${theme.fg(\"muted\", \"→ \")}${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` ${size} · ${details.outputPath}`)}`;\n\t\t}\n\t\tcase \"wait\": {\n\t\t\tif (details.timedOut) {\n\t\t\t\treturn `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` still running · waited ${formatDuration(details.waitedMs)} · ${formatSize(details.totalBytes)}`)}`;\n\t\t\t}\n\t\t\tconst exit = exitSuffix(details.exitCode, \", \");\n\t\t\treturn `${theme.fg(statusColor(details.status), statusGlyph(details.status))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", ` ${details.status}${exit} · waited ${formatDuration(details.waitedMs)} · +${formatSize(details.deltaBytes)}`)}`;\n\t\t}\n\t\tcase \"kill\":\n\t\t\treturn `${theme.fg(statusColor(\"killed\"), statusGlyph(\"killed\"))} ${theme.fg(\"accent\", details.taskId)}${theme.fg(\"muted\", \" stopped\")}`;\n\t\tcase \"list\": {\n\t\t\tconst hidden = details.hidden > 0 ? ` · ${details.hidden} more finished` : \"\";\n\t\t\treturn theme.fg(\"muted\", `${details.running} running · ${details.finished} finished${hidden}`);\n\t\t}\n\t}\n}\n\n// ── completion notification ───────────────────────────────────────────────\n\n/** One-line summary of a finished task, shared by the notification renderer. */\nfunction taskSummaryLine(details: BgNotificationDetails, theme: Theme): string {\n\tconst runtime = formatDuration(details.runtimeMs);\n\tconst label = details.description\n\t\t? `${details.description} (${commandLabel(details.command, LABELLED_COMMAND_LIMIT)})`\n\t\t: commandLabel(details.command, COMMAND_PREVIEW_LIMIT);\n\tif (details.stalled) {\n\t\tconst glyph = theme.fg(\"warning\", \"…\");\n\t\treturn `${glyph} ${theme.fg(\"accent\", details.taskId)} ${label} ${theme.fg(\"muted\", `— waiting for input (${runtime})`)}`;\n\t}\n\tconst outcome = theme.fg(\n\t\tstatusColor(details.status),\n\t\t`${details.status}${exitSuffix(details.exitCode, \", \")} in ${runtime}`,\n\t);\n\tconst glyph = theme.fg(statusColor(details.status), statusGlyph(details.status));\n\treturn `${glyph} ${theme.fg(\"accent\", details.taskId)} ${label} ${theme.fg(\"muted\", `— ${outcome}`)}`;\n}\n\n/**\n * Collapsed: status glyph, task id, label, and outcome on one line, output\n * path below. Expanded adds the embedded output tail. Returns undefined for\n * malformed details so the default custom-message rendering takes over.\n */\nexport function renderBackgroundNotification(\n\tmessage: CustomMessage<BgNotificationDetails>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n): Component | undefined {\n\tconst details = message.details;\n\tif (!details || typeof details.taskId !== \"string\") return undefined;\n\n\tconst container = new Container();\n\tcontainer.addChild(new TruncatedText(taskSummaryLine(details, theme), 1, 0));\n\t// Collapsed keeps the row compact with the file name; the full path\n\t// (model-relevant, human-rarely) shows when expanded.\n\tconst shownPath = options.expanded ? details.outputPath : fileNameOf(details.outputPath);\n\tcontainer.addChild(new Text(theme.fg(\"muted\", shownPath), 1, 0));\n\n\tif (details.tailError) {\n\t\tcontainer.addChild(new Text(theme.fg(\"error\", `Output unavailable: ${details.tailError}`), 1, 0));\n\t} else if (options.expanded && details.tailText) {\n\t\tcontainer.addChild(new Text(\"\", 0, 0));\n\t\tconst tail = capForTranscript(details.tailText, NOTIFY_TAIL_LIMIT);\n\t\tconst truncatedNote = details.tailTruncated\n\t\t\t? `\\n[showing tail of ${formatSize(details.totalBytes)} bytes; full output: ${details.outputPath}]`\n\t\t\t: \"\";\n\t\tcontainer.addChild(\n\t\t\tnew Text(`${theme.fg(\"toolOutput\", tail.trimEnd())}${theme.fg(\"muted\", truncatedNote)}`, 1, 0),\n\t\t);\n\t}\n\tif (details.stalled && options.expanded) {\n\t\tcontainer.addChild(\n\t\t\tnew Text(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"warning\",\n\t\t\t\t\t\"Blocked on interactive input — kill (bg action kill) and re-run with piped input or a non-interactive flag.\",\n\t\t\t\t),\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\treturn container;\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — the `bg` tool's wire contract: one flat schema whose `action`
|
|
3
|
+
* selects which of the remaining fields apply, plus the model-facing copy.
|
|
4
|
+
*
|
|
5
|
+
* The schema stays flat deliberately: a single tool keeps the model's tool list
|
|
6
|
+
* short (the five operations were merged for that reason). Narrowing happens
|
|
7
|
+
* inside actions.ts, not here.
|
|
8
|
+
*/
|
|
9
|
+
import { type Static, Type } from "typebox";
|
|
10
|
+
export declare const bgSchema: Type.TObject<{
|
|
11
|
+
action: Type.TUnion<[Type.TLiteral<"create">, Type.TLiteral<"read">, Type.TLiteral<"wait">, Type.TLiteral<"kill">, Type.TLiteral<"list">]>;
|
|
12
|
+
command: Type.TOptional<Type.TString>;
|
|
13
|
+
description: Type.TOptional<Type.TString>;
|
|
14
|
+
timeout: Type.TOptional<Type.TNumber>;
|
|
15
|
+
taskId: Type.TOptional<Type.TString>;
|
|
16
|
+
mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"tail">, Type.TLiteral<"head">]>>;
|
|
17
|
+
bytes: Type.TOptional<Type.TNumber>;
|
|
18
|
+
waitMs: Type.TOptional<Type.TNumber>;
|
|
19
|
+
sinceBytes: Type.TOptional<Type.TNumber>;
|
|
20
|
+
}>;
|
|
21
|
+
/** Raw tool arguments. Every per-action field is optional here; actions.ts narrows. */
|
|
22
|
+
export type BgInput = Static<typeof bgSchema>;
|
|
23
|
+
export declare function requireCommand(input: BgInput): string;
|
|
24
|
+
export declare function requireTaskId(input: BgInput): string;
|
|
25
|
+
/** Validated with the bash tool's own rule, so a rejected timeout reads the same either way. */
|
|
26
|
+
export declare function parseTimeoutSeconds(timeout: number | undefined): number | undefined;
|
|
27
|
+
export declare function clampReadBytes(bytes: number | undefined): number;
|
|
28
|
+
/** Shared with the pending-call renderer so the window it shows is the one that runs. */
|
|
29
|
+
export declare function clampWaitMs(waitMs: number | undefined): number;
|
|
30
|
+
export declare function clampSinceBytes(sinceBytes: number | undefined): number | undefined;
|
|
31
|
+
export declare const BG_TOOL_DESCRIPTION: string;
|
|
32
|
+
export declare const BG_PROMPT_SNIPPET = "Manage background shell tasks (create, read, wait, kill, list)";
|
|
33
|
+
export declare const BG_PROMPT_GUIDELINES: string[];
|
|
34
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAW5C,eAAO,MAAM,QAAQ;;;;;;;;;;EA8CnB,CAAC;AAEH,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAO9C,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMrD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQpD;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGnF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE9D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AAED,eAAO,MAAM,mBAAmB,QAWW,CAAC;AAE5C,eAAO,MAAM,iBAAiB,mEAAmE,CAAC;AAElG,eAAO,MAAM,oBAAoB,UAGhC,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — the `bg` tool's wire contract: one flat schema whose `action`
|
|
3
|
+
* selects which of the remaining fields apply, plus the model-facing copy.
|
|
4
|
+
*
|
|
5
|
+
* The schema stays flat deliberately: a single tool keeps the model's tool list
|
|
6
|
+
* short (the five operations were merged for that reason). Narrowing happens
|
|
7
|
+
* inside actions.ts, not here.
|
|
8
|
+
*/
|
|
9
|
+
import { Type } from "typebox";
|
|
10
|
+
import { resolveTimeoutMs } from "../../core/tools/bash.js";
|
|
11
|
+
import { DEFAULT_MAX_BYTES, formatSize } from "../../core/tools/truncate.js";
|
|
12
|
+
import { BG_LOGS_DEFAULT_BYTES, BG_LOGS_MIN_BYTES, BG_WAIT_DEFAULT_MS, BG_WAIT_MAX_MS, BG_WAIT_MIN_MS, } from "./constants.js";
|
|
13
|
+
export const bgSchema = Type.Object({
|
|
14
|
+
action: Type.Union([Type.Literal("create"), Type.Literal("read"), Type.Literal("wait"), Type.Literal("kill"), Type.Literal("list")], { description: "Which background-task operation to perform" }),
|
|
15
|
+
// — create —
|
|
16
|
+
command: Type.Optional(Type.String({ description: "Bash command to run in the background (create). Do not append '&'" })),
|
|
17
|
+
description: Type.Optional(Type.String({
|
|
18
|
+
description: "Short label for the task, shown in /bg and notifications, e.g. 'dev server' (create)",
|
|
19
|
+
})),
|
|
20
|
+
timeout: Type.Optional(Type.Number({
|
|
21
|
+
description: "Kill the task after this many seconds; on expiry it is reported as timeout (create)",
|
|
22
|
+
})),
|
|
23
|
+
// — read / wait / kill —
|
|
24
|
+
taskId: Type.Optional(Type.String({ description: "Task id; a unique prefix is accepted, e.g. 'bg-3f' or '3f' (read/wait/kill)" })),
|
|
25
|
+
// — read —
|
|
26
|
+
mode: Type.Optional(Type.Union([Type.Literal("tail"), Type.Literal("head")], {
|
|
27
|
+
description: "Read from the end (default) or the start of the output (read)",
|
|
28
|
+
})),
|
|
29
|
+
bytes: Type.Optional(Type.Number({
|
|
30
|
+
description: `Max bytes to return (read, default ${formatSize(BG_LOGS_DEFAULT_BYTES)}, max ${formatSize(DEFAULT_MAX_BYTES)})`,
|
|
31
|
+
})),
|
|
32
|
+
// — wait —
|
|
33
|
+
waitMs: Type.Optional(Type.Number({
|
|
34
|
+
description: `Max time to wait in ms, default ${BG_WAIT_DEFAULT_MS}, max ${BG_WAIT_MAX_MS} (wait)`,
|
|
35
|
+
})),
|
|
36
|
+
sinceBytes: Type.Optional(Type.Number({
|
|
37
|
+
description: "Only return output written after this byte offset — take it from a previous read/wait result (wait)",
|
|
38
|
+
})),
|
|
39
|
+
});
|
|
40
|
+
// ── reading the contract ──────────────────────────────────────────────────
|
|
41
|
+
// One place per field: required fields throw a message that names the next
|
|
42
|
+
// step, optional ones clamp to their documented range. Callers get plain
|
|
43
|
+
// values, so no action handler needs a cast.
|
|
44
|
+
export function requireCommand(input) {
|
|
45
|
+
const command = input.command;
|
|
46
|
+
if (!command || command.trim().length === 0) {
|
|
47
|
+
throw new Error("action 'create' requires 'command' — pass the bash command to run in the background.");
|
|
48
|
+
}
|
|
49
|
+
return command;
|
|
50
|
+
}
|
|
51
|
+
export function requireTaskId(input) {
|
|
52
|
+
const taskId = input.taskId;
|
|
53
|
+
if (!taskId || taskId.trim().length === 0) {
|
|
54
|
+
throw new Error(`action '${input.action}' requires 'taskId' — use the id returned by action create, or action list to find it.`);
|
|
55
|
+
}
|
|
56
|
+
return taskId;
|
|
57
|
+
}
|
|
58
|
+
/** Validated with the bash tool's own rule, so a rejected timeout reads the same either way. */
|
|
59
|
+
export function parseTimeoutSeconds(timeout) {
|
|
60
|
+
resolveTimeoutMs(timeout);
|
|
61
|
+
return timeout;
|
|
62
|
+
}
|
|
63
|
+
export function clampReadBytes(bytes) {
|
|
64
|
+
return Math.min(DEFAULT_MAX_BYTES, Math.max(BG_LOGS_MIN_BYTES, Math.floor(bytes ?? BG_LOGS_DEFAULT_BYTES)));
|
|
65
|
+
}
|
|
66
|
+
/** Shared with the pending-call renderer so the window it shows is the one that runs. */
|
|
67
|
+
export function clampWaitMs(waitMs) {
|
|
68
|
+
return Math.min(BG_WAIT_MAX_MS, Math.max(BG_WAIT_MIN_MS, Math.floor(waitMs ?? BG_WAIT_DEFAULT_MS)));
|
|
69
|
+
}
|
|
70
|
+
export function clampSinceBytes(sinceBytes) {
|
|
71
|
+
return sinceBytes === undefined ? undefined : Math.max(0, Math.floor(sinceBytes));
|
|
72
|
+
}
|
|
73
|
+
export const BG_TOOL_DESCRIPTION = "Run and manage background bash tasks.\n\n" +
|
|
74
|
+
"create: start a command in the background and return immediately with a task id and an " +
|
|
75
|
+
"output file path. A <background-task> notification with status, exit code, and output tail " +
|
|
76
|
+
"arrives automatically when it ends. Do NOT append '&' to the command; bg already runs it " +
|
|
77
|
+
"detached.\n\n" +
|
|
78
|
+
"read: bounded slice of a task's output; works while the task runs. The " +
|
|
79
|
+
"output file is a plain file — the read tool also works on it for line-based paging.\n\n" +
|
|
80
|
+
"wait: block until a task finishes and return its status plus output written since a given " +
|
|
81
|
+
"offset. On timeout the task is still running and you may wait again.\n\n" +
|
|
82
|
+
"kill: stop a running task (whole process tree).\n\n" +
|
|
83
|
+
"list: currently known tasks with status.";
|
|
84
|
+
export const BG_PROMPT_SNIPPET = "Manage background shell tasks (create, read, wait, kill, list)";
|
|
85
|
+
export const BG_PROMPT_GUIDELINES = [
|
|
86
|
+
"Use `bg` action create for long-running commands (dev servers, watch builds, slow tests) instead of regular bash; the completion notification arrives on its own, so continue independent work or end the turn.",
|
|
87
|
+
"Never wait on a `bg` task with sleep loops or repeated reads; use `bg` action wait when the next step depends on its result.",
|
|
88
|
+
];
|
|
89
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/background/schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — the `bg` tool's wire contract: one flat schema whose `action`\n * selects which of the remaining fields apply, plus the model-facing copy.\n *\n * The schema stays flat deliberately: a single tool keeps the model's tool list\n * short (the five operations were merged for that reason). Narrowing happens\n * inside actions.ts, not here.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport { resolveTimeoutMs } from \"../../core/tools/bash.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize } from \"../../core/tools/truncate.ts\";\nimport {\n\tBG_LOGS_DEFAULT_BYTES,\n\tBG_LOGS_MIN_BYTES,\n\tBG_WAIT_DEFAULT_MS,\n\tBG_WAIT_MAX_MS,\n\tBG_WAIT_MIN_MS,\n} from \"./constants.ts\";\n\nexport const bgSchema = Type.Object({\n\taction: Type.Union(\n\t\t[Type.Literal(\"create\"), Type.Literal(\"read\"), Type.Literal(\"wait\"), Type.Literal(\"kill\"), Type.Literal(\"list\")],\n\t\t{ description: \"Which background-task operation to perform\" },\n\t),\n\t// — create —\n\tcommand: Type.Optional(\n\t\tType.String({ description: \"Bash command to run in the background (create). Do not append '&'\" }),\n\t),\n\tdescription: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Short label for the task, shown in /bg and notifications, e.g. 'dev server' (create)\",\n\t\t}),\n\t),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: \"Kill the task after this many seconds; on expiry it is reported as timeout (create)\",\n\t\t}),\n\t),\n\t// — read / wait / kill —\n\ttaskId: Type.Optional(\n\t\tType.String({ description: \"Task id; a unique prefix is accepted, e.g. 'bg-3f' or '3f' (read/wait/kill)\" }),\n\t),\n\t// — read —\n\tmode: Type.Optional(\n\t\tType.Union([Type.Literal(\"tail\"), Type.Literal(\"head\")], {\n\t\t\tdescription: \"Read from the end (default) or the start of the output (read)\",\n\t\t}),\n\t),\n\tbytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max bytes to return (read, default ${formatSize(BG_LOGS_DEFAULT_BYTES)}, max ${formatSize(DEFAULT_MAX_BYTES)})`,\n\t\t}),\n\t),\n\t// — wait —\n\twaitMs: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max time to wait in ms, default ${BG_WAIT_DEFAULT_MS}, max ${BG_WAIT_MAX_MS} (wait)`,\n\t\t}),\n\t),\n\tsinceBytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Only return output written after this byte offset — take it from a previous read/wait result (wait)\",\n\t\t}),\n\t),\n});\n\n/** Raw tool arguments. Every per-action field is optional here; actions.ts narrows. */\nexport type BgInput = Static<typeof bgSchema>;\n\n// ── reading the contract ──────────────────────────────────────────────────\n// One place per field: required fields throw a message that names the next\n// step, optional ones clamp to their documented range. Callers get plain\n// values, so no action handler needs a cast.\n\nexport function requireCommand(input: BgInput): string {\n\tconst command = input.command;\n\tif (!command || command.trim().length === 0) {\n\t\tthrow new Error(\"action 'create' requires 'command' — pass the bash command to run in the background.\");\n\t}\n\treturn command;\n}\n\nexport function requireTaskId(input: BgInput): string {\n\tconst taskId = input.taskId;\n\tif (!taskId || taskId.trim().length === 0) {\n\t\tthrow new Error(\n\t\t\t`action '${input.action}' requires 'taskId' — use the id returned by action create, or action list to find it.`,\n\t\t);\n\t}\n\treturn taskId;\n}\n\n/** Validated with the bash tool's own rule, so a rejected timeout reads the same either way. */\nexport function parseTimeoutSeconds(timeout: number | undefined): number | undefined {\n\tresolveTimeoutMs(timeout);\n\treturn timeout;\n}\n\nexport function clampReadBytes(bytes: number | undefined): number {\n\treturn Math.min(DEFAULT_MAX_BYTES, Math.max(BG_LOGS_MIN_BYTES, Math.floor(bytes ?? BG_LOGS_DEFAULT_BYTES)));\n}\n\n/** Shared with the pending-call renderer so the window it shows is the one that runs. */\nexport function clampWaitMs(waitMs: number | undefined): number {\n\treturn Math.min(BG_WAIT_MAX_MS, Math.max(BG_WAIT_MIN_MS, Math.floor(waitMs ?? BG_WAIT_DEFAULT_MS)));\n}\n\nexport function clampSinceBytes(sinceBytes: number | undefined): number | undefined {\n\treturn sinceBytes === undefined ? undefined : Math.max(0, Math.floor(sinceBytes));\n}\n\nexport const BG_TOOL_DESCRIPTION =\n\t\"Run and manage background bash tasks.\\n\\n\" +\n\t\"create: start a command in the background and return immediately with a task id and an \" +\n\t\"output file path. A <background-task> notification with status, exit code, and output tail \" +\n\t\"arrives automatically when it ends. Do NOT append '&' to the command; bg already runs it \" +\n\t\"detached.\\n\\n\" +\n\t\"read: bounded slice of a task's output; works while the task runs. The \" +\n\t\"output file is a plain file — the read tool also works on it for line-based paging.\\n\\n\" +\n\t\"wait: block until a task finishes and return its status plus output written since a given \" +\n\t\"offset. On timeout the task is still running and you may wait again.\\n\\n\" +\n\t\"kill: stop a running task (whole process tree).\\n\\n\" +\n\t\"list: currently known tasks with status.\";\n\nexport const BG_PROMPT_SNIPPET = \"Manage background shell tasks (create, read, wait, kill, list)\";\n\nexport const BG_PROMPT_GUIDELINES = [\n\t\"Use `bg` action create for long-running commands (dev servers, watch builds, slow tests) instead of regular bash; the completion notification arrives on its own, so continue independent work or end the turn.\",\n\t\"Never wait on a `bg` task with sleep loops or repeated reads; use `bg` action wait when the next step depends on its result.\",\n];\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — how a task is described, everywhere.
|
|
3
|
+
*
|
|
4
|
+
* Every output this extension produces (five tool results, two notifications,
|
|
5
|
+
* the statusline, the /bg list and detail header) is the same thing: a BgTask
|
|
6
|
+
* projected into a medium. The values those projections derive — runtime, exit
|
|
7
|
+
* suffix, label, glyph — live here once, so the media can differ without the
|
|
8
|
+
* vocabulary drifting. Pure functions; no TUI components, no theme.
|
|
9
|
+
*/
|
|
10
|
+
import type { BgTaskStatus } from "./registry.ts";
|
|
11
|
+
/** How long a task has run, or ran. A running task has no `endedAt`, so it measures to `now`. */
|
|
12
|
+
export declare function runtimeMs(task: {
|
|
13
|
+
startedAt: number;
|
|
14
|
+
endedAt?: number;
|
|
15
|
+
}, now?: number): number;
|
|
16
|
+
export declare function runtimeLabel(task: {
|
|
17
|
+
startedAt: number;
|
|
18
|
+
endedAt?: number;
|
|
19
|
+
}, now?: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a task produced an exit code. Three-state by necessity: `undefined`
|
|
22
|
+
* while running or when the run produced none, `null` when reaped by a signal —
|
|
23
|
+
* and historical session entries still hold `null`, so this must keep accepting it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function hasExitCode(exitCode: number | null | undefined): exitCode is number;
|
|
26
|
+
/** `<separator>exit <code>`, or nothing. Callers pick the separator: " ", ", ", " · ". */
|
|
27
|
+
export declare function exitSuffix(exitCode: number | null | undefined, separator: string): string;
|
|
28
|
+
/** Label for listings: the model-provided description over the first command line. */
|
|
29
|
+
export declare function taskLabel(task: {
|
|
30
|
+
description?: string;
|
|
31
|
+
command: string;
|
|
32
|
+
}): string;
|
|
33
|
+
/** A listing row's label, fitted to a visible-column budget. */
|
|
34
|
+
export declare function taskLabelWithin(task: {
|
|
35
|
+
description?: string;
|
|
36
|
+
command: string;
|
|
37
|
+
}, width: number): string;
|
|
38
|
+
/** First command line fitted to a visible-column budget — wide characters count as two. */
|
|
39
|
+
export declare function commandLabel(command: string, width: number): string;
|
|
40
|
+
export declare function statusGlyph(status: BgTaskStatus, stalled?: boolean): string;
|
|
41
|
+
export declare function statusColor(status: BgTaskStatus, stalled?: boolean): "success" | "error" | "warning" | "accent";
|
|
42
|
+
/** The footer segment, or nothing when this session has no tasks at all. */
|
|
43
|
+
export declare function formatStatusline(counts: {
|
|
44
|
+
running: number;
|
|
45
|
+
total: number;
|
|
46
|
+
stalled: number;
|
|
47
|
+
}): string | undefined;
|
|
48
|
+
//# sourceMappingURL=task-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-view.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/task-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,iGAAiG;AACjG,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAa,GAAG,MAAM,CAEjG;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAa,GAAG,MAAM,CAEpG;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,IAAI,MAAM,CAEnF;AAED,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzF;AAED,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGjF;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtG;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAa3E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAa/G;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAUhH"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — how a task is described, everywhere.
|
|
3
|
+
*
|
|
4
|
+
* Every output this extension produces (five tool results, two notifications,
|
|
5
|
+
* the statusline, the /bg list and detail header) is the same thing: a BgTask
|
|
6
|
+
* projected into a medium. The values those projections derive — runtime, exit
|
|
7
|
+
* suffix, label, glyph — live here once, so the media can differ without the
|
|
8
|
+
* vocabulary drifting. Pure functions; no TUI components, no theme.
|
|
9
|
+
*/
|
|
10
|
+
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
11
|
+
import { firstCommandLine, formatDuration } from "./text.js";
|
|
12
|
+
/** How long a task has run, or ran. A running task has no `endedAt`, so it measures to `now`. */
|
|
13
|
+
export function runtimeMs(task, now = Date.now()) {
|
|
14
|
+
return (task.endedAt ?? now) - task.startedAt;
|
|
15
|
+
}
|
|
16
|
+
export function runtimeLabel(task, now = Date.now()) {
|
|
17
|
+
return formatDuration(runtimeMs(task, now));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Whether a task produced an exit code. Three-state by necessity: `undefined`
|
|
21
|
+
* while running or when the run produced none, `null` when reaped by a signal —
|
|
22
|
+
* and historical session entries still hold `null`, so this must keep accepting it.
|
|
23
|
+
*/
|
|
24
|
+
export function hasExitCode(exitCode) {
|
|
25
|
+
return exitCode !== undefined && exitCode !== null;
|
|
26
|
+
}
|
|
27
|
+
/** `<separator>exit <code>`, or nothing. Callers pick the separator: " ", ", ", " · ". */
|
|
28
|
+
export function exitSuffix(exitCode, separator) {
|
|
29
|
+
return hasExitCode(exitCode) ? `${separator}exit ${exitCode}` : "";
|
|
30
|
+
}
|
|
31
|
+
/** Label for listings: the model-provided description over the first command line. */
|
|
32
|
+
export function taskLabel(task) {
|
|
33
|
+
const command = firstCommandLine(task.command);
|
|
34
|
+
return task.description ? `${task.description} — ${command}` : command;
|
|
35
|
+
}
|
|
36
|
+
/** A listing row's label, fitted to a visible-column budget. */
|
|
37
|
+
export function taskLabelWithin(task, width) {
|
|
38
|
+
return truncateToWidth(taskLabel(task), width, "…");
|
|
39
|
+
}
|
|
40
|
+
/** First command line fitted to a visible-column budget — wide characters count as two. */
|
|
41
|
+
export function commandLabel(command, width) {
|
|
42
|
+
return truncateToWidth(firstCommandLine(command), width, "…");
|
|
43
|
+
}
|
|
44
|
+
export function statusGlyph(status, stalled) {
|
|
45
|
+
if (stalled)
|
|
46
|
+
return "…";
|
|
47
|
+
switch (status) {
|
|
48
|
+
case "completed":
|
|
49
|
+
return "✓";
|
|
50
|
+
case "failed":
|
|
51
|
+
case "timeout":
|
|
52
|
+
return "✗";
|
|
53
|
+
case "killed":
|
|
54
|
+
return "○";
|
|
55
|
+
default:
|
|
56
|
+
return "●";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function statusColor(status, stalled) {
|
|
60
|
+
if (stalled)
|
|
61
|
+
return "warning";
|
|
62
|
+
switch (status) {
|
|
63
|
+
case "completed":
|
|
64
|
+
return "success";
|
|
65
|
+
case "failed":
|
|
66
|
+
return "error";
|
|
67
|
+
case "timeout":
|
|
68
|
+
case "killed":
|
|
69
|
+
return "warning";
|
|
70
|
+
default:
|
|
71
|
+
return "accent";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** The footer segment, or nothing when this session has no tasks at all. */
|
|
75
|
+
export function formatStatusline(counts) {
|
|
76
|
+
if (counts.total === 0)
|
|
77
|
+
return undefined;
|
|
78
|
+
// Stalled tasks are running tasks: report them separately so the counts add up.
|
|
79
|
+
const running = counts.running - counts.stalled;
|
|
80
|
+
const ended = counts.total - counts.running;
|
|
81
|
+
const parts = [];
|
|
82
|
+
if (running > 0)
|
|
83
|
+
parts.push(`${running} running`);
|
|
84
|
+
if (counts.stalled > 0)
|
|
85
|
+
parts.push(`${counts.stalled} waiting for input`);
|
|
86
|
+
if (ended > 0)
|
|
87
|
+
parts.push(`${ended} done`);
|
|
88
|
+
return `bg ${parts.join(" · ")}`;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=task-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-view.js","sourceRoot":"","sources":["../../../src/extensions/background/task-view.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — how a task is described, everywhere.\n *\n * Every output this extension produces (five tool results, two notifications,\n * the statusline, the /bg list and detail header) is the same thing: a BgTask\n * projected into a medium. The values those projections derive — runtime, exit\n * suffix, label, glyph — live here once, so the media can differ without the\n * vocabulary drifting. Pure functions; no TUI components, no theme.\n */\n\nimport { truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { BgTaskStatus } from \"./registry.ts\";\nimport { firstCommandLine, formatDuration } from \"./text.ts\";\n/** How long a task has run, or ran. A running task has no `endedAt`, so it measures to `now`. */\nexport function runtimeMs(task: { startedAt: number; endedAt?: number }, now = Date.now()): number {\n\treturn (task.endedAt ?? now) - task.startedAt;\n}\n\nexport function runtimeLabel(task: { startedAt: number; endedAt?: number }, now = Date.now()): string {\n\treturn formatDuration(runtimeMs(task, now));\n}\n\n/**\n * Whether a task produced an exit code. Three-state by necessity: `undefined`\n * while running or when the run produced none, `null` when reaped by a signal —\n * and historical session entries still hold `null`, so this must keep accepting it.\n */\nexport function hasExitCode(exitCode: number | null | undefined): exitCode is number {\n\treturn exitCode !== undefined && exitCode !== null;\n}\n\n/** `<separator>exit <code>`, or nothing. Callers pick the separator: \" \", \", \", \" · \". */\nexport function exitSuffix(exitCode: number | null | undefined, separator: string): string {\n\treturn hasExitCode(exitCode) ? `${separator}exit ${exitCode}` : \"\";\n}\n\n/** Label for listings: the model-provided description over the first command line. */\nexport function taskLabel(task: { description?: string; command: string }): string {\n\tconst command = firstCommandLine(task.command);\n\treturn task.description ? `${task.description} — ${command}` : command;\n}\n\n/** A listing row's label, fitted to a visible-column budget. */\nexport function taskLabelWithin(task: { description?: string; command: string }, width: number): string {\n\treturn truncateToWidth(taskLabel(task), width, \"…\");\n}\n\n/** First command line fitted to a visible-column budget — wide characters count as two. */\nexport function commandLabel(command: string, width: number): string {\n\treturn truncateToWidth(firstCommandLine(command), width, \"…\");\n}\n\nexport function statusGlyph(status: BgTaskStatus, stalled?: boolean): string {\n\tif (stalled) return \"…\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"✓\";\n\t\tcase \"failed\":\n\t\tcase \"timeout\":\n\t\t\treturn \"✗\";\n\t\tcase \"killed\":\n\t\t\treturn \"○\";\n\t\tdefault:\n\t\t\treturn \"●\";\n\t}\n}\n\nexport function statusColor(status: BgTaskStatus, stalled?: boolean): \"success\" | \"error\" | \"warning\" | \"accent\" {\n\tif (stalled) return \"warning\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"success\";\n\t\tcase \"failed\":\n\t\t\treturn \"error\";\n\t\tcase \"timeout\":\n\t\tcase \"killed\":\n\t\t\treturn \"warning\";\n\t\tdefault:\n\t\t\treturn \"accent\";\n\t}\n}\n\n/** The footer segment, or nothing when this session has no tasks at all. */\nexport function formatStatusline(counts: { running: number; total: number; stalled: number }): string | undefined {\n\tif (counts.total === 0) return undefined;\n\t// Stalled tasks are running tasks: report them separately so the counts add up.\n\tconst running = counts.running - counts.stalled;\n\tconst ended = counts.total - counts.running;\n\tconst parts: string[] = [];\n\tif (running > 0) parts.push(`${running} running`);\n\tif (counts.stalled > 0) parts.push(`${counts.stalled} waiting for input`);\n\tif (ended > 0) parts.push(`${ended} done`);\n\treturn `bg ${parts.join(\" · \")}`;\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* background — string helpers with no dependencies of their own.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from task-view.ts so registry.ts can use them without importing a
|
|
5
|
+
* module that type-imports registry.ts back. Nothing here knows about BgTask.
|
|
6
|
+
*/
|
|
7
|
+
/** First non-empty line of a command, trimmed — for one-line task labels. */
|
|
8
|
+
export declare function firstCommandLine(command: string): string;
|
|
9
|
+
/** Compact duration like Pi's own timers: 12s, 3m05s, 1h02m. */
|
|
10
|
+
export declare function formatDuration(ms: number): string;
|
|
11
|
+
/** Basename of a path, slash-normalized — compact display of output files. */
|
|
12
|
+
export declare function fileNameOf(path: string): string;
|
|
13
|
+
/** The `[a · b · c]` status prefix shared by every model-facing output result. */
|
|
14
|
+
export declare function noticeLine(parts: (string | false | undefined)[]): string;
|
|
15
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/extensions/background/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,CAExE"}
|