brass-runtime 1.13.4 → 1.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/cli/main.cjs +2022 -0
- package/dist/agent/cli/main.js +184 -184
- package/dist/agent/index.cjs +153 -0
- package/dist/agent/index.js +153 -153
- package/dist/chunk-3IF374MG.js +121 -121
- package/dist/chunk-AC4RFFVX.cjs +407 -0
- package/dist/chunk-DB57UZBE.cjs +2879 -0
- package/dist/chunk-HRVX2IYW.js +345 -345
- package/dist/chunk-KT4IKCIU.cjs +2556 -0
- package/dist/chunk-TGOMLZ65.js +317 -317
- package/dist/http/index.cjs +453 -0
- package/dist/http/index.js +74 -74
- package/dist/index.cjs +855 -0
- package/dist/index.js +340 -340
- package/package.json +6 -8
- package/wasm/pkg/brass_runtime_wasm_engine.d.ts +92 -0
- package/wasm/pkg/brass_runtime_wasm_engine.js +657 -0
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +62 -0
- package/wasm/pkg/package.json +13 -0
- package/dist/agent/cli/main.d.mts +0 -1
- package/dist/agent/index.d.mts +0 -688
- package/dist/effect-ISvXPLgc.d.mts +0 -797
- package/dist/http/index.d.mts +0 -154
- package/dist/index.d.mts +0 -258
- package/dist/stream-C0-LWnUP.d.mts +0 -66
package/dist/agent/cli/main.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
import {
|
|
3
|
+
NodeShell,
|
|
4
|
+
autoApproveApprovals,
|
|
5
|
+
discoverNodeWorkspaceRoot,
|
|
6
|
+
goalForAgentPreset,
|
|
7
|
+
isAgentPreset,
|
|
8
|
+
loadNodeAgentConfig,
|
|
9
|
+
makeAutoDenyApprovals,
|
|
10
|
+
makeConfiguredPermissions,
|
|
11
|
+
makeFakeLLM,
|
|
12
|
+
makeGoogleGenerativeAILLM,
|
|
13
|
+
makeNodeFileSystem,
|
|
14
|
+
makeNodePatchService,
|
|
15
|
+
makeOpenAICompatibleLLM,
|
|
16
|
+
observationStatus,
|
|
17
|
+
runAgent,
|
|
18
|
+
summarizeAgentAction,
|
|
19
|
+
summarizeAgentObservation
|
|
20
|
+
} from "../../chunk-HRVX2IYW.js";
|
|
21
|
+
import {
|
|
22
|
+
Cause,
|
|
23
|
+
Exit,
|
|
24
|
+
Runtime,
|
|
25
|
+
async
|
|
26
|
+
} from "../../chunk-TGOMLZ65.js";
|
|
27
27
|
|
|
28
28
|
// src/agent/cli/approvals.ts
|
|
29
29
|
var dynamicImport = new Function("specifier", "return import(specifier)");
|
|
@@ -39,35 +39,35 @@ var answerToResponse = (answer, request) => {
|
|
|
39
39
|
return { type: "rejected", reason: `Unrecognized approval answer: ${answer}` };
|
|
40
40
|
};
|
|
41
41
|
var makeCliApprovalService = (options = {}) => ({
|
|
42
|
-
request: (request) =>
|
|
42
|
+
request: (request) => async((_env, cb) => {
|
|
43
43
|
let closed = false;
|
|
44
44
|
let rl;
|
|
45
45
|
dynamicImport("node:readline/promises").then(({ createInterface }) => {
|
|
46
46
|
if (closed) return void 0;
|
|
47
|
-
const input =
|
|
48
|
-
const output =
|
|
47
|
+
const input = options.input ?? process.stdin;
|
|
48
|
+
const output = options.output ?? process.stderr ?? process.stdout;
|
|
49
49
|
const defaultHint = request.defaultAnswer === "approve" ? "Y/n" : "y/N";
|
|
50
50
|
rl = createInterface({ input, output });
|
|
51
|
-
|
|
51
|
+
output?.write?.(`
|
|
52
52
|
Approval required (${request.risk})
|
|
53
|
-
`)
|
|
54
|
-
|
|
55
|
-
`)
|
|
56
|
-
|
|
57
|
-
`)
|
|
53
|
+
`);
|
|
54
|
+
output?.write?.(`Action: ${summarizeAgentAction(request.action)}
|
|
55
|
+
`);
|
|
56
|
+
output?.write?.(`Reason: ${request.reason}
|
|
57
|
+
`);
|
|
58
58
|
return rl.question(`Approve? [${defaultHint}] `);
|
|
59
59
|
}).then((answer) => {
|
|
60
60
|
if (answer === void 0 || closed) return;
|
|
61
61
|
closed = true;
|
|
62
|
-
|
|
63
|
-
cb(
|
|
62
|
+
rl?.close?.();
|
|
63
|
+
cb(Exit.succeed(answerToResponse(answer, request)));
|
|
64
64
|
}).catch((cause) => {
|
|
65
65
|
if (closed) return;
|
|
66
66
|
closed = true;
|
|
67
|
-
|
|
67
|
+
rl?.close?.();
|
|
68
68
|
cb(
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
Exit.failCause(
|
|
70
|
+
Cause.fail({
|
|
71
71
|
_tag: "AgentLoopError",
|
|
72
72
|
message: `Approval prompt failed: ${String(cause)}`
|
|
73
73
|
})
|
|
@@ -77,55 +77,55 @@ Approval required (${request.risk})
|
|
|
77
77
|
return () => {
|
|
78
78
|
if (closed) return;
|
|
79
79
|
closed = true;
|
|
80
|
-
|
|
80
|
+
rl?.close?.();
|
|
81
81
|
};
|
|
82
82
|
})
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
// src/agent/cli/doctor.ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
87
|
+
import { access, constants } from "fs/promises";
|
|
88
|
+
import { join, resolve } from "path";
|
|
89
|
+
import { spawnSync } from "child_process";
|
|
90
90
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
91
91
|
var readJsonFile = (path) => {
|
|
92
92
|
try {
|
|
93
|
-
return JSON.parse(
|
|
94
|
-
} catch
|
|
93
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
94
|
+
} catch {
|
|
95
95
|
return void 0;
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
var findPackageRoot = (start, packageName) => {
|
|
99
|
-
let current =
|
|
99
|
+
let current = resolve(start);
|
|
100
100
|
while (true) {
|
|
101
|
-
const packageJsonPath =
|
|
101
|
+
const packageJsonPath = join(current, "package.json");
|
|
102
102
|
const json = readJsonFile(packageJsonPath);
|
|
103
103
|
if (isRecord(json) && json.name === packageName) return current;
|
|
104
|
-
const parent =
|
|
104
|
+
const parent = resolve(current, "..");
|
|
105
105
|
if (parent === current) return void 0;
|
|
106
106
|
current = parent;
|
|
107
107
|
}
|
|
108
108
|
};
|
|
109
109
|
var commandVersion = (command, args = ["--version"], cwd) => {
|
|
110
|
-
const result =
|
|
110
|
+
const result = spawnSync(command, [...args], {
|
|
111
111
|
cwd,
|
|
112
112
|
encoding: "utf8",
|
|
113
113
|
shell: false,
|
|
114
114
|
timeout: 1e4
|
|
115
115
|
});
|
|
116
|
-
if (result.error || (
|
|
117
|
-
return `${
|
|
116
|
+
if (result.error || (result.status ?? 0) !== 0) return void 0;
|
|
117
|
+
return `${result.stdout ?? ""}${result.stderr ?? ""}`.trim().split(/\r?\n/g)[0];
|
|
118
118
|
};
|
|
119
119
|
var hasEnv = (name) => Boolean(name && process.env[name]);
|
|
120
120
|
var launchedFromVsCodeExtension = () => process.env.BRASS_AGENT_VSCODE_EXTENSION === "1";
|
|
121
121
|
var packageManagerFromWorkspace = (cwd) => {
|
|
122
|
-
const packageJson = readJsonFile(
|
|
122
|
+
const packageJson = readJsonFile(join(cwd, "package.json"));
|
|
123
123
|
const packageManager = isRecord(packageJson) && typeof packageJson.packageManager === "string" ? packageJson.packageManager.split("@")[0] : void 0;
|
|
124
124
|
if (packageManager) return { manager: packageManager, source: "package.json packageManager" };
|
|
125
|
-
if (
|
|
126
|
-
if (
|
|
127
|
-
if (
|
|
128
|
-
if (
|
|
125
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return { manager: "pnpm", source: "pnpm-lock.yaml" };
|
|
126
|
+
if (existsSync(join(cwd, "yarn.lock"))) return { manager: "yarn", source: "yarn.lock" };
|
|
127
|
+
if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock"))) return { manager: "bun", source: "bun lockfile" };
|
|
128
|
+
if (existsSync(join(cwd, "package-lock.json")) || existsSync(join(cwd, "npm-shrinkwrap.json"))) return { manager: "npm", source: "npm lockfile" };
|
|
129
129
|
return { manager: "npm", source: "fallback" };
|
|
130
130
|
};
|
|
131
131
|
var packageScripts = (packageJson) => isRecord(packageJson) && isRecord(packageJson.scripts) ? Object.entries(packageJson.scripts).filter(([, value]) => typeof value === "string").map(([name]) => name).sort() : [];
|
|
@@ -145,7 +145,7 @@ var projectProfileCheck = (cwd, packageJson) => {
|
|
|
145
145
|
"turbo.json",
|
|
146
146
|
"nx.json",
|
|
147
147
|
"pnpm-workspace.yaml"
|
|
148
|
-
].filter((path) =>
|
|
148
|
+
].filter((path) => existsSync(join(cwd, path)));
|
|
149
149
|
const stacks = [];
|
|
150
150
|
if (isRecord(packageJson)) stacks.push("node");
|
|
151
151
|
if (markers.some((marker) => marker === "Cargo.toml" || marker === "Cargo.lock" || marker.endsWith("Cargo.toml"))) stacks.push("rust");
|
|
@@ -222,8 +222,8 @@ var envFileCheck = (load) => {
|
|
|
222
222
|
};
|
|
223
223
|
};
|
|
224
224
|
var llmCheck = (config) => {
|
|
225
|
-
const provider =
|
|
226
|
-
const configuredApiKeyEnv =
|
|
225
|
+
const provider = (process.env.BRASS_LLM_PROVIDER ?? config?.llm?.provider)?.trim().toLowerCase();
|
|
226
|
+
const configuredApiKeyEnv = config?.llm?.apiKeyEnv;
|
|
227
227
|
if (provider === "fake") {
|
|
228
228
|
return {
|
|
229
229
|
id: "llm",
|
|
@@ -242,7 +242,7 @@ var llmCheck = (config) => {
|
|
|
242
242
|
};
|
|
243
243
|
}
|
|
244
244
|
if (provider === "openai" || provider === "openai-compatible") {
|
|
245
|
-
const endpointPresent = Boolean(
|
|
245
|
+
const endpointPresent = Boolean(process.env.BRASS_LLM_ENDPOINT ?? config?.llm?.endpoint);
|
|
246
246
|
const keyPresent = hasEnv(configuredApiKeyEnv) || hasEnv("BRASS_LLM_API_KEY");
|
|
247
247
|
return {
|
|
248
248
|
id: "llm",
|
|
@@ -259,7 +259,7 @@ var llmCheck = (config) => {
|
|
|
259
259
|
message: "Google/Gemini credentials are available and will be auto-detected."
|
|
260
260
|
};
|
|
261
261
|
}
|
|
262
|
-
if ((
|
|
262
|
+
if ((process.env.BRASS_LLM_ENDPOINT ?? config?.llm?.endpoint) && hasEnv("BRASS_LLM_API_KEY")) {
|
|
263
263
|
return {
|
|
264
264
|
id: "llm",
|
|
265
265
|
label: "LLM provider",
|
|
@@ -275,26 +275,26 @@ var llmCheck = (config) => {
|
|
|
275
275
|
};
|
|
276
276
|
};
|
|
277
277
|
var workspaceSettingsCommand = (cwd) => {
|
|
278
|
-
const settings = readJsonFile(
|
|
278
|
+
const settings = readJsonFile(join(cwd, ".vscode", "settings.json"));
|
|
279
279
|
if (!isRecord(settings)) return void 0;
|
|
280
280
|
const command = settings["brassAgent.command"];
|
|
281
281
|
return typeof command === "string" ? command : void 0;
|
|
282
282
|
};
|
|
283
283
|
var newestVsix = (extensionDir) => {
|
|
284
284
|
try {
|
|
285
|
-
return
|
|
286
|
-
} catch
|
|
285
|
+
return readdirSync(extensionDir).filter((name) => name.endsWith(".vsix")).sort().at(-1);
|
|
286
|
+
} catch {
|
|
287
287
|
return void 0;
|
|
288
288
|
}
|
|
289
289
|
};
|
|
290
290
|
var push = (checks, check) => {
|
|
291
291
|
checks.push(check);
|
|
292
292
|
};
|
|
293
|
-
var runAgentDoctor =
|
|
294
|
-
const cwd =
|
|
293
|
+
var runAgentDoctor = async (options) => {
|
|
294
|
+
const cwd = resolve(options.cwd);
|
|
295
295
|
const checks = [];
|
|
296
|
-
const repoRoot =
|
|
297
|
-
const nodeMajor = Number(
|
|
296
|
+
const repoRoot = findPackageRoot(cwd, "brass-runtime") ?? findPackageRoot(process.cwd(), "brass-runtime");
|
|
297
|
+
const nodeMajor = Number(process.versions.node.split(".")[0] ?? "0");
|
|
298
298
|
push(checks, {
|
|
299
299
|
id: "node",
|
|
300
300
|
label: "Node.js",
|
|
@@ -325,8 +325,8 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
325
325
|
push(checks, {
|
|
326
326
|
id: "workspace",
|
|
327
327
|
label: "Workspace",
|
|
328
|
-
status:
|
|
329
|
-
message:
|
|
328
|
+
status: existsSync(cwd) ? "ok" : "fail",
|
|
329
|
+
message: existsSync(cwd) ? cwd : `Workspace does not exist: ${cwd}`
|
|
330
330
|
});
|
|
331
331
|
if (options.workspaceDiscovery) {
|
|
332
332
|
const discovery = options.workspaceDiscovery;
|
|
@@ -337,7 +337,7 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
337
337
|
message: discovery.disabled ? "Workspace discovery disabled by --no-discover-workspace." : discovery.marker ? `${discovery.changed ? `Resolved ${discovery.inputCwd} -> ${discovery.cwd}` : `Using ${discovery.cwd}`} via ${discovery.marker}.` : `No workspace marker found upward from ${discovery.inputCwd}; using input cwd.`
|
|
338
338
|
});
|
|
339
339
|
}
|
|
340
|
-
const packageJsonPath =
|
|
340
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
341
341
|
const packageJson = readJsonFile(packageJsonPath);
|
|
342
342
|
push(checks, {
|
|
343
343
|
id: "workspace.packageJson",
|
|
@@ -372,7 +372,7 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
372
372
|
message: options.configPath ? `Loaded ${options.configPath}` : "No .brass-agent.json / brass-agent.config.json loaded; using built-in defaults and VS Code/CLI settings."
|
|
373
373
|
});
|
|
374
374
|
if (options.includeVsCode !== false) {
|
|
375
|
-
const codeVersion = commandVersion(
|
|
375
|
+
const codeVersion = commandVersion(process.env.BRASS_CODE_CMD ?? "code");
|
|
376
376
|
push(checks, {
|
|
377
377
|
id: "vscode.code",
|
|
378
378
|
label: "VS Code CLI",
|
|
@@ -385,13 +385,13 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
385
385
|
id: "vscode.settings",
|
|
386
386
|
label: "VS Code extension setting",
|
|
387
387
|
status: configured ? "ok" : launchedByExtension ? "skip" : "warn",
|
|
388
|
-
message: configured ? `brassAgent.command = ${configured}` : launchedByExtension ? `No workspace brassAgent.command needed; launched by the VS Code extension (${
|
|
388
|
+
message: configured ? `brassAgent.command = ${configured}` : launchedByExtension ? `No workspace brassAgent.command needed; launched by the VS Code extension (${process.env.BRASS_AGENT_VSCODE_CLI_SOURCE ?? "auto"}).` : "No workspace .vscode/settings.json brassAgent.command found."
|
|
389
389
|
});
|
|
390
390
|
}
|
|
391
391
|
if (repoRoot) {
|
|
392
|
-
const cliSource =
|
|
393
|
-
const cliBuild =
|
|
394
|
-
const extensionDir =
|
|
392
|
+
const cliSource = join(repoRoot, "src", "agent", "cli", "main.ts");
|
|
393
|
+
const cliBuild = join(repoRoot, "dist", "agent", "cli", "main.cjs");
|
|
394
|
+
const extensionDir = join(repoRoot, "extensions", "vscode-brass-agent");
|
|
395
395
|
push(checks, {
|
|
396
396
|
id: "repo.root",
|
|
397
397
|
label: "brass-runtime repo",
|
|
@@ -401,26 +401,26 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
401
401
|
push(checks, {
|
|
402
402
|
id: "repo.cliSource",
|
|
403
403
|
label: "CLI source",
|
|
404
|
-
status:
|
|
405
|
-
message:
|
|
404
|
+
status: existsSync(cliSource) ? "ok" : "fail",
|
|
405
|
+
message: existsSync(cliSource) ? `Found ${cliSource}` : `Missing ${cliSource}`
|
|
406
406
|
});
|
|
407
407
|
push(checks, {
|
|
408
408
|
id: "repo.cliBuild",
|
|
409
409
|
label: "CLI build",
|
|
410
|
-
status:
|
|
411
|
-
message:
|
|
410
|
+
status: existsSync(cliBuild) ? "ok" : "warn",
|
|
411
|
+
message: existsSync(cliBuild) ? `Found ${cliBuild}` : "dist/agent/cli/main.cjs is missing; run npm run build."
|
|
412
412
|
});
|
|
413
413
|
push(checks, {
|
|
414
414
|
id: "repo.extensionDir",
|
|
415
415
|
label: "VS Code extension source",
|
|
416
|
-
status:
|
|
417
|
-
message:
|
|
416
|
+
status: existsSync(join(extensionDir, "package.json")) ? "ok" : "warn",
|
|
417
|
+
message: existsSync(join(extensionDir, "package.json")) ? extensionDir : "extensions/vscode-brass-agent was not found."
|
|
418
418
|
});
|
|
419
419
|
push(checks, {
|
|
420
420
|
id: "repo.extensionBuild",
|
|
421
421
|
label: "VS Code extension build",
|
|
422
|
-
status:
|
|
423
|
-
message:
|
|
422
|
+
status: existsSync(join(extensionDir, "out", "extension.js")) ? "ok" : "warn",
|
|
423
|
+
message: existsSync(join(extensionDir, "out", "extension.js")) ? "out/extension.js exists." : "Extension output missing; run npm run agent:vscode:package or compile the extension."
|
|
424
424
|
});
|
|
425
425
|
const vsix = newestVsix(extensionDir);
|
|
426
426
|
push(checks, {
|
|
@@ -429,7 +429,7 @@ var runAgentDoctor = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
429
429
|
status: vsix ? "ok" : "warn",
|
|
430
430
|
message: vsix ? `Found ${vsix}` : "No .vsix found in extensions/vscode-brass-agent."
|
|
431
431
|
});
|
|
432
|
-
const cliReadable = await
|
|
432
|
+
const cliReadable = await access(cliBuild, constants.R_OK).then(() => true).catch(() => false);
|
|
433
433
|
push(checks, {
|
|
434
434
|
id: "repo.cliReadable",
|
|
435
435
|
label: "CLI artifact readable",
|
|
@@ -479,8 +479,8 @@ var printAgentDoctorReport = (report) => {
|
|
|
479
479
|
};
|
|
480
480
|
|
|
481
481
|
// src/agent/cli/envFile.ts
|
|
482
|
-
|
|
483
|
-
|
|
482
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
483
|
+
import { isAbsolute, join as join2, resolve as resolve2 } from "path";
|
|
484
484
|
var DEFAULT_AGENT_ENV_FILE_NAMES = [".brass-agent.env", ".env.local", ".env"];
|
|
485
485
|
var BASE_ALLOWED_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
486
486
|
"BRASS_LLM_PROVIDER",
|
|
@@ -519,20 +519,20 @@ var parseEnvLine = (line) => {
|
|
|
519
519
|
const withoutExport = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trimStart() : trimmed;
|
|
520
520
|
const match = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(withoutExport);
|
|
521
521
|
if (!match) return { type: "invalid" };
|
|
522
|
-
const key =
|
|
523
|
-
const rawValue =
|
|
522
|
+
const key = match[1] ?? "";
|
|
523
|
+
const rawValue = match[2] ?? "";
|
|
524
524
|
const compact = rawValue.trim();
|
|
525
525
|
const quoted = parseQuotedValue(compact);
|
|
526
|
-
const value =
|
|
526
|
+
const value = quoted ?? compact.replace(/\s+#.*$/u, "").trim();
|
|
527
527
|
return { type: "assignment", key, value };
|
|
528
528
|
};
|
|
529
529
|
var candidatePaths = (cwd, envFile) => {
|
|
530
|
-
if (envFile) return [
|
|
531
|
-
return DEFAULT_AGENT_ENV_FILE_NAMES.map((name) =>
|
|
530
|
+
if (envFile) return [isAbsolute(envFile) ? envFile : resolve2(cwd, envFile)];
|
|
531
|
+
return DEFAULT_AGENT_ENV_FILE_NAMES.map((name) => join2(cwd, name));
|
|
532
532
|
};
|
|
533
533
|
var loadAgentEnvFile = (options) => {
|
|
534
|
-
const cwd =
|
|
535
|
-
const extraKeys =
|
|
534
|
+
const cwd = resolve2(options.cwd);
|
|
535
|
+
const extraKeys = options.allowedExtraKeys?.filter(Boolean) ?? [];
|
|
536
536
|
const allowedKeys = /* @__PURE__ */ new Set([...BASE_ALLOWED_ENV_KEYS, ...extraKeys]);
|
|
537
537
|
const files = options.noEnvFile ? [] : candidatePaths(cwd, options.envFile);
|
|
538
538
|
const paths = [];
|
|
@@ -557,14 +557,14 @@ var loadAgentEnvFile = (options) => {
|
|
|
557
557
|
};
|
|
558
558
|
}
|
|
559
559
|
for (const path of files) {
|
|
560
|
-
if (!
|
|
560
|
+
if (!existsSync2(path)) {
|
|
561
561
|
if (options.envFile) errors.push(`Env file does not exist: ${path}`);
|
|
562
562
|
continue;
|
|
563
563
|
}
|
|
564
564
|
paths.push(path);
|
|
565
565
|
let raw;
|
|
566
566
|
try {
|
|
567
|
-
raw =
|
|
567
|
+
raw = readFileSync2(path, "utf8").replace(/^\uFEFF/u, "");
|
|
568
568
|
} catch (error) {
|
|
569
569
|
errors.push(`Could not read env file ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
570
570
|
continue;
|
|
@@ -595,7 +595,7 @@ var loadAgentEnvFile = (options) => {
|
|
|
595
595
|
return {
|
|
596
596
|
cwd,
|
|
597
597
|
disabled: false,
|
|
598
|
-
...options.envFile ? { explicitPath:
|
|
598
|
+
...options.envFile ? { explicitPath: isAbsolute(options.envFile) ? options.envFile : resolve2(cwd, options.envFile) } : {},
|
|
599
599
|
filesChecked: files,
|
|
600
600
|
paths,
|
|
601
601
|
loadedKeys: unique(loadedKeys),
|
|
@@ -608,36 +608,36 @@ var loadAgentEnvFile = (options) => {
|
|
|
608
608
|
};
|
|
609
609
|
|
|
610
610
|
// src/agent/cli/init.ts
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
611
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
612
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
613
|
+
import { dirname, join as join3, resolve as resolve3 } from "path";
|
|
614
614
|
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
615
615
|
var readJsonFile2 = (path) => {
|
|
616
616
|
try {
|
|
617
|
-
return JSON.parse(
|
|
618
|
-
} catch
|
|
617
|
+
return JSON.parse(readFileSync3(path, "utf8"));
|
|
618
|
+
} catch {
|
|
619
619
|
return void 0;
|
|
620
620
|
}
|
|
621
621
|
};
|
|
622
622
|
var readPackageJson = (cwd) => {
|
|
623
|
-
const json = readJsonFile2(
|
|
623
|
+
const json = readJsonFile2(join3(cwd, "package.json"));
|
|
624
624
|
return isRecord2(json) ? json : void 0;
|
|
625
625
|
};
|
|
626
626
|
var scriptNames = (packageJson) => {
|
|
627
|
-
const scripts =
|
|
627
|
+
const scripts = packageJson?.scripts;
|
|
628
628
|
if (!isRecord2(scripts)) return [];
|
|
629
629
|
return Object.entries(scripts).filter(([, value]) => typeof value === "string").map(([name]) => name).sort();
|
|
630
630
|
};
|
|
631
631
|
var hasAnyScript = (scripts, candidates) => candidates.some((candidate) => scripts.includes(candidate));
|
|
632
632
|
var inferPackageManager = (cwd, packageJson) => {
|
|
633
|
-
const packageManager = typeof
|
|
633
|
+
const packageManager = typeof packageJson?.packageManager === "string" ? packageJson.packageManager.split("@")[0] : void 0;
|
|
634
634
|
if (packageManager === "npm" || packageManager === "pnpm" || packageManager === "yarn" || packageManager === "bun") {
|
|
635
635
|
return packageManager;
|
|
636
636
|
}
|
|
637
|
-
if (
|
|
638
|
-
if (
|
|
639
|
-
if (
|
|
640
|
-
if (
|
|
637
|
+
if (existsSync3(join3(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
638
|
+
if (existsSync3(join3(cwd, "yarn.lock"))) return "yarn";
|
|
639
|
+
if (existsSync3(join3(cwd, "bun.lockb")) || existsSync3(join3(cwd, "bun.lock"))) return "bun";
|
|
640
|
+
if (existsSync3(join3(cwd, "package-lock.json")) || existsSync3(join3(cwd, "npm-shrinkwrap.json"))) return "npm";
|
|
641
641
|
return "auto";
|
|
642
642
|
};
|
|
643
643
|
var llmConfigForProfile = (profile) => {
|
|
@@ -877,13 +877,13 @@ var nextStepsForProfile = (profile) => {
|
|
|
877
877
|
}
|
|
878
878
|
return steps;
|
|
879
879
|
};
|
|
880
|
-
var writeInitFile =
|
|
881
|
-
const path =
|
|
882
|
-
const exists =
|
|
880
|
+
var writeInitFile = async (options) => {
|
|
881
|
+
const path = resolve3(options.cwd, options.relativePath);
|
|
882
|
+
const exists = existsSync3(path);
|
|
883
883
|
const status = exists ? options.force ? "overwritten" : "skipped" : "created";
|
|
884
884
|
if (!options.dryRun && status !== "skipped") {
|
|
885
|
-
await
|
|
886
|
-
await
|
|
885
|
+
await mkdir(dirname(path), { recursive: true });
|
|
886
|
+
await writeFile(path, options.content, "utf8");
|
|
887
887
|
}
|
|
888
888
|
return {
|
|
889
889
|
path,
|
|
@@ -892,11 +892,11 @@ var writeInitFile = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
892
892
|
bytes: Buffer.byteLength(options.content, "utf8")
|
|
893
893
|
};
|
|
894
894
|
};
|
|
895
|
-
var initializeAgentWorkspace =
|
|
896
|
-
const cwd =
|
|
897
|
-
const profile =
|
|
898
|
-
const force =
|
|
899
|
-
const dryRun =
|
|
895
|
+
var initializeAgentWorkspace = async (options) => {
|
|
896
|
+
const cwd = resolve3(options.cwd);
|
|
897
|
+
const profile = options.profile ?? "default";
|
|
898
|
+
const force = options.force ?? false;
|
|
899
|
+
const dryRun = options.dryRun ?? false;
|
|
900
900
|
const config = buildAgentConfig(cwd, profile);
|
|
901
901
|
const files = await Promise.all([
|
|
902
902
|
writeInitFile({
|
|
@@ -964,7 +964,7 @@ var printAgentInitResult = (result) => {
|
|
|
964
964
|
|
|
965
965
|
// src/agent/cli/main.ts
|
|
966
966
|
var dynamicImport2 = new Function("specifier", "return import(specifier)");
|
|
967
|
-
var readPatchFile =
|
|
967
|
+
var readPatchFile = async (cwd, patchFile) => {
|
|
968
968
|
const nodePath = await dynamicImport2("node:path");
|
|
969
969
|
const nodeFs = await dynamicImport2("node:fs/promises");
|
|
970
970
|
return nodeFs.readFile(nodePath.resolve(cwd, patchFile), "utf8");
|
|
@@ -1098,7 +1098,7 @@ var parseCliArgs = (argv) => {
|
|
|
1098
1098
|
}
|
|
1099
1099
|
if (arg === "--preset" || arg.startsWith("--preset=")) {
|
|
1100
1100
|
const [value, nextIndex] = readFlagValue(argv, index, "--preset");
|
|
1101
|
-
if (!
|
|
1101
|
+
if (!isAgentPreset(value)) {
|
|
1102
1102
|
throw new Error("--preset requires one of: fix-tests, inspect, typecheck, lint");
|
|
1103
1103
|
}
|
|
1104
1104
|
preset = value;
|
|
@@ -1274,7 +1274,7 @@ var parseBatchGoal = (value, path) => {
|
|
|
1274
1274
|
if (cwd !== void 0 && typeof cwd !== "string") throw new Error(`${path}.cwd must be a string.`);
|
|
1275
1275
|
if (patchFile !== void 0 && typeof patchFile !== "string") throw new Error(`${path}.patchFile must be a string.`);
|
|
1276
1276
|
if (saveRunDir !== void 0 && typeof saveRunDir !== "string") throw new Error(`${path}.saveRunDir must be a string.`);
|
|
1277
|
-
if (preset !== void 0 && (typeof preset !== "string" || !
|
|
1277
|
+
if (preset !== void 0 && (typeof preset !== "string" || !isAgentPreset(preset))) {
|
|
1278
1278
|
throw new Error(`${path}.preset must be one of: fix-tests, inspect, typecheck, lint.`);
|
|
1279
1279
|
}
|
|
1280
1280
|
if (mode !== void 0 && (typeof mode !== "string" || !isAgentMode(mode))) {
|
|
@@ -1301,7 +1301,7 @@ var parseBatchGoalsJson = (value) => {
|
|
|
1301
1301
|
if (!rawGoals) throw new Error("Batch file must be a JSON array or an object with a goals array.");
|
|
1302
1302
|
return rawGoals.map((goal, index) => parseBatchGoal(goal, `goals[${index}]`));
|
|
1303
1303
|
};
|
|
1304
|
-
var readBatchFile =
|
|
1304
|
+
var readBatchFile = async (cwd, batchFile) => {
|
|
1305
1305
|
const nodePath = await dynamicImport2("node:path");
|
|
1306
1306
|
const nodeFs = await dynamicImport2("node:fs/promises");
|
|
1307
1307
|
const path = nodePath.isAbsolute(batchFile) ? batchFile : nodePath.resolve(cwd, batchFile);
|
|
@@ -1318,21 +1318,21 @@ var readBatchFile = _chunkTGOMLZ65js.async.call(void 0, cwd, batchFile) => {
|
|
|
1318
1318
|
var resolveBatchGoalText = (item, fallbackPatchFile) => {
|
|
1319
1319
|
if (typeof item === "string") return item;
|
|
1320
1320
|
if (item.goal) return item.goal;
|
|
1321
|
-
if (item.preset) return
|
|
1322
|
-
if (
|
|
1321
|
+
if (item.preset) return goalForAgentPreset(item.preset);
|
|
1322
|
+
if (item.patchFile ?? fallbackPatchFile) return "apply supplied patch";
|
|
1323
1323
|
return "";
|
|
1324
1324
|
};
|
|
1325
1325
|
var resolveBatchMode = (item, parsed, config) => {
|
|
1326
1326
|
if (typeof item !== "string" && item.mode) return item.mode;
|
|
1327
1327
|
if (typeof item !== "string" && item.preset === "inspect" && !parsed.modeSpecified) return "read-only";
|
|
1328
|
-
return parsed.modeSpecified ? parsed.mode :
|
|
1328
|
+
return parsed.modeSpecified ? parsed.mode : config.mode ?? parsed.mode;
|
|
1329
1329
|
};
|
|
1330
1330
|
var resolveBatchRuns = (items, parsed, config) => items.map((item, index) => {
|
|
1331
1331
|
const goalText = resolveBatchGoalText(item, parsed.patchFile);
|
|
1332
|
-
const cwd = typeof item === "string" ? parsed.cwd :
|
|
1333
|
-
const patchFile = typeof item === "string" ? parsed.patchFile :
|
|
1334
|
-
const patchFileMode = typeof item === "string" ? parsed.patchFileMode :
|
|
1335
|
-
const saveRunDir = typeof item === "string" ? parsed.saveRunDir :
|
|
1332
|
+
const cwd = typeof item === "string" ? parsed.cwd : item.cwd ?? parsed.cwd;
|
|
1333
|
+
const patchFile = typeof item === "string" ? parsed.patchFile : item.patchFile ?? parsed.patchFile;
|
|
1334
|
+
const patchFileMode = typeof item === "string" ? parsed.patchFileMode : item.patchFileMode ?? parsed.patchFileMode;
|
|
1335
|
+
const saveRunDir = typeof item === "string" ? parsed.saveRunDir : item.saveRunDir ?? parsed.saveRunDir;
|
|
1336
1336
|
if (!goalText) throw new Error(`Batch goal ${index + 1} resolved to an empty goal.`);
|
|
1337
1337
|
return {
|
|
1338
1338
|
index,
|
|
@@ -1344,8 +1344,8 @@ var resolveBatchRuns = (items, parsed, config) => items.map((item, index) => {
|
|
|
1344
1344
|
...saveRunDir ? { saveRunDir } : {}
|
|
1345
1345
|
};
|
|
1346
1346
|
});
|
|
1347
|
-
var resolveParsedConfig =
|
|
1348
|
-
const workspaceDiscovery =
|
|
1347
|
+
var resolveParsedConfig = async (parsed) => {
|
|
1348
|
+
const workspaceDiscovery = discoverNodeWorkspaceRoot(parsed.cwd, {
|
|
1349
1349
|
enabled: parsed.discoverWorkspace
|
|
1350
1350
|
});
|
|
1351
1351
|
const cwdResolved = workspaceDiscovery.cwd;
|
|
@@ -1353,7 +1353,7 @@ var resolveParsedConfig = _chunkTGOMLZ65js.async.call(void 0, parsed) => {
|
|
|
1353
1353
|
...parsed,
|
|
1354
1354
|
cwd: cwdResolved
|
|
1355
1355
|
};
|
|
1356
|
-
const loaded = await
|
|
1356
|
+
const loaded = await loadNodeAgentConfig({
|
|
1357
1357
|
cwd: cwdResolved,
|
|
1358
1358
|
configPath: parsed.configPath,
|
|
1359
1359
|
noConfig: parsed.noConfig
|
|
@@ -1362,20 +1362,20 @@ var resolveParsedConfig = _chunkTGOMLZ65js.async.call(void 0, parsed) => {
|
|
|
1362
1362
|
cwd: cwdResolved,
|
|
1363
1363
|
envFile: parsed.envFile,
|
|
1364
1364
|
noEnvFile: parsed.noEnvFile,
|
|
1365
|
-
allowedExtraKeys:
|
|
1365
|
+
allowedExtraKeys: loaded.config.llm?.apiKeyEnv ? [loaded.config.llm.apiKeyEnv] : []
|
|
1366
1366
|
});
|
|
1367
1367
|
const shouldUseConfigBatch = !parsed.goalText && !parsed.preset && !parsed.patchFile;
|
|
1368
|
-
const batchItems = parsed.batchFile ? await readBatchFile(cwdResolved, parsed.batchFile) : shouldUseConfigBatch ?
|
|
1368
|
+
const batchItems = parsed.batchFile ? await readBatchFile(cwdResolved, parsed.batchFile) : shouldUseConfigBatch ? loaded.config.batch?.goals ?? [] : [];
|
|
1369
1369
|
const batchRuns = resolveBatchRuns(batchItems, parsedAtWorkspace, loaded.config);
|
|
1370
1370
|
return {
|
|
1371
1371
|
...parsedAtWorkspace,
|
|
1372
|
-
goalText: parsed.goalText || (parsed.preset ?
|
|
1373
|
-
mode: parsed.modeSpecified ? parsed.mode : parsed.preset === "inspect" ? "read-only" :
|
|
1374
|
-
approval: parsed.approvalSpecified ? parsed.approval :
|
|
1372
|
+
goalText: parsed.goalText || (parsed.preset ? goalForAgentPreset(parsed.preset) : parsed.patchFile ? "apply supplied patch" : parsed.goalText),
|
|
1373
|
+
mode: parsed.modeSpecified ? parsed.mode : parsed.preset === "inspect" ? "read-only" : loaded.config.mode ?? parsed.mode,
|
|
1374
|
+
approval: parsed.approvalSpecified ? parsed.approval : loaded.config.approval ?? parsed.approval,
|
|
1375
1375
|
config: loaded.config,
|
|
1376
1376
|
workspaceDiscovery,
|
|
1377
1377
|
batchRuns,
|
|
1378
|
-
batchStopOnFailureResolved:
|
|
1378
|
+
batchStopOnFailureResolved: parsed.batchStopOnFailure ?? loaded.config.batch?.stopOnFailure ?? parsed.ci,
|
|
1379
1379
|
envFileLoad,
|
|
1380
1380
|
...loaded.path ? { resolvedConfigPath: loaded.path } : {}
|
|
1381
1381
|
};
|
|
@@ -1491,32 +1491,32 @@ var printHelp = () => {
|
|
|
1491
1491
|
};
|
|
1492
1492
|
var envByName = (name) => name ? process.env[name] : void 0;
|
|
1493
1493
|
var makeGoogleLLMFromEnv = (config) => {
|
|
1494
|
-
const apiKey =
|
|
1494
|
+
const apiKey = envByName(config?.apiKeyEnv) ?? process.env.BRASS_GOOGLE_API_KEY ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
|
|
1495
1495
|
if (!apiKey) return void 0;
|
|
1496
|
-
return
|
|
1496
|
+
return makeGoogleGenerativeAILLM({
|
|
1497
1497
|
apiKey,
|
|
1498
|
-
model:
|
|
1499
|
-
apiVersion:
|
|
1500
|
-
baseUrl:
|
|
1501
|
-
endpoint:
|
|
1502
|
-
systemInstruction:
|
|
1503
|
-
temperature:
|
|
1504
|
-
topP:
|
|
1505
|
-
topK:
|
|
1506
|
-
maxOutputTokens:
|
|
1498
|
+
model: process.env.BRASS_GOOGLE_MODEL ?? process.env.BRASS_LLM_MODEL ?? config?.model ?? "gemini-2.5-flash",
|
|
1499
|
+
apiVersion: process.env.BRASS_GOOGLE_API_VERSION ?? config?.apiVersion ?? "v1beta",
|
|
1500
|
+
baseUrl: process.env.BRASS_GOOGLE_BASE_URL ?? config?.baseUrl,
|
|
1501
|
+
endpoint: process.env.BRASS_GOOGLE_ENDPOINT ?? config?.endpoint,
|
|
1502
|
+
systemInstruction: process.env.BRASS_GOOGLE_SYSTEM_INSTRUCTION ?? config?.systemInstruction,
|
|
1503
|
+
temperature: parseOptionalNumber(process.env.BRASS_GOOGLE_TEMPERATURE) ?? config?.temperature,
|
|
1504
|
+
topP: parseOptionalNumber(process.env.BRASS_GOOGLE_TOP_P) ?? config?.topP,
|
|
1505
|
+
topK: parseOptionalNumber(process.env.BRASS_GOOGLE_TOP_K) ?? config?.topK,
|
|
1506
|
+
maxOutputTokens: parseOptionalNumber(process.env.BRASS_GOOGLE_MAX_OUTPUT_TOKENS) ?? config?.maxOutputTokens
|
|
1507
1507
|
});
|
|
1508
1508
|
};
|
|
1509
1509
|
var makeOpenAICompatibleLLMFromEnv = (config) => {
|
|
1510
|
-
const endpoint =
|
|
1511
|
-
const apiKey =
|
|
1512
|
-
const model =
|
|
1510
|
+
const endpoint = process.env.BRASS_LLM_ENDPOINT ?? config?.endpoint;
|
|
1511
|
+
const apiKey = envByName(config?.apiKeyEnv) ?? process.env.BRASS_LLM_API_KEY;
|
|
1512
|
+
const model = process.env.BRASS_LLM_MODEL ?? config?.model ?? "gpt-4.1";
|
|
1513
1513
|
if (!endpoint || !apiKey) return void 0;
|
|
1514
|
-
return
|
|
1514
|
+
return makeOpenAICompatibleLLM({ endpoint, apiKey, model });
|
|
1515
1515
|
};
|
|
1516
1516
|
var makeLLMFromEnv = (config) => {
|
|
1517
|
-
const provider =
|
|
1518
|
-
const fakeResponse =
|
|
1519
|
-
if (provider === "fake") return
|
|
1517
|
+
const provider = (process.env.BRASS_LLM_PROVIDER ?? config?.provider)?.trim().toLowerCase();
|
|
1518
|
+
const fakeResponse = process.env.BRASS_FAKE_LLM_RESPONSE ?? config?.fakeResponse;
|
|
1519
|
+
if (provider === "fake") return makeFakeLLM({ content: fakeResponse });
|
|
1520
1520
|
if (provider === "google" || provider === "gemini") {
|
|
1521
1521
|
const google = makeGoogleLLMFromEnv(config);
|
|
1522
1522
|
if (!google) {
|
|
@@ -1538,16 +1538,16 @@ var makeLLMFromEnv = (config) => {
|
|
|
1538
1538
|
if (provider) {
|
|
1539
1539
|
throw new Error(`Unsupported LLM provider: ${provider}`);
|
|
1540
1540
|
}
|
|
1541
|
-
return
|
|
1541
|
+
return makeGoogleLLMFromEnv(config) ?? makeOpenAICompatibleLLMFromEnv(config) ?? makeFakeLLM({ content: fakeResponse });
|
|
1542
1542
|
};
|
|
1543
1543
|
var parseApprovalModeFromEnv = () => {
|
|
1544
|
-
const raw =
|
|
1544
|
+
const raw = process.env.BRASS_AGENT_APPROVAL?.trim().toLowerCase();
|
|
1545
1545
|
if (!raw) return void 0;
|
|
1546
1546
|
if (isCliApprovalMode(raw)) return raw;
|
|
1547
1547
|
throw new Error("BRASS_AGENT_APPROVAL must be one of: auto, interactive, approve, deny");
|
|
1548
1548
|
};
|
|
1549
|
-
var envTruthy = (value) => value === "1" ||
|
|
1550
|
-
var canPromptInteractively = () => Boolean(
|
|
1549
|
+
var envTruthy = (value) => value === "1" || value?.toLowerCase() === "true" || value?.toLowerCase() === "yes";
|
|
1550
|
+
var canPromptInteractively = () => Boolean(process.stdin?.isTTY && (process.stderr?.isTTY ?? process.stdout?.isTTY));
|
|
1551
1551
|
var resolveApprovalMode = (parsed) => {
|
|
1552
1552
|
if (parsed.approvalSpecified && parsed.approval !== "auto") return parsed.approval;
|
|
1553
1553
|
if (envTruthy(process.env.BRASS_AGENT_AUTO_APPROVE)) return "approve";
|
|
@@ -1561,9 +1561,9 @@ var makeApprovalServiceFromCli = (parsed) => {
|
|
|
1561
1561
|
const mode = resolveApprovalMode(parsed);
|
|
1562
1562
|
switch (mode) {
|
|
1563
1563
|
case "approve":
|
|
1564
|
-
return
|
|
1564
|
+
return autoApproveApprovals;
|
|
1565
1565
|
case "deny":
|
|
1566
|
-
return
|
|
1566
|
+
return makeAutoDenyApprovals("Approval rejected because the CLI is running without interactive input. Use --yes to auto-approve.");
|
|
1567
1567
|
case "interactive":
|
|
1568
1568
|
return makeCliApprovalService();
|
|
1569
1569
|
}
|
|
@@ -1695,32 +1695,32 @@ var createHumanEventSink = (configPath) => ({
|
|
|
1695
1695
|
console.log("");
|
|
1696
1696
|
break;
|
|
1697
1697
|
case "agent.action.started":
|
|
1698
|
-
console.log(`\u2192 ${
|
|
1698
|
+
console.log(`\u2192 ${summarizeAgentAction(event.action)}`);
|
|
1699
1699
|
break;
|
|
1700
1700
|
case "agent.action.completed": {
|
|
1701
|
-
const status =
|
|
1702
|
-
console.log(`${statusIcon2(status)} ${
|
|
1701
|
+
const status = observationStatus(event.observation);
|
|
1702
|
+
console.log(`${statusIcon2(status)} ${summarizeAgentObservation(event.observation)} ${formatDuration(event.durationMs)}`);
|
|
1703
1703
|
break;
|
|
1704
1704
|
}
|
|
1705
1705
|
case "agent.action.failed":
|
|
1706
1706
|
if (event.error._tag !== "ToolTimeout" && event.error._tag !== "PermissionDenied" && event.error._tag !== "ApprovalRejected") {
|
|
1707
|
-
console.log(`\u2717 ${
|
|
1707
|
+
console.log(`\u2717 ${summarizeAgentAction(event.action)} failed with ${event.error._tag} ${formatDuration(event.durationMs)}`);
|
|
1708
1708
|
}
|
|
1709
1709
|
break;
|
|
1710
1710
|
case "agent.tool.timeout":
|
|
1711
|
-
console.log(`! ${
|
|
1711
|
+
console.log(`! ${summarizeAgentAction(event.action)} timed out after ${event.timeoutMs}ms`);
|
|
1712
1712
|
break;
|
|
1713
1713
|
case "agent.permission.denied":
|
|
1714
|
-
console.log(`\u2717 ${
|
|
1714
|
+
console.log(`\u2717 ${summarizeAgentAction(event.action)} denied: ${event.reason}`);
|
|
1715
1715
|
break;
|
|
1716
1716
|
case "agent.approval.requested":
|
|
1717
|
-
console.log(`? approval required for ${
|
|
1717
|
+
console.log(`? approval required for ${summarizeAgentAction(event.action)} (${event.risk})`);
|
|
1718
1718
|
break;
|
|
1719
1719
|
case "agent.approval.resolved":
|
|
1720
1720
|
if (event.approved) {
|
|
1721
|
-
console.log(`\u2713 approval granted for ${
|
|
1721
|
+
console.log(`\u2713 approval granted for ${summarizeAgentAction(event.action)}`);
|
|
1722
1722
|
} else {
|
|
1723
|
-
console.log(`\u2717 approval rejected for ${
|
|
1723
|
+
console.log(`\u2717 approval rejected for ${summarizeAgentAction(event.action)}${event.reason ? `: ${event.reason}` : ""}`);
|
|
1724
1724
|
}
|
|
1725
1725
|
break;
|
|
1726
1726
|
case "agent.patch.applied":
|
|
@@ -1748,7 +1748,7 @@ var createProtocolEventSink = (options = {}) => ({
|
|
|
1748
1748
|
});
|
|
1749
1749
|
var safeFilePart = (value) => value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "run";
|
|
1750
1750
|
var markdownEscape = (value) => value.replace(/\\/g, "\\\\").replace(/`/g, "\\`");
|
|
1751
|
-
var writeRunArtifacts =
|
|
1751
|
+
var writeRunArtifacts = async (state, outputDir, options) => {
|
|
1752
1752
|
const nodePath = await dynamicImport2("node:path");
|
|
1753
1753
|
const nodeFs = await dynamicImport2("node:fs/promises");
|
|
1754
1754
|
const dir = nodePath.isAbsolute(outputDir) ? outputDir : nodePath.resolve(state.goal.cwd, outputDir);
|
|
@@ -1776,9 +1776,9 @@ var writeRunArtifacts = _chunkTGOMLZ65js.async.call(void 0, state, outputDir, op
|
|
|
1776
1776
|
"",
|
|
1777
1777
|
"## Summary",
|
|
1778
1778
|
"",
|
|
1779
|
-
|
|
1779
|
+
done?.summary?.trim() || (error ? `Error: ${error.error._tag}` : "No summary recorded.")
|
|
1780
1780
|
].filter(Boolean).join("\n"), "utf8");
|
|
1781
|
-
if (
|
|
1781
|
+
if (process.stderr?.isTTY) {
|
|
1782
1782
|
console.error(`saved run artifacts: ${jsonPath} ${mdPath}`);
|
|
1783
1783
|
}
|
|
1784
1784
|
};
|
|
@@ -1825,13 +1825,13 @@ var printHumanFinalSummary = (state) => {
|
|
|
1825
1825
|
};
|
|
1826
1826
|
var makeEventsSink = (parsed, compactOptions) => parsed.output === "human" ? createHumanEventSink(parsed.resolvedConfigPath) : parsed.output === "events-json" ? createJsonEventSink(compactOptions) : parsed.output === "protocol-json" ? createProtocolEventSink(compactOptions) : void 0;
|
|
1827
1827
|
var makeAgentEnv = (parsed, events) => {
|
|
1828
|
-
const shell =
|
|
1828
|
+
const shell = NodeShell;
|
|
1829
1829
|
return {
|
|
1830
1830
|
shell,
|
|
1831
|
-
fs:
|
|
1832
|
-
patch:
|
|
1831
|
+
fs: makeNodeFileSystem(shell),
|
|
1832
|
+
patch: makeNodePatchService(shell),
|
|
1833
1833
|
llm: makeLLMFromEnv(parsed.config.llm),
|
|
1834
|
-
permissions:
|
|
1834
|
+
permissions: makeConfiguredPermissions(parsed.config.permissions),
|
|
1835
1835
|
approvals: makeApprovalServiceFromCli(parsed),
|
|
1836
1836
|
...events ? { events } : {},
|
|
1837
1837
|
...parsed.config.tools ? { toolPolicies: parsed.config.tools } : {}
|
|
@@ -1846,12 +1846,12 @@ var singleRunFromParsed = (parsed) => ({
|
|
|
1846
1846
|
...parsed.patchFile ? { patchFile: parsed.patchFile } : {},
|
|
1847
1847
|
...parsed.saveRunDir ? { saveRunDir: parsed.saveRunDir } : {}
|
|
1848
1848
|
});
|
|
1849
|
-
var runCliAgent =
|
|
1849
|
+
var runCliAgent = async (parsed, run, compactOptions, events) => {
|
|
1850
1850
|
const env = makeAgentEnv(parsed, events);
|
|
1851
|
-
const runtime = new
|
|
1851
|
+
const runtime = new Runtime({ env });
|
|
1852
1852
|
const initialPatch = run.patchFile ? await readPatchFile(run.cwd, run.patchFile) : void 0;
|
|
1853
1853
|
const state = await runtime.toPromise(
|
|
1854
|
-
|
|
1854
|
+
runAgent(runtime, {
|
|
1855
1855
|
id: `agent-${Date.now()}-${run.index + 1}`,
|
|
1856
1856
|
cwd: run.cwd,
|
|
1857
1857
|
text: run.goalText,
|
|
@@ -1919,7 +1919,7 @@ var printWorkspaceWhere = (parsed) => {
|
|
|
1919
1919
|
if (result.configPath) console.log(`config: ${result.configPath}`);
|
|
1920
1920
|
if (result.envFiles.length > 0) console.log(`env: ${result.envFiles.join(", ")}`);
|
|
1921
1921
|
};
|
|
1922
|
-
var main =
|
|
1922
|
+
var main = async () => {
|
|
1923
1923
|
const parsed = await resolveParsedConfig(parseCliArgs(process.argv.slice(2)));
|
|
1924
1924
|
const isBatch = parsed.batchRuns.length > 0;
|
|
1925
1925
|
if (parsed.showHelp) {
|