@lazyingart/agintiflow 0.1.0 → 0.2.0
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/AGENTS.md +6 -3
- package/README.md +68 -15
- package/docker/sandbox.Dockerfile +8 -0
- package/package.json +11 -3
- package/public/app.js +644 -11
- package/public/index.html +165 -20
- package/public/styles.css +586 -13
- package/scripts/setup-agent-toolchain-docker.sh +51 -0
- package/scripts/smoke-coding-tools.js +138 -0
- package/scripts/smoke-toolchain-docker.js +185 -0
- package/scripts/smoke-web-api.js +217 -0
- package/src/agent-runner.js +286 -21
- package/src/artifact-tunnel.js +401 -0
- package/src/cli.js +47 -3
- package/src/command-policy.js +21 -0
- package/src/config.js +9 -2
- package/src/docker-sandbox.js +38 -8
- package/src/guardrails.js +31 -0
- package/src/model-client.js +300 -6
- package/src/model-routing.js +40 -0
- package/src/session-store.js +4 -0
- package/src/tool-wrappers.js +6 -0
- package/src/web-db.js +48 -5
- package/src/workspace-tools.js +438 -0
- package/web.js +265 -14
package/src/agent-runner.js
CHANGED
|
@@ -8,12 +8,103 @@ import { SessionStore } from "./session-store.js";
|
|
|
8
8
|
import { captureSnapshot } from "./snapshot.js";
|
|
9
9
|
import { checkToolUse } from "./guardrails.js";
|
|
10
10
|
import { ensureDockerSandboxReady, runDockerSandboxCommand } from "./docker-sandbox.js";
|
|
11
|
-
import { runAgentWrapper, wrapperStatusText } from "./tool-wrappers.js";
|
|
11
|
+
import { normalizeWrapperName, runAgentWrapper, wrapperStatusText } from "./tool-wrappers.js";
|
|
12
12
|
import { evaluateCommandPolicy } from "./command-policy.js";
|
|
13
13
|
import { redactSensitiveText, redactValue } from "./redaction.js";
|
|
14
|
+
import { executeWorkspaceTool, summarizeWorkspaceTools, WORKSPACE_TOOL_NAMES } from "./workspace-tools.js";
|
|
15
|
+
import { normalizeCanvasPayload } from "./artifact-tunnel.js";
|
|
14
16
|
|
|
15
17
|
const exec = promisify(execCallback);
|
|
16
18
|
const BROWSER_TOOLS = new Set(["open_url", "click", "type", "scroll", "press", "back"]);
|
|
19
|
+
const WORKSPACE_TOOLS = new Set(WORKSPACE_TOOL_NAMES);
|
|
20
|
+
|
|
21
|
+
function preserveAssistantMessage(message) {
|
|
22
|
+
const preserved = {
|
|
23
|
+
role: "assistant",
|
|
24
|
+
content: message.content || "",
|
|
25
|
+
tool_calls: message.tool_calls,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const reasoningContent = message.reasoning_content || message.reasoningContent;
|
|
29
|
+
if (reasoningContent) {
|
|
30
|
+
preserved.reasoning_content = reasoningContent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return preserved;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function repairModelMessageHistory(state, config = {}) {
|
|
37
|
+
if (config.provider !== "deepseek" || !Array.isArray(state?.messages)) {
|
|
38
|
+
return { changed: false, droppedAssistantMessages: 0, convertedAssistantMessages: 0, droppedToolMessages: 0 };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const repaired = [];
|
|
42
|
+
const droppedToolCallIds = new Set();
|
|
43
|
+
let droppedAssistantMessages = 0;
|
|
44
|
+
let convertedAssistantMessages = 0;
|
|
45
|
+
let droppedToolMessages = 0;
|
|
46
|
+
|
|
47
|
+
for (const message of state.messages) {
|
|
48
|
+
if (message.role === "assistant") {
|
|
49
|
+
const hasReasoningContent = Boolean(message.reasoning_content || message.reasoningContent);
|
|
50
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
51
|
+
const content = String(message.content || "");
|
|
52
|
+
|
|
53
|
+
if (!hasReasoningContent) {
|
|
54
|
+
if (content.startsWith("Execution plan:")) {
|
|
55
|
+
droppedAssistantMessages += 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (toolCalls.length > 0) {
|
|
60
|
+
for (const call of toolCalls) {
|
|
61
|
+
if (call?.id) droppedToolCallIds.add(call.id);
|
|
62
|
+
}
|
|
63
|
+
droppedAssistantMessages += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (content.trim()) {
|
|
68
|
+
repaired.push({
|
|
69
|
+
role: "user",
|
|
70
|
+
content: `Previous assistant response retained as compacted history for DeepSeek thinking mode:\n${content}`,
|
|
71
|
+
});
|
|
72
|
+
convertedAssistantMessages += 1;
|
|
73
|
+
} else {
|
|
74
|
+
droppedAssistantMessages += 1;
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
repaired.push(preserveAssistantMessage(message));
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (message.role === "tool" && droppedToolCallIds.has(message.tool_call_id)) {
|
|
84
|
+
droppedToolMessages += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
repaired.push(message);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const changed =
|
|
92
|
+
droppedAssistantMessages > 0 ||
|
|
93
|
+
convertedAssistantMessages > 0 ||
|
|
94
|
+
droppedToolMessages > 0 ||
|
|
95
|
+
repaired.length !== state.messages.length;
|
|
96
|
+
|
|
97
|
+
if (changed) {
|
|
98
|
+
state.messages = repaired;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
changed,
|
|
103
|
+
droppedAssistantMessages,
|
|
104
|
+
convertedAssistantMessages,
|
|
105
|
+
droppedToolMessages,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
17
108
|
|
|
18
109
|
function createInitialState(config, sessionId) {
|
|
19
110
|
const now = new Date().toISOString();
|
|
@@ -54,9 +145,15 @@ function createInitialState(config, sessionId) {
|
|
|
54
145
|
? `A shell command tool is available inside Docker sandbox mode ${config.sandboxMode}. Read-only commands have no network. Package installs or environment setup require approved package policy and Docker workspace-write mode.`
|
|
55
146
|
: "A read-only host shell command tool is available for short local inspection tasks."
|
|
56
147
|
: "No shell command tool is available.",
|
|
148
|
+
config.allowFileTools
|
|
149
|
+
? `Workspace file tools are available in ${config.commandCwd}: list_files, read_file, search_files, write_file, and apply_patch. Always use workspace-relative paths such as plot_fx.svg or docs/report.tex, never absolute host paths. Secret paths, .git internals, node_modules writes, and huge files are blocked.`
|
|
150
|
+
: "No workspace file tools are available.",
|
|
57
151
|
config.allowWrapperTools
|
|
58
|
-
? `External coding-agent wrappers are available as advisory tools only. Wrapper status: ${wrapperStatusText()}.`
|
|
152
|
+
? `External coding-agent wrappers are available as advisory tools only. Use the selected wrapper only: ${normalizeWrapperName(config.preferredWrapper)}. Wrapper status: ${wrapperStatusText()}.`
|
|
59
153
|
: "External coding-agent wrappers are disabled.",
|
|
154
|
+
"A frontend canvas/artifacts tunnel exists. Use send_to_canvas when important markdown, diffs, screenshots, images, or workspace files should be highlighted in the UI. It is optional and ordinary final text can still go directly to finish.",
|
|
155
|
+
"For visual-output requests such as draw, plot, graph, chart, diagram, figure, image, or visualization, proactively publish a canvas artifact even when the user does not mention canvas. If workspace file tools are enabled, prefer creating a small SVG or markdown artifact and call send_to_canvas with selected=true.",
|
|
156
|
+
"For LaTeX/PDF requests, create the needed source/assets, compile with the available allowlisted TeX toolchain, and publish the resulting PDF through send_to_canvas. For subfolder documents, keep outputs beside the source. Use pdflatex-compatible figure formats such as PDF or PNG.",
|
|
60
157
|
"When done, call finish with a concise result.",
|
|
61
158
|
].join(" "),
|
|
62
159
|
},
|
|
@@ -68,10 +165,16 @@ function createInitialState(config, sessionId) {
|
|
|
68
165
|
config.allowedDomains.length > 0 ? `Allowed domains: ${config.allowedDomains.join(", ")}` : "",
|
|
69
166
|
config.allowShellTool
|
|
70
167
|
? config.useDockerSandbox
|
|
71
|
-
? `Shell working directory mounted into Docker
|
|
168
|
+
? `Shell working directory mounted into Docker as /workspace from ${config.commandCwd}. Use relative paths or /workspace paths, not absolute host temp paths. Sandbox mode: ${config.sandboxMode}. Package install policy: ${config.packageInstallPolicy}.`
|
|
72
169
|
: `Shell working directory: ${config.commandCwd}`
|
|
73
170
|
: "",
|
|
74
|
-
config.
|
|
171
|
+
config.allowFileTools ? `Workspace file tools enabled in: ${config.commandCwd}. Use workspace-relative paths.` : "",
|
|
172
|
+
config.allowWrapperTools
|
|
173
|
+
? `Agent wrappers: selected=${normalizeWrapperName(config.preferredWrapper)}; ${wrapperStatusText()}`
|
|
174
|
+
: "",
|
|
175
|
+
"Canvas/artifacts tunnel: available through send_to_canvas for optional frontend rendering.",
|
|
176
|
+
"Visual-output requests should produce a canvas artifact without requiring the user to ask for canvas explicitly.",
|
|
177
|
+
"LaTeX/PDF requests should produce source artifacts and, when possible, a compiled PDF artifact. For subfolder documents, keep outputs beside the source. For figure-in-document tasks, create PDF/PNG figures that pdflatex can include.",
|
|
75
178
|
]
|
|
76
179
|
.filter(Boolean)
|
|
77
180
|
.join("\n"),
|
|
@@ -161,10 +264,13 @@ function applyContinuationPrompt(state, config, observers) {
|
|
|
161
264
|
config.allowedDomains.length > 0 ? `Allowed domains: ${config.allowedDomains.join(", ")}` : "",
|
|
162
265
|
config.allowShellTool
|
|
163
266
|
? config.useDockerSandbox
|
|
164
|
-
? `Shell working directory mounted into Docker
|
|
267
|
+
? `Shell working directory mounted into Docker as /workspace from ${config.commandCwd}. Use relative paths or /workspace paths. Sandbox mode: ${config.sandboxMode}. Package install policy: ${config.packageInstallPolicy}.`
|
|
165
268
|
: `Shell working directory: ${config.commandCwd}`
|
|
166
269
|
: "",
|
|
167
|
-
config.
|
|
270
|
+
config.allowFileTools ? `Workspace file tools enabled in: ${config.commandCwd}. Use workspace-relative paths.` : "",
|
|
271
|
+
config.allowWrapperTools
|
|
272
|
+
? `Agent wrappers: selected=${normalizeWrapperName(config.preferredWrapper)}; ${wrapperStatusText()}`
|
|
273
|
+
: "",
|
|
168
274
|
]
|
|
169
275
|
.filter(Boolean)
|
|
170
276
|
.join("\n"),
|
|
@@ -218,6 +324,44 @@ function safeExecutionEnv() {
|
|
|
218
324
|
};
|
|
219
325
|
}
|
|
220
326
|
|
|
327
|
+
function hashForLog(value) {
|
|
328
|
+
return crypto.createHash("sha256").update(String(value ?? "")).digest("hex");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function sanitizeToolArgs(toolName, args) {
|
|
332
|
+
const safeArgs = redactValue(args);
|
|
333
|
+
if (toolName === "write_file" && typeof args.content === "string") {
|
|
334
|
+
return {
|
|
335
|
+
...safeArgs,
|
|
336
|
+
content: `[${Buffer.byteLength(args.content, "utf8")} bytes sha256=${hashForLog(args.content)}]`,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (toolName === "send_to_canvas" && typeof args.content === "string") {
|
|
340
|
+
return {
|
|
341
|
+
...safeArgs,
|
|
342
|
+
content: `[${Buffer.byteLength(args.content, "utf8")} bytes sha256=${hashForLog(args.content)}]`,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (toolName === "apply_patch") {
|
|
346
|
+
return {
|
|
347
|
+
...safeArgs,
|
|
348
|
+
search: typeof args.search === "string" ? redactSensitiveText(args.search).slice(0, 160) : safeArgs.search,
|
|
349
|
+
replace: typeof args.replace === "string" ? redactSensitiveText(args.replace).slice(0, 160) : safeArgs.replace,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
return safeArgs;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function sanitizeToolResult(result) {
|
|
356
|
+
const safeResult = redactValue(result);
|
|
357
|
+
if (typeof safeResult.content === "string") {
|
|
358
|
+
safeResult.contentPreview = safeResult.content.slice(0, 600);
|
|
359
|
+
safeResult.contentBytes = Buffer.byteLength(safeResult.content, "utf8");
|
|
360
|
+
delete safeResult.content;
|
|
361
|
+
}
|
|
362
|
+
return safeResult;
|
|
363
|
+
}
|
|
364
|
+
|
|
221
365
|
async function runShellCommand(command, config, policy = evaluateCommandPolicy(command, config)) {
|
|
222
366
|
if (config.useDockerSandbox) {
|
|
223
367
|
return runDockerSandboxCommand(command, config, policy);
|
|
@@ -246,10 +390,18 @@ async function captureSyntheticSnapshot(store, step, config) {
|
|
|
246
390
|
config.startUrl ? `Suggested start URL: ${config.startUrl}` : "",
|
|
247
391
|
config.allowShellTool
|
|
248
392
|
? config.useDockerSandbox
|
|
249
|
-
? `Shell tool available in Docker with mounted workspace
|
|
393
|
+
? `Shell tool available in Docker with mounted workspace /workspace from ${config.commandCwd}. Use relative paths or /workspace paths. Sandbox mode: ${config.sandboxMode}. Package install policy: ${config.packageInstallPolicy}.`
|
|
250
394
|
: `Shell tool available in: ${config.commandCwd}`
|
|
251
395
|
: "Shell tool disabled.",
|
|
252
|
-
config.
|
|
396
|
+
config.allowFileTools
|
|
397
|
+
? `Workspace file tools available in: ${config.commandCwd}. Use workspace-relative paths.`
|
|
398
|
+
: "Workspace file tools disabled.",
|
|
399
|
+
config.allowWrapperTools
|
|
400
|
+
? `Agent wrappers available: selected=${normalizeWrapperName(config.preferredWrapper)}; ${wrapperStatusText()}`
|
|
401
|
+
: "Agent wrappers disabled.",
|
|
402
|
+
"Canvas/artifacts tunnel available through send_to_canvas.",
|
|
403
|
+
"For draw/plot/graph/chart/diagram/figure requests, publish a canvas artifact proactively.",
|
|
404
|
+
"For LaTeX/PDF requests, publish the source and compiled PDF artifacts when available. Keep subfolder outputs beside their source and use pdflatex-compatible figure formats.",
|
|
253
405
|
"Use open_url only if the task actually needs the web.",
|
|
254
406
|
]
|
|
255
407
|
.filter(Boolean)
|
|
@@ -274,7 +426,7 @@ async function buildSnapshot(browserState, store, step, config) {
|
|
|
274
426
|
|
|
275
427
|
async function executeTool(browserState, toolCall, snapshot, config, store, observers, state) {
|
|
276
428
|
const args = JSON.parse(toolCall.function.arguments || "{}");
|
|
277
|
-
const safeArgs =
|
|
429
|
+
const safeArgs = sanitizeToolArgs(toolCall.function.name, args);
|
|
278
430
|
const guard = checkToolUse({
|
|
279
431
|
toolName: toolCall.function.name,
|
|
280
432
|
args,
|
|
@@ -301,7 +453,10 @@ async function executeTool(browserState, toolCall, snapshot, config, store, obse
|
|
|
301
453
|
ok: false,
|
|
302
454
|
blocked: true,
|
|
303
455
|
reason: guard.reason,
|
|
456
|
+
category: guard.category,
|
|
457
|
+
needsApproval: guard.needsApproval,
|
|
304
458
|
toolName: toolCall.function.name,
|
|
459
|
+
args: safeArgs,
|
|
305
460
|
};
|
|
306
461
|
}
|
|
307
462
|
|
|
@@ -361,6 +516,42 @@ async function executeTool(browserState, toolCall, snapshot, config, store, obse
|
|
|
361
516
|
await new Promise((resolve) => setTimeout(resolve, Number.isFinite(args.ms) ? Number(args.ms) : 1000));
|
|
362
517
|
}
|
|
363
518
|
break;
|
|
519
|
+
case "list_files":
|
|
520
|
+
case "read_file":
|
|
521
|
+
case "search_files":
|
|
522
|
+
case "write_file":
|
|
523
|
+
case "apply_patch": {
|
|
524
|
+
const result = await executeWorkspaceTool(toolCall.function.name, args, config);
|
|
525
|
+
const eventResult = sanitizeToolResult(result);
|
|
526
|
+
if (result.blocked) {
|
|
527
|
+
await store.appendEvent("tool.blocked", {
|
|
528
|
+
toolName: toolCall.function.name,
|
|
529
|
+
args: safeArgs,
|
|
530
|
+
reason: result.reason,
|
|
531
|
+
category: result.category,
|
|
532
|
+
});
|
|
533
|
+
observers.event("tool.blocked", {
|
|
534
|
+
toolName: toolCall.function.name,
|
|
535
|
+
args: safeArgs,
|
|
536
|
+
reason: result.reason,
|
|
537
|
+
category: result.category,
|
|
538
|
+
});
|
|
539
|
+
return result;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
await store.appendEvent("tool.completed", eventResult);
|
|
543
|
+
observers.event("tool.completed", eventResult);
|
|
544
|
+
if (result.change) {
|
|
545
|
+
const change = {
|
|
546
|
+
...result.change,
|
|
547
|
+
toolName: toolCall.function.name,
|
|
548
|
+
commandCwd: config.commandCwd,
|
|
549
|
+
};
|
|
550
|
+
await store.appendEvent("file.changed", change);
|
|
551
|
+
observers.event("file.changed", change);
|
|
552
|
+
}
|
|
553
|
+
return result;
|
|
554
|
+
}
|
|
364
555
|
case "run_command": {
|
|
365
556
|
const policy = evaluateCommandPolicy(String(args.command), config);
|
|
366
557
|
if (config.useDockerSandbox) {
|
|
@@ -403,6 +594,63 @@ async function executeTool(browserState, toolCall, snapshot, config, store, obse
|
|
|
403
594
|
observers.event("tool.completed", result);
|
|
404
595
|
return result;
|
|
405
596
|
}
|
|
597
|
+
case "send_to_canvas": {
|
|
598
|
+
const normalized = normalizeCanvasPayload(args, config);
|
|
599
|
+
if (!normalized.ok) {
|
|
600
|
+
await store.appendEvent("tool.blocked", {
|
|
601
|
+
toolName: "send_to_canvas",
|
|
602
|
+
args: safeArgs,
|
|
603
|
+
reason: normalized.reason,
|
|
604
|
+
category: "canvas",
|
|
605
|
+
});
|
|
606
|
+
observers.event("tool.blocked", {
|
|
607
|
+
toolName: "send_to_canvas",
|
|
608
|
+
args: safeArgs,
|
|
609
|
+
reason: normalized.reason,
|
|
610
|
+
category: "canvas",
|
|
611
|
+
});
|
|
612
|
+
return {
|
|
613
|
+
ok: false,
|
|
614
|
+
blocked: true,
|
|
615
|
+
reason: normalized.reason,
|
|
616
|
+
toolName: "send_to_canvas",
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const canvasItem = {
|
|
621
|
+
...normalized.payload,
|
|
622
|
+
toolName: "send_to_canvas",
|
|
623
|
+
commandCwd: config.commandCwd,
|
|
624
|
+
};
|
|
625
|
+
await store.appendEvent("canvas.item", canvasItem);
|
|
626
|
+
observers.event("canvas.item", canvasItem);
|
|
627
|
+
if (canvasItem.selected) {
|
|
628
|
+
await store.appendEvent("canvas.selected", {
|
|
629
|
+
artifactId: canvasItem.artifactId,
|
|
630
|
+
title: canvasItem.title,
|
|
631
|
+
source: "agent",
|
|
632
|
+
});
|
|
633
|
+
observers.event("canvas.selected", {
|
|
634
|
+
artifactId: canvasItem.artifactId,
|
|
635
|
+
title: canvasItem.title,
|
|
636
|
+
source: "agent",
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const result = {
|
|
641
|
+
ok: true,
|
|
642
|
+
toolName: "send_to_canvas",
|
|
643
|
+
args: safeArgs,
|
|
644
|
+
artifactId: canvasItem.artifactId,
|
|
645
|
+
title: canvasItem.title,
|
|
646
|
+
kind: canvasItem.kind,
|
|
647
|
+
path: canvasItem.path,
|
|
648
|
+
selected: canvasItem.selected,
|
|
649
|
+
};
|
|
650
|
+
await store.appendEvent("tool.completed", result);
|
|
651
|
+
observers.event("tool.completed", result);
|
|
652
|
+
return result;
|
|
653
|
+
}
|
|
406
654
|
case "finish":
|
|
407
655
|
return { ok: true, done: true, result: String(args.result || ""), toolName: "finish" };
|
|
408
656
|
default:
|
|
@@ -445,6 +693,9 @@ export async function runAgent(config) {
|
|
|
445
693
|
const observers = createObservers(config);
|
|
446
694
|
const browserState = createBrowserState();
|
|
447
695
|
|
|
696
|
+
if (config.allowFileTools || config.allowShellTool) {
|
|
697
|
+
await fs.mkdir(config.commandCwd, { recursive: true });
|
|
698
|
+
}
|
|
448
699
|
await store.ensure();
|
|
449
700
|
|
|
450
701
|
let state = await store.loadState();
|
|
@@ -484,16 +735,19 @@ export async function runAgent(config) {
|
|
|
484
735
|
if (!state.plan) {
|
|
485
736
|
const plan = await createPlan(client, config, state);
|
|
486
737
|
state.plan = plan;
|
|
487
|
-
state.messages.push({
|
|
488
|
-
role: "assistant",
|
|
489
|
-
content: `Execution plan:\n${plan}`,
|
|
490
|
-
});
|
|
491
738
|
await store.savePlan(plan);
|
|
492
739
|
await store.appendEvent("plan.created", { plan });
|
|
493
740
|
await store.saveState(state);
|
|
494
741
|
observers.event("plan.created", { plan });
|
|
495
742
|
}
|
|
496
743
|
|
|
744
|
+
const repair = repairModelMessageHistory(state, config);
|
|
745
|
+
if (repair.changed) {
|
|
746
|
+
await store.appendEvent("history.repaired", repair);
|
|
747
|
+
observers.event("history.repaired", repair);
|
|
748
|
+
await store.saveState(state);
|
|
749
|
+
}
|
|
750
|
+
|
|
497
751
|
observers.log("session.context", {
|
|
498
752
|
sessionId,
|
|
499
753
|
provider: config.provider,
|
|
@@ -503,7 +757,9 @@ export async function runAgent(config) {
|
|
|
503
757
|
commandCwd: config.commandCwd,
|
|
504
758
|
allowShellTool: config.allowShellTool,
|
|
505
759
|
allowWrapperTools: config.allowWrapperTools,
|
|
760
|
+
preferredWrapper: normalizeWrapperName(config.preferredWrapper),
|
|
506
761
|
wrappers: config.allowWrapperTools ? wrapperStatusText() : "",
|
|
762
|
+
workspaceFileTools: summarizeWorkspaceTools(config),
|
|
507
763
|
shellSandbox: config.useDockerSandbox ? "docker" : "host",
|
|
508
764
|
sandboxMode: config.sandboxMode,
|
|
509
765
|
packageInstallPolicy: config.packageInstallPolicy,
|
|
@@ -549,13 +805,18 @@ export async function runAgent(config) {
|
|
|
549
805
|
elements: snapshot.elements,
|
|
550
806
|
browserOpen: Boolean(browserState.page),
|
|
551
807
|
shellToolAvailable: config.allowShellTool,
|
|
808
|
+
fileToolsAvailable: config.allowFileTools,
|
|
809
|
+
workspaceFileTools: summarizeWorkspaceTools(config),
|
|
552
810
|
agentWrappersAvailable: config.allowWrapperTools,
|
|
811
|
+
preferredWrapper: normalizeWrapperName(config.preferredWrapper),
|
|
553
812
|
agentWrappers: config.allowWrapperTools ? wrapperStatusText() : "",
|
|
554
813
|
shellSandbox: config.useDockerSandbox ? "docker" : "host",
|
|
555
814
|
sandboxMode: config.sandboxMode,
|
|
556
815
|
packageInstallPolicy: config.packageInstallPolicy,
|
|
557
816
|
commandCwd: config.commandCwd,
|
|
817
|
+
plan: state.plan || "",
|
|
558
818
|
suggestedStartUrl: config.startUrl || "",
|
|
819
|
+
canvasArtifactsAvailable: true,
|
|
559
820
|
})}`,
|
|
560
821
|
});
|
|
561
822
|
|
|
@@ -565,11 +826,7 @@ export async function runAgent(config) {
|
|
|
565
826
|
throw new Error("Model returned no assistant message.");
|
|
566
827
|
}
|
|
567
828
|
|
|
568
|
-
state.messages.push(
|
|
569
|
-
role: "assistant",
|
|
570
|
-
content: assistantMessage.content || "",
|
|
571
|
-
tool_calls: assistantMessage.tool_calls,
|
|
572
|
-
});
|
|
829
|
+
state.messages.push(preserveAssistantMessage(assistantMessage));
|
|
573
830
|
|
|
574
831
|
await store.appendEvent("model.responded", {
|
|
575
832
|
step,
|
|
@@ -618,13 +875,19 @@ export async function runAgent(config) {
|
|
|
618
875
|
|
|
619
876
|
if (toolResult.toolName === "run_command") {
|
|
620
877
|
observers.log("command.output", {
|
|
621
|
-
command: redactSensitiveText(toolResult.args
|
|
622
|
-
stdout: toolResult.stdout,
|
|
623
|
-
stderr: toolResult.stderr,
|
|
878
|
+
command: redactSensitiveText(toolResult.args?.command || ""),
|
|
879
|
+
stdout: toolResult.stdout || "",
|
|
880
|
+
stderr: toolResult.stderr || "",
|
|
624
881
|
commandPolicy: toolResult.commandPolicy,
|
|
882
|
+
blocked: Boolean(toolResult.blocked),
|
|
883
|
+
error: toolResult.error || toolResult.reason || "",
|
|
625
884
|
});
|
|
626
885
|
}
|
|
627
886
|
|
|
887
|
+
if (WORKSPACE_TOOLS.has(toolResult.toolName)) {
|
|
888
|
+
observers.log("workspace.output", sanitizeToolResult(toolResult));
|
|
889
|
+
}
|
|
890
|
+
|
|
628
891
|
if (toolResult.toolName === "delegate_agent") {
|
|
629
892
|
observers.log("wrapper.output", {
|
|
630
893
|
wrapper: toolResult.wrapper,
|
|
@@ -679,6 +942,8 @@ export async function runAgent(config) {
|
|
|
679
942
|
return {
|
|
680
943
|
sessionId,
|
|
681
944
|
result: "",
|
|
945
|
+
stopped: true,
|
|
946
|
+
reason: "max_steps_reached",
|
|
682
947
|
};
|
|
683
948
|
} finally {
|
|
684
949
|
await closeBrowser(browserState, store);
|