@pentoshi/clai 3.0.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/classic-renderer.js +9 -1
- package/dist/agent/classic-renderer.js.map +1 -1
- package/dist/agent/events.d.ts +5 -0
- package/dist/agent/plan-tool.js +80 -8
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/runner.js +114 -42
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/tool-call-parser.d.ts +5 -0
- package/dist/agent/tool-call-parser.js +15 -0
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.js +5 -0
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/events/app-event.d.ts +4 -0
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/commands/doctor.js +11 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/index.js +40 -8
- package/dist/index.js.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.js +7 -6
- package/dist/prompts/index.js.map +1 -1
- package/dist/tools/fs.d.ts +6 -0
- package/dist/tools/fs.js +56 -6
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/registry.js +77 -26
- package/dist/tools/registry.js.map +1 -1
- package/dist/tui/runtime.d.ts +19 -0
- package/dist/tui/runtime.js +92 -0
- package/dist/tui/runtime.js.map +1 -0
- package/dist/tui/state.js +2 -0
- package/dist/tui/state.js.map +1 -1
- package/dist/tui-v2/app/App.d.ts +3 -3
- package/dist/tui-v2/app/App.js +22 -10
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/plan-lifecycle.d.ts +6 -0
- package/dist/tui-v2/app/plan-lifecycle.js +43 -7
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.d.ts +5 -6
- package/dist/tui-v2/components/modal/confirm-modal.js +60 -21
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
- package/dist/tui-v2/components/modal/secret-modal.d.ts +3 -9
- package/dist/tui-v2/components/modal/secret-modal.js +17 -17
- package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.d.ts +12 -3
- package/dist/tui-v2/components/overlay/overlay-host.js +19 -4
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/plan/plan-view.d.ts +1 -1
- package/dist/tui-v2/components/plan/plan-view.js +8 -4
- package/dist/tui-v2/components/plan/plan-view.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.js +10 -1
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js +6 -0
- package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.d.ts +5 -5
- package/dist/tui-v2/components/transcript/compacted-row.js +15 -40
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.js +42 -12
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +8 -1
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/rendering/batch-sections.d.ts +12 -0
- package/dist/tui-v2/rendering/batch-sections.js +68 -0
- package/dist/tui-v2/rendering/batch-sections.js.map +1 -1
- package/dist/tui-v2/rendering/strip-tool-surfaces.d.ts +10 -0
- package/dist/tui-v2/rendering/strip-tool-surfaces.js +32 -0
- package/dist/tui-v2/rendering/strip-tool-surfaces.js.map +1 -0
- package/dist/tui-v2/rendering/tool-presenter.js +2 -0
- package/dist/tui-v2/rendering/tool-presenter.js.map +1 -1
- package/dist/tui-v2/state/transcript-hydrate.js +6 -2
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -1
- package/dist/tui-v2/state/transcript-reducer.js +74 -16
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
- package/dist/tui-v2/state/transcript-types.d.ts +1 -1
- package/package.json +13 -4
|
@@ -64,10 +64,18 @@ export function attachClassicRenderer(write = (chunk) => {
|
|
|
64
64
|
stopSpinner();
|
|
65
65
|
const call = { name: event.name, args: {} };
|
|
66
66
|
toolCalls.set(event.id, call);
|
|
67
|
-
|
|
67
|
+
// Queued — actual start is tool-start (avoids "running" while waiting).
|
|
68
|
+
const line = chalk.dim(` ○ ${event.name}`) + chalk.gray(` ${event.argsDisplay}`);
|
|
68
69
|
write(styleToolChatter(call, line) + "\n");
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
72
|
+
case "tool-start": {
|
|
73
|
+
stopSpinner();
|
|
74
|
+
const call = toolCalls.get(event.id);
|
|
75
|
+
write(chalk.cyan(` ▶ ${call?.name ?? event.id}`) +
|
|
76
|
+
chalk.dim(" running…\n"));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
71
79
|
case "tool-output": {
|
|
72
80
|
stopSpinner();
|
|
73
81
|
if (!event.chunk)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classic-renderer.js","sourceRoot":"","sources":["../../src/agent/classic-renderer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"classic-renderer.js","sourceRoot":"","sources":["../../src/agent/classic-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAwB,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAM1D,MAAM,UAAU,qBAAqB,CACnC,QAAiC,CAAC,KAAK,EAAE,EAAE;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,IAAI,OAAoC,CAAC;IAEzC,MAAM,OAAO,GAAG,CAAC,EAAU,EAAY,EAAE,CACvC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAElD,MAAM,WAAW,GAAG,GAAS,EAAE;QAC7B,OAAO,EAAE,IAAI,EAAE,CAAC;QAChB,OAAO,GAAG,SAAS,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,KAAa,EAAQ,EAAE;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAQ,EAAE;QAC1C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,YAAY,CAAC;YAClB,KAAK,iBAAiB,CAAC;YACvB,KAAK,iBAAiB;gBACpB,OAAO;YACT,KAAK,gBAAgB;gBACnB,eAAe,CAAC,UAAU,CAAC,CAAC;gBAC5B,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjC,OAAO;YACT,KAAK,QAAQ;gBACX,IACE,KAAK,CAAC,IAAI,KAAK,mBAAmB;oBAClC,KAAK,CAAC,IAAI,KAAK,UAAU;oBACzB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAC7B,CAAC;oBACD,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC5B,OAAO;gBACT,CAAC;gBACD,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7B,OAAO;YACT,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,WAAW,EAAE,CAAC;gBACd,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;gBAChE,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,KAAK,gBAAgB;gBACnB,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACnD,OAAO;YACT,KAAK,mBAAmB,CAAC,CAAC,CAAC;gBACzB,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5C,OAAO;YACT,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,WAAW,EAAE,CAAC;gBACd,MAAM,IAAI,GAAa,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;gBACtD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC9B,wEAAwE;gBACxE,MAAM,IAAI,GACR,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;gBACvE,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,WAAW,EAAE,CAAC;gBACd,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACrC,KAAK,CACH,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;oBACzC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAC3B,CAAC;gBACF,OAAO;YACT,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,WAAW,EAAE,CAAC;gBACd,IAAI,CAAC,KAAK,CAAC,KAAK;oBAAE,OAAO;gBACzB,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;oBAC3B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;oBACjC,OAAO;gBACT,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;oBAC/B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;oBAC/B,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;oBACvC,CAAC,CAAC,KAAK,CAAC,KAAK;oBACb,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnC,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;gBACxE,OAAO;YACT,CAAC;YACD,KAAK,aAAa;gBAChB,OAAO;YACT,KAAK,cAAc;gBACjB,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;gBACxD,OAAO;YACT,KAAK,aAAa;gBAChB,WAAW,EAAE,CAAC;gBACd,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;oBAClC,KAAK,CACH,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC;wBAC1B,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC;wBAC/B,IAAI;wBACJ,KAAK,CAAC,GAAG,CACP,iFAAiF;4BAC/E,sEAAsE,CACzE,CACJ,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;gBAChD,CAAC;gBACD,OAAO;YACT,KAAK,UAAU;gBACb,WAAW,EAAE,CAAC;gBACd,OAAO;YACT,KAAK,cAAc;gBACjB,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;gBACtC,OAAO;YACT,KAAK,YAAY;gBACf,WAAW,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;gBAC3C,OAAO;QACX,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
|
package/dist/agent/events.d.ts
CHANGED
|
@@ -27,6 +27,11 @@ export type AgentEvent = {
|
|
|
27
27
|
name: string;
|
|
28
28
|
argsDisplay: string;
|
|
29
29
|
}
|
|
30
|
+
/** Tool moved from queued → actually executing (cards stay in document order). */
|
|
31
|
+
| {
|
|
32
|
+
type: "tool-start";
|
|
33
|
+
id: string;
|
|
34
|
+
}
|
|
30
35
|
/** `replace: true` sets the full body (never append) so the UI never keeps a truncated live preview. */
|
|
31
36
|
| {
|
|
32
37
|
type: "tool-output";
|
package/dist/agent/plan-tool.js
CHANGED
|
@@ -2,6 +2,79 @@ import chalk from "chalk";
|
|
|
2
2
|
import { createPlan, loadPlan, savePlan, markTask, } from "../store/plan.js";
|
|
3
3
|
import { renderPlanChecklist } from "../ui/plan-pane.js";
|
|
4
4
|
import { isLumpedSingleTask } from "./tool-call-parser.js";
|
|
5
|
+
/** Coerce model-sloppy plan.create fields into clean titles. */
|
|
6
|
+
function normalizePlanGoal(args) {
|
|
7
|
+
const raw = args.goal ?? args.objective ?? args.title ?? args.name;
|
|
8
|
+
if (typeof raw === "string")
|
|
9
|
+
return raw.trim();
|
|
10
|
+
if (raw && typeof raw === "object") {
|
|
11
|
+
const o = raw;
|
|
12
|
+
for (const k of ["title", "text", "goal", "name", "summary"]) {
|
|
13
|
+
if (typeof o[k] === "string" && o[k].toString().trim()) {
|
|
14
|
+
return String(o[k]).trim();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return "";
|
|
19
|
+
}
|
|
20
|
+
function normalizePlanDetail(args) {
|
|
21
|
+
const raw = args.detail ?? args.description ?? args.approach ?? args.notes;
|
|
22
|
+
if (typeof raw === "string")
|
|
23
|
+
return raw.trim();
|
|
24
|
+
if (Array.isArray(raw)) {
|
|
25
|
+
return raw
|
|
26
|
+
.map((x) => (typeof x === "string" ? x : JSON.stringify(x)))
|
|
27
|
+
.join("\n")
|
|
28
|
+
.trim();
|
|
29
|
+
}
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
function normalizePlanKind(args) {
|
|
33
|
+
const raw = args.kind ?? args.type ?? args.category;
|
|
34
|
+
if (typeof raw === "string" && raw.trim())
|
|
35
|
+
return raw.trim().toLowerCase();
|
|
36
|
+
return "general";
|
|
37
|
+
}
|
|
38
|
+
function normalizeTaskTitle(t) {
|
|
39
|
+
if (typeof t === "string")
|
|
40
|
+
return t.trim();
|
|
41
|
+
if (typeof t === "number" && Number.isFinite(t))
|
|
42
|
+
return String(t);
|
|
43
|
+
if (t && typeof t === "object") {
|
|
44
|
+
const o = t;
|
|
45
|
+
for (const k of [
|
|
46
|
+
"title",
|
|
47
|
+
"task",
|
|
48
|
+
"name",
|
|
49
|
+
"text",
|
|
50
|
+
"description",
|
|
51
|
+
"label",
|
|
52
|
+
"step",
|
|
53
|
+
"summary",
|
|
54
|
+
]) {
|
|
55
|
+
if (typeof o[k] === "string" && o[k].toString().trim()) {
|
|
56
|
+
return String(o[k]).trim();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Accept tasks as string[], object[], or a single newline/comma-separated string.
|
|
64
|
+
* Models frequently emit `[{id,title}]` instead of plain strings.
|
|
65
|
+
*/
|
|
66
|
+
function normalizePlanTasks(args) {
|
|
67
|
+
const raw = args.tasks ?? args.steps ?? args.checklist ?? args.items ?? args.todos;
|
|
68
|
+
if (typeof raw === "string") {
|
|
69
|
+
return raw
|
|
70
|
+
.split(/\n|;|(?:,\s*(?=[A-Z0-9\-]))/)
|
|
71
|
+
.map((s) => s.replace(/^\s*[-*\d.)]+\s*/, "").trim())
|
|
72
|
+
.filter(Boolean);
|
|
73
|
+
}
|
|
74
|
+
if (!Array.isArray(raw))
|
|
75
|
+
return [];
|
|
76
|
+
return raw.map(normalizeTaskTitle).filter(Boolean);
|
|
77
|
+
}
|
|
5
78
|
/** Render the portable inline form; the Ink TUI owns its responsive sidebar. */
|
|
6
79
|
export function renderPlanForTerminal(plan) {
|
|
7
80
|
return renderPlanChecklist(plan);
|
|
@@ -54,19 +127,18 @@ export function planContextMessage(plan, approved) {
|
|
|
54
127
|
export async function handlePlanTool(call, session, ctx) {
|
|
55
128
|
void ctx;
|
|
56
129
|
if (call.name === "plan.create") {
|
|
57
|
-
const goal =
|
|
58
|
-
const detail =
|
|
59
|
-
const kind =
|
|
60
|
-
const
|
|
61
|
-
const taskTitles = rawTasks
|
|
62
|
-
.map((t) => (typeof t === "string" ? t : ""))
|
|
63
|
-
.filter(Boolean);
|
|
130
|
+
const goal = normalizePlanGoal(call.args);
|
|
131
|
+
const detail = normalizePlanDetail(call.args);
|
|
132
|
+
const kind = normalizePlanKind(call.args);
|
|
133
|
+
const taskTitles = normalizePlanTasks(call.args);
|
|
64
134
|
if (!goal || taskTitles.length === 0) {
|
|
65
135
|
return {
|
|
66
136
|
handled: true,
|
|
67
137
|
ok: false,
|
|
68
138
|
display: chalk.red(" ✗ plan.create needs a non-empty goal and at least one task title\n"),
|
|
69
|
-
modelNote: "plan.create failed: provide a string goal and a non-empty tasks array
|
|
139
|
+
modelNote: "plan.create failed: provide a string goal and a non-empty tasks array. " +
|
|
140
|
+
'Accepted task shapes: ["step 1","step 2"] or [{"title":"step 1"},{"id":"t1","title":"step 2"}]. ' +
|
|
141
|
+
'Example: {"name":"plan.create","args":{"goal":"Assess example.com","detail":"…","tasks":["DNS enum","Port scan","HTTP fingerprint"],"kind":"pentest"}}',
|
|
70
142
|
};
|
|
71
143
|
}
|
|
72
144
|
// Reject a low-quality "everything in one step" plan. A single task that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-tool.js","sourceRoot":"","sources":["../../src/agent/plan-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACL,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,GAGT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,gFAAgF;AAChF,MAAM,UAAU,qBAAqB,CAAC,IAAiB;IACrD,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAYD,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,IAAiB,EAAE,QAAiB;IACrE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CACR,uCAAuC,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,IAAI,CAC7E,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IACH,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,aAAa,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QACxE,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CACR,eAAe,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,KAAK,sCAAsC;gBACrF,0EAA0E;gBAC1E,+EAA+E,CAClF,CAAC;QACJ,CAAC;aAAM,IAAI,YAAY,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CACR,mBAAmB,YAAY,CAAC,EAAE,KAAK,YAAY,CAAC,KAAK,KAAK;gBAC5D,+EAA+E,CAClF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CACR,oFAAoF;YAClF,sFAAsF;YACtF,oFAAoF;YACpF,uDAAuD;YACvD,2DAA2D,CAC9D,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CACR,+EAA+E;YAC7E,kGAAkG;YAClG,2GAA2G;YAC3G,wGAAwG;YACxG,wGAAwG;YACxG,mGAAmG;YACnG,qCAAqC,CACxC,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAc,EACd,OAAsB,EACtB,GAA2C;IAE3C,KAAK,GAAG,CAAC;IACT,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"plan-tool.js","sourceRoot":"","sources":["../../src/agent/plan-tool.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/runner.js
CHANGED
|
@@ -24,7 +24,7 @@ import { analyzeTask } from "./task-analyzer.js";
|
|
|
24
24
|
import { LoopGuard } from "./loop-guard.js";
|
|
25
25
|
import { loadPlan } from "../store/plan.js";
|
|
26
26
|
import { pathInsideSandbox, fsWrite } from "../tools/fs.js";
|
|
27
|
-
import { stripSentinelTokens, parseToolCall, recognizeBareToolJson, looksLikeTruncatedToolCall, salvageTruncatedWrite, countToolFences, parseAllToolCalls, groupToolCallsForExecution, buildTurnHistory, collapseRepeatedText, textBeforeToolCall, formatToolArgs, looksLikePentestTask, looksLikeBuildTask, looksLikeInformationalQuery, looksLikeIdleOrSocialPrompt, looksLikeActionNarration, looksLikeWebActionNarration, looksLikePlanNarration, requiresFreshWebSearch, freshnessGuardMessage, buildWorkflowDirective, pentestWorkflowDirective, shouldDimToolChatter, looksLikePromptLeak, } from "./tool-call-parser.js";
|
|
27
|
+
import { stripSentinelTokens, parseToolCall, recognizeBareToolJson, looksLikeTruncatedToolCall, salvageTruncatedWrite, countToolFences, parseAllToolCalls, groupToolCallsForExecution, buildTurnHistory, collapseRepeatedText, textBeforeToolCall, formatToolArgs, looksLikePentestTask, looksLikeBuildTask, looksLikeInformationalQuery, looksLikeIdleOrSocialPrompt, looksLikeActionNarration, looksLikeWebActionNarration, looksLikePlanNarration, requiresFreshWebSearch, freshnessGuardMessage, buildWorkflowDirective, pentestWorkflowDirective, pentestNoLocalServerDirective, shouldDimToolChatter, looksLikePromptLeak, } from "./tool-call-parser.js";
|
|
28
28
|
import { createSessionPolicy, isPreApprovalAllowedTool, isPlanApprovedByStatus, planHasOpenWork, isAbortError, shouldEnableImageOcr, } from "./session-policy.js";
|
|
29
29
|
import { saveToolOutput, summarizeOutput, formatToolContext, } from "./tool-output-formatting.js";
|
|
30
30
|
import { planContextMessage, handlePlanTool, } from "./plan-tool.js";
|
|
@@ -129,8 +129,16 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
129
129
|
};
|
|
130
130
|
const writeStatus = (text, rendered = chalk.dim(text)) => {
|
|
131
131
|
// Footer activity is single-line; strip classic stdout newlines/indents.
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
// Never surface /output path hints as activity (garbles the status bar).
|
|
133
|
+
let cleaned = text.replace(/\s+/g, " ").trim();
|
|
134
|
+
if (/\/output\b|open full output|Ctrl\+O or|\.clai\/outputs/i.test(cleaned)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (cleaned.length > 64) {
|
|
138
|
+
const short = cleaned.match(/^[\w./-]+/);
|
|
139
|
+
cleaned = short ? short[0] : cleaned.slice(0, 61) + "…";
|
|
140
|
+
}
|
|
141
|
+
emit({ type: "status", text: cleaned || "working" });
|
|
134
142
|
if (writesDirectly)
|
|
135
143
|
process.stdout.write(rendered);
|
|
136
144
|
};
|
|
@@ -337,6 +345,16 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
337
345
|
!idleOrSocialPrompt) {
|
|
338
346
|
systemSections.push(pentestWorkflowDirective());
|
|
339
347
|
}
|
|
348
|
+
// Any remote/security engagement (even with an existing or completed plan)
|
|
349
|
+
// must never fall into the coding "start localhost dev server" habit.
|
|
350
|
+
const pentestSession = pentestLikeTurn ||
|
|
351
|
+
activePlan?.kind === "pentest" ||
|
|
352
|
+
(activePlan?.kind !== "coding" &&
|
|
353
|
+
Boolean(activePlan?.goal &&
|
|
354
|
+
/pentest|vulnerab|recon|security assess|attack surface|red team/i.test(activePlan.goal)));
|
|
355
|
+
if (pentestSession && !idleOrSocialPrompt) {
|
|
356
|
+
systemSections.push(pentestNoLocalServerDirective());
|
|
357
|
+
}
|
|
340
358
|
const renderedSystemPrompt = systemSections.join("\n\n");
|
|
341
359
|
// Reserve most of a constrained model's input budget for the user message,
|
|
342
360
|
// recent conversation, tool results, and provider framing. Dynamic project
|
|
@@ -729,6 +747,9 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
729
747
|
}
|
|
730
748
|
parentSignal.throwIfAborted();
|
|
731
749
|
options.onToolStart?.(call);
|
|
750
|
+
// Card was "queued" since writeToolCall; flip to running only when work starts.
|
|
751
|
+
emit({ type: "tool-start", id: toolEventId });
|
|
752
|
+
writeStatus(call.name, chalk.dim(` → ${call.name}\n`));
|
|
732
753
|
const interactiveCommand = (call.name === "shell.exec" &&
|
|
733
754
|
typeof call.args.command === "string" &&
|
|
734
755
|
looksInteractiveStdin(call.args.command)) ||
|
|
@@ -910,9 +931,16 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
910
931
|
artifactPath: savedOutputPath,
|
|
911
932
|
summary: contextOutput,
|
|
912
933
|
});
|
|
913
|
-
|
|
934
|
+
// Classic REPL only: short path notice. Never push long
|
|
935
|
+
// "Ctrl+O or /output last … (path)" strings into the TUI status
|
|
936
|
+
// footer — they collide with activity and garble the chrome.
|
|
937
|
+
if (writesDirectly && savedOutputPath) {
|
|
938
|
+
const short = chalk.dim(` saved ${savedOutputPath}\n`);
|
|
939
|
+
process.stdout.write(short);
|
|
940
|
+
}
|
|
941
|
+
else if (writesDirectly) {
|
|
914
942
|
const viewportHint = `${formatViewportHint(viewport)}\n`;
|
|
915
|
-
|
|
943
|
+
process.stdout.write(viewportHint);
|
|
916
944
|
}
|
|
917
945
|
}
|
|
918
946
|
return { ok: result.ok, call, result, contextOutput };
|
|
@@ -1388,15 +1416,19 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1388
1416
|
const lineCount = salvaged.content.split("\n").length;
|
|
1389
1417
|
writeNotice("info", `tool call was truncated — salvaged ${lineCount} lines and wrote to ${salvaged.path}`, chalk.cyan(` ℹ tool call was truncated — salvaged ${lineCount} lines to ${salvaged.path}\n`));
|
|
1390
1418
|
pushAssistantHistory(stripThinking(assistantText.visible).visible);
|
|
1419
|
+
const priorBytes = Buffer.byteLength(salvaged.content, "utf8");
|
|
1391
1420
|
messages.push({
|
|
1392
1421
|
role: "user",
|
|
1393
|
-
content: `Your fs.write tool call was cut off at the token limit, but the system salvaged the partial content and wrote ${lineCount} lines to ${salvaged.path}. ` +
|
|
1394
|
-
`The file
|
|
1395
|
-
`CONTINUE
|
|
1396
|
-
'```tool\n{"name":"fs.append","args":{"path":
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1422
|
+
content: `Your fs.write tool call was cut off at the token limit, but the system salvaged the partial content and wrote ${lineCount} lines (${priorBytes} bytes) to ${salvaged.path}. ` +
|
|
1423
|
+
`The file ends with: ${JSON.stringify(salvaged.lastLine)}\n\n` +
|
|
1424
|
+
`CONTINUE with ONE large fs.append of the remaining content (prefer hundreds of lines per call — do NOT use tiny ~100-line chunks):\n` +
|
|
1425
|
+
'```tool\n{"name":"fs.append","args":{"path":' +
|
|
1426
|
+
JSON.stringify(salvaged.path) +
|
|
1427
|
+
',"expectedPriorBytes":' +
|
|
1428
|
+
priorBytes +
|
|
1429
|
+
',"content":"...ONLY the remaining content not already on disk..."}}\n```\n' +
|
|
1430
|
+
`expectedPriorBytes must match the receipt so append cannot double-write. ` +
|
|
1431
|
+
`Do NOT re-read the full file; do NOT re-send content already saved.`,
|
|
1400
1432
|
});
|
|
1401
1433
|
continue;
|
|
1402
1434
|
}
|
|
@@ -1411,12 +1443,12 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1411
1443
|
messages.push({
|
|
1412
1444
|
role: "user",
|
|
1413
1445
|
content: "Your previous tool call was cut off before it finished — the JSON was incomplete, so NOTHING ran. " +
|
|
1414
|
-
"
|
|
1415
|
-
"
|
|
1416
|
-
"
|
|
1417
|
-
"
|
|
1418
|
-
"
|
|
1419
|
-
"
|
|
1446
|
+
"Prefer ONE complete fs.write when it fits (~32k output tokens is a lot of file content if reasoning stays short). " +
|
|
1447
|
+
"If the file is too large for one call:\n" +
|
|
1448
|
+
"1. fs.write the first large section (as much as fits — hundreds+ of lines)\n" +
|
|
1449
|
+
"2. fs.append the rest with expectedPriorBytes from the write receipt\n" +
|
|
1450
|
+
"3. Repeat append only if still incomplete — large chunks, not ~100-line drips\n" +
|
|
1451
|
+
"Keep reasoning SHORT — emit the ```tool block early. Do NOT claim a file was written until a tool call succeeds.",
|
|
1420
1452
|
});
|
|
1421
1453
|
continue;
|
|
1422
1454
|
}
|
|
@@ -1451,7 +1483,7 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1451
1483
|
content: `The system extracted and wrote ${lineCount} lines to ${salvaged.path} from your malformed tool call. ` +
|
|
1452
1484
|
`The file content ends at: "${salvaged.lastLine}"\n\n` +
|
|
1453
1485
|
`If the file is complete, proceed with the next step. ` +
|
|
1454
|
-
`If more content is needed, use fs.append
|
|
1486
|
+
`If more content is needed, use one large fs.append with expectedPriorBytes from the write receipt (not tiny chunks).`,
|
|
1455
1487
|
});
|
|
1456
1488
|
continue;
|
|
1457
1489
|
}
|
|
@@ -1469,10 +1501,8 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1469
1501
|
content: "Your previous message contained a ```tool block, but its JSON was INVALID, so NOTHING ran. " +
|
|
1470
1502
|
"Common causes: unescaped newlines or quotes inside a string value, an extra or missing `}` / `]`, or content too large for the output window. " +
|
|
1471
1503
|
'Re-emit ONE valid ```tool block of the exact form {"name":"<tool>","args":{...}} with balanced braces. ' +
|
|
1472
|
-
"IMPORTANT:
|
|
1473
|
-
"
|
|
1474
|
-
"2. fs.append for each subsequent ~100-line section\n" +
|
|
1475
|
-
"Keep reasoning SHORT to maximize output space for the tool call JSON. " +
|
|
1504
|
+
"IMPORTANT: Prefer ONE complete fs.write when it fits. Keep reasoning SHORT. " +
|
|
1505
|
+
"Only if the output window cuts you off, continue with large fs.append chunks + expectedPriorBytes. " +
|
|
1476
1506
|
"Do NOT claim any file was written until a tool call actually succeeds.",
|
|
1477
1507
|
});
|
|
1478
1508
|
continue;
|
|
@@ -1599,29 +1629,28 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1599
1629
|
continue;
|
|
1600
1630
|
}
|
|
1601
1631
|
// A passing build is not evidence that an app is serving requests.
|
|
1602
|
-
// On completed build plans, require start → logs → HTTP
|
|
1603
|
-
//
|
|
1632
|
+
// On completed CODING build plans only, require start → logs → HTTP
|
|
1633
|
+
// verification. NEVER apply this to pentest/remote engagements — that
|
|
1634
|
+
// forced "npm run dev on the clai repo" after a finished web assessment.
|
|
1604
1635
|
if (buildLike &&
|
|
1636
|
+
!pentestLike &&
|
|
1637
|
+
!pentestSession &&
|
|
1605
1638
|
session.planApproved.value &&
|
|
1606
1639
|
(!sawServerStart || !sawServerTail || !sawLocalHttpProbe) &&
|
|
1607
1640
|
runtimeVerificationRetries < 2) {
|
|
1608
1641
|
const runtimePlan = await loadPlan(session.sessionId).catch(() => undefined);
|
|
1609
|
-
const
|
|
1642
|
+
const codingPlanFinished = Boolean(runtimePlan &&
|
|
1643
|
+
runtimePlan.kind !== "pentest" &&
|
|
1610
1644
|
runtimePlan.tasks.length > 0 &&
|
|
1611
1645
|
runtimePlan.tasks.every((task) => task.state === "done" || task.state === "skipped"));
|
|
1612
|
-
if (
|
|
1646
|
+
if (codingPlanFinished) {
|
|
1613
1647
|
runtimeVerificationRetries += 1;
|
|
1614
1648
|
pushAssistantHistory(assistantText.visible);
|
|
1615
|
-
const missing = [
|
|
1616
|
-
!sawServerStart ? "shell.start" : "",
|
|
1617
|
-
!sawServerTail ? "shell.tail" : "",
|
|
1618
|
-
!sawLocalHttpProbe
|
|
1619
|
-
? "a successful bounded localhost HTTP probe"
|
|
1620
|
-
: "",
|
|
1621
|
-
].filter(Boolean);
|
|
1622
1649
|
messages.push({
|
|
1623
1650
|
role: "user",
|
|
1624
|
-
content: "
|
|
1651
|
+
content: "This is a CODING project only: run the missing local checks (shell.start + shell.tail + localhost HTTP probe). " +
|
|
1652
|
+
"Keep the dev server running and print the localhost link. " +
|
|
1653
|
+
"If this was a remote pentest, ignore this and finalize the report with no local server.",
|
|
1625
1654
|
});
|
|
1626
1655
|
continue;
|
|
1627
1656
|
}
|
|
@@ -1640,20 +1669,26 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1640
1669
|
const next = unfinished[0];
|
|
1641
1670
|
writeNotice("warn", `${unfinished.length} plan task(s) still unfinished — not accepting a "done" claim; resuming execution`, chalk.yellow(` ⚠ ${unfinished.length} plan task(s) still unfinished — not accepting a "done" claim; resuming execution\n`));
|
|
1642
1671
|
pushAssistantHistory(assistantText.visible);
|
|
1672
|
+
const isPentestPlan = livePlan.kind === "pentest" || pentestSession;
|
|
1643
1673
|
let instruction = `Resume now with the NEXT task ${next.id} ("${next.title}"): `;
|
|
1644
|
-
if (
|
|
1645
|
-
instruction +=
|
|
1674
|
+
if (isPentestPlan) {
|
|
1675
|
+
instruction +=
|
|
1676
|
+
`call task.update {taskId:"${next.id}", state:"in_progress"}, then do the recon/testing work ` +
|
|
1677
|
+
`(dns/http/net.scan/http.fetch/tool.batch — NOT a local dev server), VERIFY with real tool output, ` +
|
|
1678
|
+
`then task.update done. Do NOT shell.start / npm run dev / explore the clai workspace. `;
|
|
1679
|
+
}
|
|
1680
|
+
else if (next.state === "pending") {
|
|
1681
|
+
instruction += `call task.update {taskId:"${next.id}", state:"in_progress"}, then do the real work with a tool call (fs.writeMany / shell.exec / shell.start when building a local app), VERIFY it, and mark it done. `;
|
|
1646
1682
|
}
|
|
1647
1683
|
else {
|
|
1648
|
-
instruction += `do the real work with a tool call (fs.writeMany / shell.exec / shell.start) to complete it, VERIFY it, and mark it done (call task.update {taskId:"${next.id}", state:"done"}). `;
|
|
1684
|
+
instruction += `do the real work with a tool call (fs.writeMany / shell.exec / shell.start when building a local app) to complete it, VERIFY it, and mark it done (call task.update {taskId:"${next.id}", state:"done"}). `;
|
|
1649
1685
|
}
|
|
1650
1686
|
instruction += `Continue task by task until EVERY task is actually finished.`;
|
|
1651
1687
|
messages.push({
|
|
1652
1688
|
role: "user",
|
|
1653
1689
|
content: `You have NOT finished the approved plan: ${unfinished.length} task(s) remain ` +
|
|
1654
1690
|
`(${unfinished.map((t) => `[${t.id}] ${t.title}`).join("; ")}). ` +
|
|
1655
|
-
`Do NOT claim the work is complete
|
|
1656
|
-
`unless a tool call actually succeeded and you saw the output. ` +
|
|
1691
|
+
`Do NOT claim the work is complete unless a tool call actually succeeded and you saw the output. ` +
|
|
1657
1692
|
instruction,
|
|
1658
1693
|
});
|
|
1659
1694
|
continue;
|
|
@@ -1799,7 +1834,22 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1799
1834
|
// later recon from running; aborts, blocks, and sequential-barrier
|
|
1800
1835
|
// failures still stop the batch so the model can react safely.
|
|
1801
1836
|
const scopeForBatch = await loadScope().catch(() => undefined);
|
|
1837
|
+
/**
|
|
1838
|
+
* Tools that may share a concurrent wave. Pure read-only BATCH_SAFE
|
|
1839
|
+
* tools always qualify when classified safe. Heavy discovery wrappers
|
|
1840
|
+
* (pentest.recon, net.context) also run concurrent with dns/http so
|
|
1841
|
+
* nmap does not serialize the entire recon wave.
|
|
1842
|
+
* net.scan stays a barrier when it needs confirm/sudo UX.
|
|
1843
|
+
*/
|
|
1802
1844
|
const isParallelSafe = (c) => {
|
|
1845
|
+
if (c.name === "pentest.recon" ||
|
|
1846
|
+
c.name === "net.context" ||
|
|
1847
|
+
c.name === "tool.batch" ||
|
|
1848
|
+
c.name === "tool.check" ||
|
|
1849
|
+
c.name === "shell.jobs" ||
|
|
1850
|
+
c.name === "shell.tail") {
|
|
1851
|
+
return true;
|
|
1852
|
+
}
|
|
1803
1853
|
if (!BATCH_SAFE_TOOLS.has(c.name))
|
|
1804
1854
|
return false;
|
|
1805
1855
|
try {
|
|
@@ -1809,7 +1859,25 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1809
1859
|
return false;
|
|
1810
1860
|
}
|
|
1811
1861
|
};
|
|
1812
|
-
|
|
1862
|
+
/** Tools whose failure must NOT cancel sibling calls in this turn. */
|
|
1863
|
+
const shouldSoftFailTool = (name) => {
|
|
1864
|
+
if (name === "tool.batch")
|
|
1865
|
+
return true;
|
|
1866
|
+
if (BATCH_SAFE_TOOLS.has(name))
|
|
1867
|
+
return true;
|
|
1868
|
+
if (name === "pentest.recon" ||
|
|
1869
|
+
name === "net.scan" ||
|
|
1870
|
+
name === "net.pingSweep" ||
|
|
1871
|
+
name === "net.context" ||
|
|
1872
|
+
name === "shell.jobs" ||
|
|
1873
|
+
name === "shell.tail" ||
|
|
1874
|
+
name === "tool.check") {
|
|
1875
|
+
return true;
|
|
1876
|
+
}
|
|
1877
|
+
return false;
|
|
1878
|
+
};
|
|
1879
|
+
// Recon waves often emit 6–10 lookups; 4 forced a second sequential wave.
|
|
1880
|
+
const PARALLEL_LIMIT = 8;
|
|
1813
1881
|
let aborted = false;
|
|
1814
1882
|
let blocked = false;
|
|
1815
1883
|
let blockedResult = null;
|
|
@@ -1865,7 +1933,11 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1865
1933
|
}
|
|
1866
1934
|
const id = (idx >= 0 ? callIds[idx] : undefined) ?? `tool-${++nextToolEventId}`;
|
|
1867
1935
|
const res = await executeSingleTool(call, id, options.signal || new AbortController().signal);
|
|
1868
|
-
|
|
1936
|
+
// Soft-fail recon / read-only / discovery tools so a stalled
|
|
1937
|
+
// whois or failed lookup never cancels the rest of the turn with
|
|
1938
|
+
// "Cancelled — earlier tool in this batch failed."
|
|
1939
|
+
const softFail = shouldSoftFailTool(call.name);
|
|
1940
|
+
recordResult(res, softFail);
|
|
1869
1941
|
}
|
|
1870
1942
|
else {
|
|
1871
1943
|
// Concurrent group — assign ids in document order, then push their
|