pi-agent-flow 1.8.1 → 1.8.3
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/README.md +4 -30
- package/agents/audit.md +1 -2
- package/agents/build.md +1 -0
- package/agents/craft.md +12 -8
- package/agents/debug.md +2 -2
- package/agents/ideas.md +1 -0
- package/agents/scout.md +1 -0
- package/dist/agents.d.ts +41 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +283 -0
- package/dist/agents.js.map +1 -0
- package/dist/batch/batch-bash.d.ts +87 -0
- package/dist/batch/batch-bash.d.ts.map +1 -0
- package/dist/batch/batch-bash.js +369 -0
- package/dist/batch/batch-bash.js.map +1 -0
- package/dist/batch/constants.d.ts +100 -0
- package/dist/batch/constants.d.ts.map +1 -0
- package/dist/batch/constants.js +15 -0
- package/dist/batch/constants.js.map +1 -0
- package/dist/batch/execute.d.ts +21 -0
- package/dist/batch/execute.d.ts.map +1 -0
- package/dist/batch/execute.js +440 -0
- package/dist/batch/execute.js.map +1 -0
- package/dist/batch/fuzzy-edit.d.ts +29 -0
- package/dist/batch/fuzzy-edit.d.ts.map +1 -0
- package/dist/batch/fuzzy-edit.js +257 -0
- package/dist/batch/fuzzy-edit.js.map +1 -0
- package/dist/batch/index.d.ts +85 -0
- package/dist/batch/index.d.ts.map +1 -0
- package/dist/batch/index.js +422 -0
- package/dist/batch/index.js.map +1 -0
- package/dist/batch/render.d.ts +14 -0
- package/dist/batch/render.d.ts.map +1 -0
- package/dist/batch/render.js +74 -0
- package/dist/batch/render.js.map +1 -0
- package/dist/batch/symbols.d.ts +9 -0
- package/dist/batch/symbols.d.ts.map +1 -0
- package/dist/batch/symbols.js +310 -0
- package/dist/batch/symbols.js.map +1 -0
- package/dist/batch.d.ts +12 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +11 -0
- package/dist/batch.js.map +1 -0
- package/dist/cli-args.d.ts +27 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +265 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/config.d.ts +58 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +296 -0
- package/dist/config.js.map +1 -0
- package/dist/depth.d.ts +25 -0
- package/dist/depth.d.ts.map +1 -0
- package/dist/depth.js +160 -0
- package/dist/depth.js.map +1 -0
- package/dist/executor.d.ts +87 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +295 -0
- package/dist/executor.js.map +1 -0
- package/dist/flow-prompt.d.ts +23 -0
- package/dist/flow-prompt.d.ts.map +1 -0
- package/dist/flow-prompt.js +99 -0
- package/dist/flow-prompt.js.map +1 -0
- package/dist/flow.d.ts +76 -0
- package/dist/flow.d.ts.map +1 -0
- package/dist/flow.js +704 -0
- package/dist/flow.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +327 -0
- package/dist/index.js.map +1 -0
- package/dist/reasoning-strip.d.ts +26 -0
- package/dist/reasoning-strip.d.ts.map +1 -0
- package/dist/reasoning-strip.js +58 -0
- package/dist/reasoning-strip.js.map +1 -0
- package/dist/render-utils.d.ts +42 -0
- package/dist/render-utils.d.ts.map +1 -0
- package/dist/render-utils.js +182 -0
- package/dist/render-utils.js.map +1 -0
- package/dist/render.d.ts +24 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +409 -0
- package/dist/render.js.map +1 -0
- package/dist/runner-events.d.ts +59 -0
- package/dist/runner-events.d.ts.map +1 -0
- package/dist/runner-events.js +539 -0
- package/dist/runner-events.js.map +1 -0
- package/dist/session-mode.d.ts +10 -0
- package/dist/session-mode.d.ts.map +1 -0
- package/dist/session-mode.js +25 -0
- package/dist/session-mode.js.map +1 -0
- package/dist/settings-resolver.d.ts +28 -0
- package/dist/settings-resolver.d.ts.map +1 -0
- package/dist/settings-resolver.js +148 -0
- package/dist/settings-resolver.js.map +1 -0
- package/dist/sliding-prompt.d.ts +40 -0
- package/dist/sliding-prompt.d.ts.map +1 -0
- package/dist/sliding-prompt.js +121 -0
- package/dist/sliding-prompt.js.map +1 -0
- package/dist/snapshot.d.ts +29 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +199 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/structured-output.d.ts +36 -0
- package/dist/structured-output.d.ts.map +1 -0
- package/dist/structured-output.js +244 -0
- package/dist/structured-output.js.map +1 -0
- package/dist/timed-bash.d.ts +45 -0
- package/dist/timed-bash.d.ts.map +1 -0
- package/dist/timed-bash.js +219 -0
- package/dist/timed-bash.js.map +1 -0
- package/dist/tool-utils.d.ts +20 -0
- package/dist/tool-utils.d.ts.map +1 -0
- package/dist/tool-utils.js +38 -0
- package/dist/tool-utils.js.map +1 -0
- package/dist/transitions.d.ts +39 -0
- package/dist/transitions.d.ts.map +1 -0
- package/dist/transitions.js +59 -0
- package/dist/transitions.js.map +1 -0
- package/dist/types.d.ts +207 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +143 -0
- package/dist/types.js.map +1 -0
- package/dist/web-tool.d.ts +35 -0
- package/dist/web-tool.d.ts.map +1 -0
- package/dist/web-tool.js +545 -0
- package/dist/web-tool.js.map +1 -0
- package/package.json +7 -5
- package/src/agents.ts +0 -299
- package/src/ambient.d.ts +0 -107
- package/src/batch/batch-bash.ts +0 -443
- package/src/batch/constants.ts +0 -128
- package/src/batch/execute.ts +0 -551
- package/src/batch/fuzzy-edit.ts +0 -323
- package/src/batch/index.ts +0 -494
- package/src/batch/render.ts +0 -81
- package/src/batch/symbols.ts +0 -341
- package/src/batch.ts +0 -28
- package/src/cli-args.ts +0 -315
- package/src/config.ts +0 -391
- package/src/executor.ts +0 -445
- package/src/flow.ts +0 -834
- package/src/hooks.ts +0 -294
- package/src/index.ts +0 -1132
- package/src/render-utils.ts +0 -205
- package/src/render.ts +0 -524
- package/src/runner-events.ts +0 -692
- package/src/session-mode.ts +0 -33
- package/src/sliding-prompt.ts +0 -144
- package/src/structured-output.ts +0 -195
- package/src/timed-bash.ts +0 -270
- package/src/transitions.ts +0 -86
- package/src/types.ts +0 -386
- package/src/web-tool.ts +0 -663
package/src/batch/batch-bash.ts
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* batch bash -- parallel bash execution and polling.
|
|
3
|
-
*
|
|
4
|
-
* Runs multiple shell commands concurrently with a soft timeout,
|
|
5
|
-
* tracks running/pending processes, and exposes a polling interface
|
|
6
|
-
* so the agent can retrieve results of long-running commands later.
|
|
7
|
-
*
|
|
8
|
-
* The soft timeout (default 20s) does NOT kill commands. It sets the maximum
|
|
9
|
-
* wait time before the batch tool returns partial results. Commands that
|
|
10
|
-
* haven't finished continue running in the background and can be polled
|
|
11
|
-
* via the `batch_bash_poll` tool.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { spawn, type ChildProcess } from "node:child_process";
|
|
15
|
-
import { Type } from "@sinclair/typebox";
|
|
16
|
-
import {
|
|
17
|
-
type BashOpResult,
|
|
18
|
-
type PendingBashResult,
|
|
19
|
-
BASH_SOFT_TIMEOUT_MS,
|
|
20
|
-
BASH_POLL_TAIL_LINES,
|
|
21
|
-
} from "./constants.js";
|
|
22
|
-
import { classifyDuration } from "../timed-bash.js";
|
|
23
|
-
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// Process tracker -- shared between batch and batch_bash_poll tools
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
interface RunningProcess {
|
|
29
|
-
proc: ChildProcess;
|
|
30
|
-
command: string;
|
|
31
|
-
startedAt: number;
|
|
32
|
-
stdoutChunks: string[];
|
|
33
|
-
stderrChunks: string[];
|
|
34
|
-
abortController: AbortController;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface TrackedBashResult {
|
|
38
|
-
id: string;
|
|
39
|
-
command: string;
|
|
40
|
-
status: "ok" | "error" | "aborted";
|
|
41
|
-
exitCode?: number;
|
|
42
|
-
stdout: string;
|
|
43
|
-
stderr: string;
|
|
44
|
-
duration: number;
|
|
45
|
-
timingTier: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Process tracker for batch bash operations.
|
|
50
|
-
* Both the `batch` tool (launch side) and `batch_bash_poll` tool (read side)
|
|
51
|
-
* share the same instance.
|
|
52
|
-
*/
|
|
53
|
-
export class BashProcessTracker {
|
|
54
|
-
private running = new Map<string, RunningProcess>();
|
|
55
|
-
private completed = new Map<string, TrackedBashResult>();
|
|
56
|
-
|
|
57
|
-
/** Launch a bash command. Returns immediately; the process runs in the background. */
|
|
58
|
-
launch(
|
|
59
|
-
id: string,
|
|
60
|
-
command: string,
|
|
61
|
-
cwd: string,
|
|
62
|
-
signal?: AbortSignal,
|
|
63
|
-
): void {
|
|
64
|
-
// Abort any existing process with the same id
|
|
65
|
-
this.abortById(id);
|
|
66
|
-
this.completed.delete(id);
|
|
67
|
-
|
|
68
|
-
const ac = new AbortController();
|
|
69
|
-
const child = spawn(command, [], {
|
|
70
|
-
cwd,
|
|
71
|
-
shell: true,
|
|
72
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
73
|
-
signal: ac.signal,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const rp: RunningProcess = {
|
|
77
|
-
proc: child,
|
|
78
|
-
command,
|
|
79
|
-
startedAt: Date.now(),
|
|
80
|
-
stdoutChunks: [],
|
|
81
|
-
stderrChunks: [],
|
|
82
|
-
abortController: ac,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
child.stdout?.on("data", (chunk: Buffer) => {
|
|
86
|
-
rp.stdoutChunks.push(chunk.toString());
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
child.stderr?.on("data", (chunk: Buffer) => {
|
|
90
|
-
rp.stderrChunks.push(chunk.toString());
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Wire parent signal
|
|
94
|
-
if (signal) {
|
|
95
|
-
const onParentAbort = () => this.abortById(id);
|
|
96
|
-
if (signal.aborted) {
|
|
97
|
-
this.abortById(id);
|
|
98
|
-
} else {
|
|
99
|
-
signal.addEventListener("abort", onParentAbort, { once: true });
|
|
100
|
-
child.on("close", () => signal.removeEventListener("abort", onParentAbort));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
child.on("close", (code) => {
|
|
105
|
-
this.running.delete(id);
|
|
106
|
-
|
|
107
|
-
const stdout = rp.stdoutChunks.join("");
|
|
108
|
-
const stderr = rp.stderrChunks.join("");
|
|
109
|
-
const duration = Date.now() - rp.startedAt;
|
|
110
|
-
const report = classifyDuration(duration);
|
|
111
|
-
|
|
112
|
-
this.completed.set(id, {
|
|
113
|
-
id,
|
|
114
|
-
command,
|
|
115
|
-
status: code === 0 ? "ok" : "error",
|
|
116
|
-
exitCode: code ?? undefined,
|
|
117
|
-
stdout,
|
|
118
|
-
stderr,
|
|
119
|
-
duration,
|
|
120
|
-
timingTier: report.label,
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
child.on("error", (err) => {
|
|
125
|
-
this.running.delete(id);
|
|
126
|
-
|
|
127
|
-
const duration = Date.now() - rp.startedAt;
|
|
128
|
-
const report = classifyDuration(duration);
|
|
129
|
-
const stdout = rp.stdoutChunks.join("");
|
|
130
|
-
const stderr = rp.stderrChunks.join("") || err.message;
|
|
131
|
-
|
|
132
|
-
this.completed.set(id, {
|
|
133
|
-
id,
|
|
134
|
-
command,
|
|
135
|
-
status: "aborted",
|
|
136
|
-
exitCode: undefined,
|
|
137
|
-
stdout,
|
|
138
|
-
stderr,
|
|
139
|
-
duration,
|
|
140
|
-
timingTier: report.label,
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
this.running.set(id, rp);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/** Check if a command is still running. */
|
|
148
|
-
isRunning(id: string): boolean {
|
|
149
|
-
return this.running.has(id);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Get the last N lines of a running process's stdout. */
|
|
153
|
-
getRunningTail(id: string): string {
|
|
154
|
-
const rp = this.running.get(id);
|
|
155
|
-
if (!rp) return "";
|
|
156
|
-
const stdout = rp.stdoutChunks.join("");
|
|
157
|
-
return tailLines(stdout, BASH_POLL_TAIL_LINES);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** Get the result of a completed/aborted command. Does NOT remove from cache. */
|
|
161
|
-
peekCompleted(id: string): TrackedBashResult | undefined {
|
|
162
|
-
return this.completed.get(id);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** Get the result of a completed/aborted command. Removes from completed cache. */
|
|
166
|
-
popCompleted(id: string): TrackedBashResult | undefined {
|
|
167
|
-
const result = this.completed.get(id);
|
|
168
|
-
if (result) this.completed.delete(id);
|
|
169
|
-
return result;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Get the start time of a running process. */
|
|
173
|
-
getStartedAt(id: string): number | undefined {
|
|
174
|
-
return this.running.get(id)?.startedAt;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Check if a command has completed. */
|
|
178
|
-
hasCompleted(id: string): boolean {
|
|
179
|
-
return this.completed.has(id);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/** Abort a running process by id. */
|
|
183
|
-
private abortById(id: string): void {
|
|
184
|
-
const rp = this.running.get(id);
|
|
185
|
-
if (!rp) return;
|
|
186
|
-
try {
|
|
187
|
-
rp.abortController.abort();
|
|
188
|
-
rp.proc.kill("SIGTERM");
|
|
189
|
-
} catch {
|
|
190
|
-
/* already dead */
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/** Abort all running processes (cleanup). */
|
|
195
|
-
abortAll(): void {
|
|
196
|
-
for (const [id] of this.running) {
|
|
197
|
-
this.abortById(id);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// ---------------------------------------------------------------------------
|
|
203
|
-
// Helpers
|
|
204
|
-
// ---------------------------------------------------------------------------
|
|
205
|
-
|
|
206
|
-
function tailLines(text: string, n: number): string {
|
|
207
|
-
const lines = text.split("\n");
|
|
208
|
-
return lines.slice(-n).join("\n");
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** Generate a short random ID for bash ops that don't provide one. */
|
|
212
|
-
export function generateBashId(): string {
|
|
213
|
-
return Math.random().toString(36).slice(2, 10);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/** Normalize a bash op from prepareArguments into a canonical form. */
|
|
217
|
-
export function normalizeBashOp(raw: Record<string, unknown>): Record<string, unknown> {
|
|
218
|
-
return {
|
|
219
|
-
o: "bash",
|
|
220
|
-
c: raw.c ?? raw.command,
|
|
221
|
-
i: raw.i ?? raw.id ?? generateBashId(),
|
|
222
|
-
t: raw.t ?? raw.timeout,
|
|
223
|
-
h: raw.h ?? raw.cwdPath ?? raw.cwd,
|
|
224
|
-
p: raw.p ?? "bash",
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Execute a batch of bash ops concurrently.
|
|
230
|
-
*
|
|
231
|
-
* Launches all commands in parallel, then waits until all finish or the
|
|
232
|
-
* soft timeout expires. The soft timeout is the max of per-op `t` values
|
|
233
|
-
* (if any), or the global default. Commands that haven't finished within
|
|
234
|
-
* the timeout are returned as "pending" with the last N lines of output.
|
|
235
|
-
* They continue running in the background and can be polled via batch_bash_poll.
|
|
236
|
-
*/
|
|
237
|
-
export async function executeBatchBash(
|
|
238
|
-
ops: Array<{ i: string; c: string; t?: number; h?: string }>,
|
|
239
|
-
defaultCwd: string,
|
|
240
|
-
tracker: BashProcessTracker,
|
|
241
|
-
signal?: AbortSignal,
|
|
242
|
-
softTimeoutMs: number = BASH_SOFT_TIMEOUT_MS,
|
|
243
|
-
): Promise<BashOpResult[]> {
|
|
244
|
-
if (ops.length === 0) return [];
|
|
245
|
-
|
|
246
|
-
// Compute the effective batch soft timeout: if per-op timeouts are specified,
|
|
247
|
-
// use the minimum of those; otherwise fall back to the global default.
|
|
248
|
-
const perOpTimeouts = ops.filter((op) => typeof op.t === "number" && op.t! > 0).map((op) => op.t!);
|
|
249
|
-
const effectiveTimeout = perOpTimeouts.length > 0
|
|
250
|
-
? Math.min(...perOpTimeouts)
|
|
251
|
-
: softTimeoutMs;
|
|
252
|
-
|
|
253
|
-
// Launch all commands in parallel
|
|
254
|
-
for (const op of ops) {
|
|
255
|
-
const cwd = op.h ? op.h : defaultCwd;
|
|
256
|
-
tracker.launch(op.i, op.c, cwd, signal);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Wait up to effectiveTimeout for all to finish
|
|
260
|
-
await waitForSettle(ops, tracker, effectiveTimeout, signal);
|
|
261
|
-
|
|
262
|
-
// Collect results
|
|
263
|
-
const results: BashOpResult[] = [];
|
|
264
|
-
for (const op of ops) {
|
|
265
|
-
const completed = tracker.popCompleted(op.i);
|
|
266
|
-
if (completed) {
|
|
267
|
-
results.push({
|
|
268
|
-
op: "bash",
|
|
269
|
-
path: op.i,
|
|
270
|
-
id: op.i,
|
|
271
|
-
command: op.c,
|
|
272
|
-
status: completed.status === "ok" ? "ok" : "error",
|
|
273
|
-
exitCode: completed.exitCode,
|
|
274
|
-
stdout: completed.stdout,
|
|
275
|
-
stderr: completed.stderr,
|
|
276
|
-
duration: completed.duration,
|
|
277
|
-
timingTier: completed.timingTier,
|
|
278
|
-
});
|
|
279
|
-
} else {
|
|
280
|
-
// Still running -- return pending with tail
|
|
281
|
-
const tail = tracker.getRunningTail(op.i);
|
|
282
|
-
results.push({
|
|
283
|
-
op: "bash",
|
|
284
|
-
path: op.i,
|
|
285
|
-
id: op.i,
|
|
286
|
-
command: op.c,
|
|
287
|
-
status: "pending",
|
|
288
|
-
stdout: tail,
|
|
289
|
-
stderr: "",
|
|
290
|
-
duration: Date.now() - getStartTime(tracker, op.i),
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return results;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/** Get the start time of a running process, or Date.now() if not found. */
|
|
299
|
-
function getStartTime(tracker: BashProcessTracker, id: string): number {
|
|
300
|
-
return tracker.getStartedAt(id) ?? Date.now();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Wait until all ops have completed or the soft timeout expires.
|
|
305
|
-
* Uses a polling check every 100ms.
|
|
306
|
-
*/
|
|
307
|
-
function waitForSettle(
|
|
308
|
-
ops: Array<{ i: string }>,
|
|
309
|
-
tracker: BashProcessTracker,
|
|
310
|
-
timeoutMs: number,
|
|
311
|
-
signal?: AbortSignal,
|
|
312
|
-
): Promise<void> {
|
|
313
|
-
return new Promise<void>((resolve) => {
|
|
314
|
-
const deadline = Date.now() + timeoutMs;
|
|
315
|
-
|
|
316
|
-
const check = () => {
|
|
317
|
-
if (signal?.aborted) {
|
|
318
|
-
resolve();
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
const allDone = ops.every((op) => !tracker.isRunning(op.i));
|
|
322
|
-
if (allDone || Date.now() >= deadline) {
|
|
323
|
-
resolve();
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
setTimeout(check, 100);
|
|
327
|
-
};
|
|
328
|
-
check();
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/** Poll for completed bash results. */
|
|
333
|
-
export function pollBatchBashResults(
|
|
334
|
-
ids: string[],
|
|
335
|
-
tracker: BashProcessTracker,
|
|
336
|
-
): PendingBashResult[] {
|
|
337
|
-
const results: PendingBashResult[] = [];
|
|
338
|
-
for (const id of ids) {
|
|
339
|
-
if (tracker.hasCompleted(id)) {
|
|
340
|
-
const r = tracker.popCompleted(id)!;
|
|
341
|
-
results.push({
|
|
342
|
-
id,
|
|
343
|
-
command: r.command,
|
|
344
|
-
status: "completed",
|
|
345
|
-
exitCode: r.exitCode,
|
|
346
|
-
stdout: r.stdout,
|
|
347
|
-
stderr: r.stderr,
|
|
348
|
-
duration: r.duration,
|
|
349
|
-
timingTier: r.timingTier,
|
|
350
|
-
});
|
|
351
|
-
} else if (tracker.isRunning(id)) {
|
|
352
|
-
results.push({
|
|
353
|
-
id,
|
|
354
|
-
command: "",
|
|
355
|
-
status: "pending",
|
|
356
|
-
stdout: tracker.getRunningTail(id),
|
|
357
|
-
});
|
|
358
|
-
} else {
|
|
359
|
-
results.push({
|
|
360
|
-
id,
|
|
361
|
-
command: "",
|
|
362
|
-
status: "pending",
|
|
363
|
-
stdout: "",
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
return results;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// ---------------------------------------------------------------------------
|
|
371
|
-
// Poll tool schema & factory
|
|
372
|
-
// ---------------------------------------------------------------------------
|
|
373
|
-
|
|
374
|
-
export const BatchBashPollParams = Type.Object({
|
|
375
|
-
i: Type.Array(Type.String(), {
|
|
376
|
-
description: "Array of bash operation IDs to poll for results.",
|
|
377
|
-
minItems: 1,
|
|
378
|
-
}),
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
export function createBatchBashPollTool(tracker: BashProcessTracker) {
|
|
382
|
-
return {
|
|
383
|
-
name: "batch_bash_poll",
|
|
384
|
-
label: "batch_bash_poll",
|
|
385
|
-
description: [
|
|
386
|
-
"Poll for results of pending bash commands from a previous batch call.",
|
|
387
|
-
"Pass the IDs of pending commands to check their status.",
|
|
388
|
-
"Returns completed results with full stdout/stderr, or indicates still-pending with last output lines.",
|
|
389
|
-
].join("\n"),
|
|
390
|
-
promptSnippet: "Poll pending bash commands for results",
|
|
391
|
-
promptGuidelines: [
|
|
392
|
-
"Use batch_bash_poll to check on bash commands that returned pending from a batch call.",
|
|
393
|
-
"Pass the `i` (id) values from the pending results.",
|
|
394
|
-
],
|
|
395
|
-
parameters: BatchBashPollParams,
|
|
396
|
-
|
|
397
|
-
prepareArguments(input: unknown): unknown {
|
|
398
|
-
if (!input || typeof input !== "object") return { i: [] };
|
|
399
|
-
const args = input as Record<string, unknown>;
|
|
400
|
-
const ids = args.i ?? args.ids;
|
|
401
|
-
if (!Array.isArray(ids)) return { i: [] };
|
|
402
|
-
return { i: ids };
|
|
403
|
-
},
|
|
404
|
-
|
|
405
|
-
async execute(
|
|
406
|
-
_toolCallId: string,
|
|
407
|
-
input: unknown,
|
|
408
|
-
_signal?: AbortSignal,
|
|
409
|
-
_onUpdate?: unknown,
|
|
410
|
-
) {
|
|
411
|
-
const args = (input ?? {}) as Record<string, unknown>;
|
|
412
|
-
const ids = Array.isArray(args.i) ? (args.i as string[]) : Array.isArray(args.ids) ? (args.ids as string[]) : [];
|
|
413
|
-
|
|
414
|
-
if (ids.length === 0) {
|
|
415
|
-
return {
|
|
416
|
-
content: [{ type: "text", text: "Error: i (ids) array is required and must not be empty." }],
|
|
417
|
-
isError: true,
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const results = pollBatchBashResults(ids, tracker);
|
|
422
|
-
|
|
423
|
-
const lines: string[] = [];
|
|
424
|
-
for (const r of results) {
|
|
425
|
-
if (r.status === "completed") {
|
|
426
|
-
const exitInfo = r.exitCode !== undefined ? `exit ${r.exitCode}` : "interrupted";
|
|
427
|
-
lines.push(`--- [${r.id}] ${exitInfo} (${r.timingTier ?? "unknown"}) ---`);
|
|
428
|
-
if (r.stdout?.trim()) lines.push(r.stdout.trimEnd());
|
|
429
|
-
if (r.stderr?.trim()) lines.push(`[stderr]\n${r.stderr.trimEnd()}`);
|
|
430
|
-
} else {
|
|
431
|
-
lines.push(`--- [${r.id}] still running ---`);
|
|
432
|
-
if (r.stdout?.trim()) lines.push(`[output so far]\n${r.stdout.trimEnd()}`);
|
|
433
|
-
}
|
|
434
|
-
lines.push("");
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return {
|
|
438
|
-
content: [{ type: "text", text: lines.join("\n").trimEnd() }],
|
|
439
|
-
details: { results },
|
|
440
|
-
};
|
|
441
|
-
},
|
|
442
|
-
};
|
|
443
|
-
}
|
package/src/batch/constants.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* batch — constants and shared types.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// Limits
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
|
-
|
|
9
|
-
export const MAX_LINES = 2000;
|
|
10
|
-
export const MAX_BYTES = 50 * 1024; // 50KB
|
|
11
|
-
export const SAFE_FULL_READ_LIMIT = 300;
|
|
12
|
-
export const TARGETED_READ_LINE_LIMIT = 1000;
|
|
13
|
-
export const MAX_CONTEXT_MAP_ENTRIES = 100;
|
|
14
|
-
export const MAX_TOTAL_RESULT_LINES = 1500;
|
|
15
|
-
export const BASH_SOFT_TIMEOUT_MS = 20_000;
|
|
16
|
-
export const BASH_POLL_TAIL_LINES = 50;
|
|
17
|
-
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Types
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
|
|
22
|
-
export interface EditReplacement {
|
|
23
|
-
f: string;
|
|
24
|
-
r: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface FileOpInput {
|
|
28
|
-
o: "read" | "write" | "edit" | "delete" | "bash";
|
|
29
|
-
p: string;
|
|
30
|
-
c?: string;
|
|
31
|
-
e?: EditReplacement[];
|
|
32
|
-
s?: number;
|
|
33
|
-
l?: number;
|
|
34
|
-
i?: string;
|
|
35
|
-
t?: number;
|
|
36
|
-
h?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface ContextMapEntry {
|
|
40
|
-
kind: string;
|
|
41
|
-
name: string;
|
|
42
|
-
startLine: number;
|
|
43
|
-
endLine: number;
|
|
44
|
-
parent?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface OpResult {
|
|
48
|
-
op: "read" | "write" | "edit" | "delete" | "bash";
|
|
49
|
-
path: string;
|
|
50
|
-
status: "ok" | "error" | "skipped" | "pending";
|
|
51
|
-
content?: string;
|
|
52
|
-
bytes?: number;
|
|
53
|
-
blocksChanged?: number;
|
|
54
|
-
totalLines?: number;
|
|
55
|
-
contextMap?: boolean;
|
|
56
|
-
language?: string;
|
|
57
|
-
symbols?: ContextMapEntry[];
|
|
58
|
-
symbolsTruncated?: boolean;
|
|
59
|
-
warning?: string;
|
|
60
|
-
truncated?: boolean;
|
|
61
|
-
nextOffset?: number;
|
|
62
|
-
error?: string;
|
|
63
|
-
hint?: string;
|
|
64
|
-
id?: string;
|
|
65
|
-
command?: string;
|
|
66
|
-
exitCode?: number;
|
|
67
|
-
stdout?: string;
|
|
68
|
-
stderr?: string;
|
|
69
|
-
duration?: number;
|
|
70
|
-
timingTier?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface ReadTruncationResult {
|
|
74
|
-
content: string;
|
|
75
|
-
truncated: boolean;
|
|
76
|
-
nextOffset?: number;
|
|
77
|
-
linesRead: number;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface ReadOptions {
|
|
81
|
-
/**
|
|
82
|
-
* When false, readWithOffsetLimit ignores regular batch MAX_LINES and total
|
|
83
|
-
* MAX_BYTES caps. batch_read applies its own safe full-file and targeted-read
|
|
84
|
-
* guards before calling this helper.
|
|
85
|
-
*/
|
|
86
|
-
truncate?: boolean;
|
|
87
|
-
toolName?: "batch" | "batch_read";
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface ExecuteOptions {
|
|
91
|
-
readOptions?: ReadOptions;
|
|
92
|
-
includeLimitWarnings?: boolean;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export type ContextLanguage =
|
|
96
|
-
| "typescript"
|
|
97
|
-
| "javascript"
|
|
98
|
-
| "python"
|
|
99
|
-
| "terraform"
|
|
100
|
-
| "hcl"
|
|
101
|
-
| "yaml"
|
|
102
|
-
| "dockerfile"
|
|
103
|
-
| "plain";
|
|
104
|
-
|
|
105
|
-
export interface FileContextMap {
|
|
106
|
-
language: ContextLanguage;
|
|
107
|
-
symbols: ContextMapEntry[];
|
|
108
|
-
symbolsTruncated?: boolean;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export type BatchTheme = {
|
|
112
|
-
fg: (color: string, text: string) => string;
|
|
113
|
-
bold: (s: string) => string;
|
|
114
|
-
bg: (color: string, text: string) => string;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export interface PendingBashResult {
|
|
118
|
-
id: string;
|
|
119
|
-
command: string;
|
|
120
|
-
status: "pending" | "completed";
|
|
121
|
-
exitCode?: number;
|
|
122
|
-
stdout?: string;
|
|
123
|
-
stderr?: string;
|
|
124
|
-
duration?: number;
|
|
125
|
-
timingTier?: string;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export type BashOpResult = OpResult;
|