pi-agent-flow 2.0.1 → 2.0.5
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 +126 -489
- package/agents/audit.md +24 -15
- package/agents/build.md +4 -3
- package/agents/craft.md +4 -4
- package/agents/debug.md +5 -4
- package/agents/ideas.md +6 -5
- package/agents/scout.md +10 -8
- package/agents/trace.md +23 -0
- package/dist/batch/apply-patch.d.ts +60 -0
- package/dist/batch/apply-patch.d.ts.map +1 -0
- package/dist/batch/apply-patch.js +477 -0
- package/dist/batch/apply-patch.js.map +1 -0
- package/dist/batch/batch-bash.d.ts +10 -6
- package/dist/batch/batch-bash.d.ts.map +1 -1
- package/dist/batch/batch-bash.js +59 -11
- package/dist/batch/batch-bash.js.map +1 -1
- package/dist/batch/constants.d.ts +38 -6
- package/dist/batch/constants.d.ts.map +1 -1
- package/dist/batch/constants.js +26 -4
- package/dist/batch/constants.js.map +1 -1
- package/dist/batch/execute.d.ts +8 -2
- package/dist/batch/execute.d.ts.map +1 -1
- package/dist/batch/execute.js +222 -67
- package/dist/batch/execute.js.map +1 -1
- package/dist/batch/fuzzy-edit.d.ts +4 -1
- package/dist/batch/fuzzy-edit.d.ts.map +1 -1
- package/dist/batch/fuzzy-edit.js +7 -2
- package/dist/batch/fuzzy-edit.js.map +1 -1
- package/dist/batch/index.d.ts +10 -24
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +120 -120
- package/dist/batch/index.js.map +1 -1
- package/dist/batch/render.d.ts +22 -5
- package/dist/batch/render.d.ts.map +1 -1
- package/dist/batch/render.js +353 -15
- package/dist/batch/render.js.map +1 -1
- package/dist/batch/summary.d.ts.map +1 -1
- package/dist/batch/summary.js +26 -4
- package/dist/batch/summary.js.map +1 -1
- package/dist/config/config.d.ts +5 -4
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +15 -5
- package/dist/config/config.js.map +1 -1
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +7 -1
- package/dist/config/models.js.map +1 -1
- package/dist/config/settings-resolver.d.ts +5 -4
- package/dist/config/settings-resolver.d.ts.map +1 -1
- package/dist/config/settings-resolver.js +50 -21
- package/dist/config/settings-resolver.js.map +1 -1
- package/dist/core2/snapshot.d.ts +21 -0
- package/dist/core2/snapshot.d.ts.map +1 -0
- package/dist/core2/snapshot.js +214 -0
- package/dist/core2/snapshot.js.map +1 -0
- package/dist/{core → flow}/agents.d.ts.map +1 -1
- package/dist/{core → flow}/agents.js +5 -2
- package/dist/{core → flow}/agents.js.map +1 -1
- package/dist/flow/auto-warp.d.ts +1 -1
- package/dist/flow/auto-warp.js +1 -1
- package/dist/flow/command.d.ts +1 -1
- package/dist/flow/command.d.ts.map +1 -1
- package/dist/flow/complexity.d.ts +20 -0
- package/dist/flow/complexity.d.ts.map +1 -0
- package/dist/flow/complexity.js +34 -0
- package/dist/flow/complexity.js.map +1 -0
- package/dist/flow/continuation.d.ts +1 -1
- package/dist/flow/continuation.d.ts.map +1 -1
- package/dist/flow/continuation.js +4 -3
- package/dist/flow/continuation.js.map +1 -1
- package/dist/{core → flow}/depth.d.ts +4 -4
- package/dist/{core → flow}/depth.d.ts.map +1 -1
- package/dist/{core → flow}/depth.js +5 -5
- package/dist/{core → flow}/depth.js.map +1 -1
- package/dist/{core → flow}/executor.d.ts +42 -22
- package/dist/flow/executor.d.ts.map +1 -0
- package/dist/flow/executor.js +727 -0
- package/dist/flow/executor.js.map +1 -0
- package/dist/flow/index.d.ts +4 -4
- package/dist/flow/index.d.ts.map +1 -1
- package/dist/flow/index.js +4 -4
- package/dist/flow/index.js.map +1 -1
- package/dist/flow/loop-command.d.ts +1 -1
- package/dist/flow/loop-command.d.ts.map +1 -1
- package/dist/flow/loop-command.js +3 -0
- package/dist/flow/loop-command.js.map +1 -1
- package/dist/{core/flow.d.ts → flow/runner.d.ts} +20 -16
- package/dist/flow/runner.d.ts.map +1 -0
- package/dist/{core/flow.js → flow/runner.js} +105 -61
- package/dist/flow/runner.js.map +1 -0
- package/dist/{core → flow}/session-registry.d.ts.map +1 -1
- package/dist/{core → flow}/session-registry.js.map +1 -1
- package/dist/flow/settings-command.d.ts +3 -3
- package/dist/flow/settings-command.d.ts.map +1 -1
- package/dist/flow/settings-command.js +43 -22
- package/dist/flow/settings-command.js.map +1 -1
- package/dist/{core/delegation.d.ts → flow/transition.d.ts} +8 -8
- package/dist/{core/delegation.d.ts.map → flow/transition.d.ts.map} +1 -1
- package/dist/{core/delegation.js → flow/transition.js} +12 -12
- package/dist/{core/delegation.js.map → flow/transition.js.map} +1 -1
- package/dist/flow/types.d.ts +4 -0
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/flow/warp.d.ts +15 -0
- package/dist/flow/warp.d.ts.map +1 -0
- package/dist/flow/warp.js +207 -0
- package/dist/flow/warp.js.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +237 -89
- package/dist/index.js.map +1 -1
- package/dist/notify/notify.d.ts +1 -1
- package/dist/notify/notify.d.ts.map +1 -1
- package/dist/notify/notify.js +1 -1
- package/dist/snapshot/cli-args.d.ts +2 -2
- package/dist/snapshot/cli-args.d.ts.map +1 -1
- package/dist/snapshot/cli-args.js +21 -5
- package/dist/snapshot/cli-args.js.map +1 -1
- package/dist/snapshot/runner-events.d.ts +7 -2
- package/dist/snapshot/runner-events.d.ts.map +1 -1
- package/dist/snapshot/runner-events.js +137 -19
- package/dist/snapshot/runner-events.js.map +1 -1
- package/dist/snapshot/structured-output.d.ts +1 -1
- package/dist/snapshot/structured-output.d.ts.map +1 -1
- package/dist/snapshot/structured-output.js +20 -2
- package/dist/snapshot/structured-output.js.map +1 -1
- package/dist/steering/flow-prompt.d.ts +4 -4
- package/dist/steering/flow-prompt.d.ts.map +1 -1
- package/dist/steering/flow-prompt.js +18 -37
- package/dist/steering/flow-prompt.js.map +1 -1
- package/dist/steering/sliding-prompt.d.ts.map +1 -1
- package/dist/steering/sliding-prompt.js +8 -7
- package/dist/steering/sliding-prompt.js.map +1 -1
- package/dist/steering/tool-utils.d.ts +31 -8
- package/dist/steering/tool-utils.d.ts.map +1 -1
- package/dist/steering/tool-utils.js +63 -30
- package/dist/steering/tool-utils.js.map +1 -1
- package/dist/tools/ask-user.d.ts +2 -19
- package/dist/tools/ask-user.d.ts.map +1 -1
- package/dist/tools/ask-user.js +14 -38
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/timed-bash.d.ts +1 -1
- package/dist/tools/timed-bash.d.ts.map +1 -1
- package/dist/tools/timed-bash.js +11 -9
- package/dist/tools/timed-bash.js.map +1 -1
- package/dist/tools/trace.d.ts +34 -0
- package/dist/tools/trace.d.ts.map +1 -0
- package/dist/tools/trace.js +180 -0
- package/dist/tools/trace.js.map +1 -0
- package/dist/tools/web-ops.d.ts +85 -0
- package/dist/tools/web-ops.d.ts.map +1 -0
- package/dist/tools/{web-tool.js → web-ops.js} +51 -127
- package/dist/tools/web-ops.js.map +1 -0
- package/dist/tui/flow-colors.d.ts +1 -0
- package/dist/tui/flow-colors.d.ts.map +1 -1
- package/dist/tui/flow-colors.js +2 -2
- package/dist/tui/flow-colors.js.map +1 -1
- package/dist/tui/render-utils.d.ts.map +1 -1
- package/dist/tui/render-utils.js +2 -4
- package/dist/tui/render-utils.js.map +1 -1
- package/dist/tui/render.d.ts +41 -1
- package/dist/tui/render.d.ts.map +1 -1
- package/dist/tui/render.js +724 -189
- package/dist/tui/render.js.map +1 -1
- package/dist/tui/scramble/algorithm.d.ts +4 -2
- package/dist/tui/scramble/algorithm.d.ts.map +1 -1
- package/dist/tui/scramble/algorithm.js +44 -12
- package/dist/tui/scramble/algorithm.js.map +1 -1
- package/dist/tui/scramble/constants.d.ts +3 -0
- package/dist/tui/scramble/constants.d.ts.map +1 -1
- package/dist/tui/scramble/constants.js +4 -1
- package/dist/tui/scramble/constants.js.map +1 -1
- package/dist/tui/scramble/index.d.ts +3 -2
- package/dist/tui/scramble/index.d.ts.map +1 -1
- package/dist/tui/scramble/index.js +2 -2
- package/dist/tui/scramble/index.js.map +1 -1
- package/dist/tui/scramble/manager.d.ts +2 -2
- package/dist/tui/scramble/manager.d.ts.map +1 -1
- package/dist/tui/scramble/manager.js +37 -20
- package/dist/tui/scramble/manager.js.map +1 -1
- package/dist/tui/scramble/utils.js +1 -1
- package/dist/tui/scramble/utils.js.map +1 -1
- package/dist/types/flow.d.ts +17 -1
- package/dist/types/flow.d.ts.map +1 -1
- package/dist/types/flow.js +11 -2
- package/dist/types/flow.js.map +1 -1
- package/dist/types/output.d.ts +11 -36
- package/dist/types/output.d.ts.map +1 -1
- package/dist/types/output.js +1 -1
- package/dist/types/ui.d.ts +1 -1
- package/dist/types/ui.d.ts.map +1 -1
- package/package.json +10 -10
- package/dist/core/executor.d.ts.map +0 -1
- package/dist/core/executor.js +0 -378
- package/dist/core/executor.js.map +0 -1
- package/dist/core/flow.d.ts.map +0 -1
- package/dist/core/flow.js.map +0 -1
- package/dist/core/session-mode.d.ts +0 -11
- package/dist/core/session-mode.d.ts.map +0 -1
- package/dist/core/session-mode.js +0 -26
- package/dist/core/session-mode.js.map +0 -1
- package/dist/core/transitions.d.ts +0 -39
- package/dist/core/transitions.d.ts.map +0 -1
- package/dist/core/transitions.js +0 -59
- package/dist/core/transitions.js.map +0 -1
- package/dist/flow/perform-warp.d.ts +0 -28
- package/dist/flow/perform-warp.d.ts.map +0 -1
- package/dist/flow/perform-warp.js +0 -127
- package/dist/flow/perform-warp.js.map +0 -1
- package/dist/flow/warp-command.d.ts +0 -8
- package/dist/flow/warp-command.d.ts.map +0 -1
- package/dist/flow/warp-command.js +0 -144
- package/dist/flow/warp-command.js.map +0 -1
- package/dist/flow/warp-utils.d.ts +0 -11
- package/dist/flow/warp-utils.d.ts.map +0 -1
- package/dist/flow/warp-utils.js +0 -187
- package/dist/flow/warp-utils.js.map +0 -1
- package/dist/snapshot/index.d.ts +0 -2
- package/dist/snapshot/index.d.ts.map +0 -1
- package/dist/snapshot/index.js +0 -2
- package/dist/snapshot/index.js.map +0 -1
- package/dist/snapshot/reasoning-strip.d.ts +0 -22
- package/dist/snapshot/reasoning-strip.d.ts.map +0 -1
- package/dist/snapshot/reasoning-strip.js +0 -58
- package/dist/snapshot/reasoning-strip.js.map +0 -1
- package/dist/snapshot/snapshot.d.ts +0 -77
- package/dist/snapshot/snapshot.d.ts.map +0 -1
- package/dist/snapshot/snapshot.js +0 -1791
- package/dist/snapshot/snapshot.js.map +0 -1
- package/dist/tools/web-tool.d.ts +0 -46
- package/dist/tools/web-tool.d.ts.map +0 -1
- package/dist/tools/web-tool.js.map +0 -1
- /package/dist/{core → flow}/agents.d.ts +0 -0
- /package/dist/{core → flow}/session-registry.d.ts +0 -0
- /package/dist/{core → flow}/session-registry.js +0 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apply-patch — 1:1 port of OpenAI Codex CLI apply_patch tool.
|
|
3
|
+
*
|
|
4
|
+
* Parses patch text into hunks, locates context via 4-stage fuzzy matching,
|
|
5
|
+
* computes replacements, and applies them to the filesystem.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Parser constants
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
const BEGIN_PATCH_MARKER = "*** Begin Patch";
|
|
13
|
+
const END_PATCH_MARKER = "*** End Patch";
|
|
14
|
+
const ENVIRONMENT_ID_MARKER = "*** Environment ID: ";
|
|
15
|
+
const ADD_FILE_MARKER = "*** Add File: ";
|
|
16
|
+
const DELETE_FILE_MARKER = "*** Delete File: ";
|
|
17
|
+
const UPDATE_FILE_MARKER = "*** Update File: ";
|
|
18
|
+
const MOVE_TO_MARKER = "*** Move to: ";
|
|
19
|
+
const EOF_MARKER = "*** End of File";
|
|
20
|
+
const CHANGE_CONTEXT_MARKER = "@@ ";
|
|
21
|
+
const EMPTY_CHANGE_CONTEXT_MARKER = "@@";
|
|
22
|
+
export class ParseError extends Error {
|
|
23
|
+
kind;
|
|
24
|
+
lineNumber;
|
|
25
|
+
constructor(kind, message, lineNumber) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.kind = kind;
|
|
28
|
+
this.lineNumber = lineNumber;
|
|
29
|
+
this.name = "ParseError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class ComputeReplacementsError extends Error {
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = "ComputeReplacementsError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Patch parser
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
function checkPatchBoundariesStrict(lines) {
|
|
42
|
+
if (lines.length === 0) {
|
|
43
|
+
throw new ParseError("invalid-patch", "The first line of the patch must be '*** Begin Patch'");
|
|
44
|
+
}
|
|
45
|
+
const first = lines[0].trim();
|
|
46
|
+
const last = lines[lines.length - 1].trim();
|
|
47
|
+
if (first !== BEGIN_PATCH_MARKER) {
|
|
48
|
+
throw new ParseError("invalid-patch", "The first line of the patch must be '*** Begin Patch'");
|
|
49
|
+
}
|
|
50
|
+
if (last !== END_PATCH_MARKER) {
|
|
51
|
+
throw new ParseError("invalid-patch", "The last line of the patch must be '*** End Patch'");
|
|
52
|
+
}
|
|
53
|
+
return { patchLines: lines, hunkLines: lines.slice(1, -1) };
|
|
54
|
+
}
|
|
55
|
+
function checkPatchBoundariesLenient(lines) {
|
|
56
|
+
try {
|
|
57
|
+
return checkPatchBoundariesStrict(lines);
|
|
58
|
+
}
|
|
59
|
+
catch (strictErr) {
|
|
60
|
+
if (lines.length >= 4) {
|
|
61
|
+
const first = lines[0].trim();
|
|
62
|
+
const last = lines[lines.length - 1].trim();
|
|
63
|
+
if ((first === "<<EOF" || first === "<<'EOF'" || first === '<<"EOF"') &&
|
|
64
|
+
last.endsWith("EOF")) {
|
|
65
|
+
const inner = lines.slice(1, -1);
|
|
66
|
+
try {
|
|
67
|
+
return checkPatchBoundariesStrict(inner);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
/* fall through to return original error */
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
throw strictErr;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function parseEnvironmentIdPreamble(lines) {
|
|
78
|
+
if (lines.length === 0) {
|
|
79
|
+
return { remaining: lines, lineNumber: 2 };
|
|
80
|
+
}
|
|
81
|
+
const first = lines[0].trimStart();
|
|
82
|
+
if (first.startsWith(ENVIRONMENT_ID_MARKER)) {
|
|
83
|
+
const id = first.slice(ENVIRONMENT_ID_MARKER.length).trim();
|
|
84
|
+
if (id === "") {
|
|
85
|
+
throw new ParseError("invalid-patch", "apply_patch environment_id cannot be empty");
|
|
86
|
+
}
|
|
87
|
+
return { environmentId: id, remaining: lines.slice(1), lineNumber: 3 };
|
|
88
|
+
}
|
|
89
|
+
return { remaining: lines, lineNumber: 2 };
|
|
90
|
+
}
|
|
91
|
+
function parseUpdateFileChunk(lines, lineNumber, allowMissingContext) {
|
|
92
|
+
if (lines.length === 0) {
|
|
93
|
+
throw new ParseError("invalid-hunk", "Update hunk does not contain any lines", lineNumber);
|
|
94
|
+
}
|
|
95
|
+
let changeContext;
|
|
96
|
+
let startIndex = 0;
|
|
97
|
+
if (lines[0] === EMPTY_CHANGE_CONTEXT_MARKER) {
|
|
98
|
+
changeContext = undefined;
|
|
99
|
+
startIndex = 1;
|
|
100
|
+
}
|
|
101
|
+
else if (lines[0].startsWith(CHANGE_CONTEXT_MARKER)) {
|
|
102
|
+
changeContext = lines[0].slice(CHANGE_CONTEXT_MARKER.length);
|
|
103
|
+
startIndex = 1;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
if (!allowMissingContext) {
|
|
107
|
+
throw new ParseError("invalid-hunk", `Expected update hunk to start with a @@ context marker, got: '${lines[0]}'`, lineNumber);
|
|
108
|
+
}
|
|
109
|
+
changeContext = undefined;
|
|
110
|
+
startIndex = 0;
|
|
111
|
+
}
|
|
112
|
+
if (startIndex >= lines.length) {
|
|
113
|
+
throw new ParseError("invalid-hunk", "Update hunk does not contain any lines", lineNumber + 1);
|
|
114
|
+
}
|
|
115
|
+
const oldLines = [];
|
|
116
|
+
const newLines = [];
|
|
117
|
+
let isEndOfFile = false;
|
|
118
|
+
let parsedLines = 0;
|
|
119
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
120
|
+
const line = lines[i];
|
|
121
|
+
if (line === EOF_MARKER) {
|
|
122
|
+
if (parsedLines === 0) {
|
|
123
|
+
throw new ParseError("invalid-hunk", "Update hunk does not contain any lines", lineNumber + 1);
|
|
124
|
+
}
|
|
125
|
+
isEndOfFile = true;
|
|
126
|
+
parsedLines += 1;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
const firstChar = line.charAt(0);
|
|
130
|
+
if (firstChar === "") {
|
|
131
|
+
oldLines.push("");
|
|
132
|
+
newLines.push("");
|
|
133
|
+
}
|
|
134
|
+
else if (firstChar === " ") {
|
|
135
|
+
oldLines.push(line.slice(1));
|
|
136
|
+
newLines.push(line.slice(1));
|
|
137
|
+
}
|
|
138
|
+
else if (firstChar === "+") {
|
|
139
|
+
newLines.push(line.slice(1));
|
|
140
|
+
}
|
|
141
|
+
else if (firstChar === "-") {
|
|
142
|
+
oldLines.push(line.slice(1));
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
if (parsedLines === 0) {
|
|
146
|
+
throw new ParseError("invalid-hunk", `Unexpected line found in update hunk: '${line}'. Every line should start with ' ' (context line), '+' (added line), or '-' (removed line)`, lineNumber + 1);
|
|
147
|
+
}
|
|
148
|
+
// Assume start of next hunk.
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
parsedLines += 1;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
chunk: { changeContext, oldLines, newLines, isEndOfFile },
|
|
155
|
+
parsedLines: parsedLines + startIndex,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function parseOneHunk(lines, lineNumber) {
|
|
159
|
+
const firstLine = lines[0].trim();
|
|
160
|
+
if (firstLine.startsWith(ADD_FILE_MARKER)) {
|
|
161
|
+
const filePath = firstLine.slice(ADD_FILE_MARKER.length);
|
|
162
|
+
let contents = "";
|
|
163
|
+
let parsedLines = 1;
|
|
164
|
+
for (let i = 1; i < lines.length; i++) {
|
|
165
|
+
const line = lines[i];
|
|
166
|
+
if (line.startsWith("+")) {
|
|
167
|
+
contents += line.slice(1) + "\n";
|
|
168
|
+
parsedLines += 1;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return { hunk: { type: "add", path: filePath, contents }, parsedLines };
|
|
175
|
+
}
|
|
176
|
+
if (firstLine.startsWith(DELETE_FILE_MARKER)) {
|
|
177
|
+
const filePath = firstLine.slice(DELETE_FILE_MARKER.length);
|
|
178
|
+
return { hunk: { type: "delete", path: filePath }, parsedLines: 1 };
|
|
179
|
+
}
|
|
180
|
+
if (firstLine.startsWith(UPDATE_FILE_MARKER)) {
|
|
181
|
+
const filePath = firstLine.slice(UPDATE_FILE_MARKER.length);
|
|
182
|
+
let remaining = lines.slice(1);
|
|
183
|
+
let parsedLines = 1;
|
|
184
|
+
let movePath;
|
|
185
|
+
if (remaining.length > 0 && remaining[0].startsWith(MOVE_TO_MARKER)) {
|
|
186
|
+
movePath = remaining[0].slice(MOVE_TO_MARKER.length);
|
|
187
|
+
remaining = remaining.slice(1);
|
|
188
|
+
parsedLines += 1;
|
|
189
|
+
}
|
|
190
|
+
const chunks = [];
|
|
191
|
+
while (remaining.length > 0) {
|
|
192
|
+
if (remaining[0].trim() === "") {
|
|
193
|
+
parsedLines += 1;
|
|
194
|
+
remaining = remaining.slice(1);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (remaining[0].startsWith("*")) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
const { chunk, parsedLines: chunkLines } = parseUpdateFileChunk(remaining, lineNumber + parsedLines, chunks.length === 0);
|
|
201
|
+
chunks.push(chunk);
|
|
202
|
+
parsedLines += chunkLines;
|
|
203
|
+
remaining = remaining.slice(chunkLines);
|
|
204
|
+
}
|
|
205
|
+
if (chunks.length === 0) {
|
|
206
|
+
throw new ParseError("invalid-hunk", `Update file hunk for path '${filePath}' is empty`, lineNumber);
|
|
207
|
+
}
|
|
208
|
+
return { hunk: { type: "update", path: filePath, movePath, chunks }, parsedLines };
|
|
209
|
+
}
|
|
210
|
+
throw new ParseError("invalid-hunk", `'${firstLine}' is not a valid hunk header. Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'`, lineNumber);
|
|
211
|
+
}
|
|
212
|
+
export function parsePatch(patch) {
|
|
213
|
+
const trimmed = patch.trim();
|
|
214
|
+
const lines = trimmed.split("\n");
|
|
215
|
+
const { patchLines, hunkLines } = checkPatchBoundariesLenient(lines);
|
|
216
|
+
const { environmentId, remaining, lineNumber } = parseEnvironmentIdPreamble(hunkLines);
|
|
217
|
+
let remainingLines = remaining;
|
|
218
|
+
let currentLine = lineNumber;
|
|
219
|
+
const hunks = [];
|
|
220
|
+
while (remainingLines.length > 0) {
|
|
221
|
+
const { hunk, parsedLines } = parseOneHunk(remainingLines, currentLine);
|
|
222
|
+
hunks.push(hunk);
|
|
223
|
+
currentLine += parsedLines;
|
|
224
|
+
remainingLines = remainingLines.slice(parsedLines);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
patch: patchLines.join("\n"),
|
|
228
|
+
hunks,
|
|
229
|
+
environmentId,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
// seek_sequence — 4-stage fuzzy matching
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
export function seekSequence(lines, pattern, start, eof) {
|
|
236
|
+
if (pattern.length === 0) {
|
|
237
|
+
return start;
|
|
238
|
+
}
|
|
239
|
+
if (pattern.length > lines.length) {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
const searchStart = eof && lines.length >= pattern.length ? lines.length - pattern.length : start;
|
|
243
|
+
// Stage 1: exact match
|
|
244
|
+
for (let i = searchStart; i <= lines.length - pattern.length; i++) {
|
|
245
|
+
let ok = true;
|
|
246
|
+
for (let j = 0; j < pattern.length; j++) {
|
|
247
|
+
if (lines[i + j] !== pattern[j]) {
|
|
248
|
+
ok = false;
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (ok)
|
|
253
|
+
return i;
|
|
254
|
+
}
|
|
255
|
+
// Stage 2: rstrip match (ignore trailing whitespace)
|
|
256
|
+
for (let i = searchStart; i <= lines.length - pattern.length; i++) {
|
|
257
|
+
let ok = true;
|
|
258
|
+
for (let j = 0; j < pattern.length; j++) {
|
|
259
|
+
if (lines[i + j].trimEnd() !== pattern[j].trimEnd()) {
|
|
260
|
+
ok = false;
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (ok)
|
|
265
|
+
return i;
|
|
266
|
+
}
|
|
267
|
+
// Stage 3: trim match (ignore leading and trailing whitespace)
|
|
268
|
+
for (let i = searchStart; i <= lines.length - pattern.length; i++) {
|
|
269
|
+
let ok = true;
|
|
270
|
+
for (let j = 0; j < pattern.length; j++) {
|
|
271
|
+
if (lines[i + j].trim() !== pattern[j].trim()) {
|
|
272
|
+
ok = false;
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (ok)
|
|
277
|
+
return i;
|
|
278
|
+
}
|
|
279
|
+
// Stage 4: Unicode normalisation
|
|
280
|
+
function normalise(s) {
|
|
281
|
+
return s
|
|
282
|
+
.trim()
|
|
283
|
+
.split("")
|
|
284
|
+
.map((c) => {
|
|
285
|
+
switch (c) {
|
|
286
|
+
// Dashes / hyphens → ASCII '-'
|
|
287
|
+
case "\u2010":
|
|
288
|
+
case "\u2011":
|
|
289
|
+
case "\u2012":
|
|
290
|
+
case "\u2013":
|
|
291
|
+
case "\u2014":
|
|
292
|
+
case "\u2015":
|
|
293
|
+
case "\u2212":
|
|
294
|
+
return "-";
|
|
295
|
+
// Fancy single quotes → '\''
|
|
296
|
+
case "\u2018":
|
|
297
|
+
case "\u2019":
|
|
298
|
+
case "\u201A":
|
|
299
|
+
case "\u201B":
|
|
300
|
+
return "'";
|
|
301
|
+
// Fancy double quotes → '"'
|
|
302
|
+
case "\u201C":
|
|
303
|
+
case "\u201D":
|
|
304
|
+
case "\u201E":
|
|
305
|
+
case "\u201F":
|
|
306
|
+
return '"';
|
|
307
|
+
// Odd spaces → normal space
|
|
308
|
+
case "\u00A0":
|
|
309
|
+
case "\u2002":
|
|
310
|
+
case "\u2003":
|
|
311
|
+
case "\u2004":
|
|
312
|
+
case "\u2005":
|
|
313
|
+
case "\u2006":
|
|
314
|
+
case "\u2007":
|
|
315
|
+
case "\u2008":
|
|
316
|
+
case "\u2009":
|
|
317
|
+
case "\u200A":
|
|
318
|
+
case "\u202F":
|
|
319
|
+
case "\u205F":
|
|
320
|
+
case "\u3000":
|
|
321
|
+
return " ";
|
|
322
|
+
default:
|
|
323
|
+
return c;
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
.join("");
|
|
327
|
+
}
|
|
328
|
+
for (let i = searchStart; i <= lines.length - pattern.length; i++) {
|
|
329
|
+
let ok = true;
|
|
330
|
+
for (let j = 0; j < pattern.length; j++) {
|
|
331
|
+
if (normalise(lines[i + j]) !== normalise(pattern[j])) {
|
|
332
|
+
ok = false;
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (ok)
|
|
337
|
+
return i;
|
|
338
|
+
}
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
// ---------------------------------------------------------------------------
|
|
342
|
+
// compute_replacements + apply_replacements
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
export function computeReplacements(originalLines, filePath, chunks) {
|
|
345
|
+
const replacements = [];
|
|
346
|
+
let lineIndex = 0;
|
|
347
|
+
for (const chunk of chunks) {
|
|
348
|
+
if (chunk.changeContext) {
|
|
349
|
+
const idx = seekSequence(originalLines, [chunk.changeContext], lineIndex, false);
|
|
350
|
+
if (idx === undefined) {
|
|
351
|
+
throw new ComputeReplacementsError(`Failed to find context '${chunk.changeContext}' in ${filePath}`);
|
|
352
|
+
}
|
|
353
|
+
lineIndex = idx + 1;
|
|
354
|
+
}
|
|
355
|
+
if (chunk.oldLines.length === 0) {
|
|
356
|
+
// Pure addition — insert at end (or just before the trailing empty line).
|
|
357
|
+
const insertionIdx = originalLines.length > 0 && originalLines[originalLines.length - 1] === ""
|
|
358
|
+
? originalLines.length - 1
|
|
359
|
+
: originalLines.length;
|
|
360
|
+
replacements.push({ startIdx: insertionIdx, oldLen: 0, newLines: chunk.newLines });
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
let pattern = chunk.oldLines;
|
|
364
|
+
let found = seekSequence(originalLines, pattern, lineIndex, chunk.isEndOfFile);
|
|
365
|
+
let newSlice = chunk.newLines;
|
|
366
|
+
if (found === undefined && pattern.length > 0 && pattern[pattern.length - 1] === "") {
|
|
367
|
+
// Retry without the trailing empty sentinel.
|
|
368
|
+
pattern = pattern.slice(0, -1);
|
|
369
|
+
if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "") {
|
|
370
|
+
newSlice = newSlice.slice(0, -1);
|
|
371
|
+
}
|
|
372
|
+
found = seekSequence(originalLines, pattern, lineIndex, chunk.isEndOfFile);
|
|
373
|
+
}
|
|
374
|
+
if (found === undefined) {
|
|
375
|
+
throw new ComputeReplacementsError(`Failed to find expected lines in ${filePath}:\n${chunk.oldLines.join("\n")}`);
|
|
376
|
+
}
|
|
377
|
+
replacements.push({ startIdx: found, oldLen: pattern.length, newLines: newSlice });
|
|
378
|
+
lineIndex = found + pattern.length;
|
|
379
|
+
}
|
|
380
|
+
replacements.sort((a, b) => a.startIdx - b.startIdx);
|
|
381
|
+
return replacements;
|
|
382
|
+
}
|
|
383
|
+
export function applyReplacements(lines, replacements) {
|
|
384
|
+
const result = [...lines];
|
|
385
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
386
|
+
const { startIdx, oldLen, newLines } = replacements[i];
|
|
387
|
+
result.splice(startIdx, oldLen, ...newLines);
|
|
388
|
+
}
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
function deriveNewContentsFromChunks(originalContent, chunks, filePath) {
|
|
392
|
+
let originalLines = originalContent.split("\n").map((l) => l);
|
|
393
|
+
// Drop the trailing empty element that results from the final newline
|
|
394
|
+
// so that line counts match the behaviour of standard diff.
|
|
395
|
+
if (originalLines.length > 0 && originalLines[originalLines.length - 1] === "") {
|
|
396
|
+
originalLines.pop();
|
|
397
|
+
}
|
|
398
|
+
const replacements = computeReplacements(originalLines, filePath, chunks);
|
|
399
|
+
let newLines = applyReplacements(originalLines, replacements);
|
|
400
|
+
// Ensure file terminates with a newline.
|
|
401
|
+
if (newLines.length === 0 || newLines[newLines.length - 1] !== "") {
|
|
402
|
+
newLines.push("");
|
|
403
|
+
}
|
|
404
|
+
return newLines.join("\n");
|
|
405
|
+
}
|
|
406
|
+
export async function applyPatch(patchText, cwd) {
|
|
407
|
+
const args = parsePatch(patchText);
|
|
408
|
+
const added = [];
|
|
409
|
+
const modified = [];
|
|
410
|
+
const deleted = [];
|
|
411
|
+
let exact = true;
|
|
412
|
+
for (const hunk of args.hunks) {
|
|
413
|
+
switch (hunk.type) {
|
|
414
|
+
case "add": {
|
|
415
|
+
const targetPath = path.resolve(cwd, hunk.path);
|
|
416
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
417
|
+
await fs.writeFile(targetPath, hunk.contents, "utf-8");
|
|
418
|
+
added.push(hunk.path);
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
case "delete": {
|
|
422
|
+
const targetPath = path.resolve(cwd, hunk.path);
|
|
423
|
+
try {
|
|
424
|
+
await fs.unlink(targetPath);
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
if (err.code === "ENOENT") {
|
|
428
|
+
exact = false;
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
throw err;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
deleted.push(hunk.path);
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
437
|
+
case "update": {
|
|
438
|
+
const targetPath = path.resolve(cwd, hunk.path);
|
|
439
|
+
let originalContent;
|
|
440
|
+
try {
|
|
441
|
+
originalContent = await fs.readFile(targetPath, "utf-8");
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
if (err.code === "ENOENT") {
|
|
445
|
+
throw new Error(`File not found: ${hunk.path}`);
|
|
446
|
+
}
|
|
447
|
+
throw err;
|
|
448
|
+
}
|
|
449
|
+
const newContent = deriveNewContentsFromChunks(originalContent, hunk.chunks, hunk.path);
|
|
450
|
+
if (hunk.movePath) {
|
|
451
|
+
const destPath = path.resolve(cwd, hunk.movePath);
|
|
452
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
453
|
+
await fs.writeFile(destPath, newContent, "utf-8");
|
|
454
|
+
try {
|
|
455
|
+
await fs.unlink(targetPath);
|
|
456
|
+
}
|
|
457
|
+
catch (err) {
|
|
458
|
+
if (err.code === "ENOENT") {
|
|
459
|
+
exact = false;
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
throw err;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
modified.push(hunk.movePath);
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
await fs.writeFile(targetPath, newContent, "utf-8");
|
|
469
|
+
modified.push(hunk.path);
|
|
470
|
+
}
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return { affected: { added, modified, deleted }, exact };
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=apply-patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-patch.js","sourceRoot":"","sources":["../../src/batch/apply-patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,16 @@ export declare class BashProcessTracker {
|
|
|
39
39
|
abortAll(): void;
|
|
40
40
|
}
|
|
41
41
|
/** Generate a short random ID for bash ops that don't provide one. */
|
|
42
|
+
/**
|
|
43
|
+
* Run a single bash command with output truncation and optional timeout.
|
|
44
|
+
* Returns a promise that resolves with stdout, stderr, and exitCode.
|
|
45
|
+
* Uses execFile (synchronous completion) with truncateBashOutput applied.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runBashWithLimits(command: string, cwd: string, timeoutMs?: number, signal?: AbortSignal): Promise<{
|
|
48
|
+
stdout: string;
|
|
49
|
+
stderr: string;
|
|
50
|
+
exitCode: number;
|
|
51
|
+
}>;
|
|
42
52
|
export declare function generateBashId(): string;
|
|
43
53
|
/**
|
|
44
54
|
* Truncate bash stdout/stderr to prevent oversized tool results.
|
|
@@ -80,12 +90,6 @@ export declare function createBatchBashPollTool(tracker: BashProcessTracker): {
|
|
|
80
90
|
details: {
|
|
81
91
|
results: PendingBashResult[];
|
|
82
92
|
};
|
|
83
|
-
} | {
|
|
84
|
-
content: {
|
|
85
|
-
type: string;
|
|
86
|
-
text: string;
|
|
87
|
-
}[];
|
|
88
|
-
isError: boolean;
|
|
89
93
|
}>;
|
|
90
94
|
};
|
|
91
95
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-bash.d.ts","sourceRoot":"","sources":["../../src/batch/batch-bash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"batch-bash.d.ts","sourceRoot":"","sources":["../../src/batch/batch-bash.ts"],"names":[],"mappings":"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"}
|
package/dist/batch/batch-bash.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { appendDirectiveOnce } from "../steering/tool-utils.js";
|
|
2
2
|
import { compressOutput } from "./shell-compress.js";
|
|
3
3
|
/**
|
|
4
4
|
* batch bash -- parallel bash execution and polling.
|
|
@@ -11,8 +11,15 @@ import { compressOutput } from "./shell-compress.js";
|
|
|
11
11
|
* wait time before the batch tool returns partial results. Commands that
|
|
12
12
|
* haven't finished continue running in the background and can be polled
|
|
13
13
|
* via the `batch_bash_poll` tool.
|
|
14
|
+
*
|
|
15
|
+
* Why not `createLocalBashOperations` from `@earendil-works/pi-coding-agent`?
|
|
16
|
+
* That helper is a simple exec wrapper (returns a promise when the process exits).
|
|
17
|
+
* Our tracker needs background execution + polling: processes must outlive the
|
|
18
|
+
* soft timeout and be queried later via `batch_bash_poll`. We therefore use raw
|
|
19
|
+
* `node:child_process.spawn` directly to retain full control over detached mode,
|
|
20
|
+
* per-process AbortControllers, and background lifecycle.
|
|
14
21
|
*/
|
|
15
|
-
import { spawn } from "node:child_process";
|
|
22
|
+
import { spawn, execFile } from "node:child_process";
|
|
16
23
|
import { Type } from "@sinclair/typebox";
|
|
17
24
|
import { BASH_SOFT_TIMEOUT_MS, BASH_POLL_TAIL_LINES, MAX_BASH_OUTPUT_BYTES, MAX_BASH_OUTPUT_LINES, } from "./constants.js";
|
|
18
25
|
import { classifyDuration } from "../tools/timed-bash.js";
|
|
@@ -182,6 +189,39 @@ function tailLines(text, n) {
|
|
|
182
189
|
return lines.slice(-n).join("\n");
|
|
183
190
|
}
|
|
184
191
|
/** Generate a short random ID for bash ops that don't provide one. */
|
|
192
|
+
/**
|
|
193
|
+
* Run a single bash command with output truncation and optional timeout.
|
|
194
|
+
* Returns a promise that resolves with stdout, stderr, and exitCode.
|
|
195
|
+
* Uses execFile (synchronous completion) with truncateBashOutput applied.
|
|
196
|
+
*/
|
|
197
|
+
export function runBashWithLimits(command, cwd, timeoutMs, signal) {
|
|
198
|
+
return new Promise((resolve) => {
|
|
199
|
+
const child = execFile("bash", ["-c", command], { cwd, timeout: timeoutMs }, (error, stdout, stderr) => {
|
|
200
|
+
const out = truncateBashOutput(stdout);
|
|
201
|
+
const err = truncateBashOutput(stderr);
|
|
202
|
+
if (error) {
|
|
203
|
+
resolve({ stdout: out, stderr: err, exitCode: error.code ?? 1 });
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
resolve({ stdout: out, stderr: err, exitCode: 0 });
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
child.stdout?.setEncoding("utf-8");
|
|
210
|
+
child.stderr?.setEncoding("utf-8");
|
|
211
|
+
if (signal) {
|
|
212
|
+
const onAbort = () => {
|
|
213
|
+
child.kill("SIGTERM");
|
|
214
|
+
resolve({ stdout: "", stderr: "[aborted]", exitCode: -1 });
|
|
215
|
+
};
|
|
216
|
+
if (signal.aborted) {
|
|
217
|
+
onAbort();
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
185
225
|
export function generateBashId() {
|
|
186
226
|
return Math.random().toString(36).slice(2, 10);
|
|
187
227
|
}
|
|
@@ -205,14 +245,25 @@ export function truncateBashOutput(text, maxBytes = MAX_BASH_OUTPUT_BYTES, maxLi
|
|
|
205
245
|
const resultBytes = Buffer.byteLength(result, "utf-8");
|
|
206
246
|
if (resultBytes > maxBytes) {
|
|
207
247
|
const buf = Buffer.from(result, "utf-8");
|
|
208
|
-
// Find last newline before maxBytes
|
|
248
|
+
// Find last newline before maxBytes, never cutting inside a multi-byte UTF-8 character
|
|
209
249
|
let cutAt = maxBytes;
|
|
210
|
-
while (cutAt > 0
|
|
250
|
+
while (cutAt > 0) {
|
|
251
|
+
// Skip UTF-8 continuation bytes so we land on a character boundary
|
|
252
|
+
while (cutAt > 0 && (buf[cutAt] & 0xc0) === 0x80) {
|
|
253
|
+
cutAt--;
|
|
254
|
+
}
|
|
255
|
+
if (cutAt <= 0)
|
|
256
|
+
break;
|
|
257
|
+
if (buf[cutAt] === 0x0a)
|
|
258
|
+
break;
|
|
211
259
|
cutAt--;
|
|
212
260
|
}
|
|
213
261
|
if (cutAt <= 0) {
|
|
214
|
-
// No newline found within safe range; force cut at maxBytes
|
|
262
|
+
// No newline found within safe range; force cut at maxBytes aligned to char boundary
|
|
215
263
|
cutAt = maxBytes;
|
|
264
|
+
while (cutAt > 0 && (buf[cutAt] & 0xc0) === 0x80) {
|
|
265
|
+
cutAt--;
|
|
266
|
+
}
|
|
216
267
|
}
|
|
217
268
|
result = buf.slice(0, cutAt).toString("utf-8");
|
|
218
269
|
result += `\n[... truncated at ${(maxBytes / 1024).toFixed(0)} KB, ${totalBytes} total ...]`;
|
|
@@ -372,7 +423,7 @@ export function createBatchBashPollTool(tracker) {
|
|
|
372
423
|
].join("\n"),
|
|
373
424
|
promptSnippet: "Poll pending bash commands for results",
|
|
374
425
|
promptGuidelines: [
|
|
375
|
-
"Use batch_bash_poll to check on bash commands that returned pending from a batch call.",
|
|
426
|
+
"Use `batch_bash_poll` to check on bash commands that returned pending from a batch call.",
|
|
376
427
|
"Pass the `i` (id) values from the pending results.",
|
|
377
428
|
],
|
|
378
429
|
parameters: BatchBashPollParams,
|
|
@@ -389,10 +440,7 @@ export function createBatchBashPollTool(tracker) {
|
|
|
389
440
|
const args = (input ?? {});
|
|
390
441
|
const ids = Array.isArray(args.i) ? args.i : Array.isArray(args.ids) ? args.ids : [];
|
|
391
442
|
if (ids.length === 0) {
|
|
392
|
-
|
|
393
|
-
content: [{ type: "text", text: "Error: i (ids) array is required and must not be empty." }],
|
|
394
|
-
isError: true,
|
|
395
|
-
};
|
|
443
|
+
throw new Error("Error: i (ids) array is required and must not be empty.");
|
|
396
444
|
}
|
|
397
445
|
const results = pollBatchBashResults(ids, tracker);
|
|
398
446
|
const lines = [];
|
|
@@ -418,7 +466,7 @@ export function createBatchBashPollTool(tracker) {
|
|
|
418
466
|
content: [{ type: "text", text: lines.join("\n").trimEnd() }],
|
|
419
467
|
details: { results },
|
|
420
468
|
};
|
|
421
|
-
|
|
469
|
+
appendDirectiveOnce(pollResult);
|
|
422
470
|
return pollResult;
|
|
423
471
|
},
|
|
424
472
|
};
|