@vibgrate/cli 2026.722.2 → 2026.727.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/DOCS.md +418 -196
- package/README.md +34 -7
- package/dist/baseline-K7YBFKZI.js +7 -0
- package/dist/{baseline-BD3A7EXD.js.map → baseline-K7YBFKZI.js.map} +1 -1
- package/dist/chunk-3BVSDMHV.js +2496 -0
- package/dist/chunk-3BVSDMHV.js.map +1 -0
- package/dist/{chunk-PY3DNX5H.js → chunk-3Q7QBWFW.js} +13 -2
- package/dist/chunk-3Q7QBWFW.js.map +1 -0
- package/dist/chunk-4CQ3MGNN.js +136 -0
- package/dist/chunk-4CQ3MGNN.js.map +1 -0
- package/dist/chunk-5I4VSBWQ.js +764 -0
- package/dist/chunk-5I4VSBWQ.js.map +1 -0
- package/dist/chunk-5Q54GEHM.js +29 -0
- package/dist/chunk-5Q54GEHM.js.map +1 -0
- package/dist/{chunk-2O5YZVZV.js → chunk-65MEOA4E.js} +21 -18
- package/dist/chunk-65MEOA4E.js.map +1 -0
- package/dist/{chunk-WNIIKCNF.js → chunk-6IOQJGFT.js} +29 -238
- package/dist/chunk-6IOQJGFT.js.map +1 -0
- package/dist/{chunk-CS37OBE3.js → chunk-7JHPQ6WF.js} +791 -783
- package/dist/chunk-7JHPQ6WF.js.map +1 -0
- package/dist/chunk-BPF3YX2U.js +64 -0
- package/dist/chunk-BPF3YX2U.js.map +1 -0
- package/dist/chunk-BWPBB45M.js +88 -0
- package/dist/chunk-BWPBB45M.js.map +1 -0
- package/dist/chunk-C4CKTAZP.js +1695 -0
- package/dist/chunk-C4CKTAZP.js.map +1 -0
- package/dist/chunk-EDAAG7BL.js +612 -0
- package/dist/chunk-EDAAG7BL.js.map +1 -0
- package/dist/chunk-EDBV33B7.js +57 -0
- package/dist/chunk-EDBV33B7.js.map +1 -0
- package/dist/chunk-HABUT7HW.js +233 -0
- package/dist/chunk-HABUT7HW.js.map +1 -0
- package/dist/{chunk-NONYJLOJ.js → chunk-HYZVHJ3Q.js} +3 -3
- package/dist/{chunk-NONYJLOJ.js.map → chunk-HYZVHJ3Q.js.map} +1 -1
- package/dist/chunk-IS7VTH2Q.js +627 -0
- package/dist/chunk-IS7VTH2Q.js.map +1 -0
- package/dist/chunk-IZDH67DX.js +289 -0
- package/dist/chunk-IZDH67DX.js.map +1 -0
- package/dist/chunk-J7LKEB2R.js +51 -0
- package/dist/chunk-J7LKEB2R.js.map +1 -0
- package/dist/chunk-JIBOJTGS.js +313 -0
- package/dist/chunk-JIBOJTGS.js.map +1 -0
- package/dist/chunk-JZYGEZTU.js +82 -0
- package/dist/chunk-JZYGEZTU.js.map +1 -0
- package/dist/chunk-K7REHDQS.js +776 -0
- package/dist/chunk-K7REHDQS.js.map +1 -0
- package/dist/chunk-KHJO4D5N.js +108 -0
- package/dist/chunk-KHJO4D5N.js.map +1 -0
- package/dist/chunk-NDMDSPFX.js +69 -0
- package/dist/chunk-NDMDSPFX.js.map +1 -0
- package/dist/chunk-OOIG3RUM.js +276 -0
- package/dist/chunk-OOIG3RUM.js.map +1 -0
- package/dist/{chunk-6CXTPC74.js → chunk-OXQNQW5J.js} +27 -6
- package/dist/chunk-OXQNQW5J.js.map +1 -0
- package/dist/chunk-PMYWZRRS.js +62 -0
- package/dist/chunk-PMYWZRRS.js.map +1 -0
- package/dist/chunk-PXHNTC6D.js +382 -0
- package/dist/chunk-PXHNTC6D.js.map +1 -0
- package/dist/{chunk-3MXNNBLI.js → chunk-S6CYDZEW.js} +1395 -1975
- package/dist/chunk-S6CYDZEW.js.map +1 -0
- package/dist/chunk-SZLF66FJ.js +843 -0
- package/dist/chunk-SZLF66FJ.js.map +1 -0
- package/dist/chunk-VXGV6NTD.js +476 -0
- package/dist/chunk-VXGV6NTD.js.map +1 -0
- package/dist/{chunk-5BDHQ7DD.js → chunk-WLETRGAC.js} +16 -9
- package/dist/chunk-WLETRGAC.js.map +1 -0
- package/dist/{chunk-I7GY7MVN.js → chunk-YDAT7LD2.js} +51 -11
- package/dist/chunk-YDAT7LD2.js.map +1 -0
- package/dist/cli.js +3412 -513
- package/dist/cli.js.map +1 -1
- package/dist/execution-env-3BN7Z737.js +3 -0
- package/dist/execution-env-3BN7Z737.js.map +1 -0
- package/dist/federation-EPZDUWCK.js +6 -0
- package/dist/federation-EPZDUWCK.js.map +1 -0
- package/dist/git-ref-HPRLUFFW.js +3 -0
- package/dist/git-ref-HPRLUFFW.js.map +1 -0
- package/dist/graph-backend-ZMSYOZMW.js +10 -0
- package/dist/graph-backend-ZMSYOZMW.js.map +1 -0
- package/dist/index.d.ts +432 -126
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/{interactive-A4DISSIW.js → interactive-ICL7D7LO.js} +185 -226
- package/dist/interactive-ICL7D7LO.js.map +1 -0
- package/dist/llm-host-2RAYQSDQ.js +8 -0
- package/dist/llm-host-2RAYQSDQ.js.map +1 -0
- package/dist/load-OHVKDX4R.js +7 -0
- package/dist/load-OHVKDX4R.js.map +1 -0
- package/dist/local-runtime-OJFLX2HI.js +4 -0
- package/dist/local-runtime-OJFLX2HI.js.map +1 -0
- package/dist/model-execution-profile-MQ2QCP24.js +3 -0
- package/dist/model-execution-profile-MQ2QCP24.js.map +1 -0
- package/dist/model-orchestrator-FFTZI3U2.js +8 -0
- package/dist/model-orchestrator-FFTZI3U2.js.map +1 -0
- package/dist/parse-worker.d.ts +1 -1
- package/dist/parse-worker.js +1 -1
- package/dist/paths-MCH75O3G.js +5 -0
- package/dist/paths-MCH75O3G.js.map +1 -0
- package/dist/resolve-gguf-4UPIGPEE.js +7 -0
- package/dist/resolve-gguf-4UPIGPEE.js.map +1 -0
- package/dist/runtime-session-IDU5BDUJ.js +17 -0
- package/dist/runtime-session-IDU5BDUJ.js.map +1 -0
- package/dist/session-L2OSDRPI.js +10 -0
- package/dist/{session-POJUDFPH.js.map → session-L2OSDRPI.js.map} +1 -1
- package/dist/{stream-json-Q2JGWPHB.js → stream-json-F74W5FCK.js} +16 -6
- package/dist/stream-json-F74W5FCK.js.map +1 -0
- package/dist/{types-Jl6RJ175.d.ts → types-ZMg1mSuu.d.ts} +3 -1
- package/dist/vgd-EGBQD7BW.js +16 -0
- package/dist/vgd-EGBQD7BW.js.map +1 -0
- package/package.json +9 -6
- package/dist/baseline-BD3A7EXD.js +0 -7
- package/dist/chunk-2O5YZVZV.js.map +0 -1
- package/dist/chunk-3MXNNBLI.js.map +0 -1
- package/dist/chunk-5BDHQ7DD.js.map +0 -1
- package/dist/chunk-6CXTPC74.js.map +0 -1
- package/dist/chunk-CS37OBE3.js.map +0 -1
- package/dist/chunk-GGJZA3Q6.js +0 -961
- package/dist/chunk-GGJZA3Q6.js.map +0 -1
- package/dist/chunk-I7GY7MVN.js.map +0 -1
- package/dist/chunk-JBXNQCGE.js +0 -484
- package/dist/chunk-JBXNQCGE.js.map +0 -1
- package/dist/chunk-PY3DNX5H.js.map +0 -1
- package/dist/chunk-WNIIKCNF.js.map +0 -1
- package/dist/interactive-A4DISSIW.js.map +0 -1
- package/dist/session-POJUDFPH.js +0 -6
- package/dist/stream-json-Q2JGWPHB.js.map +0 -1
package/dist/chunk-JBXNQCGE.js
DELETED
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
import { resolveLib, loadCatalog, readDoc, localPackageDocs, resolveVersion, resolveOne } from './chunk-GGJZA3Q6.js';
|
|
2
|
-
import { buildCodeContext, buildAgentMessages, redactSecrets, unifiedDiff, applyEdit } from './chunk-CS37OBE3.js';
|
|
3
|
-
import { recordCliCall, CLI_TOOL_ALIASES, impactOf, queryGraph } from './chunk-WNIIKCNF.js';
|
|
4
|
-
|
|
5
|
-
// src/code/secrets.ts
|
|
6
|
-
var SECRET_FILE = new RegExp(
|
|
7
|
-
[
|
|
8
|
-
String.raw`(^|/)\.env(\.[\w.-]+)?$`,
|
|
9
|
-
// .env, .env.local, .env.production
|
|
10
|
-
String.raw`(^|/)\.npmrc$`,
|
|
11
|
-
String.raw`(^|/)\.netrc$`,
|
|
12
|
-
String.raw`(^|/)\.pgpass$`,
|
|
13
|
-
String.raw`(^|/)\.git-credentials$`,
|
|
14
|
-
String.raw`(^|/)id_(rsa|dsa|ecdsa|ed25519)$`,
|
|
15
|
-
String.raw`\.pem$`,
|
|
16
|
-
String.raw`\.key$`,
|
|
17
|
-
String.raw`\.p12$`,
|
|
18
|
-
String.raw`\.pfx$`,
|
|
19
|
-
String.raw`(^|/)credentials(\.json)?$`,
|
|
20
|
-
// aws credentials, gcloud
|
|
21
|
-
String.raw`(^|/)\.aws/credentials$`,
|
|
22
|
-
String.raw`(^|/)secrets?\.(ya?ml|json|toml|env)$`
|
|
23
|
-
].join("|"),
|
|
24
|
-
"i"
|
|
25
|
-
);
|
|
26
|
-
function isSecretPath(file) {
|
|
27
|
-
const normalized = file.replace(/\\/g, "/");
|
|
28
|
-
return SECRET_FILE.test(normalized);
|
|
29
|
-
}
|
|
30
|
-
function secretRefusal(file) {
|
|
31
|
-
return `refusing to read ${file} \u2014 it looks like a secrets/credentials file, and this content would be sent to the model. Reference the values by name instead, or read a non-secret file.`;
|
|
32
|
-
}
|
|
33
|
-
var TOKEN_SHAPES = /\b(sk|pk|rk|xoxb|xoxp|ghp|gho|ghs|ghu|glpat|AKIA|ASIA|AIza|ya29|hf|nvapi|sk-ant|sk-or)[-_][A-Za-z0-9\-_./+]{8,}/g;
|
|
34
|
-
var BEARER = /\b(Authorization|Bearer|token|api[_-]?key)\b\s*[:=]\s*['"]?[A-Za-z0-9\-_./+]{12,}['"]?/gi;
|
|
35
|
-
var ASSIGNMENT = /\b([A-Za-z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|CREDENTIAL|PRIVATE|ACCESS|SESSION)[A-Za-z0-9_]*)\s*([:=])\s*['"]?([^\s'";,]{6,})/gi;
|
|
36
|
-
var URL_AUTH = /\b([a-z][a-z0-9+.-]*:\/\/)([^:/\s]+):([^@/\s]+)@/gi;
|
|
37
|
-
function redactText(text) {
|
|
38
|
-
return text.replace(URL_AUTH, "$1$2:***redacted***@").replace(TOKEN_SHAPES, (_m, prefix) => `${prefix}-***redacted***`).replace(BEARER, (_m, k) => `${k}: ***redacted***`).replace(ASSIGNMENT, (_m, name, op) => `${name}${op}***redacted***`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/code/safety.ts
|
|
42
|
-
var DANGEROUS = [
|
|
43
|
-
{ pattern: /\brm\s+(-[a-z]*f[a-z]*\s+)?(-[a-z]*r[a-z]*\s+)?(-[a-z]*\s+)*(\/|~|\$HOME|\.)(\s|$)/i, reason: "recursive/forced delete of a root or home path" },
|
|
44
|
-
{ pattern: /\brm\s+-[a-z]*r[a-z]*f|\brm\s+-[a-z]*f[a-z]*r/i, reason: "recursive force delete" },
|
|
45
|
-
{ pattern: /\bmkfs\b|\bmke2fs\b/i, reason: "formats a filesystem" },
|
|
46
|
-
{ pattern: /\bdd\b[^|]*\bof=\/dev\//i, reason: "writes raw to a device" },
|
|
47
|
-
{ pattern: />\s*\/dev\/(sd|nvme|hd|disk)/i, reason: "writes raw to a disk device" },
|
|
48
|
-
{ pattern: /:\s*\(\s*\)\s*\{[^}]*\}\s*;\s*:/, reason: "fork bomb" },
|
|
49
|
-
{ pattern: /\b(curl|wget|fetch)\b[^\n|]*\|\s*(sudo\s+)?(sh|bash|zsh|python|node|ruby|perl)\b/i, reason: "pipes a download straight into a shell/interpreter" },
|
|
50
|
-
{ pattern: /\bgit\s+push\b[^\n]*(--force\b|-f\b)/i, reason: "force-push (rewrites remote history)" },
|
|
51
|
-
{ pattern: /\bgit\s+(reset\s+--hard|clean\s+-[a-z]*f)/i, reason: "destroys uncommitted work" },
|
|
52
|
-
{ pattern: /\b(shutdown|reboot|halt|poweroff)\b/i, reason: "powers off / reboots the machine" },
|
|
53
|
-
{ pattern: /\bchmod\s+-R\s+0*777\s+(\/|~)/i, reason: "world-writable on a root/home path" },
|
|
54
|
-
{ pattern: /\bsudo\b/i, reason: "runs as root (never automatic)" },
|
|
55
|
-
{ pattern: /\beval\b\s+["'`]?\$\(/i, reason: "evaluates dynamically-constructed shell" }
|
|
56
|
-
];
|
|
57
|
-
function dangerousCommand(command, extraDeny = []) {
|
|
58
|
-
const cmd = command.trim();
|
|
59
|
-
for (const { pattern, reason } of DANGEROUS) {
|
|
60
|
-
if (pattern.test(cmd)) return reason;
|
|
61
|
-
}
|
|
62
|
-
for (const raw of extraDeny) {
|
|
63
|
-
if (!raw) continue;
|
|
64
|
-
try {
|
|
65
|
-
if (new RegExp(raw, "i").test(cmd)) return `matches a project denylist rule (${raw})`;
|
|
66
|
-
} catch {
|
|
67
|
-
if (cmd.toLowerCase().includes(raw.toLowerCase())) return `matches a project denylist rule (${raw})`;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// src/code/tools.ts
|
|
74
|
-
var MAX_OUTPUT = 12e3;
|
|
75
|
-
var AGENT_TOOLS = [
|
|
76
|
-
{
|
|
77
|
-
name: "search_code",
|
|
78
|
-
description: "Search the codebase by concept or identifier using the deterministic code graph (preferred over reading files blindly). Returns the most relevant symbols with file:line.",
|
|
79
|
-
parameters: { type: "object", properties: { query: { type: "string", description: 'What to find, e.g. "where auth failures are handled"' } }, required: ["query"] }
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: "read_file",
|
|
83
|
-
description: "Read a file (optionally a line range). Use after search_code to see the exact code.",
|
|
84
|
-
parameters: { type: "object", properties: { path: { type: "string" }, start_line: { type: "number" }, end_line: { type: "number" } }, required: ["path"] }
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: "list_files",
|
|
88
|
-
description: "List files known to the code map, optionally filtered by directory prefix and a simple substring/extension pattern.",
|
|
89
|
-
parameters: { type: "object", properties: { dir: { type: "string" }, pattern: { type: "string" } } }
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: "graph_impact",
|
|
93
|
-
description: "What depends on a symbol \u2014 the blast radius of changing it (callers/importers/subtypes). Use before editing shared code.",
|
|
94
|
-
parameters: { type: "object", properties: { symbol: { type: "string" } }, required: ["symbol"] }
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: "library_docs",
|
|
98
|
-
description: "Get version-correct documentation for a dependency this project actually uses (from the installed package), so you use the right API for the installed version. Prefer this over guessing a library's API.",
|
|
99
|
-
parameters: { type: "object", properties: { name: { type: "string", description: 'package name, e.g. "react" or "zod"' } }, required: ["name"] }
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: "edit_file",
|
|
103
|
-
description: "Edit a file by replacing an exact snippet. The SEARCH text must match current file contents (whitespace-flexible). Requires approval.",
|
|
104
|
-
parameters: { type: "object", properties: { path: { type: "string" }, search: { type: "string" }, replace: { type: "string" } }, required: ["path", "search", "replace"] }
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: "create_file",
|
|
108
|
-
description: "Create a new file with the given contents. Requires approval.",
|
|
109
|
-
parameters: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] }
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: "delete_file",
|
|
113
|
-
description: "Delete a file. Requires approval.",
|
|
114
|
-
parameters: { type: "object", properties: { path: { type: "string" } }, required: ["path"] }
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: "run_command",
|
|
118
|
-
description: "Run a shell command (e.g. the test or build command) and read its output. Requires approval.",
|
|
119
|
-
parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: "finish",
|
|
123
|
-
description: "Finish the task. Call this when the change is complete, with a short summary of what you did.",
|
|
124
|
-
parameters: { type: "object", properties: { summary: { type: "string" } }, required: ["summary"] }
|
|
125
|
-
}
|
|
126
|
-
];
|
|
127
|
-
async function executeTool(call, ctx) {
|
|
128
|
-
const a = call.arguments;
|
|
129
|
-
try {
|
|
130
|
-
switch (call.name) {
|
|
131
|
-
case "search_code":
|
|
132
|
-
return search(ctx, str(a.query));
|
|
133
|
-
case "read_file":
|
|
134
|
-
return readFile(ctx, str(a.path), num(a.start_line), num(a.end_line));
|
|
135
|
-
case "list_files":
|
|
136
|
-
return listFiles(ctx, str(a.dir), str(a.pattern));
|
|
137
|
-
case "graph_impact":
|
|
138
|
-
return graphImpact(ctx, str(a.symbol));
|
|
139
|
-
case "library_docs":
|
|
140
|
-
return libraryDocs(ctx, str(a.name));
|
|
141
|
-
case "edit_file":
|
|
142
|
-
return editFile(ctx, str(a.path), str(a.search), str(a.replace));
|
|
143
|
-
case "create_file":
|
|
144
|
-
return createFile(ctx, str(a.path), str(a.content));
|
|
145
|
-
case "delete_file":
|
|
146
|
-
return deleteFile(ctx, str(a.path));
|
|
147
|
-
case "run_command":
|
|
148
|
-
return runCommand(ctx, str(a.command));
|
|
149
|
-
case "finish":
|
|
150
|
-
return { content: "done", mutated: false, finished: true, finalSummary: str(a.summary) || "done" };
|
|
151
|
-
default:
|
|
152
|
-
return { content: `unknown tool "${call.name}". Available: ${AGENT_TOOLS.map((t) => t.name).join(", ")}`, mutated: false };
|
|
153
|
-
}
|
|
154
|
-
} catch (e) {
|
|
155
|
-
return { content: `tool ${call.name} failed: ${e.message}`, mutated: false };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
function search(ctx, query) {
|
|
159
|
-
if (!query) return { content: "search_code needs a query", mutated: false };
|
|
160
|
-
const res = queryGraph(ctx.graph, query, { budget: 1500, limit: 10 });
|
|
161
|
-
if (res.matches.length === 0) return { content: `no symbols matched "${query}"`, mutated: false };
|
|
162
|
-
const lines = res.matches.map((m) => `- ${m.node.qualifiedName} (${m.node.kind}) ${m.node.file}:${m.node.span.start}${m.node.signature ? ` ${m.node.signature}` : ""}`);
|
|
163
|
-
return { content: `Matches for "${query}":
|
|
164
|
-
${lines.join("\n")}`, mutated: false };
|
|
165
|
-
}
|
|
166
|
-
function readFile(ctx, path, start, end) {
|
|
167
|
-
if (isSecretPath(path)) return { content: secretRefusal(path), mutated: false };
|
|
168
|
-
const content = ctx.fsImpl.read(path);
|
|
169
|
-
if (content === null) return { content: `${path} not found`, mutated: false };
|
|
170
|
-
const lines = content.split("\n");
|
|
171
|
-
const from = start && start > 0 ? start - 1 : 0;
|
|
172
|
-
const to = end && end > 0 ? end : lines.length;
|
|
173
|
-
const slice = lines.slice(from, to).join("\n");
|
|
174
|
-
const shown = truncate(redactText(slice));
|
|
175
|
-
const header = start || end ? `${path} (lines ${from + 1}-${Math.min(to, lines.length)} of ${lines.length})` : `${path} (${lines.length} lines)`;
|
|
176
|
-
return { content: `${header}:
|
|
177
|
-
${shown}`, mutated: false };
|
|
178
|
-
}
|
|
179
|
-
function listFiles(ctx, dir, pattern) {
|
|
180
|
-
const prefix = dir ? dir.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "") : "";
|
|
181
|
-
const files = [...new Set(ctx.graph.nodes.filter((n) => n.kind === "file").map((n) => n.file))].filter((f) => !isSecretPath(f)).filter((f) => prefix ? f === prefix || f.startsWith(prefix + "/") : true).filter((f) => pattern ? f.includes(pattern) || f.endsWith(pattern) : true).sort();
|
|
182
|
-
if (files.length === 0) return { content: `no files${dir ? ` under ${dir}` : ""}${pattern ? ` matching "${pattern}"` : ""}`, mutated: false };
|
|
183
|
-
return { content: `${files.length} file(s):
|
|
184
|
-
${files.slice(0, 200).join("\n")}`, mutated: false };
|
|
185
|
-
}
|
|
186
|
-
function libraryDocs(ctx, name) {
|
|
187
|
-
if (!name) return { content: "library_docs needs a package name", mutated: false };
|
|
188
|
-
const entry = resolveLib(loadCatalog(ctx.root), name);
|
|
189
|
-
if (entry) {
|
|
190
|
-
const doc = readDoc(ctx.root, entry);
|
|
191
|
-
if (doc.trim()) return { content: `Docs for ${name}${entry.version && entry.version !== "*" ? ` @ ${entry.version}` : ""} (${entry.source.type}):
|
|
192
|
-
${truncate(redactText(doc))}`, mutated: false };
|
|
193
|
-
}
|
|
194
|
-
const local = localPackageDocs(ctx.root, name);
|
|
195
|
-
if (local?.docs.trim()) {
|
|
196
|
-
return { content: `Docs for ${name}${local.version ? ` @ ${local.version}` : ""} (${local.source}):
|
|
197
|
-
${truncate(redactText(local.docs))}`, mutated: false };
|
|
198
|
-
}
|
|
199
|
-
const v = resolveVersion(ctx.root, name);
|
|
200
|
-
return {
|
|
201
|
-
content: `no bundled docs for ${name}${v.served ? ` (installed ${v.served})` : " (not found in this project)"}. Read its source under node_modules/${name}, or add curated docs with \`vg lib add\`.`,
|
|
202
|
-
mutated: false
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
function graphImpact(ctx, symbol) {
|
|
206
|
-
const { node } = resolveOne(ctx.graph, symbol);
|
|
207
|
-
if (!node) return { content: `no symbol named "${symbol}" in the map`, mutated: false };
|
|
208
|
-
const impact = impactOf(ctx.graph, node.id, { depth: 3 });
|
|
209
|
-
if (impact.affected.length === 0) return { content: `nothing depends on ${node.qualifiedName} (safe to change in isolation)`, mutated: false };
|
|
210
|
-
const lines = impact.affected.slice(0, 20).map((i) => `- ${i.name} (${i.file}:${i.line})`);
|
|
211
|
-
return { content: `${impact.affected.length} symbol(s) depend on ${node.qualifiedName}:
|
|
212
|
-
${lines.join("\n")}`, mutated: false };
|
|
213
|
-
}
|
|
214
|
-
async function editFile(ctx, path, search2, replace) {
|
|
215
|
-
const before = ctx.fsImpl.read(path);
|
|
216
|
-
const { content: after, outcome } = applyEdit(before, { op: "replace", file: path, search: search2, replace }, ctx.spans.get(normalize(path)) ?? []);
|
|
217
|
-
if (outcome.status !== "applied") {
|
|
218
|
-
return { content: `edit not applied (${outcome.status}): ${outcome.reason ?? ""}`, mutated: false };
|
|
219
|
-
}
|
|
220
|
-
const diff = unifiedDiff(before, after, path);
|
|
221
|
-
if (!await ctx.approve({ kind: "edit", file: path, diff })) {
|
|
222
|
-
return { content: `edit to ${path} was declined by the user`, mutated: false };
|
|
223
|
-
}
|
|
224
|
-
ctx.fsImpl.write(path, after ?? "");
|
|
225
|
-
return { content: `edited ${path}`, mutated: true, change: { file: path, before, after, outcomes: [outcome], diff } };
|
|
226
|
-
}
|
|
227
|
-
async function createFile(ctx, path, content) {
|
|
228
|
-
const existing = ctx.fsImpl.read(path);
|
|
229
|
-
if (existing !== null) return { content: `${path} already exists \u2014 use edit_file`, mutated: false };
|
|
230
|
-
if (!await ctx.approve({ kind: "create", file: path, bytes: Buffer.byteLength(content) })) {
|
|
231
|
-
return { content: `creating ${path} was declined by the user`, mutated: false };
|
|
232
|
-
}
|
|
233
|
-
ctx.fsImpl.write(path, content);
|
|
234
|
-
return { content: `created ${path}`, mutated: true, change: { file: path, before: null, after: content, outcomes: [{ edit: { op: "create", file: path, content }, status: "applied" }], diff: unifiedDiff(null, content, path) } };
|
|
235
|
-
}
|
|
236
|
-
async function deleteFile(ctx, path) {
|
|
237
|
-
const before = ctx.fsImpl.read(path);
|
|
238
|
-
if (before === null) return { content: `${path} does not exist`, mutated: false };
|
|
239
|
-
if (!await ctx.approve({ kind: "delete", file: path })) {
|
|
240
|
-
return { content: `deleting ${path} was declined by the user`, mutated: false };
|
|
241
|
-
}
|
|
242
|
-
ctx.fsImpl.remove(path);
|
|
243
|
-
return { content: `deleted ${path}`, mutated: true, change: { file: path, before, after: null, outcomes: [{ edit: { op: "delete", file: path }, status: "applied" }], diff: unifiedDiff(before, null, path) } };
|
|
244
|
-
}
|
|
245
|
-
async function runCommand(ctx, command) {
|
|
246
|
-
if (!command) return { content: "run_command needs a command", mutated: false };
|
|
247
|
-
if (ctx.auto) {
|
|
248
|
-
const reason = dangerousCommand(command, ctx.denyCommands);
|
|
249
|
-
if (reason) return { content: `refused to run \`${command}\` autonomously \u2014 ${reason}. Run it yourself if you intend to, or re-run without --auto to approve it interactively.`, mutated: false };
|
|
250
|
-
}
|
|
251
|
-
if (!await ctx.approve({ kind: "run", command })) {
|
|
252
|
-
return { content: `running \`${command}\` was declined by the user`, mutated: false };
|
|
253
|
-
}
|
|
254
|
-
const res = ctx.run(command);
|
|
255
|
-
return { content: `$ ${command}
|
|
256
|
-
exit ${res.exitCode}
|
|
257
|
-
${truncate(res.stdout)}`, mutated: true };
|
|
258
|
-
}
|
|
259
|
-
function truncate(s) {
|
|
260
|
-
if (s.length <= MAX_OUTPUT) return s;
|
|
261
|
-
return s.slice(0, MAX_OUTPUT) + `
|
|
262
|
-
\u2026 (truncated ${s.length - MAX_OUTPUT} chars)`;
|
|
263
|
-
}
|
|
264
|
-
function str(v) {
|
|
265
|
-
return typeof v === "string" ? v : v === void 0 || v === null ? "" : String(v);
|
|
266
|
-
}
|
|
267
|
-
function num(v) {
|
|
268
|
-
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
|
|
269
|
-
return Number.isFinite(n) ? n : void 0;
|
|
270
|
-
}
|
|
271
|
-
function normalize(file) {
|
|
272
|
-
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// src/code/agent.ts
|
|
276
|
-
var DEFAULT_MAX_STEPS = 24;
|
|
277
|
-
var DEFAULT_CONTEXT_BUDGET = 16e3;
|
|
278
|
-
var KEEP_ROUNDS = 8;
|
|
279
|
-
var NUDGE_AT = 3;
|
|
280
|
-
var STOP_AT = 5;
|
|
281
|
-
async function runAgent(options) {
|
|
282
|
-
const { graph, root, instruction, providers, fsImpl } = options;
|
|
283
|
-
const maxSteps = options.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
284
|
-
const contextBudget = options.contextBudget ?? DEFAULT_CONTEXT_BUDGET;
|
|
285
|
-
const now = options.now ?? (() => 0);
|
|
286
|
-
const onEvent = options.onEvent ?? (() => {
|
|
287
|
-
});
|
|
288
|
-
const allTools = [...AGENT_TOOLS, ...options.externalTools?.specs ?? []];
|
|
289
|
-
const context = buildCodeContext(graph, instruction, { budget: options.budget ?? 3e3 });
|
|
290
|
-
const messages = buildAgentMessages(context);
|
|
291
|
-
if (options.priorSummary) {
|
|
292
|
-
messages.push({ role: "user", content: options.priorSummary });
|
|
293
|
-
}
|
|
294
|
-
if (options.testCommand) {
|
|
295
|
-
messages.push({ role: "user", content: `When you want to verify a change, the project's test command is: \`${options.testCommand}\`` });
|
|
296
|
-
}
|
|
297
|
-
const spans = buildSpanIndex(graph);
|
|
298
|
-
const changes = [];
|
|
299
|
-
const repeats = /* @__PURE__ */ new Map();
|
|
300
|
-
let recordedSearch = false;
|
|
301
|
-
let commandCount = 0;
|
|
302
|
-
let verifyRounds = options.verify?.maxRounds ?? 2;
|
|
303
|
-
const usage = { promptTokens: 0, completionTokens: 0 };
|
|
304
|
-
let providerInfo = { id: providers[0]?.id ?? "none", model: providers[0]?.model ?? "", fellBack: false };
|
|
305
|
-
const ctx = { root, graph, fsImpl, spans, run: options.run, approve: options.approve, auto: options.auto, denyCommands: options.denyCommands };
|
|
306
|
-
const finish = (stopped, finalText, steps) => {
|
|
307
|
-
const result = { finalText, changes, steps, stopped, provider: providerInfo, usage };
|
|
308
|
-
if (!options.noAudit) writeAgentAudit(fsImpl, { instruction, providerInfo, changes, commandCount, steps, stopped }, now());
|
|
309
|
-
return result;
|
|
310
|
-
};
|
|
311
|
-
const verifyOnFinish = () => {
|
|
312
|
-
const v = options.verify;
|
|
313
|
-
if (!v || verifyRounds <= 0 || changes.length === 0) return "done";
|
|
314
|
-
const res = options.run(v.command);
|
|
315
|
-
onEvent({ type: "verify", command: v.command, passed: res.exitCode === 0 });
|
|
316
|
-
if (res.exitCode === 0) return "done";
|
|
317
|
-
verifyRounds--;
|
|
318
|
-
messages.push({ role: "user", content: `The task isn't finished \u2014 \`${v.command}\` failed (exit ${res.exitCode}):
|
|
319
|
-
${res.stdout.slice(0, 8e3)}
|
|
320
|
-
|
|
321
|
-
Fix the failing tests, then call finish again.${verifyRounds === 0 ? " (last verification attempt)" : ""}` });
|
|
322
|
-
return "retry";
|
|
323
|
-
};
|
|
324
|
-
for (let step = 1; step <= maxSteps; step++) {
|
|
325
|
-
onEvent({ type: "step", n: step });
|
|
326
|
-
const compacted = compact(messages, contextBudget, changes);
|
|
327
|
-
if (compacted.droppedRounds > 0) {
|
|
328
|
-
messages.length = 0;
|
|
329
|
-
messages.push(...compacted.messages);
|
|
330
|
-
onEvent({ type: "compact", droppedRounds: compacted.droppedRounds });
|
|
331
|
-
}
|
|
332
|
-
let result;
|
|
333
|
-
try {
|
|
334
|
-
const c = await complete(providers, messages, allTools, onEvent, options.stream);
|
|
335
|
-
result = c.result;
|
|
336
|
-
providerInfo = { id: c.provider.id, model: c.provider.model, fellBack: c.fellBack };
|
|
337
|
-
} catch (e) {
|
|
338
|
-
const msg = redactSecrets(e.message);
|
|
339
|
-
onEvent({ type: "assistant", text: `error: ${msg}` });
|
|
340
|
-
return finish("error", msg, step);
|
|
341
|
-
}
|
|
342
|
-
if (result.usage) {
|
|
343
|
-
usage.promptTokens += result.usage.promptTokens ?? 0;
|
|
344
|
-
usage.completionTokens += result.usage.completionTokens ?? 0;
|
|
345
|
-
onEvent({ type: "usage", promptTokens: result.usage.promptTokens ?? 0, completionTokens: result.usage.completionTokens ?? 0 });
|
|
346
|
-
}
|
|
347
|
-
if (result.text) onEvent({ type: "assistant", text: result.text });
|
|
348
|
-
const toolCalls = result.toolCalls ?? [];
|
|
349
|
-
if (toolCalls.length === 0) {
|
|
350
|
-
messages.push({ role: "assistant", content: result.text });
|
|
351
|
-
return finish("no-tools", result.text, step);
|
|
352
|
-
}
|
|
353
|
-
messages.push({ role: "assistant", content: result.text, toolCalls });
|
|
354
|
-
for (const call of toolCalls) {
|
|
355
|
-
onEvent({ type: "tool-call", name: call.name, args: call.arguments });
|
|
356
|
-
if (call.name === "search_code" && options.attribution?.client && !recordedSearch) {
|
|
357
|
-
recordedSearch = true;
|
|
358
|
-
recordSearchSaving(root, context, options.attribution, now());
|
|
359
|
-
}
|
|
360
|
-
const toolResult = options.externalTools?.owns(call.name) ? await options.externalTools.execute(call) : await executeTool(call, ctx);
|
|
361
|
-
if (call.name === "run_command" && toolResult.mutated) commandCount++;
|
|
362
|
-
if (toolResult.change) {
|
|
363
|
-
changes.push(toolResult.change);
|
|
364
|
-
onEvent({ type: "change", change: toolResult.change });
|
|
365
|
-
}
|
|
366
|
-
const sig = `${call.name}:${stableArgs(call.arguments)}`;
|
|
367
|
-
let content = toolResult.content;
|
|
368
|
-
let stopNoProgress = false;
|
|
369
|
-
if (toolResult.mutated || toolResult.finished) {
|
|
370
|
-
repeats.delete(sig);
|
|
371
|
-
} else {
|
|
372
|
-
const n = (repeats.get(sig) ?? 0) + 1;
|
|
373
|
-
repeats.set(sig, n);
|
|
374
|
-
if (n >= STOP_AT) stopNoProgress = true;
|
|
375
|
-
else if (n >= NUDGE_AT) content += `
|
|
376
|
-
|
|
377
|
-
(note: you have called this exact tool call ${n} times with no change \u2014 try a different approach, read more context, or call finish.)`;
|
|
378
|
-
}
|
|
379
|
-
onEvent({ type: "tool-result", name: call.name, content, mutated: toolResult.mutated });
|
|
380
|
-
messages.push({ role: "tool", content, toolCallId: call.id, name: call.name });
|
|
381
|
-
if (toolResult.finished) {
|
|
382
|
-
if (verifyOnFinish() === "retry") break;
|
|
383
|
-
return finish("finished", toolResult.finalSummary ?? "done", step);
|
|
384
|
-
}
|
|
385
|
-
if (stopNoProgress) return finish("no-progress", `stopped: the model repeated \`${call.name}\` without making progress`, step);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return finish("max-steps", "reached the step limit before finishing", maxSteps);
|
|
389
|
-
}
|
|
390
|
-
async function complete(providers, messages, tools, onEvent, stream) {
|
|
391
|
-
if (providers.length === 0) throw new Error("no model provider available");
|
|
392
|
-
const onToken = stream ? (t) => onEvent({ type: "token", text: t }) : void 0;
|
|
393
|
-
let lastErr;
|
|
394
|
-
for (let i = 0; i < providers.length; i++) {
|
|
395
|
-
try {
|
|
396
|
-
const result = await providers[i].chat(messages, { temperature: 0, tools, stream, onToken });
|
|
397
|
-
return { result, provider: providers[i], fellBack: i > 0 };
|
|
398
|
-
} catch (e) {
|
|
399
|
-
lastErr = e;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
throw new Error(lastErr instanceof Error ? redactSecrets(lastErr.message) : String(lastErr));
|
|
403
|
-
}
|
|
404
|
-
function compact(messages, budget, changes) {
|
|
405
|
-
if (estimateTokens(messages) <= budget) return { messages, droppedRounds: 0 };
|
|
406
|
-
const head = messages.slice(0, 3);
|
|
407
|
-
const body = messages.slice(3);
|
|
408
|
-
const rounds = [];
|
|
409
|
-
for (const m of body) {
|
|
410
|
-
if (m.role === "assistant" || rounds.length === 0) rounds.push([m]);
|
|
411
|
-
else rounds[rounds.length - 1].push(m);
|
|
412
|
-
}
|
|
413
|
-
if (rounds.length <= KEEP_ROUNDS) return { messages, droppedRounds: 0 };
|
|
414
|
-
const dropped = rounds.slice(0, rounds.length - KEEP_ROUNDS);
|
|
415
|
-
const kept = rounds.slice(-KEEP_ROUNDS).flat();
|
|
416
|
-
const toolCalls = dropped.flat().reduce((n, m) => n + (m.role === "assistant" ? m.toolCalls?.length ?? 0 : 0), 0);
|
|
417
|
-
const filesChanged = [...new Set(changes.map((c) => c.file))];
|
|
418
|
-
const note = {
|
|
419
|
-
role: "user",
|
|
420
|
-
content: `[earlier steps summarized to save context: ${dropped.length} round(s), ${toolCalls} tool call(s) omitted.${filesChanged.length ? ` Files changed so far: ${filesChanged.join(", ")}.` : ""} Continue the task.]`
|
|
421
|
-
};
|
|
422
|
-
return { messages: [...head, note, ...kept], droppedRounds: dropped.length };
|
|
423
|
-
}
|
|
424
|
-
function recordSearchSaving(root, context, attribution, ts) {
|
|
425
|
-
const files = new Set(context.seeds.map((s) => s.node.file).filter(Boolean));
|
|
426
|
-
recordCliCall(
|
|
427
|
-
root,
|
|
428
|
-
{
|
|
429
|
-
tool: CLI_TOOL_ALIASES.ask,
|
|
430
|
-
client: attribution.client,
|
|
431
|
-
provider: attribution.provider,
|
|
432
|
-
model: attribution.model,
|
|
433
|
-
outcome: context.seeds.length ? "complete" : "miss",
|
|
434
|
-
vgTokens: context.tokensEstimate,
|
|
435
|
-
baselineFiles: files.size
|
|
436
|
-
},
|
|
437
|
-
ts
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
function writeAgentAudit(fsImpl, rec, ts) {
|
|
441
|
-
try {
|
|
442
|
-
fsImpl.appendAudit(
|
|
443
|
-
JSON.stringify({
|
|
444
|
-
ts,
|
|
445
|
-
kind: "agent",
|
|
446
|
-
instruction: rec.instruction.slice(0, 500),
|
|
447
|
-
provider: rec.providerInfo.id,
|
|
448
|
-
model: rec.providerInfo.model,
|
|
449
|
-
steps: rec.steps,
|
|
450
|
-
stopped: rec.stopped,
|
|
451
|
-
commands: rec.commandCount,
|
|
452
|
-
files: rec.changes.map((c) => ({ file: c.file, statuses: c.outcomes.map((o) => o.status) }))
|
|
453
|
-
})
|
|
454
|
-
);
|
|
455
|
-
} catch {
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
function stableArgs(args) {
|
|
459
|
-
const keys = Object.keys(args).sort();
|
|
460
|
-
return JSON.stringify(keys.map((k) => [k, args[k]]));
|
|
461
|
-
}
|
|
462
|
-
function estimateTokens(messages) {
|
|
463
|
-
let chars = 0;
|
|
464
|
-
for (const m of messages) {
|
|
465
|
-
chars += m.content.length;
|
|
466
|
-
if (m.role === "assistant" && m.toolCalls) chars += JSON.stringify(m.toolCalls).length;
|
|
467
|
-
}
|
|
468
|
-
return Math.ceil(chars / 4);
|
|
469
|
-
}
|
|
470
|
-
function buildSpanIndex(graph) {
|
|
471
|
-
const map = /* @__PURE__ */ new Map();
|
|
472
|
-
for (const n of graph.nodes) {
|
|
473
|
-
if (n.kind === "file" || n.kind === "external") continue;
|
|
474
|
-
const file = n.file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
475
|
-
const list = map.get(file) ?? [];
|
|
476
|
-
list.push({ qualifiedName: n.qualifiedName, file, start: n.span.start, end: n.span.end });
|
|
477
|
-
map.set(file, list);
|
|
478
|
-
}
|
|
479
|
-
return map;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
export { runAgent };
|
|
483
|
-
//# sourceMappingURL=chunk-JBXNQCGE.js.map
|
|
484
|
-
//# sourceMappingURL=chunk-JBXNQCGE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code/secrets.ts","../src/code/safety.ts","../src/code/tools.ts","../src/code/agent.ts"],"names":["search"],"mappings":"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","file":"chunk-JBXNQCGE.js","sourcesContent":["/**\n * Secret-safe file access for the VG Code agent (VG-CLI-CODE §13, GUARDRAILS §1.1).\n *\n * The agent reads files and hands them to a model — which, for a hosted model,\n * means they leave the machine. So a coding agent that will happily open `.env`\n * or a private key and paste it into a prompt is a credential-egress bug. Two\n * defenses, applied at the boundary (before anything reaches the model):\n *\n * 1. **Refuse** to read files that exist only to hold secrets (`.env`, key\n * material, `.npmrc`, `.netrc`, cloud credentials…).\n * 2. **Redact** credential shapes from the content of any file we *do* read —\n * token prefixes, `Authorization` headers, and `NAME_KEY=value` style\n * assignments — so a stray secret in an otherwise-normal file is masked.\n *\n * Pure and unit-tested; no I/O here.\n */\n\n/** Files whose whole purpose is secrets — never read them into a prompt. */\nconst SECRET_FILE = new RegExp(\n [\n String.raw`(^|/)\\.env(\\.[\\w.-]+)?$`, // .env, .env.local, .env.production\n String.raw`(^|/)\\.npmrc$`,\n String.raw`(^|/)\\.netrc$`,\n String.raw`(^|/)\\.pgpass$`,\n String.raw`(^|/)\\.git-credentials$`,\n String.raw`(^|/)id_(rsa|dsa|ecdsa|ed25519)$`,\n String.raw`\\.pem$`,\n String.raw`\\.key$`,\n String.raw`\\.p12$`,\n String.raw`\\.pfx$`,\n String.raw`(^|/)credentials(\\.json)?$`, // aws credentials, gcloud\n String.raw`(^|/)\\.aws/credentials$`,\n String.raw`(^|/)secrets?\\.(ya?ml|json|toml|env)$`,\n ].join('|'),\n 'i',\n);\n\n/** Whether a path should never be read into a model prompt. */\nexport function isSecretPath(file: string): boolean {\n const normalized = file.replace(/\\\\/g, '/');\n return SECRET_FILE.test(normalized);\n}\n\n/** A one-line, actionable refusal message for a blocked read. */\nexport function secretRefusal(file: string): string {\n return `refusing to read ${file} — it looks like a secrets/credentials file, and this content would be sent to the model. Reference the values by name instead, or read a non-secret file.`;\n}\n\n// Known credential token prefixes (same family the ingest redaction guards).\nconst TOKEN_SHAPES = /\\b(sk|pk|rk|xoxb|xoxp|ghp|gho|ghs|ghu|glpat|AKIA|ASIA|AIza|ya29|hf|nvapi|sk-ant|sk-or)[-_][A-Za-z0-9\\-_./+]{8,}/g;\nconst BEARER = /\\b(Authorization|Bearer|token|api[_-]?key)\\b\\s*[:=]\\s*['\"]?[A-Za-z0-9\\-_./+]{12,}['\"]?/gi;\n// `NAME_KEY=secret`, `PASSWORD: \"…\"`, connection strings — mask the value only.\nconst ASSIGNMENT = /\\b([A-Za-z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|CREDENTIAL|PRIVATE|ACCESS|SESSION)[A-Za-z0-9_]*)\\s*([:=])\\s*['\"]?([^\\s'\";,]{6,})/gi;\nconst URL_AUTH = /\\b([a-z][a-z0-9+.-]*:\\/\\/)([^:/\\s]+):([^@/\\s]+)@/gi;\n\n/**\n * Redact credential shapes from text before it reaches the model. Masks the\n * secret value, never the surrounding structure, so the model still sees that a\n * key exists (and its name) without seeing the value.\n */\nexport function redactText(text: string): string {\n return text\n .replace(URL_AUTH, '$1$2:***redacted***@')\n .replace(TOKEN_SHAPES, (_m, prefix) => `${prefix}-***redacted***`)\n .replace(BEARER, (_m, k) => `${k}: ***redacted***`)\n .replace(ASSIGNMENT, (_m, name, op) => `${name}${op}***redacted***`);\n}\n","/**\n * Command safety for autonomous agent runs (VG-CLI-CODE §13).\n *\n * Interactively, `run_command` is gated by a human who sees the exact command\n * and says yes. Under `--auto` there is no human in the loop, so a small\n * denylist blocks the handful of commands that are catastrophic or exfiltrating\n * — a filesystem wipe, piping the internet into a shell, a force-push, a fork\n * bomb. This is defense-in-depth for autonomous mode, not a substitute for\n * review: it fails safe (an unrecognised command is still gated/approved), and a\n * project can extend the denylist in `.vibgrate/code.json`.\n *\n * Pure and unit-tested.\n */\n\nconst DANGEROUS: { pattern: RegExp; reason: string }[] = [\n { pattern: /\\brm\\s+(-[a-z]*f[a-z]*\\s+)?(-[a-z]*r[a-z]*\\s+)?(-[a-z]*\\s+)*(\\/|~|\\$HOME|\\.)(\\s|$)/i, reason: 'recursive/forced delete of a root or home path' },\n { pattern: /\\brm\\s+-[a-z]*r[a-z]*f|\\brm\\s+-[a-z]*f[a-z]*r/i, reason: 'recursive force delete' },\n { pattern: /\\bmkfs\\b|\\bmke2fs\\b/i, reason: 'formats a filesystem' },\n { pattern: /\\bdd\\b[^|]*\\bof=\\/dev\\//i, reason: 'writes raw to a device' },\n { pattern: />\\s*\\/dev\\/(sd|nvme|hd|disk)/i, reason: 'writes raw to a disk device' },\n { pattern: /:\\s*\\(\\s*\\)\\s*\\{[^}]*\\}\\s*;\\s*:/, reason: 'fork bomb' },\n { pattern: /\\b(curl|wget|fetch)\\b[^\\n|]*\\|\\s*(sudo\\s+)?(sh|bash|zsh|python|node|ruby|perl)\\b/i, reason: 'pipes a download straight into a shell/interpreter' },\n { pattern: /\\bgit\\s+push\\b[^\\n]*(--force\\b|-f\\b)/i, reason: 'force-push (rewrites remote history)' },\n { pattern: /\\bgit\\s+(reset\\s+--hard|clean\\s+-[a-z]*f)/i, reason: 'destroys uncommitted work' },\n { pattern: /\\b(shutdown|reboot|halt|poweroff)\\b/i, reason: 'powers off / reboots the machine' },\n { pattern: /\\bchmod\\s+-R\\s+0*777\\s+(\\/|~)/i, reason: 'world-writable on a root/home path' },\n { pattern: /\\bsudo\\b/i, reason: 'runs as root (never automatic)' },\n { pattern: /\\beval\\b\\s+[\"'`]?\\$\\(/i, reason: 'evaluates dynamically-constructed shell' },\n];\n\n/**\n * Return a reason string when `command` is too dangerous to run autonomously, or\n * null when it is allowed. `extraDeny` are project-configured substrings/regex\n * sources to also block. Matching is deliberately conservative — only clearly\n * destructive shapes trip it, so ordinary build/test commands run freely.\n */\nexport function dangerousCommand(command: string, extraDeny: string[] = []): string | null {\n const cmd = command.trim();\n for (const { pattern, reason } of DANGEROUS) {\n if (pattern.test(cmd)) return reason;\n }\n for (const raw of extraDeny) {\n if (!raw) continue;\n try {\n if (new RegExp(raw, 'i').test(cmd)) return `matches a project denylist rule (${raw})`;\n } catch {\n // Not a valid regex → treat as a literal substring.\n if (cmd.toLowerCase().includes(raw.toLowerCase())) return `matches a project denylist rule (${raw})`;\n }\n }\n return null;\n}\n","/**\n * The VG Code agent tool set (VG-CLI-CODE §12).\n *\n * These are the tools the model calls during a coding session — the same shape\n * as any coding agent (read a file, list files, search, edit, run a command),\n * but with two Vibgrate differences: **search is the code graph** (a deterministic\n * `query_graph`, not a grep), and **every mutating tool is governed** — edits and\n * shell commands go through an approval gate, never applied silently. Read-only\n * tools (read/list/search/impact) are side-effect-free and auto-approved.\n *\n * The executor is pure over an injected {@link ToolContext} (filesystem, graph,\n * shell runner, approval callback), so the whole tool layer is unit-tested with\n * no real disk, model, or shell.\n */\n\nimport { queryGraph } from '../engine/query.js';\nimport { impactOf } from '../engine/impact.js';\nimport { resolveOne } from '../engine/lookup.js';\nimport { loadCatalog, resolveLib, readDoc, localPackageDocs, resolveVersion } from '../engine/lib.js';\nimport { applyEdit, type SymbolSpan } from './apply.js';\nimport { unifiedDiff } from './diff.js';\nimport { isSecretPath, secretRefusal, redactText } from './secrets.js';\nimport { dangerousCommand } from './safety.js';\nimport type { CodeFs } from './session.js';\nimport type { ToolCall, ToolSpec, FileChange } from './types.js';\nimport type { VgGraph } from '../schema.js';\n\n/** A state-changing action the agent wants to take — shown to the gate for approval. */\nexport type MutatingAction =\n | { kind: 'edit'; file: string; diff: string }\n | { kind: 'create'; file: string; bytes: number }\n | { kind: 'delete'; file: string }\n | { kind: 'run'; command: string }\n | { kind: 'tool'; name: string; args: Record<string, unknown> };\n\nexport interface ShellResult {\n stdout: string;\n exitCode: number;\n}\n\nexport interface ToolContext {\n root: string;\n graph: VgGraph;\n fsImpl: CodeFs;\n spans: Map<string, SymbolSpan[]>;\n /** Run a shell command (injected; tests pass a fake). */\n run: (command: string) => ShellResult;\n /** Approval gate for a mutating action. Resolve false to refuse. */\n approve: (action: MutatingAction) => Promise<boolean>;\n /** Autonomous mode — enforce the command denylist since no human reviews each call. */\n auto?: boolean;\n /** Project-configured extra denylist rules for autonomous commands. */\n denyCommands?: string[];\n}\n\nexport interface ToolResult {\n /** Text handed back to the model as the tool result. */\n content: string;\n /** True if the action changed workspace state (write/delete/command). */\n mutated: boolean;\n /** Set by `finish` — the loop stops. */\n finished?: boolean;\n finalSummary?: string;\n /** The file change produced by an approved edit/create/delete (for the transcript). */\n change?: FileChange;\n}\n\n/** Max characters of file/command output we feed back, to protect the context window. */\nconst MAX_OUTPUT = 12_000;\n\n/** The tools advertised to the model. Names are stable — they are the wire contract. */\nexport const AGENT_TOOLS: ToolSpec[] = [\n {\n name: 'search_code',\n description: 'Search the codebase by concept or identifier using the deterministic code graph (preferred over reading files blindly). Returns the most relevant symbols with file:line.',\n parameters: { type: 'object', properties: { query: { type: 'string', description: 'What to find, e.g. \"where auth failures are handled\"' } }, required: ['query'] },\n },\n {\n name: 'read_file',\n description: 'Read a file (optionally a line range). Use after search_code to see the exact code.',\n parameters: { type: 'object', properties: { path: { type: 'string' }, start_line: { type: 'number' }, end_line: { type: 'number' } }, required: ['path'] },\n },\n {\n name: 'list_files',\n description: 'List files known to the code map, optionally filtered by directory prefix and a simple substring/extension pattern.',\n parameters: { type: 'object', properties: { dir: { type: 'string' }, pattern: { type: 'string' } } },\n },\n {\n name: 'graph_impact',\n description: 'What depends on a symbol — the blast radius of changing it (callers/importers/subtypes). Use before editing shared code.',\n parameters: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n {\n name: 'library_docs',\n description: \"Get version-correct documentation for a dependency this project actually uses (from the installed package), so you use the right API for the installed version. Prefer this over guessing a library's API.\",\n parameters: { type: 'object', properties: { name: { type: 'string', description: 'package name, e.g. \"react\" or \"zod\"' } }, required: ['name'] },\n },\n {\n name: 'edit_file',\n description: 'Edit a file by replacing an exact snippet. The SEARCH text must match current file contents (whitespace-flexible). Requires approval.',\n parameters: { type: 'object', properties: { path: { type: 'string' }, search: { type: 'string' }, replace: { type: 'string' } }, required: ['path', 'search', 'replace'] },\n },\n {\n name: 'create_file',\n description: 'Create a new file with the given contents. Requires approval.',\n parameters: { type: 'object', properties: { path: { type: 'string' }, content: { type: 'string' } }, required: ['path', 'content'] },\n },\n {\n name: 'delete_file',\n description: 'Delete a file. Requires approval.',\n parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] },\n },\n {\n name: 'run_command',\n description: 'Run a shell command (e.g. the test or build command) and read its output. Requires approval.',\n parameters: { type: 'object', properties: { command: { type: 'string' } }, required: ['command'] },\n },\n {\n name: 'finish',\n description: 'Finish the task. Call this when the change is complete, with a short summary of what you did.',\n parameters: { type: 'object', properties: { summary: { type: 'string' } }, required: ['summary'] },\n },\n];\n\n/** Execute one tool call against the workspace. Never throws — errors come back as tool content. */\nexport async function executeTool(call: ToolCall, ctx: ToolContext): Promise<ToolResult> {\n const a = call.arguments;\n try {\n switch (call.name) {\n case 'search_code':\n return search(ctx, str(a.query));\n case 'read_file':\n return readFile(ctx, str(a.path), num(a.start_line), num(a.end_line));\n case 'list_files':\n return listFiles(ctx, str(a.dir), str(a.pattern));\n case 'graph_impact':\n return graphImpact(ctx, str(a.symbol));\n case 'library_docs':\n return libraryDocs(ctx, str(a.name));\n case 'edit_file':\n return editFile(ctx, str(a.path), str(a.search), str(a.replace));\n case 'create_file':\n return createFile(ctx, str(a.path), str(a.content));\n case 'delete_file':\n return deleteFile(ctx, str(a.path));\n case 'run_command':\n return runCommand(ctx, str(a.command));\n case 'finish':\n return { content: 'done', mutated: false, finished: true, finalSummary: str(a.summary) || 'done' };\n default:\n return { content: `unknown tool \"${call.name}\". Available: ${AGENT_TOOLS.map((t) => t.name).join(', ')}`, mutated: false };\n }\n } catch (e) {\n return { content: `tool ${call.name} failed: ${(e as Error).message}`, mutated: false };\n }\n}\n\n/* ── read-only tools (auto-approved) ─────────────────────────────────────── */\n\nfunction search(ctx: ToolContext, query: string): ToolResult {\n if (!query) return { content: 'search_code needs a query', mutated: false };\n const res = queryGraph(ctx.graph, query, { budget: 1500, limit: 10 });\n if (res.matches.length === 0) return { content: `no symbols matched \"${query}\"`, mutated: false };\n const lines = res.matches.map((m) => `- ${m.node.qualifiedName} (${m.node.kind}) ${m.node.file}:${m.node.span.start}${m.node.signature ? ` ${m.node.signature}` : ''}`);\n return { content: `Matches for \"${query}\":\\n${lines.join('\\n')}`, mutated: false };\n}\n\nfunction readFile(ctx: ToolContext, path: string, start?: number, end?: number): ToolResult {\n // Never send a secrets file to the model (GUARDRAILS §1.1).\n if (isSecretPath(path)) return { content: secretRefusal(path), mutated: false };\n const content = ctx.fsImpl.read(path);\n if (content === null) return { content: `${path} not found`, mutated: false };\n const lines = content.split('\\n');\n const from = start && start > 0 ? start - 1 : 0;\n const to = end && end > 0 ? end : lines.length;\n const slice = lines.slice(from, to).join('\\n');\n // Redact any stray credential shapes before the content reaches the model.\n const shown = truncate(redactText(slice));\n const header = start || end ? `${path} (lines ${from + 1}-${Math.min(to, lines.length)} of ${lines.length})` : `${path} (${lines.length} lines)`;\n return { content: `${header}:\\n${shown}`, mutated: false };\n}\n\nfunction listFiles(ctx: ToolContext, dir?: string, pattern?: string): ToolResult {\n const prefix = dir ? dir.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/\\/$/, '') : '';\n const files = [...new Set(ctx.graph.nodes.filter((n) => n.kind === 'file').map((n) => n.file))]\n .filter((f) => !isSecretPath(f)) // don't surface secret files to the model\n .filter((f) => (prefix ? f === prefix || f.startsWith(prefix + '/') : true))\n .filter((f) => (pattern ? f.includes(pattern) || f.endsWith(pattern) : true))\n .sort();\n if (files.length === 0) return { content: `no files${dir ? ` under ${dir}` : ''}${pattern ? ` matching \"${pattern}\"` : ''}`, mutated: false };\n return { content: `${files.length} file(s):\\n${files.slice(0, 200).join('\\n')}`, mutated: false };\n}\n\n/** Version-correct docs for an installed dependency — the Vibgrate differentiator, as a tool. */\nfunction libraryDocs(ctx: ToolContext, name: string): ToolResult {\n if (!name) return { content: 'library_docs needs a package name', mutated: false };\n // Committed catalog first (curated/pinned docs), then the installed package on disk.\n const entry = resolveLib(loadCatalog(ctx.root), name);\n if (entry) {\n const doc = readDoc(ctx.root, entry);\n if (doc.trim()) return { content: `Docs for ${name}${entry.version && entry.version !== '*' ? ` @ ${entry.version}` : ''} (${entry.source.type}):\\n${truncate(redactText(doc))}`, mutated: false };\n }\n const local = localPackageDocs(ctx.root, name);\n if (local?.docs.trim()) {\n return { content: `Docs for ${name}${local.version ? ` @ ${local.version}` : ''} (${local.source}):\\n${truncate(redactText(local.docs))}`, mutated: false };\n }\n const v = resolveVersion(ctx.root, name);\n return {\n content: `no bundled docs for ${name}${v.served ? ` (installed ${v.served})` : ' (not found in this project)'}. Read its source under node_modules/${name}, or add curated docs with \\`vg lib add\\`.`,\n mutated: false,\n };\n}\n\nfunction graphImpact(ctx: ToolContext, symbol: string): ToolResult {\n const { node } = resolveOne(ctx.graph, symbol);\n if (!node) return { content: `no symbol named \"${symbol}\" in the map`, mutated: false };\n const impact = impactOf(ctx.graph, node.id, { depth: 3 });\n if (impact.affected.length === 0) return { content: `nothing depends on ${node.qualifiedName} (safe to change in isolation)`, mutated: false };\n const lines = impact.affected.slice(0, 20).map((i) => `- ${i.name} (${i.file}:${i.line})`);\n return { content: `${impact.affected.length} symbol(s) depend on ${node.qualifiedName}:\\n${lines.join('\\n')}`, mutated: false };\n}\n\n/* ── mutating tools (gated) ──────────────────────────────────────────────── */\n\nasync function editFile(ctx: ToolContext, path: string, search: string, replace: string): Promise<ToolResult> {\n const before = ctx.fsImpl.read(path);\n const { content: after, outcome } = applyEdit(before, { op: 'replace', file: path, search, replace }, ctx.spans.get(normalize(path)) ?? []);\n if (outcome.status !== 'applied') {\n return { content: `edit not applied (${outcome.status}): ${outcome.reason ?? ''}`, mutated: false };\n }\n const diff = unifiedDiff(before, after, path);\n if (!(await ctx.approve({ kind: 'edit', file: path, diff }))) {\n return { content: `edit to ${path} was declined by the user`, mutated: false };\n }\n ctx.fsImpl.write(path, after ?? '');\n return { content: `edited ${path}`, mutated: true, change: { file: path, before, after, outcomes: [outcome], diff } };\n}\n\nasync function createFile(ctx: ToolContext, path: string, content: string): Promise<ToolResult> {\n const existing = ctx.fsImpl.read(path);\n if (existing !== null) return { content: `${path} already exists — use edit_file`, mutated: false };\n if (!(await ctx.approve({ kind: 'create', file: path, bytes: Buffer.byteLength(content) }))) {\n return { content: `creating ${path} was declined by the user`, mutated: false };\n }\n ctx.fsImpl.write(path, content);\n return { content: `created ${path}`, mutated: true, change: { file: path, before: null, after: content, outcomes: [{ edit: { op: 'create', file: path, content }, status: 'applied' }], diff: unifiedDiff(null, content, path) } };\n}\n\nasync function deleteFile(ctx: ToolContext, path: string): Promise<ToolResult> {\n const before = ctx.fsImpl.read(path);\n if (before === null) return { content: `${path} does not exist`, mutated: false };\n if (!(await ctx.approve({ kind: 'delete', file: path }))) {\n return { content: `deleting ${path} was declined by the user`, mutated: false };\n }\n ctx.fsImpl.remove(path);\n return { content: `deleted ${path}`, mutated: true, change: { file: path, before, after: null, outcomes: [{ edit: { op: 'delete', file: path }, status: 'applied' }], diff: unifiedDiff(before, null, path) } };\n}\n\nasync function runCommand(ctx: ToolContext, command: string): Promise<ToolResult> {\n if (!command) return { content: 'run_command needs a command', mutated: false };\n // In autonomous mode there is no human reviewing each command, so the denylist\n // blocks the catastrophic/exfiltrating shapes outright. Interactively, the\n // human sees the exact command at the approval prompt, so we don't pre-block.\n if (ctx.auto) {\n const reason = dangerousCommand(command, ctx.denyCommands);\n if (reason) return { content: `refused to run \\`${command}\\` autonomously — ${reason}. Run it yourself if you intend to, or re-run without --auto to approve it interactively.`, mutated: false };\n }\n if (!(await ctx.approve({ kind: 'run', command }))) {\n return { content: `running \\`${command}\\` was declined by the user`, mutated: false };\n }\n const res = ctx.run(command);\n return { content: `$ ${command}\\nexit ${res.exitCode}\\n${truncate(res.stdout)}`, mutated: true };\n}\n\nfunction truncate(s: string): string {\n if (s.length <= MAX_OUTPUT) return s;\n return s.slice(0, MAX_OUTPUT) + `\\n… (truncated ${s.length - MAX_OUTPUT} chars)`;\n}\n\nfunction str(v: unknown): string {\n return typeof v === 'string' ? v : v === undefined || v === null ? '' : String(v);\n}\nfunction num(v: unknown): number | undefined {\n const n = typeof v === 'number' ? v : typeof v === 'string' ? Number(v) : NaN;\n return Number.isFinite(n) ? n : undefined;\n}\nfunction normalize(file: string): string {\n return file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n}\n","/**\n * The VG Code agentic loop (VG-CLI-CODE §12).\n *\n * This is what makes `vg code` a coding *agent* rather than a one-shot proposer:\n * the model is given the tool set (search the graph, read, list, impact, edit,\n * create, delete, run a command) and iterates — call tools, read the results,\n * call more tools — until it calls `finish` (or a step cap is hit). Mutating\n * tools pass through the injected approval gate, so the same governance holds\n * whether you approve each step interactively or run autonomously with `--auto`.\n *\n * For real multi-step sessions it also: writes an append-only, secret-free\n * **audit record** at the end of every run (governance parity with the\n * single-shot path); **compacts the transcript** so a long session stays under\n * the context-rot threshold that is the whole reason the graph exists; and\n * **guards against no-progress loops** so a model that repeats a failing call\n * stops cleanly instead of burning to the step cap.\n *\n * The model is the only non-deterministic seam (behind the provider list, with\n * fallback). Everything else — the loop, tool execution, gating, compaction,\n * guard, audit — is deterministic and unit-tested with a scripted provider.\n */\n\nimport { buildCodeContext } from './context.js';\nimport { buildAgentMessages } from './prompt.js';\nimport { AGENT_TOOLS, executeTool, type MutatingAction, type ShellResult, type ToolContext, type ToolResult } from './tools.js';\nimport { recordCliCall, CLI_TOOL_ALIASES } from '../engine/savings.js';\nimport type { SymbolSpan } from './apply.js';\nimport type { CodeFs } from './session.js';\nimport type { ChatMessage, FileChange, Provider, ProviderResult, ToolCall, ToolSpec } from './types.js';\nimport type { VgGraph } from '../schema.js';\nimport { redactSecrets } from './providers.js';\n\nexport type AgentEvent =\n | { type: 'assistant'; text: string }\n | { type: 'token'; text: string }\n | { type: 'tool-call'; name: string; args: Record<string, unknown> }\n | { type: 'tool-result'; name: string; content: string; mutated: boolean }\n | { type: 'change'; change: FileChange }\n | { type: 'compact'; droppedRounds: number }\n | { type: 'usage'; promptTokens: number; completionTokens: number }\n | { type: 'verify'; command: string; passed: boolean }\n | { type: 'step'; n: number };\n\nexport interface AgentOptions {\n graph: VgGraph;\n root: string;\n instruction: string;\n providers: Provider[];\n fsImpl: CodeFs;\n /** Run a shell command (injected). */\n run: (command: string) => ShellResult;\n /** Approval gate for mutating actions. */\n approve: (action: MutatingAction) => Promise<boolean>;\n maxSteps?: number;\n budget?: number;\n /** Approx token budget for the running transcript before it is compacted. */\n contextBudget?: number;\n /** Autonomous mode — enforce the command denylist (no human reviews each call). */\n auto?: boolean;\n /** Project-configured extra denylist rules for autonomous commands. */\n denyCommands?: string[];\n /** The project's test/verify command, surfaced to the model. */\n testCommand?: string;\n /** Auto-verify: after the model finishes, run this command and make it fix failures. */\n verify?: { command: string; maxRounds?: number };\n /** Stream assistant tokens as they arrive (emits `token` events). */\n stream?: boolean;\n /** A recap of earlier tasks (from `--continue`) to seed continuity. */\n priorSummary?: string;\n /** External MCP tools the model may also call (already approval-bound). */\n externalTools?: { specs: ToolSpec[]; owns: (name: string) => boolean; execute: (call: ToolCall) => Promise<ToolResult> };\n onEvent?: (e: AgentEvent) => void;\n /** Per-model savings attribution for graph-backed (`search_code`) calls. */\n attribution?: { client: string; provider?: string; model?: string };\n now?: () => number;\n /** Skip the audit record (tests / programmatic dry calls). */\n noAudit?: boolean;\n}\n\nexport type AgentStop = 'finished' | 'max-steps' | 'no-tools' | 'no-progress' | 'error';\n\nexport interface AgentResult {\n finalText: string;\n changes: FileChange[];\n steps: number;\n stopped: AgentStop;\n provider: { id: string; model: string; fellBack: boolean };\n /** Total tokens the model reported over the run (for the cost meter). */\n usage: { promptTokens: number; completionTokens: number };\n}\n\nconst DEFAULT_MAX_STEPS = 24;\n/** Compact the transcript once it grows past this many estimated tokens. */\nconst DEFAULT_CONTEXT_BUDGET = 16_000;\n/** Rounds (assistant + its tool results) to keep verbatim when compacting. */\nconst KEEP_ROUNDS = 8;\n/** After this many identical, non-progressing repeats, nudge the model. */\nconst NUDGE_AT = 3;\n/** After this many, stop the run as no-progress. */\nconst STOP_AT = 5;\n\nexport async function runAgent(options: AgentOptions): Promise<AgentResult> {\n const { graph, root, instruction, providers, fsImpl } = options;\n const maxSteps = options.maxSteps ?? DEFAULT_MAX_STEPS;\n const contextBudget = options.contextBudget ?? DEFAULT_CONTEXT_BUDGET;\n const now = options.now ?? (() => 0);\n const onEvent = options.onEvent ?? (() => {});\n\n const allTools = [...AGENT_TOOLS, ...(options.externalTools?.specs ?? [])];\n const context = buildCodeContext(graph, instruction, { budget: options.budget ?? 3000 });\n const messages: ChatMessage[] = buildAgentMessages(context);\n if (options.priorSummary) {\n messages.push({ role: 'user', content: options.priorSummary });\n }\n if (options.testCommand) {\n messages.push({ role: 'user', content: `When you want to verify a change, the project's test command is: \\`${options.testCommand}\\`` });\n }\n const spans = buildSpanIndex(graph);\n\n const changes: FileChange[] = [];\n const repeats = new Map<string, number>();\n let recordedSearch = false;\n let commandCount = 0;\n let verifyRounds = options.verify?.maxRounds ?? 2;\n const usage = { promptTokens: 0, completionTokens: 0 };\n let providerInfo = { id: providers[0]?.id ?? 'none', model: providers[0]?.model ?? '', fellBack: false };\n\n const ctx: ToolContext = { root, graph, fsImpl, spans, run: options.run, approve: options.approve, auto: options.auto, denyCommands: options.denyCommands };\n\n /** Single terminal path: writes the audit record once, then returns. */\n const finish = (stopped: AgentStop, finalText: string, steps: number): AgentResult => {\n const result: AgentResult = { finalText, changes, steps, stopped, provider: providerInfo, usage };\n if (!options.noAudit) writeAgentAudit(fsImpl, { instruction, providerInfo, changes, commandCount, steps, stopped }, now());\n return result;\n };\n\n /**\n * When the model calls finish: if auto-verify is on, changes were made, and\n * rounds remain, run the verify command. On failure feed the output back and\n * return 'retry' (the loop continues so the model fixes it); otherwise 'done'.\n */\n const verifyOnFinish = (): 'retry' | 'done' => {\n const v = options.verify;\n if (!v || verifyRounds <= 0 || changes.length === 0) return 'done';\n const res = options.run(v.command);\n onEvent({ type: 'verify', command: v.command, passed: res.exitCode === 0 });\n if (res.exitCode === 0) return 'done';\n verifyRounds--;\n messages.push({ role: 'user', content: `The task isn't finished — \\`${v.command}\\` failed (exit ${res.exitCode}):\\n${res.stdout.slice(0, 8000)}\\n\\nFix the failing tests, then call finish again.${verifyRounds === 0 ? ' (last verification attempt)' : ''}` });\n return 'retry';\n };\n\n for (let step = 1; step <= maxSteps; step++) {\n onEvent({ type: 'step', n: step });\n\n // Keep the transcript under the budget: preserve the cache-stable prefix\n // (system + graph context + task) and the recent rounds, summarize the rest.\n const compacted = compact(messages, contextBudget, changes);\n if (compacted.droppedRounds > 0) {\n messages.length = 0;\n messages.push(...compacted.messages);\n onEvent({ type: 'compact', droppedRounds: compacted.droppedRounds });\n }\n\n let result: ProviderResult;\n try {\n const c = await complete(providers, messages, allTools, onEvent, options.stream);\n result = c.result;\n providerInfo = { id: c.provider.id, model: c.provider.model, fellBack: c.fellBack };\n } catch (e) {\n const msg = redactSecrets((e as Error).message);\n onEvent({ type: 'assistant', text: `error: ${msg}` });\n return finish('error', msg, step);\n }\n\n // Accumulate token usage for the cost meter.\n if (result.usage) {\n usage.promptTokens += result.usage.promptTokens ?? 0;\n usage.completionTokens += result.usage.completionTokens ?? 0;\n onEvent({ type: 'usage', promptTokens: result.usage.promptTokens ?? 0, completionTokens: result.usage.completionTokens ?? 0 });\n }\n\n if (result.text) onEvent({ type: 'assistant', text: result.text });\n\n const toolCalls = result.toolCalls ?? [];\n if (toolCalls.length === 0) {\n messages.push({ role: 'assistant', content: result.text });\n return finish('no-tools', result.text, step);\n }\n\n messages.push({ role: 'assistant', content: result.text, toolCalls });\n\n for (const call of toolCalls) {\n onEvent({ type: 'tool-call', name: call.name, args: call.arguments });\n if (call.name === 'search_code' && options.attribution?.client && !recordedSearch) {\n recordedSearch = true;\n recordSearchSaving(root, context, options.attribution, now());\n }\n\n const toolResult = options.externalTools?.owns(call.name) ? await options.externalTools.execute(call) : await executeTool(call, ctx);\n if (call.name === 'run_command' && toolResult.mutated) commandCount++;\n if (toolResult.change) {\n changes.push(toolResult.change);\n onEvent({ type: 'change', change: toolResult.change });\n }\n\n // No-progress guard: a mutating call is progress (reset); a repeated\n // non-mutating identical call accumulates → nudge, then stop.\n const sig = `${call.name}:${stableArgs(call.arguments)}`;\n let content = toolResult.content;\n let stopNoProgress = false;\n if (toolResult.mutated || toolResult.finished) {\n repeats.delete(sig);\n } else {\n const n = (repeats.get(sig) ?? 0) + 1;\n repeats.set(sig, n);\n if (n >= STOP_AT) stopNoProgress = true;\n else if (n >= NUDGE_AT) content += `\\n\\n(note: you have called this exact tool call ${n} times with no change — try a different approach, read more context, or call finish.)`;\n }\n\n onEvent({ type: 'tool-result', name: call.name, content, mutated: toolResult.mutated });\n messages.push({ role: 'tool', content, toolCallId: call.id, name: call.name });\n\n if (toolResult.finished) {\n // Auto-verify: on failure, keep going so the model fixes it.\n if (verifyOnFinish() === 'retry') break;\n return finish('finished', toolResult.finalSummary ?? 'done', step);\n }\n if (stopNoProgress) return finish('no-progress', `stopped: the model repeated \\`${call.name}\\` without making progress`, step);\n }\n }\n return finish('max-steps', 'reached the step limit before finishing', maxSteps);\n}\n\n/** Try providers in order, falling back on transport failure. Throws the last actionable error. */\nasync function complete(\n providers: Provider[],\n messages: ChatMessage[],\n tools: ToolSpec[],\n onEvent: (e: AgentEvent) => void,\n stream?: boolean,\n): Promise<{ result: ProviderResult; provider: Provider; fellBack: boolean }> {\n if (providers.length === 0) throw new Error('no model provider available');\n const onToken = stream ? (t: string): void => onEvent({ type: 'token', text: t }) : undefined;\n let lastErr: unknown;\n for (let i = 0; i < providers.length; i++) {\n try {\n const result = await providers[i].chat(messages, { temperature: 0, tools, stream, onToken });\n return { result, provider: providers[i], fellBack: i > 0 };\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(lastErr instanceof Error ? redactSecrets(lastErr.message) : String(lastErr));\n}\n\n/**\n * Compact the transcript when it exceeds `budget` tokens: keep the first three\n * messages (system + graph context + task — the cache-stable prefix) and the\n * last {@link KEEP_ROUNDS} rounds verbatim, replacing the middle with a short\n * summary. A \"round\" is an assistant turn plus the tool results it triggered, so\n * an assistant/tool pair is never split (which an OpenAI-compatible API rejects).\n */\nexport function compact(messages: ChatMessage[], budget: number, changes: FileChange[]): { messages: ChatMessage[]; droppedRounds: number } {\n if (estimateTokens(messages) <= budget) return { messages, droppedRounds: 0 };\n const head = messages.slice(0, 3);\n const body = messages.slice(3);\n const rounds: ChatMessage[][] = [];\n for (const m of body) {\n if (m.role === 'assistant' || rounds.length === 0) rounds.push([m]);\n else rounds[rounds.length - 1].push(m);\n }\n if (rounds.length <= KEEP_ROUNDS) return { messages, droppedRounds: 0 };\n const dropped = rounds.slice(0, rounds.length - KEEP_ROUNDS);\n const kept = rounds.slice(-KEEP_ROUNDS).flat();\n const toolCalls = dropped.flat().reduce((n, m) => n + (m.role === 'assistant' ? (m.toolCalls?.length ?? 0) : 0), 0);\n const filesChanged = [...new Set(changes.map((c) => c.file))];\n const note: ChatMessage = {\n role: 'user',\n content: `[earlier steps summarized to save context: ${dropped.length} round(s), ${toolCalls} tool call(s) omitted.${filesChanged.length ? ` Files changed so far: ${filesChanged.join(', ')}.` : ''} Continue the task.]`,\n };\n return { messages: [...head, note, ...kept], droppedRounds: dropped.length };\n}\n\nfunction recordSearchSaving(root: string, context: ReturnType<typeof buildCodeContext>, attribution: NonNullable<AgentOptions['attribution']>, ts: number): void {\n const files = new Set(context.seeds.map((s) => s.node.file).filter(Boolean));\n recordCliCall(\n root,\n {\n tool: CLI_TOOL_ALIASES.ask,\n client: attribution.client,\n provider: attribution.provider,\n model: attribution.model,\n outcome: context.seeds.length ? 'complete' : 'miss',\n vgTokens: context.tokensEstimate,\n baselineFiles: files.size,\n },\n ts,\n );\n}\n\n/** An append-only, secret-free audit record for one agent run (no code, no output, no keys). */\nfunction writeAgentAudit(\n fsImpl: CodeFs,\n rec: { instruction: string; providerInfo: { id: string; model: string }; changes: FileChange[]; commandCount: number; steps: number; stopped: AgentStop },\n ts: number,\n): void {\n try {\n fsImpl.appendAudit(\n JSON.stringify({\n ts,\n kind: 'agent',\n instruction: rec.instruction.slice(0, 500),\n provider: rec.providerInfo.id,\n model: rec.providerInfo.model,\n steps: rec.steps,\n stopped: rec.stopped,\n commands: rec.commandCount,\n files: rec.changes.map((c) => ({ file: c.file, statuses: c.outcomes.map((o) => o.status) })),\n }),\n );\n } catch {\n /* audit is best-effort — never fail a run on a logging problem */\n }\n}\n\n/** Deterministic argument signature for the repeat guard (order-independent). */\nfunction stableArgs(args: Record<string, unknown>): string {\n const keys = Object.keys(args).sort();\n return JSON.stringify(keys.map((k) => [k, args[k]]));\n}\n\n/** ~4 chars/token estimate over the transcript, including serialized tool calls. */\nfunction estimateTokens(messages: ChatMessage[]): number {\n let chars = 0;\n for (const m of messages) {\n chars += m.content.length;\n if (m.role === 'assistant' && m.toolCalls) chars += JSON.stringify(m.toolCalls).length;\n }\n return Math.ceil(chars / 4);\n}\n\n/** Per-file symbol spans, so an agent edit lands in the right place when its SEARCH is ambiguous. */\nfunction buildSpanIndex(graph: VgGraph): Map<string, SymbolSpan[]> {\n const map = new Map<string, SymbolSpan[]>();\n for (const n of graph.nodes) {\n if (n.kind === 'file' || n.kind === 'external') continue;\n const file = n.file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n const list = map.get(file) ?? [];\n list.push({ qualifiedName: n.qualifiedName, file, start: n.span.start, end: n.span.end });\n map.set(file, list);\n }\n return map;\n}\n"]}
|