@astralyn/pi 1.4.9 → 1.4.11
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 +69 -0
- package/dist/bundle/chunks/{chunk-BAGHIP5J.js → chunk-NUQMVNKQ.js} +3 -3
- package/dist/bundle/chunks/{chunk-3PKXUKTB.js → chunk-PUU43PDV.js} +121 -136
- package/dist/bundle/chunks/{chunk-F66AY3WR.js → chunk-TH3QDDPD.js} +1 -1
- package/dist/bundle/chunks/{execute-P22VMM2H.js → execute-VLAIP26K.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-VKMBQTR2.js → virtual-modules-63XNTSVN.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +34 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +99 -5
- package/dist/core/agent-session.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/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +14 -7
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/isolated-session.d.ts +7 -2
- package/dist/core/isolated-session.d.ts.map +1 -1
- package/dist/core/isolated-session.js +7 -3
- package/dist/core/isolated-session.js.map +1 -1
- package/dist/core/session-manager.d.ts +17 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +29 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tasks/delivery.d.ts +31 -12
- package/dist/core/tasks/delivery.d.ts.map +1 -1
- package/dist/core/tasks/delivery.js +97 -36
- package/dist/core/tasks/delivery.js.map +1 -1
- package/dist/core/tasks/execution.d.ts +27 -14
- package/dist/core/tasks/execution.d.ts.map +1 -1
- package/dist/core/tasks/execution.js +90 -86
- package/dist/core/tasks/execution.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +7 -11
- package/dist/core/tasks/limits.d.ts.map +1 -1
- package/dist/core/tasks/limits.js +8 -16
- package/dist/core/tasks/limits.js.map +1 -1
- package/dist/core/tasks/output.d.ts +9 -1
- package/dist/core/tasks/output.d.ts.map +1 -1
- package/dist/core/tasks/output.js +23 -10
- package/dist/core/tasks/output.js.map +1 -1
- package/dist/core/tasks/presentation.d.ts +1 -1
- package/dist/core/tasks/presentation.d.ts.map +1 -1
- package/dist/core/tasks/presentation.js +6 -4
- package/dist/core/tasks/presentation.js.map +1 -1
- package/dist/core/tasks/record.d.ts +41 -29
- package/dist/core/tasks/record.d.ts.map +1 -1
- package/dist/core/tasks/record.js +82 -37
- package/dist/core/tasks/record.js.map +1 -1
- package/dist/core/tasks/reminder.js +2 -2
- package/dist/core/tasks/reminder.js.map +1 -1
- package/dist/core/tasks/runtime.d.ts +15 -23
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +50 -178
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/scheduler.d.ts +3 -1
- package/dist/core/tasks/scheduler.d.ts.map +1 -1
- package/dist/core/tasks/scheduler.js +16 -12
- package/dist/core/tasks/scheduler.js.map +1 -1
- package/dist/core/tasks/session.d.ts +24 -6
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +70 -22
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/store.d.ts +17 -4
- package/dist/core/tasks/store.d.ts.map +1 -1
- package/dist/core/tasks/store.js +45 -48
- package/dist/core/tasks/store.js.map +1 -1
- package/dist/core/tasks/types.d.ts +64 -93
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +7 -0
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -1
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +20 -13
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/extensions/agent/activity-lines.d.ts +10 -0
- package/dist/extensions/agent/activity-lines.d.ts.map +1 -0
- package/dist/extensions/agent/activity-lines.js +76 -0
- package/dist/extensions/agent/activity-lines.js.map +1 -0
- package/dist/extensions/agent/activity.d.ts +25 -4
- package/dist/extensions/agent/activity.d.ts.map +1 -1
- package/dist/extensions/agent/activity.js +76 -21
- package/dist/extensions/agent/activity.js.map +1 -1
- package/dist/extensions/agent/artifacts.d.ts +15 -0
- package/dist/extensions/agent/artifacts.d.ts.map +1 -0
- package/dist/extensions/agent/artifacts.js +44 -0
- package/dist/extensions/agent/artifacts.js.map +1 -0
- package/dist/extensions/agent/progress.d.ts +30 -4
- package/dist/extensions/agent/progress.d.ts.map +1 -1
- package/dist/extensions/agent/progress.js +84 -11
- package/dist/extensions/agent/progress.js.map +1 -1
- package/dist/extensions/agent/render.d.ts.map +1 -1
- package/dist/extensions/agent/render.js +8 -24
- package/dist/extensions/agent/render.js.map +1 -1
- package/dist/extensions/agent/report.d.ts +11 -3
- package/dist/extensions/agent/report.d.ts.map +1 -1
- package/dist/extensions/agent/report.js +32 -7
- package/dist/extensions/agent/report.js.map +1 -1
- package/dist/extensions/agent/tool.d.ts.map +1 -1
- package/dist/extensions/agent/tool.js +20 -5
- package/dist/extensions/agent/tool.js.map +1 -1
- package/dist/extensions/agent/types.d.ts +2 -0
- package/dist/extensions/agent/types.d.ts.map +1 -1
- package/dist/extensions/agent/types.js.map +1 -1
- package/dist/extensions/agent/worker.d.ts +7 -0
- package/dist/extensions/agent/worker.d.ts.map +1 -1
- package/dist/extensions/agent/worker.js +9 -3
- package/dist/extensions/agent/worker.js.map +1 -1
- package/dist/extensions/cached-compaction/summary.d.ts +1 -1
- package/dist/extensions/cached-compaction/summary.d.ts.map +1 -1
- package/dist/extensions/cached-compaction/summary.js +13 -16
- package/dist/extensions/cached-compaction/summary.js.map +1 -1
- package/dist/extensions/search/index.d.ts.map +1 -1
- package/dist/extensions/search/index.js +6 -7
- package/dist/extensions/search/index.js.map +1 -1
- package/dist/extensions/tasks/tool/actions.d.ts +1 -2
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/actions.js +12 -80
- package/dist/extensions/tasks/tool/actions.js.map +1 -1
- package/dist/extensions/tasks/tool/constants.d.ts +1 -3
- package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/constants.js +1 -3
- package/dist/extensions/tasks/tool/constants.js.map +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts +2 -3
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/schema.js +10 -18
- package/dist/extensions/tasks/tool/schema.js.map +1 -1
- package/dist/extensions/tasks/tool/types.d.ts +1 -17
- package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/types.js.map +1 -1
- package/dist/extensions/tasks/tool.d.ts +1 -2
- package/dist/extensions/tasks/tool.d.ts.map +1 -1
- package/dist/extensions/tasks/tool.js +5 -6
- package/dist/extensions/tasks/tool.js.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.js +2 -2
- package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
- package/dist/extensions/tasks/ui/footer.d.ts +37 -0
- package/dist/extensions/tasks/ui/footer.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/footer.js +129 -0
- package/dist/extensions/tasks/ui/footer.js.map +1 -0
- package/dist/extensions/tasks/ui/frame.d.ts +36 -0
- package/dist/extensions/tasks/ui/frame.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/frame.js +33 -0
- package/dist/extensions/tasks/ui/frame.js.map +1 -0
- package/dist/extensions/tasks/ui/help.d.ts +6 -0
- package/dist/extensions/tasks/ui/help.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/help.js +53 -0
- package/dist/extensions/tasks/ui/help.js.map +1 -0
- package/dist/extensions/tasks/ui/inspector.d.ts +4 -3
- package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/inspector.js +25 -6
- package/dist/extensions/tasks/ui/inspector.js.map +1 -1
- package/dist/extensions/tasks/ui/layout.d.ts +15 -18
- package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/layout.js +162 -255
- package/dist/extensions/tasks/ui/layout.js.map +1 -1
- package/dist/extensions/tasks/ui/list.d.ts +3 -1
- package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/list.js +19 -14
- package/dist/extensions/tasks/ui/list.js.map +1 -1
- package/dist/extensions/tasks/ui/manager.d.ts +17 -5
- package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/manager.js +147 -90
- package/dist/extensions/tasks/ui/manager.js.map +1 -1
- package/dist/extensions/tasks/ui/model.d.ts +32 -5
- package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/model.js +7 -7
- package/dist/extensions/tasks/ui/model.js.map +1 -1
- package/dist/extensions/tasks/ui/panes.d.ts +40 -0
- package/dist/extensions/tasks/ui/panes.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/panes.js +144 -0
- package/dist/extensions/tasks/ui/panes.js.map +1 -0
- package/dist/extensions/tasks/ui/render.d.ts +2 -16
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/render.js +13 -85
- package/dist/extensions/tasks/ui/render.js.map +1 -1
- package/dist/extensions/tasks/ui/viewport.d.ts +12 -4
- package/dist/extensions/tasks/ui/viewport.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/viewport.js +23 -7
- package/dist/extensions/tasks/ui/viewport.js.map +1 -1
- package/dist/extensions/tasks/ui/views.d.ts +12 -6
- package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/views.js +39 -32
- package/dist/extensions/tasks/ui/views.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +11 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -17
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +38 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +11 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +48 -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 +2 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/bundled/extensions/agent.md +39 -7
- package/docs/bundled/extensions/statusline.md +1 -1
- package/docs/bundled/tasks.md +28 -37
- package/docs/bundled/tool-presentation.md +1 -1
- package/docs/extensions.md +15 -13
- package/docs/json.md +3 -0
- package/docs/models-configuration.md +1 -1
- package/docs/models.md +7 -85
- package/docs/rpc.md +14 -0
- package/docs/sdk.md +12 -2
- package/docs/session-format.md +11 -5
- package/docs/sessions.md +1 -1
- package/docs/usage.md +2 -0
- package/package.json +3 -4
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +0 -14
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +0 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +0 -13
- package/dist/modes/interactive/tool-view/tool-execution.js.map +0 -1
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/npm-shrinkwrap.json +0 -4207
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
2
2
|
import type { Usage } from "@earendil-works/pi-ai/compat";
|
|
3
|
+
import type { Theme } from "../../modes/interactive/theme/theme.ts";
|
|
3
4
|
/** An executor-owned machine source: the task ID prefix, never a dispatch key for the runtime. */
|
|
4
5
|
export type TaskKind = string;
|
|
6
|
+
/**
|
|
7
|
+
* Where the task actually runs. `background` exactly when its caller was released with a
|
|
8
|
+
* background outcome; a caller that is waiting, or was asked to leave but is still held while
|
|
9
|
+
* the executor prepares, is `foreground`.
|
|
10
|
+
*/
|
|
5
11
|
export type TaskMode = "foreground" | "background";
|
|
6
12
|
export declare const TASK_TERMINAL_STATUSES: readonly ["completed", "partial", "failed", "cancelled", "timeout"];
|
|
7
13
|
export type TaskTerminalStatus = (typeof TASK_TERMINAL_STATUSES)[number];
|
|
@@ -45,14 +51,18 @@ export interface TaskSnapshot {
|
|
|
45
51
|
outputPath?: string;
|
|
46
52
|
/** Bounded model-readable result text. */
|
|
47
53
|
result?: TaskText;
|
|
48
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The executor's human-only view. In /tasks it replaces the result as what a person reads;
|
|
56
|
+
* model-facing reads always use `result`. A terminal snapshot has one only if the completion
|
|
57
|
+
* supplied it: the last progress display does not survive settlement.
|
|
58
|
+
*/
|
|
49
59
|
display?: TaskText;
|
|
50
60
|
error?: string;
|
|
51
61
|
}
|
|
52
62
|
export interface TaskUpdate<T> {
|
|
53
63
|
/** Model-readable progress; also forwarded to a foreground caller's onUpdate. */
|
|
54
64
|
result: AgentToolResult<T>;
|
|
55
|
-
/**
|
|
65
|
+
/** The live human-only view while running; replaces the result in /tasks and ends at settlement. */
|
|
56
66
|
display?: string;
|
|
57
67
|
/** Cumulative usage so far, settled once if the execution ends without a final usage. */
|
|
58
68
|
usage?: Usage;
|
|
@@ -61,7 +71,10 @@ export interface TaskCompletion<T> {
|
|
|
61
71
|
result: AgentToolResult<T>;
|
|
62
72
|
/** Defaults to completed, or cancelled when the task was already cancelled. */
|
|
63
73
|
status?: TaskTerminalStatus;
|
|
64
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* The terminal human-only view. In /tasks it replaces the result as what a person reads; model-facing
|
|
76
|
+
* reads and completion context always use `result`. Without it, the terminal snapshot has no display.
|
|
77
|
+
*/
|
|
65
78
|
display?: string;
|
|
66
79
|
/** Terminal diagnostic, stored independently of log slices and bounded to 4096 bytes. */
|
|
67
80
|
error?: string;
|
|
@@ -73,7 +86,9 @@ export interface TaskCompletion<T> {
|
|
|
73
86
|
export interface TaskControl<T> {
|
|
74
87
|
readonly id: string;
|
|
75
88
|
readonly signal: AbortSignal;
|
|
89
|
+
/** Actual placement: `background` only once the caller was released. */
|
|
76
90
|
readonly mode: TaskMode;
|
|
91
|
+
/** Called once the caller is released and the mode becomes `background`. */
|
|
77
92
|
onModeChange(listener: (mode: TaskMode) => void): () => void;
|
|
78
93
|
/** The executor's own preflight passed; from now on the caller may be handed off to the background. */
|
|
79
94
|
accept(): void;
|
|
@@ -83,6 +98,14 @@ export interface TaskControl<T> {
|
|
|
83
98
|
/** Cancel this execution, for example when an executor policy limit is exceeded. */
|
|
84
99
|
cancel(): void;
|
|
85
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Renders a live task's human Output in the Tasks panel: styled, already fitted lines of at most
|
|
103
|
+
* `width` columns, or `undefined` to use the default view (the published `display`, else the
|
|
104
|
+
* result). Called on every repaint while the task runs, so it must be cheap and synchronous.
|
|
105
|
+
* It lives in memory with the running task: never persisted, absent from snapshots, and dropped
|
|
106
|
+
* at settlement. The returned text is trusted extension output, not task text.
|
|
107
|
+
*/
|
|
108
|
+
export type TaskPresenter = (width: number, theme: Theme) => string[] | undefined;
|
|
86
109
|
export interface TaskExecution<T> {
|
|
87
110
|
kind: TaskKind;
|
|
88
111
|
/** Human source name; defaults to `kind`. */
|
|
@@ -95,8 +118,9 @@ export interface TaskExecution<T> {
|
|
|
95
118
|
toolCallId: string;
|
|
96
119
|
background?: boolean;
|
|
97
120
|
/**
|
|
98
|
-
* At most `limit` executions sharing `key` run at once
|
|
99
|
-
*
|
|
121
|
+
* At most `limit` executions sharing `key` run at once; lanes belong to one `kind`, so another
|
|
122
|
+
* executor may reuse the key. Later ones wait as queued tasks whose `run` starts when a slot
|
|
123
|
+
* frees; a queued task can be handed off or cancelled.
|
|
100
124
|
*/
|
|
101
125
|
concurrency?: {
|
|
102
126
|
key: string;
|
|
@@ -104,8 +128,14 @@ export interface TaskExecution<T> {
|
|
|
104
128
|
};
|
|
105
129
|
signal?: AbortSignal;
|
|
106
130
|
onUpdate?: (result: AgentToolResult<T>) => void;
|
|
131
|
+
/** Renders the running task's Output in /tasks; see {@link TaskPresenter}. Dropped at settlement. */
|
|
132
|
+
present?: TaskPresenter;
|
|
107
133
|
run(control: TaskControl<T>): Promise<TaskCompletion<T>>;
|
|
108
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* How a tool call ends. A `background` outcome says why the caller was released: `submitted`
|
|
137
|
+
* when it asked for background, `detached` when it was moved while the work ran.
|
|
138
|
+
*/
|
|
109
139
|
export type TaskToolOutcome<T> = {
|
|
110
140
|
kind: "result";
|
|
111
141
|
result: AgentToolResult<T>;
|
|
@@ -114,14 +144,21 @@ export type TaskToolOutcome<T> = {
|
|
|
114
144
|
} | {
|
|
115
145
|
kind: "background";
|
|
116
146
|
task: TaskSnapshot;
|
|
147
|
+
reason: "submitted" | "detached";
|
|
117
148
|
};
|
|
118
|
-
/** Which slice of a task's output to read. Defaults to
|
|
149
|
+
/** Which slice of a task's output to read. Defaults to 8 KiB. */
|
|
119
150
|
export interface TaskReadOptions {
|
|
120
|
-
/**
|
|
151
|
+
/**
|
|
152
|
+
* `head` reads the start of the output, `tail` its end. Without it a `report` is read from its
|
|
153
|
+
* start and a `log` from its end.
|
|
154
|
+
*/
|
|
121
155
|
mode?: "head" | "tail";
|
|
122
156
|
/** Maximum bytes to return, bounded by the runtime. */
|
|
123
157
|
bytes?: number;
|
|
124
|
-
/**
|
|
158
|
+
/**
|
|
159
|
+
* First unread byte. `head` reads forward from this offset; `tail` returns the newest window
|
|
160
|
+
* at or after it. Without it the output kind selects the default end.
|
|
161
|
+
*/
|
|
125
162
|
sinceBytes?: number;
|
|
126
163
|
}
|
|
127
164
|
export interface TaskRead {
|
|
@@ -132,84 +169,14 @@ export interface TaskRead {
|
|
|
132
169
|
totalBytes: number;
|
|
133
170
|
truncated: boolean;
|
|
134
171
|
fromByte?: number;
|
|
172
|
+
/** Raw source-byte end supplied by the runtime; older/custom hosts may omit it. */
|
|
173
|
+
endByte?: number;
|
|
135
174
|
}
|
|
136
175
|
/** Optional host integration for products built on the execution runtime. */
|
|
137
176
|
export interface TasksSessionContext {
|
|
138
177
|
/** Running tasks that navigating to `targetId` would cancel on this session branch. */
|
|
139
178
|
stoppedByTreeNavigation(targetId: string): TaskSnapshot[];
|
|
140
179
|
}
|
|
141
|
-
/** How a wait ended. `closed` means the host shut down, so execution state is unconfirmed. */
|
|
142
|
-
export type TaskWaitOutcome = "settled" | "interrupted" | "timed_out" | "closed";
|
|
143
|
-
interface TaskObservationOptions {
|
|
144
|
-
/** Defaults to 20 seconds and is bounded by the runtime. A timeout never cancels execution. */
|
|
145
|
-
timeoutMs?: number;
|
|
146
|
-
/** Rejects the wait with the signal's reason; execution continues. */
|
|
147
|
-
signal?: AbortSignal;
|
|
148
|
-
/**
|
|
149
|
-
* The tool call whose result carries this observation to the model. With a session host, a
|
|
150
|
-
* settled background task stays out of automatic notifications until that result is persisted.
|
|
151
|
-
* Without it, or in a standalone runtime, the wait is purely observational.
|
|
152
|
-
*/
|
|
153
|
-
toolCallId?: string;
|
|
154
|
-
}
|
|
155
|
-
export interface TaskWaitOptions extends TaskObservationOptions {
|
|
156
|
-
/** Read output while delivery is still held; skipped when steering interrupted the wait. */
|
|
157
|
-
read?: Pick<TaskReadOptions, "bytes" | "sinceBytes">;
|
|
158
|
-
}
|
|
159
|
-
export interface TaskWaitResult {
|
|
160
|
-
outcome: TaskWaitOutcome;
|
|
161
|
-
waitedMs: number;
|
|
162
|
-
/** The task when the wait ended, before `read` was taken. */
|
|
163
|
-
task: TaskSnapshot;
|
|
164
|
-
read?: TaskRead;
|
|
165
|
-
}
|
|
166
|
-
export interface TaskWaitAnyOptions extends TaskObservationOptions {
|
|
167
|
-
/** Read the settled task's output while delivery is still held. */
|
|
168
|
-
read?: Pick<TaskReadOptions, "bytes">;
|
|
169
|
-
}
|
|
170
|
-
export interface TaskWaitAnyResult {
|
|
171
|
-
/** `no_tasks`: no background task was running at call time, so nothing was observed. */
|
|
172
|
-
outcome: TaskWaitOutcome | "no_tasks";
|
|
173
|
-
waitedMs: number;
|
|
174
|
-
/** The first cohort member to settle; present only for `settled`. */
|
|
175
|
-
task?: TaskSnapshot;
|
|
176
|
-
read?: TaskRead;
|
|
177
|
-
/** Cohort members still running when the wait ended. */
|
|
178
|
-
running: TaskSnapshot[];
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Host hooks that make waits part of a durable session. TaskSession supplies them; products
|
|
182
|
-
* embedding a bare TaskRuntime omit them and keep waits observational.
|
|
183
|
-
*/
|
|
184
|
-
export interface TaskWaitHost {
|
|
185
|
-
/** Current steering signal. Aborting it ends management waits only, never execution. */
|
|
186
|
-
readonly interruptSignal: AbortSignal;
|
|
187
|
-
/**
|
|
188
|
-
* A wait observed a settled background task and its `toolCallId` is known. Called while the
|
|
189
|
-
* runtime still holds delivery; the host takes over until that tool result persists.
|
|
190
|
-
*/
|
|
191
|
-
bind(toolCallId: string, taskId: string): void;
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* What TaskDelivery consumes from the runtime. The runtime keeps only the per-record facts that
|
|
195
|
-
* retention and admission need (a settled handoff is undelivered, claimed or delivered, and a
|
|
196
|
-
* record under a hold is never a candidate); pausing, failure tracking, the in-flight delivery
|
|
197
|
-
* and wait receipts belong to TaskDelivery.
|
|
198
|
-
*/
|
|
199
|
-
export interface TaskDeliveryLedger {
|
|
200
|
-
readonly enabled: boolean;
|
|
201
|
-
list(): TaskSnapshot[];
|
|
202
|
-
/** Settled handoffs eligible for automatic delivery: visible, unclaimed, unobserved and unheld. */
|
|
203
|
-
pendingNotifications(): TaskSnapshot[];
|
|
204
|
-
/** Take a pending notification; false when it is no longer a candidate. */
|
|
205
|
-
claimNotification(id: string): boolean;
|
|
206
|
-
/** Return a claimed notification to pending after a failed delivery. */
|
|
207
|
-
releaseNotification(id: string): void;
|
|
208
|
-
/** Acknowledge a persisted delivery or wait result. */
|
|
209
|
-
markDelivered(id: string): void;
|
|
210
|
-
/** Keep a record out of automatic delivery, and its output retained, until released. */
|
|
211
|
-
holdDelivery(id: string): () => void;
|
|
212
|
-
}
|
|
213
180
|
/** Session-bound public capability. Captured instances close on runtime replacement. */
|
|
214
181
|
export interface TasksContext {
|
|
215
182
|
readonly enabled: boolean;
|
|
@@ -221,17 +188,10 @@ export interface TasksContext {
|
|
|
221
188
|
get(id: string): TaskSnapshot;
|
|
222
189
|
read(id: string, options?: TaskReadOptions): Promise<TaskRead>;
|
|
223
190
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
* acknowledges delivery. Rejects with `TaskLookupError` for an unknown or ambiguous id.
|
|
227
|
-
*/
|
|
228
|
-
wait(id: string, options?: TaskWaitOptions): Promise<TaskWaitResult>;
|
|
229
|
-
/**
|
|
230
|
-
* Observe the first task running at call time to settle. Tasks started later are excluded,
|
|
231
|
-
* and `no_tasks` is returned for an empty cohort. Delivery holds cover the whole cohort until
|
|
232
|
-
* the observation completes; members other than the winner then resume ordinary notification.
|
|
191
|
+
* The running task's live Output from its executor's `present`, or `undefined` for an unknown,
|
|
192
|
+
* settled or presenter-less task, or when the presenter throws; callers then use the default view.
|
|
233
193
|
*/
|
|
234
|
-
|
|
194
|
+
presentOutput(id: string, width: number, theme: Theme): string[] | undefined;
|
|
235
195
|
kill(id: string): boolean;
|
|
236
196
|
/**
|
|
237
197
|
* Move running foreground executions to the background while background slots remain;
|
|
@@ -251,8 +211,6 @@ export interface TaskRuntimeOptions {
|
|
|
251
211
|
backgroundAllowed?: boolean;
|
|
252
212
|
/** Branch-impact queries for a durable host; standalone runtimes omit it. */
|
|
253
213
|
session?: TasksSessionContext;
|
|
254
|
-
/** Wait receipts and steering interruption for a durable host; standalone runtimes leave waits observational. */
|
|
255
|
-
waits?: TaskWaitHost;
|
|
256
214
|
anchor?: () => string | null;
|
|
257
215
|
/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */
|
|
258
216
|
maxBackground?: number;
|
|
@@ -262,7 +220,21 @@ export interface TaskRuntimeOptions {
|
|
|
262
220
|
onCleanupError?: (message: string) => void;
|
|
263
221
|
/** Synchronous persistence before terminal observers or notifications. */
|
|
264
222
|
onSettled?: (task: TaskSnapshot, usage: Usage | undefined) => void;
|
|
223
|
+
/**
|
|
224
|
+
* Whether the host can supervise new background work, such as its management tool being
|
|
225
|
+
* active. Gates admission and detaching only; work already admitted is unaffected.
|
|
226
|
+
*/
|
|
227
|
+
canManageBackground?: () => boolean;
|
|
228
|
+
/** The runtime closed: a host holding retention pins for it must release them so output cleanup runs. */
|
|
229
|
+
onClosed?: () => void;
|
|
265
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background
|
|
233
|
+
* work is admitted only while it is active, so the model can always read and stop what
|
|
234
|
+
* it starts. Model-facing copy names it through this constant.
|
|
235
|
+
*/
|
|
236
|
+
export declare const TASKS_TOOL_NAME = "tasks";
|
|
237
|
+
export declare const TASK_MANAGEMENT_REJECTION = "Background execution needs the tasks tool to read and stop the work, and it is not active. Activate the tasks tool or run in the foreground. No work was started.";
|
|
266
238
|
export declare const TASK_BACKGROUND_REJECTION = "Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";
|
|
267
239
|
export declare function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus;
|
|
268
240
|
/**
|
|
@@ -276,5 +248,4 @@ export declare class TaskLookupError extends Error {
|
|
|
276
248
|
readonly matches: TaskSnapshot[];
|
|
277
249
|
constructor(kind: "unknown" | "ambiguous", matches: TaskSnapshot[]);
|
|
278
250
|
}
|
|
279
|
-
export {};
|
|
280
251
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"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"}
|
package/dist/core/tasks/types.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export const TASK_TERMINAL_STATUSES = ["completed", "partial", "failed", "cancelled", "timeout"];
|
|
2
2
|
export const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
3
|
+
/**
|
|
4
|
+
* The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background
|
|
5
|
+
* work is admitted only while it is active, so the model can always read and stop what
|
|
6
|
+
* it starts. Model-facing copy names it through this constant.
|
|
7
|
+
*/
|
|
8
|
+
export const TASKS_TOOL_NAME = "tasks";
|
|
9
|
+
export const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read and stop the work, and it is not active. Activate the ${TASKS_TOOL_NAME} tool or run in the foreground. No work was started.`;
|
|
3
10
|
export const TASK_BACKGROUND_REJECTION = "Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";
|
|
4
11
|
export function isTaskTerminal(status) {
|
|
5
12
|
return TASK_TERMINAL_STATUSES.includes(status);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAG1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AAgR1D,MAAM,CAAC,MAAM,yBAAyB,GACrC,yHAAyH,CAAC;AAE3H,MAAM,UAAU,cAAc,CAAC,MAAkB;IAChD,OAAQ,sBAA4C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGzC,YAAY,IAA6B,EAAE,OAAuB;QACjE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\n\n/** An executor-owned machine source: the task ID prefix, never a dispatch key for the runtime. */\nexport type TaskKind = string;\nexport type TaskMode = \"foreground\" | \"background\";\nexport const TASK_TERMINAL_STATUSES = [\"completed\", \"partial\", \"failed\", \"cancelled\", \"timeout\"] as const;\nexport type TaskTerminalStatus = (typeof TASK_TERMINAL_STATUSES)[number];\nexport type TaskStatus = \"queued\" | \"running\" | \"stopping\" | TaskTerminalStatus;\nexport const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\n/**\n * How a task's output is shaped, declared by its executor:\n * a `log` streams and carries its outcome at the end; a `report` is one finished document.\n */\nexport type TaskOutputKind = \"log\" | \"report\";\n\n/** A bounded snapshot; truncation is recorded at the source, never inferred from text. */\nexport interface TaskText {\n\ttext: string;\n\ttruncated: boolean;\n}\n\n/** What the task was asked to do, such as a shell command or a delegated briefing. */\nexport interface TaskInput extends TaskText {\n\t/** Human label for the input, such as \"Command\" or \"Prompt\". */\n\tlabel: string;\n\t/** Optional syntax-highlighting language. */\n\tlanguage?: string;\n}\n\n/** One labelled Details row, such as [\"Directory\", \"/repo\"] or [\"Exit\", \"1\"]. */\nexport type TaskFact = readonly [label: string, value: string];\n\n/** A read-only view of one task; the runtime returns frozen snapshots. */\nexport interface TaskSnapshot {\n\tid: string;\n\tkind: TaskKind;\n\t/** Human source name, such as \"Bash\" or \"Agent\". */\n\tlabel: string;\n\ttitle: string;\n\toutput: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tanchorId: string | null;\n\tmode: TaskMode;\n\tstatus: TaskStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\toutputPath?: string;\n\t/** Bounded model-readable result text. */\n\tresult?: TaskText;\n\t/** Additional human-only Output text; model-facing reads use the result instead. */\n\tdisplay?: TaskText;\n\terror?: string;\n}\n\nexport interface TaskUpdate<T> {\n\t/** Model-readable progress; also forwarded to a foreground caller's onUpdate. */\n\tresult: AgentToolResult<T>;\n\t/** Additional human-only Output text. */\n\tdisplay?: string;\n\t/** Cumulative usage so far, settled once if the execution ends without a final usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskCompletion<T> {\n\tresult: AgentToolResult<T>;\n\t/** Defaults to completed, or cancelled when the task was already cancelled. */\n\tstatus?: TaskTerminalStatus;\n\t/** Additional human-only Output text, excluded from tasks read and completion context. */\n\tdisplay?: string;\n\t/** Terminal diagnostic, stored independently of log slices and bounded to 4096 bytes. */\n\terror?: string;\n\t/** Terminal Details rows; a label replaces the same label given at launch. */\n\tfacts?: TaskFact[];\n\t/** Authoritative cumulative usage; overrides the result's usage and the latest published usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskControl<T> {\n\treadonly id: string;\n\treadonly signal: AbortSignal;\n\treadonly mode: TaskMode;\n\tonModeChange(listener: (mode: TaskMode) => void): () => void;\n\t/** The executor's own preflight passed; from now on the caller may be handed off to the background. */\n\taccept(): void;\n\tpublish(update: TaskUpdate<T>): void;\n\t/** Register once; cleanup must own only this exclusively-created file and close its writer first. */\n\tattachOutput(path: string, cleanup?: () => void | Promise<void>): void;\n\t/** Cancel this execution, for example when an executor policy limit is exceeded. */\n\tcancel(): void;\n}\n\nexport interface TaskExecution<T> {\n\tkind: TaskKind;\n\t/** Human source name; defaults to `kind`. */\n\tlabel?: string;\n\ttitle: string;\n\t/** Defaults to `log`. */\n\toutput?: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tbackground?: boolean;\n\t/**\n\t * At most `limit` executions sharing `key` run at once. Later ones wait as queued tasks\n\t * whose `run` starts when a slot frees; a queued task can be handed off or cancelled.\n\t */\n\tconcurrency?: { key: string; limit: number };\n\tsignal?: AbortSignal;\n\tonUpdate?: (result: AgentToolResult<T>) => void;\n\trun(control: TaskControl<T>): Promise<TaskCompletion<T>>;\n}\n\nexport type TaskToolOutcome<T> =\n\t| { kind: \"result\"; result: AgentToolResult<T>; status: TaskTerminalStatus; error?: string }\n\t| { kind: \"background\"; task: TaskSnapshot };\n\n/** Which slice of a task's output to read. Defaults to the last 8 KiB. */\nexport interface TaskReadOptions {\n\t/** `tail` (default) reads the end of the output, `head` its start. */\n\tmode?: \"head\" | \"tail\";\n\t/** Maximum bytes to return, bounded by the runtime. */\n\tbytes?: number;\n\t/** Only output written after this byte offset; takes precedence over `mode`. */\n\tsinceBytes?: number;\n}\n\nexport interface TaskRead {\n\ttask: TaskSnapshot;\n\ttext: string;\n\t/** Bounded log-read/expiry diagnostic, independent of text slicing and byte offsets. */\n\treadError?: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte?: number;\n}\n\n/** Optional host integration for products built on the execution runtime. */\nexport interface TasksSessionContext {\n\t/** Running tasks that navigating to `targetId` would cancel on this session branch. */\n\tstoppedByTreeNavigation(targetId: string): TaskSnapshot[];\n}\n\n/** How a wait ended. `closed` means the host shut down, so execution state is unconfirmed. */\nexport type TaskWaitOutcome = \"settled\" | \"interrupted\" | \"timed_out\" | \"closed\";\n\ninterface TaskObservationOptions {\n\t/** Defaults to 20 seconds and is bounded by the runtime. A timeout never cancels execution. */\n\ttimeoutMs?: number;\n\t/** Rejects the wait with the signal's reason; execution continues. */\n\tsignal?: AbortSignal;\n\t/**\n\t * The tool call whose result carries this observation to the model. With a session host, a\n\t * settled background task stays out of automatic notifications until that result is persisted.\n\t * Without it, or in a standalone runtime, the wait is purely observational.\n\t */\n\ttoolCallId?: string;\n}\n\nexport interface TaskWaitOptions extends TaskObservationOptions {\n\t/** Read output while delivery is still held; skipped when steering interrupted the wait. */\n\tread?: Pick<TaskReadOptions, \"bytes\" | \"sinceBytes\">;\n}\n\nexport interface TaskWaitResult {\n\toutcome: TaskWaitOutcome;\n\twaitedMs: number;\n\t/** The task when the wait ended, before `read` was taken. */\n\ttask: TaskSnapshot;\n\tread?: TaskRead;\n}\n\nexport interface TaskWaitAnyOptions extends TaskObservationOptions {\n\t/** Read the settled task's output while delivery is still held. */\n\tread?: Pick<TaskReadOptions, \"bytes\">;\n}\n\nexport interface TaskWaitAnyResult {\n\t/** `no_tasks`: no background task was running at call time, so nothing was observed. */\n\toutcome: TaskWaitOutcome | \"no_tasks\";\n\twaitedMs: number;\n\t/** The first cohort member to settle; present only for `settled`. */\n\ttask?: TaskSnapshot;\n\tread?: TaskRead;\n\t/** Cohort members still running when the wait ended. */\n\trunning: TaskSnapshot[];\n}\n\n/**\n * Host hooks that make waits part of a durable session. TaskSession supplies them; products\n * embedding a bare TaskRuntime omit them and keep waits observational.\n */\nexport interface TaskWaitHost {\n\t/** Current steering signal. Aborting it ends management waits only, never execution. */\n\treadonly interruptSignal: AbortSignal;\n\t/**\n\t * A wait observed a settled background task and its `toolCallId` is known. Called while the\n\t * runtime still holds delivery; the host takes over until that tool result persists.\n\t */\n\tbind(toolCallId: string, taskId: string): void;\n}\n\n/**\n * What TaskDelivery consumes from the runtime. The runtime keeps only the per-record facts that\n * retention and admission need (a settled handoff is undelivered, claimed or delivered, and a\n * record under a hold is never a candidate); pausing, failure tracking, the in-flight delivery\n * and wait receipts belong to TaskDelivery.\n */\nexport interface TaskDeliveryLedger {\n\treadonly enabled: boolean;\n\tlist(): TaskSnapshot[];\n\t/** Settled handoffs eligible for automatic delivery: visible, unclaimed, unobserved and unheld. */\n\tpendingNotifications(): TaskSnapshot[];\n\t/** Take a pending notification; false when it is no longer a candidate. */\n\tclaimNotification(id: string): boolean;\n\t/** Return a claimed notification to pending after a failed delivery. */\n\treleaseNotification(id: string): void;\n\t/** Acknowledge a persisted delivery or wait result. */\n\tmarkDelivered(id: string): void;\n\t/** Keep a record out of automatic delivery, and its output retained, until released. */\n\tholdDelivery(id: string): () => void;\n}\n\n/** Session-bound public capability. Captured instances close on runtime replacement. */\nexport interface TasksContext {\n\treadonly enabled: boolean;\n\treadonly closed?: boolean;\n\t/** Present when the runtime is attached to Pi's durable session lifecycle. */\n\treadonly session?: TasksSessionContext;\n\texecute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>>;\n\tlist(): TaskSnapshot[];\n\tget(id: string): TaskSnapshot;\n\tread(id: string, options?: TaskReadOptions): Promise<TaskRead>;\n\t/**\n\t * Observe one task. With `toolCallId` in a session host, the whole observation (wait, read,\n\t * receipt) is atomic with respect to automatic delivery; a standalone runtime never\n\t * acknowledges delivery. Rejects with `TaskLookupError` for an unknown or ambiguous id.\n\t */\n\twait(id: string, options?: TaskWaitOptions): Promise<TaskWaitResult>;\n\t/**\n\t * Observe the first task running at call time to settle. Tasks started later are excluded,\n\t * and `no_tasks` is returned for an empty cohort. Delivery holds cover the whole cohort until\n\t * the observation completes; members other than the winner then resume ordinary notification.\n\t */\n\twaitAny(options?: TaskWaitAnyOptions): Promise<TaskWaitAnyResult>;\n\tkill(id: string): boolean;\n\t/**\n\t * Move running foreground executions to the background while background slots remain;\n\t * returns how many moved. Throws when eligible work exists but every slot is taken.\n\t */\n\tdetachForeground(): number;\n\t/** Whether this execution can move now, including host policy and available background slots. */\n\tcanDetach(id: string): boolean;\n\t/** Returns false when the task cannot move; throws when every background slot is taken. */\n\tdetach(id: string): boolean;\n\tsubscribe(listener: () => void): () => void;\n\t/** Keep retained output available without delaying completion delivery. */\n\tretain(id: string): () => void;\n}\n\nexport interface TaskRuntimeOptions {\n\tenabled?: boolean;\n\tbackgroundAllowed?: boolean;\n\t/** Branch-impact queries for a durable host; standalone runtimes omit it. */\n\tsession?: TasksSessionContext;\n\t/** Wait receipts and steering interruption for a durable host; standalone runtimes leave waits observational. */\n\twaits?: TaskWaitHost;\n\tanchor?: () => string | null;\n\t/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */\n\tmaxBackground?: number;\n\t/** Per-history limit: foreground and background tasks each get this allowance. */\n\tmaxHistory?: number;\n\t/** Best-effort cleanup errors, bounded to 4096 bytes; no retries or execution failure. */\n\tonCleanupError?: (message: string) => void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tonSettled?: (task: TaskSnapshot, usage: Usage | undefined) => void;\n}\n\nexport const TASK_BACKGROUND_REJECTION =\n\t\"Background execution is not permitted in this host. Run with background: false or omit background. No work was started.\";\n\nexport function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus {\n\treturn (TASK_TERMINAL_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * A failed id lookup, typed so hosts can enrich the message without matching\n * on message text. `matches` snapshots exactly the records the id or prefix\n * resolved against — including records outside the current branch, which\n * list() hides but prefix matching still collides with.\n */\nexport class TaskLookupError extends Error {\n\treadonly kind: \"unknown\" | \"ambiguous\";\n\treadonly matches: TaskSnapshot[];\n\tconstructor(kind: \"unknown\" | \"ambiguous\", matches: TaskSnapshot[]) {\n\t\tsuper(kind === \"ambiguous\" ? \"Ambiguous task ID\" : \"Unknown task ID\");\n\t\tthis.name = \"TaskLookupError\";\n\t\tthis.kind = kind;\n\t\tthis.matches = matches;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/tasks/types.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAG1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AA+N1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,eAAe,uEAAuE,eAAe,sDAAsD,CAAC;AAEvO,MAAM,CAAC,MAAM,yBAAyB,GACrC,yHAAyH,CAAC;AAE3H,MAAM,UAAU,cAAc,CAAC,MAAkB;IAChD,OAAQ,sBAA4C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAGzC,YAAY,IAA6B,EAAE,OAAuB;QACjE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;CACD","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\n/** An executor-owned machine source: the task ID prefix, never a dispatch key for the runtime. */\nexport type TaskKind = string;\n/**\n * Where the task actually runs. `background` exactly when its caller was released with a\n * background outcome; a caller that is waiting, or was asked to leave but is still held while\n * the executor prepares, is `foreground`.\n */\nexport type TaskMode = \"foreground\" | \"background\";\nexport const TASK_TERMINAL_STATUSES = [\"completed\", \"partial\", \"failed\", \"cancelled\", \"timeout\"] as const;\nexport type TaskTerminalStatus = (typeof TASK_TERMINAL_STATUSES)[number];\nexport type TaskStatus = \"queued\" | \"running\" | \"stopping\" | TaskTerminalStatus;\nexport const TASK_KIND_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\n/**\n * How a task's output is shaped, declared by its executor:\n * a `log` streams and carries its outcome at the end; a `report` is one finished document.\n */\nexport type TaskOutputKind = \"log\" | \"report\";\n\n/** A bounded snapshot; truncation is recorded at the source, never inferred from text. */\nexport interface TaskText {\n\ttext: string;\n\ttruncated: boolean;\n}\n\n/** What the task was asked to do, such as a shell command or a delegated briefing. */\nexport interface TaskInput extends TaskText {\n\t/** Human label for the input, such as \"Command\" or \"Prompt\". */\n\tlabel: string;\n\t/** Optional syntax-highlighting language. */\n\tlanguage?: string;\n}\n\n/** One labelled Details row, such as [\"Directory\", \"/repo\"] or [\"Exit\", \"1\"]. */\nexport type TaskFact = readonly [label: string, value: string];\n\n/** A read-only view of one task; the runtime returns frozen snapshots. */\nexport interface TaskSnapshot {\n\tid: string;\n\tkind: TaskKind;\n\t/** Human source name, such as \"Bash\" or \"Agent\". */\n\tlabel: string;\n\ttitle: string;\n\toutput: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tanchorId: string | null;\n\tmode: TaskMode;\n\tstatus: TaskStatus;\n\tstartedAt: number;\n\tendedAt?: number;\n\toutputPath?: string;\n\t/** Bounded model-readable result text. */\n\tresult?: TaskText;\n\t/**\n\t * The executor's human-only view. In /tasks it replaces the result as what a person reads;\n\t * model-facing reads always use `result`. A terminal snapshot has one only if the completion\n\t * supplied it: the last progress display does not survive settlement.\n\t */\n\tdisplay?: TaskText;\n\terror?: string;\n}\n\nexport interface TaskUpdate<T> {\n\t/** Model-readable progress; also forwarded to a foreground caller's onUpdate. */\n\tresult: AgentToolResult<T>;\n\t/** The live human-only view while running; replaces the result in /tasks and ends at settlement. */\n\tdisplay?: string;\n\t/** Cumulative usage so far, settled once if the execution ends without a final usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskCompletion<T> {\n\tresult: AgentToolResult<T>;\n\t/** Defaults to completed, or cancelled when the task was already cancelled. */\n\tstatus?: TaskTerminalStatus;\n\t/**\n\t * The terminal human-only view. In /tasks it replaces the result as what a person reads; model-facing\n\t * reads and completion context always use `result`. Without it, the terminal snapshot has no display.\n\t */\n\tdisplay?: string;\n\t/** Terminal diagnostic, stored independently of log slices and bounded to 4096 bytes. */\n\terror?: string;\n\t/** Terminal Details rows; a label replaces the same label given at launch. */\n\tfacts?: TaskFact[];\n\t/** Authoritative cumulative usage; overrides the result's usage and the latest published usage. */\n\tusage?: Usage;\n}\n\nexport interface TaskControl<T> {\n\treadonly id: string;\n\treadonly signal: AbortSignal;\n\t/** Actual placement: `background` only once the caller was released. */\n\treadonly mode: TaskMode;\n\t/** Called once the caller is released and the mode becomes `background`. */\n\tonModeChange(listener: (mode: TaskMode) => void): () => void;\n\t/** The executor's own preflight passed; from now on the caller may be handed off to the background. */\n\taccept(): void;\n\tpublish(update: TaskUpdate<T>): void;\n\t/** Register once; cleanup must own only this exclusively-created file and close its writer first. */\n\tattachOutput(path: string, cleanup?: () => void | Promise<void>): void;\n\t/** Cancel this execution, for example when an executor policy limit is exceeded. */\n\tcancel(): void;\n}\n\n/**\n * Renders a live task's human Output in the Tasks panel: styled, already fitted lines of at most\n * `width` columns, or `undefined` to use the default view (the published `display`, else the\n * result). Called on every repaint while the task runs, so it must be cheap and synchronous.\n * It lives in memory with the running task: never persisted, absent from snapshots, and dropped\n * at settlement. The returned text is trusted extension output, not task text.\n */\nexport type TaskPresenter = (width: number, theme: Theme) => string[] | undefined;\n\nexport interface TaskExecution<T> {\n\tkind: TaskKind;\n\t/** Human source name; defaults to `kind`. */\n\tlabel?: string;\n\ttitle: string;\n\t/** Defaults to `log`. */\n\toutput?: TaskOutputKind;\n\tinput?: TaskInput;\n\tfacts?: TaskFact[];\n\ttoolCallId: string;\n\tbackground?: boolean;\n\t/**\n\t * At most `limit` executions sharing `key` run at once; lanes belong to one `kind`, so another\n\t * executor may reuse the key. Later ones wait as queued tasks whose `run` starts when a slot\n\t * frees; a queued task can be handed off or cancelled.\n\t */\n\tconcurrency?: { key: string; limit: number };\n\tsignal?: AbortSignal;\n\tonUpdate?: (result: AgentToolResult<T>) => void;\n\t/** Renders the running task's Output in /tasks; see {@link TaskPresenter}. Dropped at settlement. */\n\tpresent?: TaskPresenter;\n\trun(control: TaskControl<T>): Promise<TaskCompletion<T>>;\n}\n\n/**\n * How a tool call ends. A `background` outcome says why the caller was released: `submitted`\n * when it asked for background, `detached` when it was moved while the work ran.\n */\nexport type TaskToolOutcome<T> =\n\t| { kind: \"result\"; result: AgentToolResult<T>; status: TaskTerminalStatus; error?: string }\n\t| { kind: \"background\"; task: TaskSnapshot; reason: \"submitted\" | \"detached\" };\n\n/** Which slice of a task's output to read. Defaults to 8 KiB. */\nexport interface TaskReadOptions {\n\t/**\n\t * `head` reads the start of the output, `tail` its end. Without it a `report` is read from its\n\t * start and a `log` from its end.\n\t */\n\tmode?: \"head\" | \"tail\";\n\t/** Maximum bytes to return, bounded by the runtime. */\n\tbytes?: number;\n\t/**\n\t * First unread byte. `head` reads forward from this offset; `tail` returns the newest window\n\t * at or after it. Without it the output kind selects the default end.\n\t */\n\tsinceBytes?: number;\n}\n\nexport interface TaskRead {\n\ttask: TaskSnapshot;\n\ttext: string;\n\t/** Bounded log-read/expiry diagnostic, independent of text slicing and byte offsets. */\n\treadError?: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte?: number;\n\t/** Raw source-byte end supplied by the runtime; older/custom hosts may omit it. */\n\tendByte?: number;\n}\n\n/** Optional host integration for products built on the execution runtime. */\nexport interface TasksSessionContext {\n\t/** Running tasks that navigating to `targetId` would cancel on this session branch. */\n\tstoppedByTreeNavigation(targetId: string): TaskSnapshot[];\n}\n\n/** Session-bound public capability. Captured instances close on runtime replacement. */\nexport interface TasksContext {\n\treadonly enabled: boolean;\n\treadonly closed?: boolean;\n\t/** Present when the runtime is attached to Pi's durable session lifecycle. */\n\treadonly session?: TasksSessionContext;\n\texecute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>>;\n\tlist(): TaskSnapshot[];\n\tget(id: string): TaskSnapshot;\n\tread(id: string, options?: TaskReadOptions): Promise<TaskRead>;\n\t/**\n\t * The running task's live Output from its executor's `present`, or `undefined` for an unknown,\n\t * settled or presenter-less task, or when the presenter throws; callers then use the default view.\n\t */\n\tpresentOutput(id: string, width: number, theme: Theme): string[] | undefined;\n\tkill(id: string): boolean;\n\t/**\n\t * Move running foreground executions to the background while background slots remain;\n\t * returns how many moved. Throws when eligible work exists but every slot is taken.\n\t */\n\tdetachForeground(): number;\n\t/** Whether this execution can move now, including host policy and available background slots. */\n\tcanDetach(id: string): boolean;\n\t/** Returns false when the task cannot move; throws when every background slot is taken. */\n\tdetach(id: string): boolean;\n\tsubscribe(listener: () => void): () => void;\n\t/** Keep retained output available without delaying completion delivery. */\n\tretain(id: string): () => void;\n}\n\nexport interface TaskRuntimeOptions {\n\tenabled?: boolean;\n\tbackgroundAllowed?: boolean;\n\t/** Branch-impact queries for a durable host; standalone runtimes omit it. */\n\tsession?: TasksSessionContext;\n\tanchor?: () => string | null;\n\t/** Admission limit for unsettled background tasks; foreground work is bounded by its caller. */\n\tmaxBackground?: number;\n\t/** Per-history limit: foreground and background tasks each get this allowance. */\n\tmaxHistory?: number;\n\t/** Best-effort cleanup errors, bounded to 4096 bytes; no retries or execution failure. */\n\tonCleanupError?: (message: string) => void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tonSettled?: (task: TaskSnapshot, usage: Usage | undefined) => void;\n\t/**\n\t * Whether the host can supervise new background work, such as its management tool being\n\t * active. Gates admission and detaching only; work already admitted is unaffected.\n\t */\n\tcanManageBackground?: () => boolean;\n\t/** The runtime closed: a host holding retention pins for it must release them so output cleanup runs. */\n\tonClosed?: () => void;\n}\n\n/**\n * The model-facing management tool, owned by the bundled `builtin:tasks` extension. Background\n * work is admitted only while it is active, so the model can always read and stop what\n * it starts. Model-facing copy names it through this constant.\n */\nexport const TASKS_TOOL_NAME = \"tasks\";\n\nexport const TASK_MANAGEMENT_REJECTION = `Background execution needs the ${TASKS_TOOL_NAME} tool to read and stop the work, and it is not active. Activate the ${TASKS_TOOL_NAME} tool or run in the foreground. No work was started.`;\n\nexport const TASK_BACKGROUND_REJECTION =\n\t\"Background execution is not permitted in this host. Run with background: false or omit background. No work was started.\";\n\nexport function isTaskTerminal(status: TaskStatus): status is TaskTerminalStatus {\n\treturn (TASK_TERMINAL_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * A failed id lookup, typed so hosts can enrich the message without matching\n * on message text. `matches` snapshots exactly the records the id or prefix\n * resolved against — including records outside the current branch, which\n * list() hides but prefix matching still collides with.\n */\nexport class TaskLookupError extends Error {\n\treadonly kind: \"unknown\" | \"ambiguous\";\n\treadonly matches: TaskSnapshot[];\n\tconstructor(kind: \"unknown\" | \"ambiguous\", matches: TaskSnapshot[]) {\n\t\tsuper(kind === \"ambiguous\" ? \"Ambiguous task ID\" : \"Unknown task ID\");\n\t\tthis.name = \"TaskLookupError\";\n\t\tthis.kind = kind;\n\t\tthis.matches = matches;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-execution.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-execution.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,eAAO,MAAM,2BAA2B,QAAmB,CAAC;AAE5D,UAAU,qBAAqB;IAC9B,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,WAAW,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAClD;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;CACjB;AAwCD,6EAA6E;AAC7E,wBAAsB,eAAe,CACpC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,cAAc,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"shell-execution.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-execution.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,eAAO,MAAM,2BAA2B,QAAmB,CAAC;AAE5D,UAAU,qBAAqB;IAC9B,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,WAAW,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAClD;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAC;CACjB;AAwCD,6EAA6E;AAC7E,wBAAsB,eAAe,CACpC,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,cAAc,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC,CAkKtD"}
|
|
@@ -198,7 +198,8 @@ export async function runShellCommand(options) {
|
|
|
198
198
|
...(failure ? { isError: true } : {}),
|
|
199
199
|
}
|
|
200
200
|
: {}),
|
|
201
|
-
|
|
201
|
+
// The command's output only: its failure is the completion's `error`, composed where a result is shown.
|
|
202
|
+
content: [{ type: "text", text }],
|
|
202
203
|
details,
|
|
203
204
|
},
|
|
204
205
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-execution.js","sourceRoot":"","sources":["../../../src/core/tools/shell-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { unlink } from \"node:fs/promises\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { boundText } from \"../tasks/output.ts\";\nimport type { TaskCompletion, TaskControl } from \"../tasks/types.ts\";\nimport type { BashOperations, BashSpawnContext } from \"./bash.ts\";\nimport { OutputAccumulator, type OutputSnapshot } from \"./output-accumulator.ts\";\nimport { BASH_UPDATE_THROTTLE_MS } from \"./renderers/bash.ts\";\nimport type { BashToolDetails } from \"./shell-tool.ts\";\nimport { formatSize } from \"./truncate.ts\";\n\nexport const MAX_BACKGROUND_OUTPUT_BYTES = 20 * 1024 * 1024;\n\ninterface ShellExecutionOptions {\n\toperations: BashOperations;\n\tcontext: BashSpawnContext;\n\ttempFilePrefix: string;\n\ttimeout?: number;\n\t/** The task this command runs as; its signal cancels the process. */\n\tcontrol: TaskControl<BashToolDetails | undefined>;\n\t/**\n\t * The command belongs to a session task, which may leave the foreground: its output log is\n\t * created and attached to the task from the first byte, and a final snapshot is always\n\t * published. Otherwise the log is created only if output is truncated.\n\t */\n\ttaskLog: boolean;\n}\n\ninterface ShellFailure {\n\tstatus: \"failed\" | \"cancelled\" | \"timeout\";\n\terror: string;\n}\n\n/** Interpret the documented BashOperations error markers once, before formatting output. */\nfunction shellFailure(error: unknown): ShellFailure {\n\tif (error instanceof Error && error.message === \"aborted\") return { status: \"cancelled\", error: \"Command aborted\" };\n\tif (error instanceof Error && error.message.startsWith(\"timeout:\"))\n\t\treturn { status: \"timeout\", error: `Command timed out after ${error.message.split(\":\")[1]} seconds` };\n\treturn { status: \"failed\", error: boundText(error instanceof Error ? error.message : String(error), 4096) };\n}\n\nfunction formatOutput(\n\toutput: OutputAccumulator,\n\tsnapshot: OutputSnapshot,\n\ttaskLog: boolean,\n\temptyText: string,\n): { text: string; details: BashToolDetails | undefined } {\n\tconst truncation = snapshot.truncation;\n\tlet text = snapshot.content || emptyText;\n\tlet details: BashToolDetails | undefined = taskLog ? { fullOutputPath: snapshot.fullOutputPath } : undefined;\n\tif (truncation.truncated) {\n\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\tconst endLine = truncation.totalLines;\n\t\tif (truncation.lastLinePartial) {\n\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t} else {\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(truncation.maxBytes)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t}\n\t}\n\treturn { text, details };\n}\n\n/** One process and one output owner across foreground/background handoff. */\nexport async function runShellCommand(\n\toptions: ShellExecutionOptions,\n): Promise<TaskCompletion<BashToolDetails | undefined>> {\n\tconst { operations, context, control, taskLog, timeout } = options;\n\tconst signal = control.signal;\n\tconst output = new OutputAccumulator({ tempFilePrefix: options.tempFilePrefix, persistFromStart: taskLog });\n\tconst startedAt = performance.now();\n\tlet outputError: Error | undefined;\n\tlet acceptingOutput = true;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet updateTimer: NodeJS.Timeout | undefined;\n\tlet updateDirty = false;\n\tlet lastUpdateAt = 0;\n\n\tconst failOutput = (error: unknown) => {\n\t\tif (outputError) return;\n\t\toutputError = error instanceof Error ? error : new Error(String(error));\n\t\ttry {\n\t\t\tcontrol.cancel();\n\t\t} catch {\n\t\t\t// Late data must not throw through a process observer.\n\t\t}\n\t};\n\tconst checkOutputLimit = () => {\n\t\tif (control.mode === \"background\" && output.getTotalBytes() > MAX_BACKGROUND_OUTPUT_BYTES) {\n\t\t\tfailOutput(new Error(\"Background command exceeded the 20 MiB output limit\"));\n\t\t}\n\t};\n\tconst snapshot = () =>\n\t\toutput.snapshot({\n\t\t\tpersistIfTruncated: true,\n\t\t\tmaxBytes: control.mode === \"background\" ? 40 * 1024 : undefined,\n\t\t});\n\tconst publish = (snapshot?: OutputSnapshot) => {\n\t\tconst result: AgentToolResult<BashToolDetails | undefined> = {\n\t\t\tcontent: snapshot ? [{ type: \"text\", text: snapshot.content }] : [],\n\t\t\tdetails: snapshot\n\t\t\t\t? {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t};\n\t\tcontrol.publish({ result });\n\t};\n\tconst emitOutputUpdate = () => {\n\t\tif (!updateDirty) return;\n\t\tupdateDirty = false;\n\t\tlastUpdateAt = Date.now();\n\t\tpublish(snapshot());\n\t};\n\tconst clearUpdateTimer = () => {\n\t\tif (updateTimer) clearTimeout(updateTimer);\n\t\tupdateTimer = undefined;\n\t};\n\tconst scheduleOutputUpdate = () => {\n\t\tupdateDirty = true;\n\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\tif (delay <= 0) {\n\t\t\tclearUpdateTimer();\n\t\t\temitOutputUpdate();\n\t\t} else {\n\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\tupdateTimer = undefined;\n\t\t\t\temitOutputUpdate();\n\t\t\t}, delay);\n\t\t}\n\t};\n\tconst handleData = (data: Buffer) => {\n\t\tif (!acceptingOutput || outputError) return;\n\t\ttry {\n\t\t\tif (control.mode === \"background\" && output.getTotalBytes() + data.length > MAX_BACKGROUND_OUTPUT_BYTES) {\n\t\t\t\tconst remaining = Math.max(0, MAX_BACKGROUND_OUTPUT_BYTES - output.getTotalBytes());\n\t\t\t\toutput.append(data.subarray(0, remaining));\n\t\t\t\tfailOutput(new Error(\"Background command exceeded the 20 MiB output limit\"));\n\t\t\t} else output.append(data);\n\t\t\tscheduleOutputUpdate();\n\t\t} catch (error) {\n\t\t\tfailOutput(error);\n\t\t}\n\t};\n\n\ttry {\n\t\tif (taskLog) {\n\t\t\tconst path = output.snapshot().fullOutputPath!;\n\t\t\tconst cleanup = async () => {\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\tawait unlink(path).catch((error: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (error.code !== \"ENOENT\") throw error;\n\t\t\t\t});\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcontrol.attachOutput(path, cleanup);\n\t\t\t} catch (error) {\n\t\t\t\tawait cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\t// Detach must check a silent foreground log too, preserving bytes already written.\n\t\tunsubscribe = control.onModeChange(checkOutputLimit);\n\t\tpublish();\n\t\tlet failure: ShellFailure | undefined;\n\t\tlet exitCode: number | null | undefined;\n\t\ttry {\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst execution = operations.exec(context.command, context.cwd, {\n\t\t\t\tonData: handleData,\n\t\t\t\tsignal,\n\t\t\t\ttimeout,\n\t\t\t\tenv: context.env,\n\t\t\t});\n\t\t\tcontrol.accept();\n\t\t\t({ exitCode } = await execution);\n\t\t\tif (exitCode === null) {\n\t\t\t\tfailure = { status: \"failed\", error: \"Command terminated without an exit code\" };\n\t\t\t} else if (exitCode !== 0) {\n\t\t\t\tfailure = { status: \"failed\", error: `Command exited with code ${exitCode}` };\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tfailure = shellFailure(error);\n\t\t}\n\t\tacceptingOutput = false;\n\t\toutput.finish();\n\t\tclearUpdateTimer();\n\t\tif (taskLog) publish(snapshot());\n\t\telse emitOutputUpdate();\n\t\tconst final = snapshot();\n\t\tawait output.closeTempFile();\n\t\t// Final progress/cleanup can re-enter handoff. Classify policy cancellation\n\t\t// after those callbacks, independently of the process's abort marker.\n\t\tif (outputError) failure = { status: \"failed\", error: boundText(outputError.message, 4096) };\n\t\tconst { text, details } = formatOutput(output, final, taskLog, failure ? \"\" : \"(no output)\");\n\t\tconst fullOutput =\n\t\t\ttypeof exitCode === \"number\" && !outputError ? await output.readFullOutput(1024 * 1024) : undefined;\n\t\treturn {\n\t\t\tstatus: failure?.status,\n\t\t\terror: failure?.error,\n\t\t\t...(exitCode !== undefined ? { facts: [[\"Exit\", exitCode === null ? \"signal\" : String(exitCode)]] } : {}),\n\t\t\tresult: {\n\t\t\t\t...(fullOutput && typeof exitCode === \"number\"\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tstructuredContent: {\n\t\t\t\t\t\t\t\toutput: fullOutput.content,\n\t\t\t\t\t\t\t\ttruncated: fullOutput.truncated,\n\t\t\t\t\t\t\t\t...(fullOutput.truncated && final.fullOutputPath\n\t\t\t\t\t\t\t\t\t? { full_output_path: final.fullOutputPath }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\texit_code: exitCode,\n\t\t\t\t\t\t\t\twall_time_seconds: Math.round((performance.now() - startedAt) / 100) / 10,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t...(failure ? { isError: true } : {}),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tcontent: [{ type: \"text\", text: failure ? `${text ? `${text}\\n\\n` : \"\"}${failure.error}` : text }],\n\t\t\t\tdetails,\n\t\t\t},\n\t\t};\n\t} finally {\n\t\tacceptingOutput = false;\n\t\tunsubscribe?.();\n\t\tclearUpdateTimer();\n\t\tawait output.closeTempFile();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shell-execution.js","sourceRoot":"","sources":["../../../src/core/tools/shell-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { unlink } from \"node:fs/promises\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { boundText } from \"../tasks/output.ts\";\nimport type { TaskCompletion, TaskControl } from \"../tasks/types.ts\";\nimport type { BashOperations, BashSpawnContext } from \"./bash.ts\";\nimport { OutputAccumulator, type OutputSnapshot } from \"./output-accumulator.ts\";\nimport { BASH_UPDATE_THROTTLE_MS } from \"./renderers/bash.ts\";\nimport type { BashToolDetails } from \"./shell-tool.ts\";\nimport { formatSize } from \"./truncate.ts\";\n\nexport const MAX_BACKGROUND_OUTPUT_BYTES = 20 * 1024 * 1024;\n\ninterface ShellExecutionOptions {\n\toperations: BashOperations;\n\tcontext: BashSpawnContext;\n\ttempFilePrefix: string;\n\ttimeout?: number;\n\t/** The task this command runs as; its signal cancels the process. */\n\tcontrol: TaskControl<BashToolDetails | undefined>;\n\t/**\n\t * The command belongs to a session task, which may leave the foreground: its output log is\n\t * created and attached to the task from the first byte, and a final snapshot is always\n\t * published. Otherwise the log is created only if output is truncated.\n\t */\n\ttaskLog: boolean;\n}\n\ninterface ShellFailure {\n\tstatus: \"failed\" | \"cancelled\" | \"timeout\";\n\terror: string;\n}\n\n/** Interpret the documented BashOperations error markers once, before formatting output. */\nfunction shellFailure(error: unknown): ShellFailure {\n\tif (error instanceof Error && error.message === \"aborted\") return { status: \"cancelled\", error: \"Command aborted\" };\n\tif (error instanceof Error && error.message.startsWith(\"timeout:\"))\n\t\treturn { status: \"timeout\", error: `Command timed out after ${error.message.split(\":\")[1]} seconds` };\n\treturn { status: \"failed\", error: boundText(error instanceof Error ? error.message : String(error), 4096) };\n}\n\nfunction formatOutput(\n\toutput: OutputAccumulator,\n\tsnapshot: OutputSnapshot,\n\ttaskLog: boolean,\n\temptyText: string,\n): { text: string; details: BashToolDetails | undefined } {\n\tconst truncation = snapshot.truncation;\n\tlet text = snapshot.content || emptyText;\n\tlet details: BashToolDetails | undefined = taskLog ? { fullOutputPath: snapshot.fullOutputPath } : undefined;\n\tif (truncation.truncated) {\n\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\tconst endLine = truncation.totalLines;\n\t\tif (truncation.lastLinePartial) {\n\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t} else {\n\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(truncation.maxBytes)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t}\n\t}\n\treturn { text, details };\n}\n\n/** One process and one output owner across foreground/background handoff. */\nexport async function runShellCommand(\n\toptions: ShellExecutionOptions,\n): Promise<TaskCompletion<BashToolDetails | undefined>> {\n\tconst { operations, context, control, taskLog, timeout } = options;\n\tconst signal = control.signal;\n\tconst output = new OutputAccumulator({ tempFilePrefix: options.tempFilePrefix, persistFromStart: taskLog });\n\tconst startedAt = performance.now();\n\tlet outputError: Error | undefined;\n\tlet acceptingOutput = true;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet updateTimer: NodeJS.Timeout | undefined;\n\tlet updateDirty = false;\n\tlet lastUpdateAt = 0;\n\n\tconst failOutput = (error: unknown) => {\n\t\tif (outputError) return;\n\t\toutputError = error instanceof Error ? error : new Error(String(error));\n\t\ttry {\n\t\t\tcontrol.cancel();\n\t\t} catch {\n\t\t\t// Late data must not throw through a process observer.\n\t\t}\n\t};\n\tconst checkOutputLimit = () => {\n\t\tif (control.mode === \"background\" && output.getTotalBytes() > MAX_BACKGROUND_OUTPUT_BYTES) {\n\t\t\tfailOutput(new Error(\"Background command exceeded the 20 MiB output limit\"));\n\t\t}\n\t};\n\tconst snapshot = () =>\n\t\toutput.snapshot({\n\t\t\tpersistIfTruncated: true,\n\t\t\tmaxBytes: control.mode === \"background\" ? 40 * 1024 : undefined,\n\t\t});\n\tconst publish = (snapshot?: OutputSnapshot) => {\n\t\tconst result: AgentToolResult<BashToolDetails | undefined> = {\n\t\t\tcontent: snapshot ? [{ type: \"text\", text: snapshot.content }] : [],\n\t\t\tdetails: snapshot\n\t\t\t\t? {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t};\n\t\tcontrol.publish({ result });\n\t};\n\tconst emitOutputUpdate = () => {\n\t\tif (!updateDirty) return;\n\t\tupdateDirty = false;\n\t\tlastUpdateAt = Date.now();\n\t\tpublish(snapshot());\n\t};\n\tconst clearUpdateTimer = () => {\n\t\tif (updateTimer) clearTimeout(updateTimer);\n\t\tupdateTimer = undefined;\n\t};\n\tconst scheduleOutputUpdate = () => {\n\t\tupdateDirty = true;\n\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\tif (delay <= 0) {\n\t\t\tclearUpdateTimer();\n\t\t\temitOutputUpdate();\n\t\t} else {\n\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\tupdateTimer = undefined;\n\t\t\t\temitOutputUpdate();\n\t\t\t}, delay);\n\t\t}\n\t};\n\tconst handleData = (data: Buffer) => {\n\t\tif (!acceptingOutput || outputError) return;\n\t\ttry {\n\t\t\tif (control.mode === \"background\" && output.getTotalBytes() + data.length > MAX_BACKGROUND_OUTPUT_BYTES) {\n\t\t\t\tconst remaining = Math.max(0, MAX_BACKGROUND_OUTPUT_BYTES - output.getTotalBytes());\n\t\t\t\toutput.append(data.subarray(0, remaining));\n\t\t\t\tfailOutput(new Error(\"Background command exceeded the 20 MiB output limit\"));\n\t\t\t} else output.append(data);\n\t\t\tscheduleOutputUpdate();\n\t\t} catch (error) {\n\t\t\tfailOutput(error);\n\t\t}\n\t};\n\n\ttry {\n\t\tif (taskLog) {\n\t\t\tconst path = output.snapshot().fullOutputPath!;\n\t\t\tconst cleanup = async () => {\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\tawait unlink(path).catch((error: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (error.code !== \"ENOENT\") throw error;\n\t\t\t\t});\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcontrol.attachOutput(path, cleanup);\n\t\t\t} catch (error) {\n\t\t\t\tawait cleanup();\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\t// Detach must check a silent foreground log too, preserving bytes already written.\n\t\tunsubscribe = control.onModeChange(checkOutputLimit);\n\t\tpublish();\n\t\tlet failure: ShellFailure | undefined;\n\t\tlet exitCode: number | null | undefined;\n\t\ttry {\n\t\t\tif (signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst execution = operations.exec(context.command, context.cwd, {\n\t\t\t\tonData: handleData,\n\t\t\t\tsignal,\n\t\t\t\ttimeout,\n\t\t\t\tenv: context.env,\n\t\t\t});\n\t\t\tcontrol.accept();\n\t\t\t({ exitCode } = await execution);\n\t\t\tif (exitCode === null) {\n\t\t\t\tfailure = { status: \"failed\", error: \"Command terminated without an exit code\" };\n\t\t\t} else if (exitCode !== 0) {\n\t\t\t\tfailure = { status: \"failed\", error: `Command exited with code ${exitCode}` };\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tfailure = shellFailure(error);\n\t\t}\n\t\tacceptingOutput = false;\n\t\toutput.finish();\n\t\tclearUpdateTimer();\n\t\tif (taskLog) publish(snapshot());\n\t\telse emitOutputUpdate();\n\t\tconst final = snapshot();\n\t\tawait output.closeTempFile();\n\t\t// Final progress/cleanup can re-enter handoff. Classify policy cancellation\n\t\t// after those callbacks, independently of the process's abort marker.\n\t\tif (outputError) failure = { status: \"failed\", error: boundText(outputError.message, 4096) };\n\t\tconst { text, details } = formatOutput(output, final, taskLog, failure ? \"\" : \"(no output)\");\n\t\tconst fullOutput =\n\t\t\ttypeof exitCode === \"number\" && !outputError ? await output.readFullOutput(1024 * 1024) : undefined;\n\t\treturn {\n\t\t\tstatus: failure?.status,\n\t\t\terror: failure?.error,\n\t\t\t...(exitCode !== undefined ? { facts: [[\"Exit\", exitCode === null ? \"signal\" : String(exitCode)]] } : {}),\n\t\t\tresult: {\n\t\t\t\t...(fullOutput && typeof exitCode === \"number\"\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tstructuredContent: {\n\t\t\t\t\t\t\t\toutput: fullOutput.content,\n\t\t\t\t\t\t\t\ttruncated: fullOutput.truncated,\n\t\t\t\t\t\t\t\t...(fullOutput.truncated && final.fullOutputPath\n\t\t\t\t\t\t\t\t\t? { full_output_path: final.fullOutputPath }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\texit_code: exitCode,\n\t\t\t\t\t\t\t\twall_time_seconds: Math.round((performance.now() - startedAt) / 100) / 10,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t...(failure ? { isError: true } : {}),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t// The command's output only: its failure is the completion's `error`, composed where a result is shown.\n\t\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\t\tdetails,\n\t\t\t},\n\t\t};\n\t} finally {\n\t\tacceptingOutput = false;\n\t\tunsubscribe?.();\n\t\tclearUpdateTimer();\n\t\tawait output.closeTempFile();\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-tool.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG/E,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EAGpB,KAAK,eAAe,EACpB,MAAM,WAAW,CAAC;AAKnB,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5F,QAAA,MAAM,UAAU;;;;EASd,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;CAGnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAetD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;
|
|
1
|
+
{"version":3,"file":"shell-tool.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG/E,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EAGpB,KAAK,eAAe,EACpB,MAAM,WAAW,CAAC;AAKnB,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5F,QAAA,MAAM,UAAU;;;;EASd,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;CAGnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAetD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAyBF,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,eAAe,GAAG;IAAE,UAAU,EAAE,cAAc,CAAA;CAAE,GACvD,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CA4FjF;AAYD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAK9C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe;;;;iCAQpE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { TaskRuntime } from "../tasks/runtime.js";
|
|
3
|
+
import { TASKS_TOOL_NAME } from "../tasks/types.js";
|
|
3
4
|
import { resolveSpawnContext, resolveTimeoutMs, } from "./bash.js";
|
|
4
5
|
import { createShellRenderers } from "./renderers/bash.js";
|
|
5
6
|
import { runShellCommand } from "./shell-execution.js";
|
|
@@ -29,18 +30,24 @@ const bashOutputSchema = Type.Union([
|
|
|
29
30
|
}),
|
|
30
31
|
Type.Object({ task_id: Type.String(), status: Type.String() }),
|
|
31
32
|
]);
|
|
32
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Translate terminal shell failures to the native foreground tool contract once. A task result
|
|
35
|
+
* holds the command's output only; the foreground text is that output followed by the failure.
|
|
36
|
+
*/
|
|
33
37
|
function shellToolResult(completion) {
|
|
34
38
|
const status = completion.status;
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
const output = completion.result.content
|
|
40
|
+
.filter((part) => part.type === "text")
|
|
41
|
+
.map((part) => part.text)
|
|
42
|
+
.join("\n");
|
|
43
|
+
const withError = (error) => (output ? `${output}\n\n${error}` : error);
|
|
44
|
+
if (completion.result.structuredContent) {
|
|
45
|
+
if (!completion.result.isError || !completion.error)
|
|
46
|
+
return completion.result;
|
|
47
|
+
return { ...completion.result, content: [{ type: "text", text: withError(completion.error) }] };
|
|
48
|
+
}
|
|
37
49
|
if (status === "failed" || status === "timeout" || status === "cancelled") {
|
|
38
|
-
|
|
39
|
-
.filter((part) => part.type === "text")
|
|
40
|
-
.map((part) => part.text)
|
|
41
|
-
.join("\n");
|
|
42
|
-
const message = completion.error ? text || completion.error : `${text ? `${text}\n\n` : ""}Command ${status}`;
|
|
43
|
-
throw new Error(message);
|
|
50
|
+
throw new Error(completion.error ? withError(completion.error) : `${output ? `${output}\n\n` : ""}Command ${status}`);
|
|
44
51
|
}
|
|
45
52
|
return completion.result;
|
|
46
53
|
}
|
|
@@ -52,7 +59,7 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
52
59
|
return {
|
|
53
60
|
name: config.name,
|
|
54
61
|
label: config.label,
|
|
55
|
-
description: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use
|
|
62
|
+
description: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits — use it when your next step needs the output; background: true returns immediately with a task ID — use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use ${TASKS_TOOL_NAME} read to inspect output and ${TASKS_TOOL_NAME} kill to stop it. Background output is limited to 20 MiB.`,
|
|
56
63
|
promptSnippet: config.promptSnippet,
|
|
57
64
|
promptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,
|
|
58
65
|
parameters: bashSchema,
|
|
@@ -102,13 +109,13 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
102
109
|
}
|
|
103
110
|
if (outcome.kind === "result")
|
|
104
111
|
return shellToolResult(outcome);
|
|
105
|
-
const tail = `Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. Completion arrives
|
|
112
|
+
const tail = `Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. Completion arrives and wakes you automatically — do not poll or wait on it; continue with other work, or end your turn and hand back to the user. If you would only wait for the result, prefer foreground next time. Use ${TASKS_TOOL_NAME} read to inspect output or ${TASKS_TOOL_NAME} kill to stop it.`;
|
|
106
113
|
// Shell execution can become background work in two ways, and the model has to know which
|
|
107
114
|
// one it got: a submitted background command starts from an empty log, while a detached
|
|
108
115
|
// one already holds output and keeps its original timeout.
|
|
109
|
-
const handoff =
|
|
116
|
+
const handoff = outcome.reason === "submitted"
|
|
110
117
|
? `Command handed to background. ${tail}`
|
|
111
|
-
: `Command moved to the background while it was running, by the user. The execution continues unchanged — no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so
|
|
118
|
+
: `Command moved to the background while it was running, by the user. The execution continues unchanged — no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so ${TASKS_TOOL_NAME} read now returns partial output, not a fresh start. ${tail}`;
|
|
112
119
|
return {
|
|
113
120
|
structuredContent: { task_id: outcome.task.id, status: outcome.task.status },
|
|
114
121
|
content: [
|