zelari-code 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/gauntlet/blind.js +38 -0
- package/dist/cli/gauntlet/blind.js.map +1 -0
- package/dist/cli/gauntlet/complete.js +90 -0
- package/dist/cli/gauntlet/complete.js.map +1 -0
- package/dist/cli/gauntlet/decompose.js +163 -0
- package/dist/cli/gauntlet/decompose.js.map +1 -0
- package/dist/cli/gauntlet/events.js +30 -0
- package/dist/cli/gauntlet/events.js.map +1 -0
- package/dist/cli/gauntlet/loop.js +142 -0
- package/dist/cli/gauntlet/loop.js.map +1 -0
- package/dist/cli/gauntlet/policy.js +61 -0
- package/dist/cli/gauntlet/policy.js.map +1 -0
- package/dist/cli/gauntlet/prompts.js +70 -0
- package/dist/cli/gauntlet/prompts.js.map +1 -0
- package/dist/cli/gauntlet/run.js +213 -0
- package/dist/cli/gauntlet/run.js.map +1 -0
- package/dist/cli/gauntlet/schedule.js +34 -0
- package/dist/cli/gauntlet/schedule.js.map +1 -0
- package/dist/cli/gauntlet/verdict.js +58 -0
- package/dist/cli/gauntlet/verdict.js.map +1 -0
- package/dist/cli/headless.js +11 -0
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/main.bundled.js +992 -114
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/runHeadless.js +18 -0
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/toolRegistry.js +13 -6
- package/dist/cli/toolRegistry.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -595,8 +595,8 @@ async function runGrokOAuthFlow(options = {}) {
|
|
|
595
595
|
);
|
|
596
596
|
} catch {
|
|
597
597
|
}
|
|
598
|
-
const
|
|
599
|
-
const effectiveTimeout = Math.min(
|
|
598
|
+
const timeoutMs2 = options.timeoutMs ?? DEFAULT_OAUTH_TIMEOUT_MS;
|
|
599
|
+
const effectiveTimeout = Math.min(timeoutMs2, deviceAuth.expiresIn * 1e3);
|
|
600
600
|
return pollForDeviceToken({
|
|
601
601
|
clientId: clientId2,
|
|
602
602
|
deviceCode: deviceAuth.deviceCode,
|
|
@@ -739,7 +739,7 @@ function generateOAuthState() {
|
|
|
739
739
|
}
|
|
740
740
|
async function waitForLoopbackCallback(options) {
|
|
741
741
|
const host = options.host ?? "127.0.0.1";
|
|
742
|
-
const
|
|
742
|
+
const timeoutMs2 = options.timeoutMs ?? 3e5;
|
|
743
743
|
const expectedPath = options.path.startsWith("/") ? options.path : `/${options.path}`;
|
|
744
744
|
return new Promise((resolve3, reject) => {
|
|
745
745
|
let settled = false;
|
|
@@ -759,12 +759,12 @@ async function waitForLoopbackCallback(options) {
|
|
|
759
759
|
const ok = Boolean(result.code) && !result.error;
|
|
760
760
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
761
761
|
res.end(oauthResultHtml(ok, result.errorDescription ?? result.error));
|
|
762
|
-
|
|
762
|
+
finish2(result);
|
|
763
763
|
});
|
|
764
764
|
const timer = setTimeout(() => {
|
|
765
|
-
|
|
766
|
-
},
|
|
767
|
-
const
|
|
765
|
+
finish2(void 0, new Error(`Timed out waiting for OAuth callback on http://${host}:${options.port}`));
|
|
766
|
+
}, timeoutMs2);
|
|
767
|
+
const finish2 = (value, err) => {
|
|
768
768
|
if (settled) return;
|
|
769
769
|
settled = true;
|
|
770
770
|
clearTimeout(timer);
|
|
@@ -773,7 +773,7 @@ async function waitForLoopbackCallback(options) {
|
|
|
773
773
|
else resolve3(value ?? {});
|
|
774
774
|
});
|
|
775
775
|
};
|
|
776
|
-
server.on("error", (err) =>
|
|
776
|
+
server.on("error", (err) => finish2(void 0, err));
|
|
777
777
|
server.listen(options.port, host);
|
|
778
778
|
});
|
|
779
779
|
}
|
|
@@ -971,8 +971,8 @@ async function pollChatgptDeviceAuth(options) {
|
|
|
971
971
|
const clientId2 = options.clientId || process.env.CHATGPT_OAUTH_CLIENT_ID || DEFAULT_CHATGPT_CLIENT_ID;
|
|
972
972
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
973
973
|
const sleep = options.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
974
|
-
const
|
|
975
|
-
const deadline = Date.now() +
|
|
974
|
+
const timeoutMs2 = options.timeoutMs ?? 3e5;
|
|
975
|
+
const deadline = Date.now() + timeoutMs2;
|
|
976
976
|
let interval = options.interval ?? 5;
|
|
977
977
|
let authorizationCode;
|
|
978
978
|
let codeVerifier;
|
|
@@ -19419,9 +19419,9 @@ function assertHttpUrl(raw) {
|
|
|
19419
19419
|
}
|
|
19420
19420
|
return url2;
|
|
19421
19421
|
}
|
|
19422
|
-
async function fetchWithTimeout(url2, init, outerSignal,
|
|
19422
|
+
async function fetchWithTimeout(url2, init, outerSignal, timeoutMs2) {
|
|
19423
19423
|
const ctrl = new AbortController();
|
|
19424
|
-
const timer = setTimeout(() => ctrl.abort(new Error(`timeout after ${
|
|
19424
|
+
const timer = setTimeout(() => ctrl.abort(new Error(`timeout after ${timeoutMs2}ms`)), timeoutMs2);
|
|
19425
19425
|
const onOuterAbort = () => ctrl.abort(outerSignal?.reason);
|
|
19426
19426
|
outerSignal?.addEventListener("abort", onOuterAbort, { once: true });
|
|
19427
19427
|
try {
|
|
@@ -23327,8 +23327,8 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23327
23327
|
/** Execute a single hook, swallowing every failure into an allow. */
|
|
23328
23328
|
async runHookSafely(hook, payload) {
|
|
23329
23329
|
try {
|
|
23330
|
-
const
|
|
23331
|
-
const raw = hook.url ? await this.postHttp(hook.url, payload,
|
|
23330
|
+
const timeoutMs2 = hook.timeoutMs ?? this.defaultTimeoutMs;
|
|
23331
|
+
const raw = hook.url ? await this.postHttp(hook.url, payload, timeoutMs2) : await this.execCommand(hook.command ?? "", payload, timeoutMs2, hook.cwd);
|
|
23332
23332
|
const decision = parseJson(raw);
|
|
23333
23333
|
if (!decision) {
|
|
23334
23334
|
this.logger(`hook "${hook.name}" returned invalid JSON (fail-open): ${raw.slice(0, 200)}`);
|
|
@@ -23345,7 +23345,7 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23345
23345
|
}
|
|
23346
23346
|
}
|
|
23347
23347
|
/** Spawn `command`, write JSON payload to stdin, read stdout until close. */
|
|
23348
|
-
execCommand(command, payload,
|
|
23348
|
+
execCommand(command, payload, timeoutMs2, cwd) {
|
|
23349
23349
|
return new Promise((resolve3, reject) => {
|
|
23350
23350
|
const child = spawn2(command, {
|
|
23351
23351
|
shell: true,
|
|
@@ -23357,8 +23357,8 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23357
23357
|
let stderr = "";
|
|
23358
23358
|
const timer = setTimeout(() => {
|
|
23359
23359
|
child.kill("SIGKILL");
|
|
23360
|
-
reject(new Error(`timed out after ${
|
|
23361
|
-
},
|
|
23360
|
+
reject(new Error(`timed out after ${timeoutMs2}ms`));
|
|
23361
|
+
}, timeoutMs2);
|
|
23362
23362
|
child.stdout?.on("data", (d) => {
|
|
23363
23363
|
stdout += d.toString();
|
|
23364
23364
|
});
|
|
@@ -23384,9 +23384,9 @@ var init_lifecycleHookRunner = __esm({
|
|
|
23384
23384
|
});
|
|
23385
23385
|
}
|
|
23386
23386
|
/** POST JSON payload; resolve with the response body text. */
|
|
23387
|
-
async postHttp(url2, payload,
|
|
23387
|
+
async postHttp(url2, payload, timeoutMs2) {
|
|
23388
23388
|
const ctrl = new AbortController();
|
|
23389
|
-
const timer = setTimeout(() => ctrl.abort(),
|
|
23389
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs2);
|
|
23390
23390
|
try {
|
|
23391
23391
|
const res = await fetch(url2, {
|
|
23392
23392
|
method: "POST",
|
|
@@ -27962,7 +27962,7 @@ function deepFreeze(value) {
|
|
|
27962
27962
|
return Object.freeze(value);
|
|
27963
27963
|
}
|
|
27964
27964
|
async function runInSandbox(opts) {
|
|
27965
|
-
const { bundleCode, sdk, timeoutMs } = opts;
|
|
27965
|
+
const { bundleCode, sdk, timeoutMs: timeoutMs2 } = opts;
|
|
27966
27966
|
if (!opts.skipFootgunScan) {
|
|
27967
27967
|
const footguns = scanForFootguns(bundleCode);
|
|
27968
27968
|
if (footguns.length > 0) {
|
|
@@ -27982,7 +27982,7 @@ async function runInSandbox(opts) {
|
|
|
27982
27982
|
});
|
|
27983
27983
|
const start = Date.now();
|
|
27984
27984
|
const vmOpts = {
|
|
27985
|
-
timeout: Math.max(1,
|
|
27985
|
+
timeout: Math.max(1, timeoutMs2),
|
|
27986
27986
|
displayErrors: true,
|
|
27987
27987
|
breakOnSigint: true
|
|
27988
27988
|
};
|
|
@@ -27992,7 +27992,7 @@ async function runInSandbox(opts) {
|
|
|
27992
27992
|
} catch (err) {
|
|
27993
27993
|
const msg = err && typeof err === "object" && "message" in err ? String(err.message ?? "") : String(err);
|
|
27994
27994
|
if (/timed out/i.test(msg)) {
|
|
27995
|
-
throw new PlanError("budget_exceeded", `script exceeded ${
|
|
27995
|
+
throw new PlanError("budget_exceeded", `script exceeded ${timeoutMs2}ms budget`);
|
|
27996
27996
|
}
|
|
27997
27997
|
if (opts.signal?.aborted) {
|
|
27998
27998
|
throw new PlanError("cancelled", "script aborted by host");
|
|
@@ -29237,7 +29237,7 @@ var init_nodeProviders = __esm({
|
|
|
29237
29237
|
async exec(command, options = {}) {
|
|
29238
29238
|
const started = Date.now();
|
|
29239
29239
|
const cwd = this.workspace.resolve(options.cwd ?? ".");
|
|
29240
|
-
const
|
|
29240
|
+
const timeoutMs2 = options.timeoutMs ?? this.defaults.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
29241
29241
|
const maxChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
|
|
29242
29242
|
const isWindows = process.platform === "win32";
|
|
29243
29243
|
const file2 = isWindows ? "cmd.exe" : "/bin/sh";
|
|
@@ -29260,7 +29260,7 @@ var init_nodeProviders = __esm({
|
|
|
29260
29260
|
const timer = setTimeout(() => {
|
|
29261
29261
|
timedOut = true;
|
|
29262
29262
|
killTree(child);
|
|
29263
|
-
},
|
|
29263
|
+
}, timeoutMs2);
|
|
29264
29264
|
child.stdout?.on("data", (d) => {
|
|
29265
29265
|
stdout = append(stdout, d.toString("utf-8"));
|
|
29266
29266
|
});
|
|
@@ -30198,9 +30198,9 @@ var init_sessionEvidence = __esm({
|
|
|
30198
30198
|
|
|
30199
30199
|
// packages/core/dist/verification/criteriaPack.v1.js
|
|
30200
30200
|
function codingCriteriaPack(options = {}) {
|
|
30201
|
-
const
|
|
30201
|
+
const timeoutMs2 = options.commandTimeoutMs ?? 6e5;
|
|
30202
30202
|
const withDefault = (o, d) => o === void 0 ? d : o;
|
|
30203
|
-
const command = (command2) => command2 ? { kind: "command", command: command2, timeoutMs } : void 0;
|
|
30203
|
+
const command = (command2) => command2 ? { kind: "command", command: command2, timeoutMs: timeoutMs2 } : void 0;
|
|
30204
30204
|
const criteria = [
|
|
30205
30205
|
{
|
|
30206
30206
|
id: "correctness.error-signals",
|
|
@@ -33281,7 +33281,7 @@ var init_registry2 = __esm({
|
|
|
33281
33281
|
if (!parsed.success) {
|
|
33282
33282
|
return typedErr(`Invalid input: ${parsed.error.message}`);
|
|
33283
33283
|
}
|
|
33284
|
-
const
|
|
33284
|
+
const timeoutMs2 = options.timeoutMs ?? tool.timeoutMs ?? 3e4;
|
|
33285
33285
|
const parentSignal = options.signal;
|
|
33286
33286
|
const controller = new AbortController();
|
|
33287
33287
|
let timer;
|
|
@@ -33331,8 +33331,8 @@ var init_registry2 = __esm({
|
|
|
33331
33331
|
timer = setTimeout(() => {
|
|
33332
33332
|
if (!controller.signal.aborted)
|
|
33333
33333
|
controller.abort();
|
|
33334
|
-
reject(new Error(`Tool "${name}" timed out after ${
|
|
33335
|
-
},
|
|
33334
|
+
reject(new Error(`Tool "${name}" timed out after ${timeoutMs2}ms`));
|
|
33335
|
+
}, timeoutMs2);
|
|
33336
33336
|
})
|
|
33337
33337
|
]);
|
|
33338
33338
|
if (result.ok) {
|
|
@@ -33678,11 +33678,11 @@ async function runDiagnosticsForFile(file2, options = {}) {
|
|
|
33678
33678
|
const provider = providerForFile(file2, options.providers);
|
|
33679
33679
|
if (!provider) return [];
|
|
33680
33680
|
const cwd = options.cwd ?? process.cwd();
|
|
33681
|
-
const
|
|
33681
|
+
const timeoutMs2 = options.timeoutMs ?? 5e3;
|
|
33682
33682
|
const runner = options.runner ?? defaultRunner;
|
|
33683
33683
|
try {
|
|
33684
33684
|
const bin = options.runner ? provider.bin : resolveBin(provider.bin, cwd);
|
|
33685
|
-
const result = await runner(bin, provider.args(file2), { cwd, timeoutMs });
|
|
33685
|
+
const result = await runner(bin, provider.args(file2), { cwd, timeoutMs: timeoutMs2 });
|
|
33686
33686
|
return provider.parse(result.stdout, file2);
|
|
33687
33687
|
} catch {
|
|
33688
33688
|
return [];
|
|
@@ -35184,7 +35184,7 @@ function renderVerdict(verdict, candidateCount) {
|
|
|
35184
35184
|
return lines.join("\n");
|
|
35185
35185
|
}
|
|
35186
35186
|
function createKrakenSelectTool(deps) {
|
|
35187
|
-
const
|
|
35187
|
+
const timeoutMs2 = deps.timeoutMs ?? 12e4;
|
|
35188
35188
|
return {
|
|
35189
35189
|
name: "kraken_select",
|
|
35190
35190
|
description: "Compare the candidate research reports spawned this turn (task purpose=candidate) and select the hypothesis best supported by OBSERVED EVIDENCE. A dedicated verifier call (default: the current model) judges grounded vs unsupported claims; degraded observations are never treated as proof of absence. Returns the selected candidate, a rationale, and requiredChecks the implementation must pass. Call it ONCE per turn, after candidate tentacles finished and BEFORE implementing. If it reports needs_more_evidence, either spawn ONE more differentiated candidate or proceed with your own judgment.",
|
|
@@ -35241,7 +35241,7 @@ function createKrakenSelectTool(deps) {
|
|
|
35241
35241
|
model: id.model,
|
|
35242
35242
|
provider: id.provider,
|
|
35243
35243
|
tools: [],
|
|
35244
|
-
signal: AbortSignal.timeout(
|
|
35244
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
35245
35245
|
});
|
|
35246
35246
|
judgingUsage = usage;
|
|
35247
35247
|
if (raw.trim().length === 0) throw new Error("empty verifier response");
|
|
@@ -38792,7 +38792,7 @@ exec node "$(dirname "$0")/askpass.cjs"
|
|
|
38792
38792
|
}
|
|
38793
38793
|
return sh;
|
|
38794
38794
|
}
|
|
38795
|
-
function runSsh(target, remoteCommand,
|
|
38795
|
+
function runSsh(target, remoteCommand, timeoutMs2 = 6e4) {
|
|
38796
38796
|
return new Promise((resolve3) => {
|
|
38797
38797
|
if (target.auth === "password" && !getSshPassword(target.id)) {
|
|
38798
38798
|
resolve3({
|
|
@@ -38832,7 +38832,7 @@ function runSsh(target, remoteCommand, timeoutMs = 6e4) {
|
|
|
38832
38832
|
stdout,
|
|
38833
38833
|
stderr: stderr + "\n[ssh] timeout"
|
|
38834
38834
|
});
|
|
38835
|
-
},
|
|
38835
|
+
}, timeoutMs2);
|
|
38836
38836
|
child.on("error", (err) => {
|
|
38837
38837
|
clearTimeout(timer);
|
|
38838
38838
|
resolve3({
|
|
@@ -39061,7 +39061,7 @@ async function readChecks(cwd) {
|
|
|
39061
39061
|
return [];
|
|
39062
39062
|
}
|
|
39063
39063
|
}
|
|
39064
|
-
function runShell(command, cwd,
|
|
39064
|
+
function runShell(command, cwd, timeoutMs2, signal) {
|
|
39065
39065
|
return new Promise((resolve3) => {
|
|
39066
39066
|
const isWin = process.platform === "win32";
|
|
39067
39067
|
const child = spawn10(isWin ? "cmd.exe" : "/bin/sh", isWin ? ["/c", command] : ["-c", command], {
|
|
@@ -39073,7 +39073,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
39073
39073
|
let stdout = "";
|
|
39074
39074
|
let stderr = "";
|
|
39075
39075
|
let settled = false;
|
|
39076
|
-
const
|
|
39076
|
+
const finish2 = (exitCode) => {
|
|
39077
39077
|
if (settled) return;
|
|
39078
39078
|
settled = true;
|
|
39079
39079
|
resolve3({ exitCode, stdout, stderr });
|
|
@@ -39083,8 +39083,8 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
39083
39083
|
child.kill("SIGTERM");
|
|
39084
39084
|
} catch {
|
|
39085
39085
|
}
|
|
39086
|
-
|
|
39087
|
-
},
|
|
39086
|
+
finish2(124);
|
|
39087
|
+
}, timeoutMs2);
|
|
39088
39088
|
if (signal) {
|
|
39089
39089
|
if (signal.aborted) {
|
|
39090
39090
|
try {
|
|
@@ -39092,7 +39092,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
39092
39092
|
} catch {
|
|
39093
39093
|
}
|
|
39094
39094
|
clearTimeout(timer);
|
|
39095
|
-
|
|
39095
|
+
finish2(130);
|
|
39096
39096
|
return;
|
|
39097
39097
|
}
|
|
39098
39098
|
signal.addEventListener(
|
|
@@ -39103,7 +39103,7 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
39103
39103
|
} catch {
|
|
39104
39104
|
}
|
|
39105
39105
|
clearTimeout(timer);
|
|
39106
|
-
|
|
39106
|
+
finish2(130);
|
|
39107
39107
|
},
|
|
39108
39108
|
{ once: true }
|
|
39109
39109
|
);
|
|
@@ -39118,11 +39118,11 @@ function runShell(command, cwd, timeoutMs, signal) {
|
|
|
39118
39118
|
});
|
|
39119
39119
|
child.on("error", () => {
|
|
39120
39120
|
clearTimeout(timer);
|
|
39121
|
-
|
|
39121
|
+
finish2(1);
|
|
39122
39122
|
});
|
|
39123
39123
|
child.on("close", (code) => {
|
|
39124
39124
|
clearTimeout(timer);
|
|
39125
|
-
|
|
39125
|
+
finish2(code ?? 1);
|
|
39126
39126
|
});
|
|
39127
39127
|
});
|
|
39128
39128
|
}
|
|
@@ -39144,9 +39144,9 @@ async function runBacktest(cwd, signal) {
|
|
|
39144
39144
|
const results = [];
|
|
39145
39145
|
for (const c of checks) {
|
|
39146
39146
|
const expectExit = c.expectExit ?? 0;
|
|
39147
|
-
const
|
|
39147
|
+
const timeoutMs2 = c.timeoutMs ?? 12e4;
|
|
39148
39148
|
const start = Date.now();
|
|
39149
|
-
const { exitCode, stdout, stderr } = await runShell(c.command, cwd,
|
|
39149
|
+
const { exitCode, stdout, stderr } = await runShell(c.command, cwd, timeoutMs2, signal);
|
|
39150
39150
|
const combined = `${stdout}${stderr}`;
|
|
39151
39151
|
const preview = combined.slice(0, 400);
|
|
39152
39152
|
let ok = exitCode === expectExit;
|
|
@@ -39858,8 +39858,9 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39858
39858
|
if (hooks) registry4.setLifecycleHooks(hooks);
|
|
39859
39859
|
const readOnly = options.readOnly === true || options.planMode === true || profile === "explore";
|
|
39860
39860
|
const verifyMode = profile === "verify";
|
|
39861
|
-
const
|
|
39862
|
-
const
|
|
39861
|
+
const gauntletParent = options.gauntletParent === true;
|
|
39862
|
+
const allowMutators = !readOnly && !verifyMode && !gauntletParent;
|
|
39863
|
+
const allowBash = (allowMutators || verifyMode) && !gauntletParent;
|
|
39863
39864
|
const permPolicy = options.permissionPolicy ?? defaultPermissionPolicy();
|
|
39864
39865
|
const withPerm = (t) => wrapWithPermissions(t, permPolicy, options.onPermissionAsk);
|
|
39865
39866
|
registry4.register(withPerm(safeReadFile));
|
|
@@ -39892,21 +39893,21 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39892
39893
|
if (allowBash) {
|
|
39893
39894
|
registry4.register(withPerm(safeBash));
|
|
39894
39895
|
}
|
|
39895
|
-
const askUserTool = options.readOnly === true || profile === "explore" || profile === "verify" ? null : createAskUserTool(options.onAskUser);
|
|
39896
|
+
const askUserTool = options.readOnly === true || profile === "explore" || profile === "verify" || gauntletParent ? null : createAskUserTool(options.onAskUser);
|
|
39896
39897
|
if (askUserTool) {
|
|
39897
39898
|
registry4.register(withPerm(askUserTool));
|
|
39898
39899
|
}
|
|
39899
|
-
const enableSkill = options.enableSkill !== false && options.readOnly !== true && profile !== "explore" && profile !== "verify";
|
|
39900
|
+
const enableSkill = options.enableSkill !== false && options.readOnly !== true && !gauntletParent && profile !== "explore" && profile !== "verify";
|
|
39900
39901
|
const skillTool = enableSkill ? withPerm(createSkillTool({ cwd: root })) : null;
|
|
39901
39902
|
if (skillTool) {
|
|
39902
39903
|
registry4.register(skillTool);
|
|
39903
39904
|
}
|
|
39904
|
-
const enableTodos = options.enableTodos !== false && options.readOnly !== true && profile === "full";
|
|
39905
|
+
const enableTodos = options.enableTodos !== false && options.readOnly !== true && !gauntletParent && profile === "full";
|
|
39905
39906
|
const todoWrite = enableTodos ? withPerm(createTodoWriteTool()) : null;
|
|
39906
39907
|
const todoRead = enableTodos ? withPerm(createTodoReadTool()) : null;
|
|
39907
39908
|
if (todoWrite) registry4.register(todoWrite);
|
|
39908
39909
|
if (todoRead) registry4.register(todoRead);
|
|
39909
|
-
const enablePlanTasks = options.enablePlanTasks !== false && options.readOnly !== true && (profile === "full" || options.planMode === true) && profile !== "explore" && profile !== "verify" && profile !== "general";
|
|
39910
|
+
const enablePlanTasks = options.enablePlanTasks !== false && options.readOnly !== true && !gauntletParent && (profile === "full" || options.planMode === true) && profile !== "explore" && profile !== "verify" && profile !== "general";
|
|
39910
39911
|
const planTaskToolsWrapped = (enablePlanTasks ? createPlanTaskTools({ projectRoot: root, onTaskEvent: options.onTaskEvent }) : []).map((t) => withPerm(t));
|
|
39911
39912
|
for (const t of planTaskToolsWrapped) {
|
|
39912
39913
|
registry4.register(t);
|
|
@@ -39957,7 +39958,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39957
39958
|
permissions: semanticTool.permissions ?? []
|
|
39958
39959
|
});
|
|
39959
39960
|
}
|
|
39960
|
-
if (!readOnly && process.env.ZELARI_BROWSER !== "0") {
|
|
39961
|
+
if (!readOnly && !gauntletParent && process.env.ZELARI_BROWSER !== "0") {
|
|
39961
39962
|
const browserTool = createBrowserTool();
|
|
39962
39963
|
registry4.register(browserTool);
|
|
39963
39964
|
tools.push({
|
|
@@ -39966,7 +39967,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39966
39967
|
permissions: browserTool.permissions ?? []
|
|
39967
39968
|
});
|
|
39968
39969
|
}
|
|
39969
|
-
if (!readOnly && process.env.ZELARI_SSH !== "0") {
|
|
39970
|
+
if (!readOnly && !gauntletParent && process.env.ZELARI_SSH !== "0") {
|
|
39970
39971
|
for (const t of createSshTools()) {
|
|
39971
39972
|
registry4.register(t);
|
|
39972
39973
|
tools.push({
|
|
@@ -39976,7 +39977,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
39976
39977
|
});
|
|
39977
39978
|
}
|
|
39978
39979
|
}
|
|
39979
|
-
if (!readOnly) {
|
|
39980
|
+
if (!readOnly && !gauntletParent) {
|
|
39980
39981
|
for (const t of createWorldModelTools()) {
|
|
39981
39982
|
const safe = wrapWithAudit(t, audit, sessionId2);
|
|
39982
39983
|
registry4.register(safe);
|
|
@@ -40202,10 +40203,10 @@ function wrapWithDiagnostics(original, root, runner) {
|
|
|
40202
40203
|
const filePath = value && typeof value === "object" && typeof value.path === "string" ? value.path : void 0;
|
|
40203
40204
|
if (!filePath) return result;
|
|
40204
40205
|
try {
|
|
40205
|
-
const
|
|
40206
|
+
const timeoutMs2 = Number(process.env.ZELARI_DIAGNOSTICS_TIMEOUT_MS) || 5e3;
|
|
40206
40207
|
const diags = await runDiagnosticsForFile(filePath, {
|
|
40207
40208
|
cwd: root,
|
|
40208
|
-
timeoutMs,
|
|
40209
|
+
timeoutMs: timeoutMs2,
|
|
40209
40210
|
...runner ? { runner } : {}
|
|
40210
40211
|
});
|
|
40211
40212
|
const formatted = formatDiagnostics(diags, { relativeTo: root });
|
|
@@ -40470,6 +40471,7 @@ function parseHeadlessFlags(argv) {
|
|
|
40470
40471
|
let krakenGraph;
|
|
40471
40472
|
let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
|
|
40472
40473
|
let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
|
|
40474
|
+
let gauntlet = process.env.ZELARI_GAUNTLET === "1" || process.env.ZELARI_GAUNTLET === "true";
|
|
40473
40475
|
for (let i = 0; i < argv.length; i++) {
|
|
40474
40476
|
const arg = argv[i];
|
|
40475
40477
|
if (arg === "--headless") continue;
|
|
@@ -40640,6 +40642,10 @@ function parseHeadlessFlags(argv) {
|
|
|
40640
40642
|
} else if (arg === "--run-plan") {
|
|
40641
40643
|
runPlan = argv[i + 1];
|
|
40642
40644
|
i++;
|
|
40645
|
+
} else if (arg === "--gauntlet") {
|
|
40646
|
+
gauntlet = true;
|
|
40647
|
+
} else if (arg === "--no-gauntlet") {
|
|
40648
|
+
gauntlet = false;
|
|
40643
40649
|
}
|
|
40644
40650
|
}
|
|
40645
40651
|
if (councilFlag && !modeExplicit) {
|
|
@@ -40674,7 +40680,8 @@ function parseHeadlessFlags(argv) {
|
|
|
40674
40680
|
...strictDone ? { strictDone: true } : {},
|
|
40675
40681
|
...krakenGraph ? { krakenGraph } : {},
|
|
40676
40682
|
...planOnly ? { planOnly: true } : {},
|
|
40677
|
-
...runPlan ? { runPlan } : {}
|
|
40683
|
+
...runPlan ? { runPlan } : {},
|
|
40684
|
+
...gauntlet ? { gauntlet: true } : {}
|
|
40678
40685
|
}
|
|
40679
40686
|
};
|
|
40680
40687
|
}
|
|
@@ -41985,10 +41992,10 @@ __export(claudeProvider_exports, {
|
|
|
41985
41992
|
createLocalCliProvider: () => createLocalCliProvider
|
|
41986
41993
|
});
|
|
41987
41994
|
import { spawn as spawn11 } from "node:child_process";
|
|
41988
|
-
function waitForExit(child,
|
|
41995
|
+
function waitForExit(child, timeoutMs2 = 2e3) {
|
|
41989
41996
|
return new Promise((resolve3) => {
|
|
41990
41997
|
if (child.exitCode != null) return resolve3(child.exitCode);
|
|
41991
|
-
const timer = setTimeout(() => resolve3(child.exitCode ?? null),
|
|
41998
|
+
const timer = setTimeout(() => resolve3(child.exitCode ?? null), timeoutMs2);
|
|
41992
41999
|
timer.unref?.();
|
|
41993
42000
|
child.once("exit", (code) => {
|
|
41994
42001
|
clearTimeout(timer);
|
|
@@ -43559,10 +43566,10 @@ function distTagForVersion(version2) {
|
|
|
43559
43566
|
function registryUrlForTag(tag = distTagForVersion(getCurrentVersion())) {
|
|
43560
43567
|
return `https://registry.npmjs.org/zelari-code/${tag}`;
|
|
43561
43568
|
}
|
|
43562
|
-
async function fetchLatestVersion(fetcher = fetch, registryUrl = REGISTRY_URL,
|
|
43569
|
+
async function fetchLatestVersion(fetcher = fetch, registryUrl = REGISTRY_URL, timeoutMs2 = 5e3) {
|
|
43563
43570
|
try {
|
|
43564
43571
|
const controller = new AbortController();
|
|
43565
|
-
const timer = setTimeout(() => controller.abort(),
|
|
43572
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs2);
|
|
43566
43573
|
const response = await fetcher(registryUrl, { signal: controller.signal });
|
|
43567
43574
|
clearTimeout(timer);
|
|
43568
43575
|
if (!response.ok) {
|
|
@@ -43732,11 +43739,11 @@ var init_mcpClient = __esm({
|
|
|
43732
43739
|
* Call a tool. Returns the concatenated text content; non-text content
|
|
43733
43740
|
* items are summarized by type. Throws when the server flags isError.
|
|
43734
43741
|
*/
|
|
43735
|
-
async callTool(name, args,
|
|
43742
|
+
async callTool(name, args, timeoutMs2 = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
43736
43743
|
const res = await this.request(
|
|
43737
43744
|
"tools/call",
|
|
43738
43745
|
{ name, arguments: args },
|
|
43739
|
-
|
|
43746
|
+
timeoutMs2
|
|
43740
43747
|
);
|
|
43741
43748
|
const text = (res.content ?? []).map(
|
|
43742
43749
|
(c) => c.type === "text" && typeof c.text === "string" ? c.text : `[${c.type ?? "unknown"} content]`
|
|
@@ -43753,7 +43760,7 @@ var init_mcpClient = __esm({
|
|
|
43753
43760
|
this.child = null;
|
|
43754
43761
|
}
|
|
43755
43762
|
// ── JSON-RPC plumbing ────────────────────────────────────────────────
|
|
43756
|
-
request(method, params,
|
|
43763
|
+
request(method, params, timeoutMs2 = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
43757
43764
|
const child = this.child;
|
|
43758
43765
|
if (!child)
|
|
43759
43766
|
return Promise.reject(new Error(`[mcp:${this.serverName}] not started`));
|
|
@@ -43764,10 +43771,10 @@ var init_mcpClient = __esm({
|
|
|
43764
43771
|
this.pending.delete(id);
|
|
43765
43772
|
reject(
|
|
43766
43773
|
new Error(
|
|
43767
|
-
`[mcp:${this.serverName}] ${method} timed out after ${
|
|
43774
|
+
`[mcp:${this.serverName}] ${method} timed out after ${timeoutMs2}ms`
|
|
43768
43775
|
)
|
|
43769
43776
|
);
|
|
43770
|
-
},
|
|
43777
|
+
}, timeoutMs2);
|
|
43771
43778
|
this.pending.set(id, { resolve: resolve3, reject, timer });
|
|
43772
43779
|
child.stdin.write(payload + "\n", (err) => {
|
|
43773
43780
|
if (err) {
|
|
@@ -44841,7 +44848,7 @@ function pickSmokeScript(scripts) {
|
|
|
44841
44848
|
}
|
|
44842
44849
|
return null;
|
|
44843
44850
|
}
|
|
44844
|
-
async function runProjectSmoke(projectRoot,
|
|
44851
|
+
async function runProjectSmoke(projectRoot, timeoutMs2 = DEFAULT_TIMEOUT_MS3) {
|
|
44845
44852
|
if (process.env["ZELARI_SMOKE"] === "0") {
|
|
44846
44853
|
return { ran: false, reason: "ZELARI_SMOKE=0 (disabled)" };
|
|
44847
44854
|
}
|
|
@@ -44874,7 +44881,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44874
44881
|
let stdout = "";
|
|
44875
44882
|
let stderr = "";
|
|
44876
44883
|
let settled = false;
|
|
44877
|
-
const
|
|
44884
|
+
const finish2 = (result) => {
|
|
44878
44885
|
if (settled) return;
|
|
44879
44886
|
settled = true;
|
|
44880
44887
|
clearTimeout(timer);
|
|
@@ -44882,15 +44889,15 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44882
44889
|
};
|
|
44883
44890
|
const timer = setTimeout(() => {
|
|
44884
44891
|
child.kill("SIGTERM");
|
|
44885
|
-
|
|
44892
|
+
finish2({
|
|
44886
44893
|
ran: true,
|
|
44887
44894
|
ok: false,
|
|
44888
44895
|
script,
|
|
44889
44896
|
exitCode: -1,
|
|
44890
44897
|
output: stdout + stderr,
|
|
44891
|
-
reason: `smoke timeout after ${
|
|
44898
|
+
reason: `smoke timeout after ${timeoutMs2}ms`
|
|
44892
44899
|
});
|
|
44893
|
-
},
|
|
44900
|
+
}, timeoutMs2);
|
|
44894
44901
|
child.stdout?.on("data", (chunk) => {
|
|
44895
44902
|
stdout += chunk.toString("utf8");
|
|
44896
44903
|
});
|
|
@@ -44898,7 +44905,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44898
44905
|
stderr += chunk.toString("utf8");
|
|
44899
44906
|
});
|
|
44900
44907
|
child.on("error", (err) => {
|
|
44901
|
-
|
|
44908
|
+
finish2({
|
|
44902
44909
|
ran: true,
|
|
44903
44910
|
ok: false,
|
|
44904
44911
|
script,
|
|
@@ -44910,7 +44917,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
44910
44917
|
child.on("close", (code) => {
|
|
44911
44918
|
const exitCode = code ?? -1;
|
|
44912
44919
|
const ok = exitCode === 0;
|
|
44913
|
-
|
|
44920
|
+
finish2({
|
|
44914
44921
|
ran: true,
|
|
44915
44922
|
ok,
|
|
44916
44923
|
script,
|
|
@@ -46519,7 +46526,7 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
46519
46526
|
const closeAll = server.closeAllConnections;
|
|
46520
46527
|
if (typeof closeAll === "function") closeAll.call(server);
|
|
46521
46528
|
let done = false;
|
|
46522
|
-
const
|
|
46529
|
+
const finish2 = () => {
|
|
46523
46530
|
if (done) return;
|
|
46524
46531
|
done = true;
|
|
46525
46532
|
if (process.platform !== "win32") {
|
|
@@ -46528,8 +46535,8 @@ function startPermissionBroker(socketPath, handlers, opts) {
|
|
|
46528
46535
|
res();
|
|
46529
46536
|
}
|
|
46530
46537
|
};
|
|
46531
|
-
server.close(() =>
|
|
46532
|
-
setTimeout(
|
|
46538
|
+
server.close(() => finish2());
|
|
46539
|
+
setTimeout(finish2, 1e3).unref?.();
|
|
46533
46540
|
})
|
|
46534
46541
|
});
|
|
46535
46542
|
});
|
|
@@ -46966,13 +46973,13 @@ async function createDefaultLlmClient(opts) {
|
|
|
46966
46973
|
const llm = await resolveLlm(opts);
|
|
46967
46974
|
return {
|
|
46968
46975
|
async complete({ system, user }) {
|
|
46969
|
-
const
|
|
46976
|
+
const timeoutMs2 = resolvePlannerTimeoutMs();
|
|
46970
46977
|
const controller = new AbortController();
|
|
46971
46978
|
let timedOut = false;
|
|
46972
|
-
const t =
|
|
46979
|
+
const t = timeoutMs2 > 0 ? setTimeout(() => {
|
|
46973
46980
|
timedOut = true;
|
|
46974
46981
|
controller.abort();
|
|
46975
|
-
},
|
|
46982
|
+
}, timeoutMs2) : void 0;
|
|
46976
46983
|
try {
|
|
46977
46984
|
const url2 = `${llm.baseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
46978
46985
|
let res;
|
|
@@ -46998,7 +47005,7 @@ async function createDefaultLlmClient(opts) {
|
|
|
46998
47005
|
} catch (err) {
|
|
46999
47006
|
if (timedOut) {
|
|
47000
47007
|
throw new PlannerTransportError(
|
|
47001
|
-
`Planner request timed out after ${Math.round(
|
|
47008
|
+
`Planner request timed out after ${Math.round(timeoutMs2 / 1e3)}s (no response). Raise ZELARI_KRAKEN_PLANNER_TIMEOUT_MS, or set ZELARI_KRAKEN_PLANNER_MODEL to a faster non-reasoning model.`
|
|
47002
47009
|
);
|
|
47003
47010
|
}
|
|
47004
47011
|
throw new PlannerTransportError(
|
|
@@ -49381,10 +49388,10 @@ async function validateApiKey(providerId, apiKey, options = {}) {
|
|
|
49381
49388
|
return { ok: true, skipped: true, reason: "no_base_url" };
|
|
49382
49389
|
}
|
|
49383
49390
|
const probeUrl = options.probeUrl ?? `${spec.baseUrl.replace(/\/+$/, "")}/models`;
|
|
49384
|
-
const
|
|
49391
|
+
const timeoutMs2 = options.timeoutMs ?? 5e3;
|
|
49385
49392
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
49386
49393
|
const controller = new AbortController();
|
|
49387
|
-
const timer = setTimeout(() => controller.abort(),
|
|
49394
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs2);
|
|
49388
49395
|
try {
|
|
49389
49396
|
const response = await fetchImpl(probeUrl, {
|
|
49390
49397
|
method: "GET",
|
|
@@ -49413,7 +49420,7 @@ async function validateApiKey(providerId, apiKey, options = {}) {
|
|
|
49413
49420
|
return {
|
|
49414
49421
|
ok: false,
|
|
49415
49422
|
reason: isAbort ? "network" : "network",
|
|
49416
|
-
detail: isAbort ? `timeout after ${
|
|
49423
|
+
detail: isAbort ? `timeout after ${timeoutMs2}ms` : msg,
|
|
49417
49424
|
durationMs
|
|
49418
49425
|
};
|
|
49419
49426
|
} finally {
|
|
@@ -50182,6 +50189,864 @@ var init_atMentions = __esm({
|
|
|
50182
50189
|
}
|
|
50183
50190
|
});
|
|
50184
50191
|
|
|
50192
|
+
// src/cli/gauntlet/policy.ts
|
|
50193
|
+
var policy_exports = {};
|
|
50194
|
+
__export(policy_exports, {
|
|
50195
|
+
DEFAULT_MAX_PARALLEL: () => DEFAULT_MAX_PARALLEL2,
|
|
50196
|
+
DEFAULT_MAX_PIECES: () => DEFAULT_MAX_PIECES,
|
|
50197
|
+
DEFAULT_MAX_ROUNDS: () => DEFAULT_MAX_ROUNDS,
|
|
50198
|
+
DEFAULT_WALL_MS: () => DEFAULT_WALL_MS,
|
|
50199
|
+
GAUNTLET_PARENT_BLOCKED_TOOLS: () => GAUNTLET_PARENT_BLOCKED_TOOLS,
|
|
50200
|
+
isGauntletFlagOn: () => isGauntletFlagOn,
|
|
50201
|
+
resolveGauntletCaps: () => resolveGauntletCaps,
|
|
50202
|
+
shouldRunGauntletHostLoop: () => shouldRunGauntletHostLoop
|
|
50203
|
+
});
|
|
50204
|
+
function envInt(raw, fallback, min, max) {
|
|
50205
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
50206
|
+
const n = Number.parseInt(raw, 10);
|
|
50207
|
+
if (!Number.isFinite(n)) return fallback;
|
|
50208
|
+
return Math.min(max, Math.max(min, n));
|
|
50209
|
+
}
|
|
50210
|
+
function isGauntletFlagOn(explicit, env = process.env) {
|
|
50211
|
+
if (explicit === true) return true;
|
|
50212
|
+
if (explicit === false) return false;
|
|
50213
|
+
const raw = env.ZELARI_GAUNTLET;
|
|
50214
|
+
if (!raw) return false;
|
|
50215
|
+
return raw === "1" || raw.toLowerCase() === "true";
|
|
50216
|
+
}
|
|
50217
|
+
function resolveGauntletCaps(env = process.env) {
|
|
50218
|
+
const wallRaw = env.ZELARI_GAUNTLET_WALL_MS;
|
|
50219
|
+
let wallClockMs = DEFAULT_WALL_MS;
|
|
50220
|
+
if (wallRaw !== void 0 && wallRaw !== "") {
|
|
50221
|
+
const n = Number.parseInt(wallRaw, 10);
|
|
50222
|
+
if (Number.isFinite(n) && n >= 0) wallClockMs = n;
|
|
50223
|
+
}
|
|
50224
|
+
return {
|
|
50225
|
+
maxPieces: envInt(env.ZELARI_GAUNTLET_MAX_PIECES, DEFAULT_MAX_PIECES, 1, 16),
|
|
50226
|
+
maxRounds: envInt(env.ZELARI_GAUNTLET_MAX_ROUNDS, DEFAULT_MAX_ROUNDS, 1, 8),
|
|
50227
|
+
maxParallel: envInt(env.ZELARI_GAUNTLET_MAX_PARALLEL, DEFAULT_MAX_PARALLEL2, 1, 4),
|
|
50228
|
+
wallClockMs
|
|
50229
|
+
};
|
|
50230
|
+
}
|
|
50231
|
+
function shouldRunGauntletHostLoop(opts) {
|
|
50232
|
+
if (!isGauntletFlagOn(opts.gauntlet)) return false;
|
|
50233
|
+
if (opts.krakenGraph) return false;
|
|
50234
|
+
if (opts.useCouncil || opts.mode === "council" || opts.mode === "zelari") return false;
|
|
50235
|
+
const phase2 = opts.phase ?? "build";
|
|
50236
|
+
return phase2 !== "plan";
|
|
50237
|
+
}
|
|
50238
|
+
var DEFAULT_MAX_PIECES, DEFAULT_MAX_ROUNDS, DEFAULT_MAX_PARALLEL2, DEFAULT_WALL_MS, GAUNTLET_PARENT_BLOCKED_TOOLS;
|
|
50239
|
+
var init_policy = __esm({
|
|
50240
|
+
"src/cli/gauntlet/policy.ts"() {
|
|
50241
|
+
"use strict";
|
|
50242
|
+
DEFAULT_MAX_PIECES = 6;
|
|
50243
|
+
DEFAULT_MAX_ROUNDS = 3;
|
|
50244
|
+
DEFAULT_MAX_PARALLEL2 = 2;
|
|
50245
|
+
DEFAULT_WALL_MS = 45 * 60 * 1e3;
|
|
50246
|
+
GAUNTLET_PARENT_BLOCKED_TOOLS = [
|
|
50247
|
+
"write_file",
|
|
50248
|
+
"edit_file",
|
|
50249
|
+
"apply_diff",
|
|
50250
|
+
"bash"
|
|
50251
|
+
];
|
|
50252
|
+
}
|
|
50253
|
+
});
|
|
50254
|
+
|
|
50255
|
+
// src/cli/gauntlet/complete.ts
|
|
50256
|
+
function timeoutMs(env = process.env) {
|
|
50257
|
+
const raw = env.ZELARI_GAUNTLET_DECOMPOSE_TIMEOUT_MS;
|
|
50258
|
+
if (raw === void 0 || raw === "") return DEFAULT_TIMEOUT_MS4;
|
|
50259
|
+
const n = Number.parseInt(raw, 10);
|
|
50260
|
+
return Number.isFinite(n) && n >= 0 ? n : DEFAULT_TIMEOUT_MS4;
|
|
50261
|
+
}
|
|
50262
|
+
async function gauntletComplete(args, opts) {
|
|
50263
|
+
const provider = opts.provider;
|
|
50264
|
+
const meta3 = await resolveApiKeyWithMeta(provider);
|
|
50265
|
+
if (!meta3?.apiKey) {
|
|
50266
|
+
throw new Error(`No API key for provider '${provider}'`);
|
|
50267
|
+
}
|
|
50268
|
+
const baseUrl = resolveBaseUrl(provider);
|
|
50269
|
+
if (!baseUrl) {
|
|
50270
|
+
throw new Error(`No base URL for provider '${provider}'`);
|
|
50271
|
+
}
|
|
50272
|
+
const model = process.env.ZELARI_KRAKEN_PLANNER_MODEL?.trim() || opts.model || getModelForProvider(provider) || getProviderConfig().modelByProvider[provider] || "";
|
|
50273
|
+
if (!model) throw new Error(`No model for provider '${provider}'`);
|
|
50274
|
+
const ms = timeoutMs();
|
|
50275
|
+
const controller = new AbortController();
|
|
50276
|
+
const onParentAbort = () => controller.abort();
|
|
50277
|
+
opts.signal?.addEventListener("abort", onParentAbort, { once: true });
|
|
50278
|
+
let timedOut = false;
|
|
50279
|
+
const timer = ms > 0 ? setTimeout(() => {
|
|
50280
|
+
timedOut = true;
|
|
50281
|
+
controller.abort();
|
|
50282
|
+
}, ms) : void 0;
|
|
50283
|
+
try {
|
|
50284
|
+
const url2 = `${baseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
50285
|
+
const res = await fetch(url2, {
|
|
50286
|
+
method: "POST",
|
|
50287
|
+
signal: controller.signal,
|
|
50288
|
+
headers: {
|
|
50289
|
+
"content-type": "application/json",
|
|
50290
|
+
authorization: `Bearer ${meta3.apiKey}`
|
|
50291
|
+
},
|
|
50292
|
+
body: JSON.stringify({
|
|
50293
|
+
model,
|
|
50294
|
+
temperature: 0.2,
|
|
50295
|
+
max_tokens: DEFAULT_MAX_TOKENS,
|
|
50296
|
+
stream: false,
|
|
50297
|
+
messages: [
|
|
50298
|
+
{ role: "system", content: args.system },
|
|
50299
|
+
{ role: "user", content: args.user }
|
|
50300
|
+
]
|
|
50301
|
+
})
|
|
50302
|
+
});
|
|
50303
|
+
if (!res.ok) {
|
|
50304
|
+
const errBody = await res.text().catch(() => "");
|
|
50305
|
+
throw new Error(`decompose HTTP ${res.status}${errBody ? `: ${errBody.slice(0, 160)}` : ""}`);
|
|
50306
|
+
}
|
|
50307
|
+
const json2 = await res.json();
|
|
50308
|
+
const msg = json2.choices?.[0]?.message;
|
|
50309
|
+
const text = msg?.content?.trim() || msg?.reasoning_content?.trim() || "";
|
|
50310
|
+
if (!text) throw new Error("decompose: empty model response");
|
|
50311
|
+
return text;
|
|
50312
|
+
} catch (err) {
|
|
50313
|
+
if (timedOut) {
|
|
50314
|
+
throw new Error(
|
|
50315
|
+
`decompose timed out after ${Math.round(ms / 1e3)}s \u2014 using a single piece. Raise ZELARI_GAUNTLET_DECOMPOSE_TIMEOUT_MS or set ZELARI_KRAKEN_PLANNER_MODEL to a fast model.`
|
|
50316
|
+
);
|
|
50317
|
+
}
|
|
50318
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
50319
|
+
} finally {
|
|
50320
|
+
if (timer) clearTimeout(timer);
|
|
50321
|
+
opts.signal?.removeEventListener("abort", onParentAbort);
|
|
50322
|
+
}
|
|
50323
|
+
}
|
|
50324
|
+
var DEFAULT_TIMEOUT_MS4, DEFAULT_MAX_TOKENS;
|
|
50325
|
+
var init_complete = __esm({
|
|
50326
|
+
"src/cli/gauntlet/complete.ts"() {
|
|
50327
|
+
"use strict";
|
|
50328
|
+
init_providerConfig();
|
|
50329
|
+
init_keyStore();
|
|
50330
|
+
init_openai_compatible();
|
|
50331
|
+
DEFAULT_TIMEOUT_MS4 = 6e4;
|
|
50332
|
+
DEFAULT_MAX_TOKENS = 2048;
|
|
50333
|
+
}
|
|
50334
|
+
});
|
|
50335
|
+
|
|
50336
|
+
// src/cli/gauntlet/decompose.ts
|
|
50337
|
+
function fallbackPieces(goal) {
|
|
50338
|
+
const prompt = goal.trim() || "Complete the user Goal.";
|
|
50339
|
+
return [
|
|
50340
|
+
{
|
|
50341
|
+
id: "g1",
|
|
50342
|
+
label: labelFromGoal(prompt),
|
|
50343
|
+
prompt,
|
|
50344
|
+
acceptance: []
|
|
50345
|
+
}
|
|
50346
|
+
];
|
|
50347
|
+
}
|
|
50348
|
+
function labelFromGoal(goal) {
|
|
50349
|
+
const line = goal.trim().split(/\r?\n/, 1)[0] ?? "Goal";
|
|
50350
|
+
return line.slice(0, MAX_LABEL) || "Goal";
|
|
50351
|
+
}
|
|
50352
|
+
function parsePiecesJson(raw, maxPieces) {
|
|
50353
|
+
if (!raw || typeof raw !== "object") return null;
|
|
50354
|
+
const rec = raw;
|
|
50355
|
+
const list = rec.pieces ?? rec.nodes;
|
|
50356
|
+
if (!Array.isArray(list) || list.length === 0) return null;
|
|
50357
|
+
const out = [];
|
|
50358
|
+
for (let i = 0; i < list.length && out.length < maxPieces; i++) {
|
|
50359
|
+
const item = list[i];
|
|
50360
|
+
if (!item || typeof item !== "object") continue;
|
|
50361
|
+
const row = item;
|
|
50362
|
+
const prompt = typeof row.prompt === "string" ? row.prompt.trim() : typeof row.goal === "string" ? row.goal.trim() : "";
|
|
50363
|
+
if (!prompt) continue;
|
|
50364
|
+
const id = typeof row.id === "string" && row.id.trim() ? row.id.trim().slice(0, 32) : `g${out.length + 1}`;
|
|
50365
|
+
const label = typeof row.label === "string" && row.label.trim() ? row.label.trim().slice(0, MAX_LABEL) : labelFromGoal(prompt);
|
|
50366
|
+
const acceptance = Array.isArray(row.acceptance) ? row.acceptance.filter((a) => typeof a === "string" && a.trim().length > 0).map((a) => a.trim()).slice(0, MAX_ACCEPTANCE) : [];
|
|
50367
|
+
const scope = Array.isArray(row.scope) ? row.scope.filter((s) => typeof s === "string" && s.trim().length > 0).map((s) => s.trim()).slice(0, 16) : void 0;
|
|
50368
|
+
const bar = Array.isArray(row.bar) ? row.bar.filter((s) => typeof s === "string" && s.trim().length > 0).map((s) => s.trim()).slice(0, 4) : void 0;
|
|
50369
|
+
out.push({
|
|
50370
|
+
id: uniqueId2(id, out),
|
|
50371
|
+
label,
|
|
50372
|
+
prompt: prompt.slice(0, MAX_PROMPT),
|
|
50373
|
+
acceptance,
|
|
50374
|
+
...scope && scope.length > 0 ? { scope } : {},
|
|
50375
|
+
...bar && bar.length > 0 ? { bar } : {}
|
|
50376
|
+
});
|
|
50377
|
+
}
|
|
50378
|
+
return out.length > 0 ? out : null;
|
|
50379
|
+
}
|
|
50380
|
+
function formatHistoryNote(messages, maxMessages = 4, each = 400) {
|
|
50381
|
+
const slice = messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-maxMessages);
|
|
50382
|
+
if (slice.length === 0) return "";
|
|
50383
|
+
return slice.map((m) => {
|
|
50384
|
+
const body = m.content.replace(/\s+/g, " ").trim().slice(0, each);
|
|
50385
|
+
return `${m.role}: ${body}`;
|
|
50386
|
+
}).join("\n");
|
|
50387
|
+
}
|
|
50388
|
+
function buildDecomposeUser(opts) {
|
|
50389
|
+
const parts = [
|
|
50390
|
+
`Max pieces: ${opts.maxPieces}`,
|
|
50391
|
+
"",
|
|
50392
|
+
"## Goal",
|
|
50393
|
+
opts.goal.trim() || "(empty)"
|
|
50394
|
+
];
|
|
50395
|
+
if (opts.historyNote?.trim()) {
|
|
50396
|
+
parts.push("", "## Prior turns (context only \u2014 the Goal above is authoritative)", opts.historyNote.trim());
|
|
50397
|
+
}
|
|
50398
|
+
if (opts.workspace?.trim()) {
|
|
50399
|
+
parts.push("", "## Workspace", opts.workspace.trim());
|
|
50400
|
+
}
|
|
50401
|
+
return parts.join("\n");
|
|
50402
|
+
}
|
|
50403
|
+
function piecesFromModelText(text, maxPieces) {
|
|
50404
|
+
try {
|
|
50405
|
+
const json2 = extractJsonObject(text, { requireKey: "pieces" });
|
|
50406
|
+
return parsePiecesJson(json2, maxPieces);
|
|
50407
|
+
} catch {
|
|
50408
|
+
return null;
|
|
50409
|
+
}
|
|
50410
|
+
}
|
|
50411
|
+
async function decomposeGoal(opts) {
|
|
50412
|
+
const fallback = fallbackPieces(opts.goal);
|
|
50413
|
+
if (!opts.complete) return { pieces: fallback, source: "fallback" };
|
|
50414
|
+
try {
|
|
50415
|
+
const text = await opts.complete({
|
|
50416
|
+
system: GAUNTLET_DECOMPOSE_SYSTEM,
|
|
50417
|
+
user: buildDecomposeUser(opts)
|
|
50418
|
+
});
|
|
50419
|
+
const parsed = piecesFromModelText(text, opts.maxPieces);
|
|
50420
|
+
if (parsed && parsed.length > 0) return { pieces: parsed, source: "llm" };
|
|
50421
|
+
return { pieces: fallback, source: "fallback", error: "decompose JSON unusable" };
|
|
50422
|
+
} catch (err) {
|
|
50423
|
+
return {
|
|
50424
|
+
pieces: fallback,
|
|
50425
|
+
source: "fallback",
|
|
50426
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50427
|
+
};
|
|
50428
|
+
}
|
|
50429
|
+
}
|
|
50430
|
+
function uniqueId2(id, existing) {
|
|
50431
|
+
if (!existing.some((p3) => p3.id === id)) return id;
|
|
50432
|
+
let n = 2;
|
|
50433
|
+
while (existing.some((p3) => p3.id === `${id}-${n}`)) n += 1;
|
|
50434
|
+
return `${id}-${n}`;
|
|
50435
|
+
}
|
|
50436
|
+
var MAX_LABEL, MAX_PROMPT, MAX_ACCEPTANCE, GAUNTLET_DECOMPOSE_SYSTEM;
|
|
50437
|
+
var init_decompose = __esm({
|
|
50438
|
+
"src/cli/gauntlet/decompose.ts"() {
|
|
50439
|
+
"use strict";
|
|
50440
|
+
init_planner();
|
|
50441
|
+
MAX_LABEL = 80;
|
|
50442
|
+
MAX_PROMPT = 8e3;
|
|
50443
|
+
MAX_ACCEPTANCE = 8;
|
|
50444
|
+
GAUNTLET_DECOMPOSE_SYSTEM = [
|
|
50445
|
+
"Decompose the user Goal into independently shippable Gauntlet pieces.",
|
|
50446
|
+
"Return ONLY JSON (no markdown, no prose):",
|
|
50447
|
+
'{ "pieces": [ { "id": string, "label": string, "prompt": string, "scope"?: string[], "acceptance"?: string[], "bar"?: string[] } ] }',
|
|
50448
|
+
"Rules:",
|
|
50449
|
+
"- 1 to N pieces (N is given in the user message). Prefer fewer. One piece is valid when the goal is atomic.",
|
|
50450
|
+
'- "prompt" is self-contained: the builder will not see this conversation.',
|
|
50451
|
+
'- "scope" is a path allowlist so disjoint pieces can run in parallel. Omit if unsure (forces sequential).',
|
|
50452
|
+
'- "acceptance" is checkable (file, command, observable). Never subjective ("elegant").',
|
|
50453
|
+
'- "bar" (optional) is on-disk reference path(s) the critic compares against blindly (gold file, screenshot, test).',
|
|
50454
|
+
"- Use paths from the workspace listing. Do not invent a tree.",
|
|
50455
|
+
"- Decompose the USER GOAL literally. Do not enlarge it into a different project."
|
|
50456
|
+
].join("\n");
|
|
50457
|
+
}
|
|
50458
|
+
});
|
|
50459
|
+
|
|
50460
|
+
// src/cli/gauntlet/events.ts
|
|
50461
|
+
function gauntletProgressEvent(sessionId2, progress) {
|
|
50462
|
+
return {
|
|
50463
|
+
type: "gauntlet_progress",
|
|
50464
|
+
sessionId: sessionId2,
|
|
50465
|
+
ts: Date.now(),
|
|
50466
|
+
progress
|
|
50467
|
+
};
|
|
50468
|
+
}
|
|
50469
|
+
function formatGauntletSummary(results, opts) {
|
|
50470
|
+
if (results.length === 0) {
|
|
50471
|
+
if (opts?.timedOut) return "Gauntlet stopped: wall clock. No pieces finished.";
|
|
50472
|
+
if (opts?.cancelled) return "Gauntlet cancelled. No pieces finished.";
|
|
50473
|
+
return "Gauntlet: no pieces ran.";
|
|
50474
|
+
}
|
|
50475
|
+
const head = opts?.timedOut ? "Gauntlet stopped: wall clock." : opts?.cancelled ? "Gauntlet cancelled." : "Gauntlet finished.";
|
|
50476
|
+
const lines = [head, ""];
|
|
50477
|
+
for (const r of results) {
|
|
50478
|
+
const gap = r.gap ? ` \u2014 ${r.gap}` : "";
|
|
50479
|
+
const win = r.winner ? ` [A/B ${r.winner}]` : "";
|
|
50480
|
+
lines.push(`- ${r.label} (${r.id}): ${r.verdict} after ${r.rounds} round(s)${win}${gap}`);
|
|
50481
|
+
}
|
|
50482
|
+
return lines.join("\n");
|
|
50483
|
+
}
|
|
50484
|
+
var init_events3 = __esm({
|
|
50485
|
+
"src/cli/gauntlet/events.ts"() {
|
|
50486
|
+
"use strict";
|
|
50487
|
+
}
|
|
50488
|
+
});
|
|
50489
|
+
|
|
50490
|
+
// src/cli/gauntlet/blind.ts
|
|
50491
|
+
function assignBlindLabels(items, rand = Math.random) {
|
|
50492
|
+
if (rand() < 0.5) {
|
|
50493
|
+
return { A: items[0], B: items[1], firstLabel: "A" };
|
|
50494
|
+
}
|
|
50495
|
+
return { A: items[1], B: items[0], firstLabel: "B" };
|
|
50496
|
+
}
|
|
50497
|
+
function qualityBarSection(bars, rand = Math.random) {
|
|
50498
|
+
if (!bars || bars.length === 0) return "";
|
|
50499
|
+
if (bars.length === 1) {
|
|
50500
|
+
return [
|
|
50501
|
+
"## Quality bar (blind)",
|
|
50502
|
+
"Inspect this reference on disk. PASS only if the work in Scope meets or beats it.",
|
|
50503
|
+
"Do not assume the new files are better \u2014 compare concretely.",
|
|
50504
|
+
`- ${bars[0]}`
|
|
50505
|
+
].join("\n");
|
|
50506
|
+
}
|
|
50507
|
+
const pair = assignBlindLabels([bars[0], bars[1]], rand);
|
|
50508
|
+
return [
|
|
50509
|
+
"## Blind A/B",
|
|
50510
|
+
"Two unlabeled artifacts on disk. Compare them against the piece acceptance.",
|
|
50511
|
+
'Do not assume which is newer or which you are "supposed" to prefer.',
|
|
50512
|
+
`A: ${pair.A}`,
|
|
50513
|
+
`B: ${pair.B}`,
|
|
50514
|
+
"Also emit: WINNER: A | B | TIE"
|
|
50515
|
+
].join("\n");
|
|
50516
|
+
}
|
|
50517
|
+
function parseBlindWinner(text) {
|
|
50518
|
+
const m = WINNER_RE.exec(text);
|
|
50519
|
+
if (!m) return void 0;
|
|
50520
|
+
const v = m[1].toUpperCase();
|
|
50521
|
+
if (v === "A" || v === "B" || v === "TIE") return v;
|
|
50522
|
+
return void 0;
|
|
50523
|
+
}
|
|
50524
|
+
var WINNER_RE;
|
|
50525
|
+
var init_blind = __esm({
|
|
50526
|
+
"src/cli/gauntlet/blind.ts"() {
|
|
50527
|
+
"use strict";
|
|
50528
|
+
WINNER_RE = /\bWINNER:\s*(A|B|TIE)\b/i;
|
|
50529
|
+
}
|
|
50530
|
+
});
|
|
50531
|
+
|
|
50532
|
+
// src/cli/gauntlet/verdict.ts
|
|
50533
|
+
function parseGauntletVerdict(text, opts = {}) {
|
|
50534
|
+
const evidence = (opts.toolTraceCount ?? 0) > 0;
|
|
50535
|
+
if (opts.builderFailed) {
|
|
50536
|
+
return {
|
|
50537
|
+
kind: "GAP",
|
|
50538
|
+
gap: (opts.builderError ?? "builder failed").trim() || "builder failed",
|
|
50539
|
+
evidence
|
|
50540
|
+
};
|
|
50541
|
+
}
|
|
50542
|
+
const raw = (text ?? "").trim();
|
|
50543
|
+
if (!raw) {
|
|
50544
|
+
return { kind: "BLOCKED", gap: "critic produced no output", evidence };
|
|
50545
|
+
}
|
|
50546
|
+
const explicit = VERDICT_RE.exec(raw);
|
|
50547
|
+
let kind = explicit ? explicit[1].toUpperCase() : void 0;
|
|
50548
|
+
const reports = [...raw.matchAll(REPORT_STATUS_RE)].map((m) => m[1].toLowerCase());
|
|
50549
|
+
const anyFail = reports.includes("fail");
|
|
50550
|
+
const anyUnknown = reports.includes("unknown");
|
|
50551
|
+
const anyPass = reports.includes("pass");
|
|
50552
|
+
if (!kind) {
|
|
50553
|
+
if (anyFail) kind = "GAP";
|
|
50554
|
+
else if (anyPass && !anyUnknown) kind = "PASS";
|
|
50555
|
+
else if (anyUnknown && !anyPass) kind = "BLOCKED";
|
|
50556
|
+
else kind = "BLOCKED";
|
|
50557
|
+
}
|
|
50558
|
+
const gapMatch = GAP_RE.exec(raw);
|
|
50559
|
+
let gap = gapMatch ? gapMatch[1].trim() : void 0;
|
|
50560
|
+
if (kind === "GAP" && !gap) {
|
|
50561
|
+
gap = anyFail ? "a verify-report check failed" : "critic named a gap without a GAP: line";
|
|
50562
|
+
}
|
|
50563
|
+
if (kind === "PASS" && !evidence) {
|
|
50564
|
+
return {
|
|
50565
|
+
kind: "GAP",
|
|
50566
|
+
gap: "unknown \u2260 pass: critic declared PASS without tool evidence",
|
|
50567
|
+
evidence: false
|
|
50568
|
+
};
|
|
50569
|
+
}
|
|
50570
|
+
if (kind === "PASS" && anyFail) {
|
|
50571
|
+
return {
|
|
50572
|
+
kind: "GAP",
|
|
50573
|
+
gap: gap ?? "verify-report contains a fail",
|
|
50574
|
+
evidence
|
|
50575
|
+
};
|
|
50576
|
+
}
|
|
50577
|
+
return { kind, ...gap ? { gap } : {}, evidence };
|
|
50578
|
+
}
|
|
50579
|
+
var VERDICT_RE, GAP_RE, REPORT_STATUS_RE;
|
|
50580
|
+
var init_verdict2 = __esm({
|
|
50581
|
+
"src/cli/gauntlet/verdict.ts"() {
|
|
50582
|
+
"use strict";
|
|
50583
|
+
VERDICT_RE = /\bVERDICT:\s*(PASS|GAP|BLOCKED)\b/i;
|
|
50584
|
+
GAP_RE = /\bGAP:\s*(.+)/i;
|
|
50585
|
+
REPORT_STATUS_RE = /^status:\s*(pass|fail|unknown)\b/gim;
|
|
50586
|
+
}
|
|
50587
|
+
});
|
|
50588
|
+
|
|
50589
|
+
// src/cli/gauntlet/prompts.ts
|
|
50590
|
+
function builderUserPrompt(piece, gap, briefing) {
|
|
50591
|
+
const parts = [
|
|
50592
|
+
`You are the BUILDER for one Gauntlet piece. Implement it on disk.`,
|
|
50593
|
+
`Do not spawn sub-agents. Stay inside Scope if provided.`
|
|
50594
|
+
];
|
|
50595
|
+
if (briefing?.trim()) {
|
|
50596
|
+
parts.push("", "## Workspace briefing (do not treat as already-done work)", briefing.trim());
|
|
50597
|
+
}
|
|
50598
|
+
parts.push("", `## Piece: ${piece.label}`, piece.prompt.trim());
|
|
50599
|
+
if (piece.scope && piece.scope.length > 0) {
|
|
50600
|
+
parts.push("", "## Scope", ...piece.scope.map((s) => `- ${s}`));
|
|
50601
|
+
}
|
|
50602
|
+
if (piece.acceptance.length > 0) {
|
|
50603
|
+
parts.push("", "## Acceptance", ...piece.acceptance.map((a) => `- ${a}`));
|
|
50604
|
+
}
|
|
50605
|
+
if (gap && gap.trim()) {
|
|
50606
|
+
parts.push(
|
|
50607
|
+
"",
|
|
50608
|
+
"## Previous critic GAP (fix ONLY this)",
|
|
50609
|
+
gap.trim(),
|
|
50610
|
+
"Do not widen scope. Re-check the acceptance after the fix."
|
|
50611
|
+
);
|
|
50612
|
+
}
|
|
50613
|
+
parts.push("", "Return: files touched, what changed, residual risks.");
|
|
50614
|
+
return parts.join("\n");
|
|
50615
|
+
}
|
|
50616
|
+
function criticUserPrompt(piece, round, rand) {
|
|
50617
|
+
const parts = [
|
|
50618
|
+
`Round ${round}. Inspect the current tree against this piece.`,
|
|
50619
|
+
"Do not edit files. Do not take the builder's word \u2014 open files / run checks.",
|
|
50620
|
+
"",
|
|
50621
|
+
`## Piece: ${piece.label}`,
|
|
50622
|
+
piece.prompt.trim()
|
|
50623
|
+
];
|
|
50624
|
+
if (piece.scope && piece.scope.length > 0) {
|
|
50625
|
+
parts.push("", "## Scope", ...piece.scope.map((s) => `- ${s}`));
|
|
50626
|
+
}
|
|
50627
|
+
if (piece.acceptance.length > 0) {
|
|
50628
|
+
parts.push("", "## Acceptance (check each)", ...piece.acceptance.map((a) => `- ${a}`));
|
|
50629
|
+
} else {
|
|
50630
|
+
parts.push(
|
|
50631
|
+
"",
|
|
50632
|
+
"## Acceptance",
|
|
50633
|
+
"- The piece prompt is satisfied by files on disk.",
|
|
50634
|
+
"- Relevant typecheck/tests pass when the project has them."
|
|
50635
|
+
);
|
|
50636
|
+
}
|
|
50637
|
+
const bar = qualityBarSection(piece.bar, rand);
|
|
50638
|
+
if (bar) parts.push("", bar);
|
|
50639
|
+
return parts.join("\n");
|
|
50640
|
+
}
|
|
50641
|
+
var GAUNTLET_CRITIC_SYSTEM;
|
|
50642
|
+
var init_prompts = __esm({
|
|
50643
|
+
"src/cli/gauntlet/prompts.ts"() {
|
|
50644
|
+
"use strict";
|
|
50645
|
+
init_blind();
|
|
50646
|
+
GAUNTLET_CRITIC_SYSTEM = [
|
|
50647
|
+
"You are a ruthless VERIFY critic in a Gauntlet Loop.",
|
|
50648
|
+
"Inspect the REAL files and commands on disk. Do not trust a builder self-report.",
|
|
50649
|
+
"You have no builder transcript \u2014 only the Goal, Scope, Acceptance, and the tree.",
|
|
50650
|
+
"OBSERVATION INTEGRITY: unknown \u2260 pass. EMPTY/degraded tools are not evidence.",
|
|
50651
|
+
"Name at most ONE biggest remaining gap. Do not write a laundry list.",
|
|
50652
|
+
"You may read files and run test/build commands via bash. Prefer targeted checks.",
|
|
50653
|
+
"",
|
|
50654
|
+
"End with BOTH:",
|
|
50655
|
+
"1. One <verify-report> block per acceptance criterion:",
|
|
50656
|
+
"<verify-report>",
|
|
50657
|
+
"check: <criterion text as given>",
|
|
50658
|
+
"status: pass | fail | unknown",
|
|
50659
|
+
"note: <one line of evidence (command or file + outcome)>",
|
|
50660
|
+
"</verify-report>",
|
|
50661
|
+
"2. A trailer on its own lines:",
|
|
50662
|
+
"VERDICT: PASS | GAP | BLOCKED",
|
|
50663
|
+
"GAP: <single biggest remaining gap; omit on PASS>",
|
|
50664
|
+
"3. If a Blind A/B section is present, also emit WINNER: A | B | TIE"
|
|
50665
|
+
].join("\n");
|
|
50666
|
+
}
|
|
50667
|
+
});
|
|
50668
|
+
|
|
50669
|
+
// src/cli/gauntlet/schedule.ts
|
|
50670
|
+
function piecesCanRunInParallel(a, b) {
|
|
50671
|
+
return disjointScopeSets(a.scope, b.scope);
|
|
50672
|
+
}
|
|
50673
|
+
function scheduleWaves(pieces, maxParallel) {
|
|
50674
|
+
const cap3 = Math.max(1, maxParallel);
|
|
50675
|
+
const remaining = [...pieces];
|
|
50676
|
+
const waves = [];
|
|
50677
|
+
while (remaining.length > 0) {
|
|
50678
|
+
const wave = [];
|
|
50679
|
+
const leftover = [];
|
|
50680
|
+
for (const p3 of remaining) {
|
|
50681
|
+
if (wave.length >= cap3) {
|
|
50682
|
+
leftover.push(p3);
|
|
50683
|
+
continue;
|
|
50684
|
+
}
|
|
50685
|
+
if (wave.length === 0 || wave.every((w) => piecesCanRunInParallel(w, p3))) {
|
|
50686
|
+
wave.push(p3);
|
|
50687
|
+
} else {
|
|
50688
|
+
leftover.push(p3);
|
|
50689
|
+
}
|
|
50690
|
+
}
|
|
50691
|
+
waves.push(wave);
|
|
50692
|
+
remaining.splice(0, remaining.length, ...leftover);
|
|
50693
|
+
}
|
|
50694
|
+
return waves;
|
|
50695
|
+
}
|
|
50696
|
+
var init_schedule = __esm({
|
|
50697
|
+
"src/cli/gauntlet/schedule.ts"() {
|
|
50698
|
+
"use strict";
|
|
50699
|
+
init_dist();
|
|
50700
|
+
}
|
|
50701
|
+
});
|
|
50702
|
+
|
|
50703
|
+
// src/cli/gauntlet/loop.ts
|
|
50704
|
+
async function runGauntletLoop(args) {
|
|
50705
|
+
const { caps, deps } = args;
|
|
50706
|
+
const pieces = args.pieces.slice(0, caps.maxPieces);
|
|
50707
|
+
const started = (deps.now ?? Date.now)();
|
|
50708
|
+
const results = [];
|
|
50709
|
+
const emitProgress = (partial2) => {
|
|
50710
|
+
const progress = {
|
|
50711
|
+
...partial2,
|
|
50712
|
+
elapsedMs: (deps.now ?? Date.now)() - started
|
|
50713
|
+
};
|
|
50714
|
+
deps.emit(gauntletProgressEvent(deps.sessionId, progress));
|
|
50715
|
+
deps.note?.("gauntlet.progress", progress);
|
|
50716
|
+
};
|
|
50717
|
+
const wall = caps.wallClockMs === void 0 ? DEFAULT_WALL_MS : caps.wallClockMs;
|
|
50718
|
+
const expired = () => wall > 0 && (deps.now ?? Date.now)() - started >= wall;
|
|
50719
|
+
const aborted2 = () => Boolean(deps.signal?.aborted);
|
|
50720
|
+
const stop = () => aborted2() || expired();
|
|
50721
|
+
const indexOf = (piece) => pieces.findIndex((p3) => p3.id === piece.id);
|
|
50722
|
+
const runOnePiece = async (piece) => {
|
|
50723
|
+
let last = {
|
|
50724
|
+
kind: "BLOCKED",
|
|
50725
|
+
gap: "no round ran",
|
|
50726
|
+
evidence: false
|
|
50727
|
+
};
|
|
50728
|
+
let gap;
|
|
50729
|
+
let winner;
|
|
50730
|
+
let rounds = 0;
|
|
50731
|
+
const i = Math.max(0, indexOf(piece));
|
|
50732
|
+
for (let round = 1; round <= caps.maxRounds; round++) {
|
|
50733
|
+
if (stop()) break;
|
|
50734
|
+
rounds = round;
|
|
50735
|
+
const phase2 = gap ? "repairing" : "building";
|
|
50736
|
+
emitProgress({
|
|
50737
|
+
phase: phase2,
|
|
50738
|
+
pieceId: piece.id,
|
|
50739
|
+
pieceLabel: piece.label,
|
|
50740
|
+
pieceIndex: i,
|
|
50741
|
+
pieceCount: pieces.length,
|
|
50742
|
+
round,
|
|
50743
|
+
maxRounds: caps.maxRounds
|
|
50744
|
+
});
|
|
50745
|
+
const built = await deps.runBuilder({
|
|
50746
|
+
piece,
|
|
50747
|
+
prompt: builderUserPrompt(piece, gap, deps.briefing),
|
|
50748
|
+
round
|
|
50749
|
+
});
|
|
50750
|
+
if (stop()) break;
|
|
50751
|
+
emitProgress({
|
|
50752
|
+
phase: "critiquing",
|
|
50753
|
+
pieceId: piece.id,
|
|
50754
|
+
pieceLabel: piece.label,
|
|
50755
|
+
pieceIndex: i,
|
|
50756
|
+
pieceCount: pieces.length,
|
|
50757
|
+
round,
|
|
50758
|
+
maxRounds: caps.maxRounds
|
|
50759
|
+
});
|
|
50760
|
+
const criticized = await deps.runCritic({
|
|
50761
|
+
piece,
|
|
50762
|
+
prompt: criticUserPrompt(piece, round),
|
|
50763
|
+
systemPrompt: GAUNTLET_CRITIC_SYSTEM,
|
|
50764
|
+
round
|
|
50765
|
+
});
|
|
50766
|
+
last = parseGauntletVerdict(criticized.result, {
|
|
50767
|
+
toolTraceCount: criticized.toolTraceCount ?? 0,
|
|
50768
|
+
builderFailed: !built.ok,
|
|
50769
|
+
builderError: built.error
|
|
50770
|
+
});
|
|
50771
|
+
winner = parseBlindWinner(criticized.result) ?? winner;
|
|
50772
|
+
emitProgress({
|
|
50773
|
+
phase: last.kind === "PASS" ? "settled" : last.kind === "BLOCKED" ? "blocked" : "repairing",
|
|
50774
|
+
pieceId: piece.id,
|
|
50775
|
+
pieceLabel: piece.label,
|
|
50776
|
+
pieceIndex: i,
|
|
50777
|
+
pieceCount: pieces.length,
|
|
50778
|
+
round,
|
|
50779
|
+
maxRounds: caps.maxRounds,
|
|
50780
|
+
verdict: last.kind,
|
|
50781
|
+
gap: last.gap,
|
|
50782
|
+
winner
|
|
50783
|
+
});
|
|
50784
|
+
if (last.kind === "PASS" || last.kind === "BLOCKED") break;
|
|
50785
|
+
gap = last.gap;
|
|
50786
|
+
}
|
|
50787
|
+
return {
|
|
50788
|
+
id: piece.id,
|
|
50789
|
+
label: piece.label,
|
|
50790
|
+
verdict: last,
|
|
50791
|
+
rounds,
|
|
50792
|
+
...winner ? { winner } : {}
|
|
50793
|
+
};
|
|
50794
|
+
};
|
|
50795
|
+
for (const wave of scheduleWaves(pieces, caps.maxParallel)) {
|
|
50796
|
+
if (stop()) return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50797
|
+
if (wave.length === 1) {
|
|
50798
|
+
results.push(await runOnePiece(wave[0]));
|
|
50799
|
+
} else {
|
|
50800
|
+
const waveResults = await Promise.all(wave.map((p3) => runOnePiece(p3)));
|
|
50801
|
+
results.push(...waveResults);
|
|
50802
|
+
}
|
|
50803
|
+
if (stop()) return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50804
|
+
}
|
|
50805
|
+
return finish(results, { cancelled: aborted2(), timedOut: expired() });
|
|
50806
|
+
}
|
|
50807
|
+
function finish(results, flags) {
|
|
50808
|
+
const cancelled = flags.timedOut ? false : flags.cancelled;
|
|
50809
|
+
const timedOut = flags.timedOut;
|
|
50810
|
+
const settled = !cancelled && !timedOut && results.length > 0 && results.every((r) => r.verdict.kind === "PASS");
|
|
50811
|
+
return {
|
|
50812
|
+
settled,
|
|
50813
|
+
cancelled,
|
|
50814
|
+
timedOut,
|
|
50815
|
+
pieces: results,
|
|
50816
|
+
summary: formatGauntletSummary(
|
|
50817
|
+
results.map((r) => ({
|
|
50818
|
+
id: r.id,
|
|
50819
|
+
label: r.label,
|
|
50820
|
+
verdict: r.verdict.kind,
|
|
50821
|
+
rounds: r.rounds,
|
|
50822
|
+
gap: r.verdict.gap,
|
|
50823
|
+
winner: r.winner
|
|
50824
|
+
})),
|
|
50825
|
+
{ timedOut, cancelled }
|
|
50826
|
+
)
|
|
50827
|
+
};
|
|
50828
|
+
}
|
|
50829
|
+
var init_loop = __esm({
|
|
50830
|
+
"src/cli/gauntlet/loop.ts"() {
|
|
50831
|
+
"use strict";
|
|
50832
|
+
init_blind();
|
|
50833
|
+
init_policy();
|
|
50834
|
+
init_verdict2();
|
|
50835
|
+
init_prompts();
|
|
50836
|
+
init_schedule();
|
|
50837
|
+
init_events3();
|
|
50838
|
+
}
|
|
50839
|
+
});
|
|
50840
|
+
|
|
50841
|
+
// src/cli/gauntlet/run.ts
|
|
50842
|
+
var run_exports = {};
|
|
50843
|
+
__export(run_exports, {
|
|
50844
|
+
runHeadlessGauntlet: () => runHeadlessGauntlet
|
|
50845
|
+
});
|
|
50846
|
+
async function runHeadlessGauntlet(opts, provider, model) {
|
|
50847
|
+
const sessionId2 = opts.resumeSessionId ?? crypto.randomUUID();
|
|
50848
|
+
const spine = await openHeadlessSpine({
|
|
50849
|
+
sessionId: sessionId2,
|
|
50850
|
+
mode: opts.mode,
|
|
50851
|
+
profile: opts.profile,
|
|
50852
|
+
workspace: process.cwd()
|
|
50853
|
+
});
|
|
50854
|
+
emitEvent(sessionStartedEvent(spine));
|
|
50855
|
+
const seeded = await seedHeadlessModelHistory(spine, opts.history);
|
|
50856
|
+
if (opts.task) spine.userMessage(opts.task);
|
|
50857
|
+
spine.note("gauntlet.start", { goal: opts.task.slice(0, 200) });
|
|
50858
|
+
const abort = new AbortController();
|
|
50859
|
+
const onSigint = () => {
|
|
50860
|
+
emitEvent({ type: "log", message: "[gauntlet] SIGINT \u2014 cancelling" });
|
|
50861
|
+
abort.abort();
|
|
50862
|
+
};
|
|
50863
|
+
process.once("SIGINT", onSigint);
|
|
50864
|
+
const wallMs = resolveGauntletCaps().wallClockMs ?? 0;
|
|
50865
|
+
const wallTimer = wallMs > 0 ? setTimeout(() => {
|
|
50866
|
+
emitEvent({ type: "log", message: "[gauntlet] wall clock \u2014 aborting tentacles" });
|
|
50867
|
+
abort.abort();
|
|
50868
|
+
}, wallMs) : void 0;
|
|
50869
|
+
const cwd = process.cwd();
|
|
50870
|
+
const audit = new AuditLogger();
|
|
50871
|
+
const createSubAgentContext = createKrakenSubAgentContextFactory({
|
|
50872
|
+
root: cwd,
|
|
50873
|
+
audit,
|
|
50874
|
+
sessionId: sessionId2,
|
|
50875
|
+
provider,
|
|
50876
|
+
model
|
|
50877
|
+
});
|
|
50878
|
+
const deps = {
|
|
50879
|
+
createSubAgentContext,
|
|
50880
|
+
allowWorktree: false,
|
|
50881
|
+
harnessFactory: (config2) => {
|
|
50882
|
+
const harness = new AgentHarness(config2);
|
|
50883
|
+
return {
|
|
50884
|
+
async *run() {
|
|
50885
|
+
for await (const ev of harness.run()) {
|
|
50886
|
+
if (ev.type === "thinking_delta" || ev.type === "tool_execution_start" || ev.type === "tool_execution_end") {
|
|
50887
|
+
emitEvent(ev);
|
|
50888
|
+
spine.observe(ev);
|
|
50889
|
+
}
|
|
50890
|
+
yield ev;
|
|
50891
|
+
}
|
|
50892
|
+
},
|
|
50893
|
+
cancel: () => harness.cancel()
|
|
50894
|
+
};
|
|
50895
|
+
}
|
|
50896
|
+
};
|
|
50897
|
+
const emit = (event) => {
|
|
50898
|
+
if (opts.output === "json") emitEvent(event);
|
|
50899
|
+
else if (typeof event.message === "string") {
|
|
50900
|
+
process.stderr.write(`${event.message}
|
|
50901
|
+
`);
|
|
50902
|
+
}
|
|
50903
|
+
};
|
|
50904
|
+
emitEvent({ type: "agent_start", model, provider, role: "gauntlet" });
|
|
50905
|
+
emit({ type: "log", message: "[gauntlet] host loop \u2014 builder/critic rounds, parent cannot write" });
|
|
50906
|
+
const caps = resolveGauntletCaps();
|
|
50907
|
+
const workspace = buildWorkspaceSummary(cwd, { maxChars: 2500 });
|
|
50908
|
+
const historyNote = formatHistoryNote(seeded.history);
|
|
50909
|
+
emitEvent(
|
|
50910
|
+
gauntletProgressEvent(sessionId2, {
|
|
50911
|
+
phase: "decomposing",
|
|
50912
|
+
pieceId: "",
|
|
50913
|
+
pieceLabel: "Goal",
|
|
50914
|
+
pieceIndex: 0,
|
|
50915
|
+
pieceCount: 1,
|
|
50916
|
+
round: 0,
|
|
50917
|
+
maxRounds: caps.maxRounds,
|
|
50918
|
+
elapsedMs: 0
|
|
50919
|
+
})
|
|
50920
|
+
);
|
|
50921
|
+
try {
|
|
50922
|
+
const decomposed = await decomposeGoal({
|
|
50923
|
+
goal: opts.task,
|
|
50924
|
+
maxPieces: caps.maxPieces,
|
|
50925
|
+
workspace,
|
|
50926
|
+
historyNote,
|
|
50927
|
+
complete: (req) => gauntletComplete(req, { provider, model, signal: abort.signal })
|
|
50928
|
+
});
|
|
50929
|
+
spine.note("gauntlet.decompose", {
|
|
50930
|
+
source: decomposed.source,
|
|
50931
|
+
count: decomposed.pieces.length,
|
|
50932
|
+
...decomposed.error ? { error: decomposed.error.slice(0, 240) } : {}
|
|
50933
|
+
});
|
|
50934
|
+
emit({
|
|
50935
|
+
type: "log",
|
|
50936
|
+
message: `[gauntlet] ${decomposed.pieces.length} piece(s) from ${decomposed.source}${decomposed.error ? ` (${decomposed.error.slice(0, 80)})` : ""}`
|
|
50937
|
+
});
|
|
50938
|
+
const result = await runGauntletLoop({
|
|
50939
|
+
pieces: decomposed.pieces,
|
|
50940
|
+
caps,
|
|
50941
|
+
deps: {
|
|
50942
|
+
sessionId: sessionId2,
|
|
50943
|
+
signal: abort.signal,
|
|
50944
|
+
emit,
|
|
50945
|
+
briefing: workspace.slice(0, 1200),
|
|
50946
|
+
note: (text, data) => spine.note(text, data),
|
|
50947
|
+
runBuilder: async ({ piece, prompt, round }) => {
|
|
50948
|
+
emit({
|
|
50949
|
+
type: "log",
|
|
50950
|
+
message: `[gauntlet] ${piece.id} round ${round}/${caps.maxRounds} builder`
|
|
50951
|
+
});
|
|
50952
|
+
const tent = await runTentacle({
|
|
50953
|
+
deps,
|
|
50954
|
+
agent: "general",
|
|
50955
|
+
thoroughness: "medium",
|
|
50956
|
+
parentCwd: cwd,
|
|
50957
|
+
sessionId: sessionId2,
|
|
50958
|
+
signal: abort.signal,
|
|
50959
|
+
args: {
|
|
50960
|
+
description: `gauntlet-builder ${piece.id} r${round}`,
|
|
50961
|
+
prompt,
|
|
50962
|
+
...piece.scope ? { scope: piece.scope } : {},
|
|
50963
|
+
...piece.acceptance.length > 0 ? { acceptance: piece.acceptance } : {}
|
|
50964
|
+
}
|
|
50965
|
+
});
|
|
50966
|
+
if (!tent.ok) return { ok: false, result: "", error: tent.error };
|
|
50967
|
+
return {
|
|
50968
|
+
ok: true,
|
|
50969
|
+
result: tent.result,
|
|
50970
|
+
toolTraceCount: tent.toolTrace?.length ?? 0
|
|
50971
|
+
};
|
|
50972
|
+
},
|
|
50973
|
+
runCritic: async ({ piece, prompt, systemPrompt, round }) => {
|
|
50974
|
+
emit({
|
|
50975
|
+
type: "log",
|
|
50976
|
+
message: `[gauntlet] ${piece.id} round ${round}/${caps.maxRounds} critic`
|
|
50977
|
+
});
|
|
50978
|
+
const tent = await runTentacle({
|
|
50979
|
+
deps,
|
|
50980
|
+
agent: "verify",
|
|
50981
|
+
thoroughness: "medium",
|
|
50982
|
+
parentCwd: cwd,
|
|
50983
|
+
sessionId: sessionId2,
|
|
50984
|
+
signal: abort.signal,
|
|
50985
|
+
systemPromptOverride: systemPrompt,
|
|
50986
|
+
args: {
|
|
50987
|
+
description: `gauntlet-critic ${piece.id} r${round}`,
|
|
50988
|
+
prompt,
|
|
50989
|
+
...piece.scope ? { scope: piece.scope } : {},
|
|
50990
|
+
...piece.acceptance.length > 0 ? { acceptance: piece.acceptance } : {}
|
|
50991
|
+
}
|
|
50992
|
+
});
|
|
50993
|
+
if (!tent.ok) {
|
|
50994
|
+
return { ok: false, result: tent.error, error: tent.error, toolTraceCount: 0 };
|
|
50995
|
+
}
|
|
50996
|
+
return {
|
|
50997
|
+
ok: true,
|
|
50998
|
+
result: tent.result,
|
|
50999
|
+
toolTraceCount: tent.toolTrace?.length ?? 0
|
|
51000
|
+
};
|
|
51001
|
+
}
|
|
51002
|
+
}
|
|
51003
|
+
});
|
|
51004
|
+
emitEvent({ type: "message_start", role: "assistant" });
|
|
51005
|
+
emitEvent({ type: "message_delta", delta: result.summary });
|
|
51006
|
+
emitEvent({ type: "message_end", totalLength: result.summary.length });
|
|
51007
|
+
emitEvent({
|
|
51008
|
+
type: "agent_end",
|
|
51009
|
+
reason: result.cancelled || result.timedOut ? "cancelled" : result.settled ? "completed" : "error"
|
|
51010
|
+
});
|
|
51011
|
+
if (result.timedOut) {
|
|
51012
|
+
emit({ type: "log", message: `[gauntlet] wall clock (${Math.round(wallMs / 6e4)}m)` });
|
|
51013
|
+
await spine.interrupt("gauntlet-wall-clock");
|
|
51014
|
+
return 1;
|
|
51015
|
+
}
|
|
51016
|
+
if (result.cancelled) {
|
|
51017
|
+
await spine.interrupt("gauntlet-cancelled");
|
|
51018
|
+
return 1;
|
|
51019
|
+
}
|
|
51020
|
+
await spine.close(result.settled ? "gauntlet-pass" : "gauntlet-incomplete");
|
|
51021
|
+
return result.settled ? 0 : 3;
|
|
51022
|
+
} catch (err) {
|
|
51023
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51024
|
+
emitEvent({ type: "error", severity: "fatal", message: msg, code: "gauntlet" });
|
|
51025
|
+
await spine.interrupt(`gauntlet-error: ${msg}`).catch(() => void 0);
|
|
51026
|
+
return 2;
|
|
51027
|
+
} finally {
|
|
51028
|
+
if (wallTimer) clearTimeout(wallTimer);
|
|
51029
|
+
process.removeListener("SIGINT", onSigint);
|
|
51030
|
+
}
|
|
51031
|
+
}
|
|
51032
|
+
var init_run = __esm({
|
|
51033
|
+
"src/cli/gauntlet/run.ts"() {
|
|
51034
|
+
"use strict";
|
|
51035
|
+
init_harness();
|
|
51036
|
+
init_headless();
|
|
51037
|
+
init_headlessSpine();
|
|
51038
|
+
init_auditLogger();
|
|
51039
|
+
init_toolRegistry();
|
|
51040
|
+
init_taskTool();
|
|
51041
|
+
init_complete();
|
|
51042
|
+
init_decompose();
|
|
51043
|
+
init_events3();
|
|
51044
|
+
init_loop();
|
|
51045
|
+
init_policy();
|
|
51046
|
+
init_workspaceSummary();
|
|
51047
|
+
}
|
|
51048
|
+
});
|
|
51049
|
+
|
|
50185
51050
|
// src/cli/triggerLock.ts
|
|
50186
51051
|
var triggerLock_exports = {};
|
|
50187
51052
|
__export(triggerLock_exports, {
|
|
@@ -50956,7 +51821,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50956
51821
|
}
|
|
50957
51822
|
return { error: { code: -32601, message: `method not found: ${method}` } };
|
|
50958
51823
|
}
|
|
50959
|
-
async function callApprove(args,
|
|
51824
|
+
async function callApprove(args, timeoutMs2) {
|
|
50960
51825
|
const toolName = typeof args.tool_name === "string" ? args.tool_name : "";
|
|
50961
51826
|
if (!toolName) {
|
|
50962
51827
|
return { error: { code: -32602, message: "approve requires a string tool_name" } };
|
|
@@ -50975,7 +51840,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50975
51840
|
toolUseId: typeof args.tool_use_id === "string" ? args.tool_use_id : void 0,
|
|
50976
51841
|
suggestions
|
|
50977
51842
|
},
|
|
50978
|
-
{ requestTimeoutMs:
|
|
51843
|
+
{ requestTimeoutMs: timeoutMs2 }
|
|
50979
51844
|
);
|
|
50980
51845
|
const result = res.behavior === "allow" ? {
|
|
50981
51846
|
behavior: "allow",
|
|
@@ -50995,7 +51860,7 @@ function startPermissionMcpServer(opts) {
|
|
|
50995
51860
|
);
|
|
50996
51861
|
}
|
|
50997
51862
|
}
|
|
50998
|
-
async function callAskUser(args,
|
|
51863
|
+
async function callAskUser(args, timeoutMs2) {
|
|
50999
51864
|
const question = typeof args.question === "string" ? args.question : "";
|
|
51000
51865
|
if (!question) {
|
|
51001
51866
|
return { error: { code: -32602, message: "ask_user requires a string question" } };
|
|
@@ -51013,7 +51878,7 @@ function startPermissionMcpServer(opts) {
|
|
|
51013
51878
|
choices,
|
|
51014
51879
|
context
|
|
51015
51880
|
},
|
|
51016
|
-
{ requestTimeoutMs:
|
|
51881
|
+
{ requestTimeoutMs: timeoutMs2 }
|
|
51017
51882
|
);
|
|
51018
51883
|
const text = res.behavior === "allow" && typeof res.answer === "string" ? res.answer : res.message ?? "No answer was given \u2014 use your best judgment.";
|
|
51019
51884
|
return textResult(text);
|
|
@@ -55861,8 +56726,8 @@ async function readPackageScripts(cwd = process.cwd()) {
|
|
|
55861
56726
|
return {};
|
|
55862
56727
|
}
|
|
55863
56728
|
}
|
|
55864
|
-
function buildNativeCriteria(commands,
|
|
55865
|
-
const pack = codingCriteriaPack({ ...commands, commandTimeoutMs:
|
|
56729
|
+
function buildNativeCriteria(commands, timeoutMs2) {
|
|
56730
|
+
const pack = codingCriteriaPack({ ...commands, commandTimeoutMs: timeoutMs2 });
|
|
55866
56731
|
return pack.criteria.filter(
|
|
55867
56732
|
(c) => !(c.required && (!c.check || c.check.kind === "none"))
|
|
55868
56733
|
);
|
|
@@ -56164,7 +57029,7 @@ ${detail}
|
|
|
56164
57029
|
let settled = false;
|
|
56165
57030
|
const askTimeoutMs = askUserTimeoutMs();
|
|
56166
57031
|
let cancelAskTimeout = () => void 0;
|
|
56167
|
-
const
|
|
57032
|
+
const finish2 = (ok, note) => {
|
|
56168
57033
|
if (settled) return;
|
|
56169
57034
|
settled = true;
|
|
56170
57035
|
cancelAskTimeout();
|
|
@@ -56173,7 +57038,7 @@ ${detail}
|
|
|
56173
57038
|
resolve3(ok);
|
|
56174
57039
|
};
|
|
56175
57040
|
cancelAskTimeout = armPickerTimeout(
|
|
56176
|
-
() =>
|
|
57041
|
+
() => finish2(
|
|
56177
57042
|
false,
|
|
56178
57043
|
`[permission] ask for "${req.toolName}" timed out after ${Math.round(
|
|
56179
57044
|
askTimeoutMs / 1e3
|
|
@@ -56202,12 +57067,12 @@ ${detail}
|
|
|
56202
57067
|
onAnswer: (value) => {
|
|
56203
57068
|
const v = value.trim().toLowerCase();
|
|
56204
57069
|
if (v === "deny" || v.startsWith("deny")) {
|
|
56205
|
-
|
|
57070
|
+
finish2(false);
|
|
56206
57071
|
return;
|
|
56207
57072
|
}
|
|
56208
57073
|
if (v === "always-tool" || v.includes("always") && v.includes("tool")) {
|
|
56209
57074
|
grantSessionTool(req.toolName);
|
|
56210
|
-
|
|
57075
|
+
finish2(
|
|
56211
57076
|
true,
|
|
56212
57077
|
`[permission] Granted "${req.toolName}" for this session (tool).`
|
|
56213
57078
|
);
|
|
@@ -56216,19 +57081,19 @@ ${detail}
|
|
|
56216
57081
|
if (v === "always-cat" || v.includes("always") && !v.includes("tool")) {
|
|
56217
57082
|
for (const c of cats) grantSessionCategory(c);
|
|
56218
57083
|
grantSessionTool(req.toolName);
|
|
56219
|
-
|
|
57084
|
+
finish2(
|
|
56220
57085
|
true,
|
|
56221
57086
|
`[permission] Granted ${catLabel} (+ ${req.toolName}) for this session.`
|
|
56222
57087
|
);
|
|
56223
57088
|
return;
|
|
56224
57089
|
}
|
|
56225
57090
|
if (v === "allow" || v.startsWith("allow") || v === "yes" || v === "y" || v === "1") {
|
|
56226
|
-
|
|
57091
|
+
finish2(true);
|
|
56227
57092
|
return;
|
|
56228
57093
|
}
|
|
56229
|
-
|
|
57094
|
+
finish2(false);
|
|
56230
57095
|
},
|
|
56231
|
-
onCancel: () =>
|
|
57096
|
+
onCancel: () => finish2(false)
|
|
56232
57097
|
});
|
|
56233
57098
|
});
|
|
56234
57099
|
}
|
|
@@ -56547,7 +57412,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56547
57412
|
let settled = false;
|
|
56548
57413
|
const askTimeoutMs = askUserTimeoutMs();
|
|
56549
57414
|
let cancelAskTimeout = () => void 0;
|
|
56550
|
-
const
|
|
57415
|
+
const finish2 = (value) => {
|
|
56551
57416
|
if (settled) return;
|
|
56552
57417
|
settled = true;
|
|
56553
57418
|
cancelAskTimeout();
|
|
@@ -56563,7 +57428,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56563
57428
|
)}s \u2014 proseguo con assunzione documentata (ZELARI_ASK_USER_TIMEOUT_MS).`,
|
|
56564
57429
|
Date.now()
|
|
56565
57430
|
);
|
|
56566
|
-
|
|
57431
|
+
finish2(null);
|
|
56567
57432
|
},
|
|
56568
57433
|
askTimeoutMs
|
|
56569
57434
|
);
|
|
@@ -56571,8 +57436,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
56571
57436
|
kind: "clarification",
|
|
56572
57437
|
title: req.question,
|
|
56573
57438
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
56574
|
-
onAnswer: (value) =>
|
|
56575
|
-
onCancel: () =>
|
|
57439
|
+
onAnswer: (value) => finish2(value),
|
|
57440
|
+
onCancel: () => finish2(null)
|
|
56576
57441
|
});
|
|
56577
57442
|
}) : void 0;
|
|
56578
57443
|
const onPermissionAsk = setPicker2 ? createPermissionAskHandler({
|
|
@@ -57361,7 +58226,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57361
58226
|
let settled = false;
|
|
57362
58227
|
const askTimeoutMs = askUserTimeoutMs();
|
|
57363
58228
|
let cancelAskTimeout = () => void 0;
|
|
57364
|
-
const
|
|
58229
|
+
const finish2 = (value) => {
|
|
57365
58230
|
if (settled) return;
|
|
57366
58231
|
settled = true;
|
|
57367
58232
|
cancelAskTimeout();
|
|
@@ -57377,7 +58242,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57377
58242
|
)}s \u2014 il membro prosegue con assunzione documentata (ZELARI_ASK_USER_TIMEOUT_MS).`,
|
|
57378
58243
|
Date.now()
|
|
57379
58244
|
);
|
|
57380
|
-
|
|
58245
|
+
finish2(null);
|
|
57381
58246
|
},
|
|
57382
58247
|
askTimeoutMs
|
|
57383
58248
|
);
|
|
@@ -57385,8 +58250,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57385
58250
|
kind: "clarification",
|
|
57386
58251
|
title: req.question,
|
|
57387
58252
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
57388
|
-
onAnswer: (value) =>
|
|
57389
|
-
onCancel: () =>
|
|
58253
|
+
onAnswer: (value) => finish2(value),
|
|
58254
|
+
onCancel: () => finish2(null)
|
|
57390
58255
|
});
|
|
57391
58256
|
}) : void 0;
|
|
57392
58257
|
let phaseRunMode = overrides.runMode ?? (workPhase === "plan" ? "design-phase" : "implementation");
|
|
@@ -57530,7 +58395,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57530
58395
|
Date.now()
|
|
57531
58396
|
);
|
|
57532
58397
|
let settled = false;
|
|
57533
|
-
const
|
|
58398
|
+
const finish2 = (value) => {
|
|
57534
58399
|
if (settled) return;
|
|
57535
58400
|
settled = true;
|
|
57536
58401
|
setPicker2(null);
|
|
@@ -57540,8 +58405,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il membro riprende dop
|
|
|
57540
58405
|
kind: "clarification",
|
|
57541
58406
|
title: req.question,
|
|
57542
58407
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
57543
|
-
onAnswer: (value) =>
|
|
57544
|
-
onCancel: () =>
|
|
58408
|
+
onAnswer: (value) => finish2(value),
|
|
58409
|
+
onCancel: () => finish2(null)
|
|
57545
58410
|
});
|
|
57546
58411
|
}) : void 0
|
|
57547
58412
|
})) {
|
|
@@ -58146,7 +59011,7 @@ function usePermissionBroker(opts) {
|
|
|
58146
59011
|
}
|
|
58147
59012
|
let settled = false;
|
|
58148
59013
|
let cancelWaitTimeout;
|
|
58149
|
-
const
|
|
59014
|
+
const finish2 = (value) => {
|
|
58150
59015
|
if (settled) return;
|
|
58151
59016
|
settled = true;
|
|
58152
59017
|
cancelWaitTimeout?.();
|
|
@@ -58162,7 +59027,7 @@ function usePermissionBroker(opts) {
|
|
|
58162
59027
|
)}s \u2014 richiesta annullata.`,
|
|
58163
59028
|
Date.now()
|
|
58164
59029
|
);
|
|
58165
|
-
|
|
59030
|
+
finish2(null);
|
|
58166
59031
|
}, waitTimeoutMs);
|
|
58167
59032
|
appendSystem(
|
|
58168
59033
|
setMessages,
|
|
@@ -58174,8 +59039,8 @@ function usePermissionBroker(opts) {
|
|
|
58174
59039
|
kind: "clarification",
|
|
58175
59040
|
title: req.question,
|
|
58176
59041
|
items: choices.map((c) => ({ value: c, label: c })),
|
|
58177
|
-
onAnswer: (value) =>
|
|
58178
|
-
onCancel: () =>
|
|
59042
|
+
onAnswer: (value) => finish2(value),
|
|
59043
|
+
onCancel: () => finish2(null)
|
|
58179
59044
|
});
|
|
58180
59045
|
});
|
|
58181
59046
|
void startPermissionBroker(socketPath, {
|
|
@@ -62280,7 +63145,7 @@ function verifierReviewEnabled(selection = loadVerifierModelSelection(), env = p
|
|
|
62280
63145
|
if (v === "1" || v === "true" || v === "on") return true;
|
|
62281
63146
|
return selection.mode === "fixed";
|
|
62282
63147
|
}
|
|
62283
|
-
function makeVerifierCallModel(loadStream, identity,
|
|
63148
|
+
function makeVerifierCallModel(loadStream, identity, timeoutMs2 = 12e4) {
|
|
62284
63149
|
return async ({ system, user }) => {
|
|
62285
63150
|
const stream = await loadStream(identity.provider, identity.model);
|
|
62286
63151
|
if (!stream) {
|
|
@@ -62294,7 +63159,7 @@ function makeVerifierCallModel(loadStream, identity, timeoutMs = 12e4) {
|
|
|
62294
63159
|
model: identity.model,
|
|
62295
63160
|
provider: identity.provider,
|
|
62296
63161
|
tools: [],
|
|
62297
|
-
signal: AbortSignal.timeout(
|
|
63162
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
62298
63163
|
});
|
|
62299
63164
|
return { text, provider: identity.provider, model: identity.model };
|
|
62300
63165
|
};
|
|
@@ -62451,6 +63316,18 @@ ${err.stack}` : "";
|
|
|
62451
63316
|
if (opts.krakenGraph) {
|
|
62452
63317
|
return runHeadlessKrakenGraph(opts, provider, model);
|
|
62453
63318
|
}
|
|
63319
|
+
const { shouldRunGauntletHostLoop: shouldRunGauntletHostLoop2 } = await Promise.resolve().then(() => (init_policy(), policy_exports));
|
|
63320
|
+
if (shouldRunGauntletHostLoop2(opts)) {
|
|
63321
|
+
const { runHeadlessGauntlet: runHeadlessGauntlet2 } = await Promise.resolve().then(() => (init_run(), run_exports));
|
|
63322
|
+
return runHeadlessGauntlet2(opts, provider, model);
|
|
63323
|
+
}
|
|
63324
|
+
if (opts.gauntlet) {
|
|
63325
|
+
const why = opts.krakenGraph ? "kraken-graph owns dispatch" : (opts.phase ?? "build") === "plan" ? "PLAN is already write-stripped; host loop is BUILD-only" : "mode is not kraken-build";
|
|
63326
|
+
const line = `[gauntlet] flag set but host loop skipped (${why})`;
|
|
63327
|
+
if (opts.output === "json") emitEvent({ type: "log", message: line });
|
|
63328
|
+
else process.stderr.write(`[zelari-code --headless] ${line}
|
|
63329
|
+
`);
|
|
63330
|
+
}
|
|
62454
63331
|
if (mode === "zelari") {
|
|
62455
63332
|
return runHeadlessZelari(opts, provider, model, providerStream);
|
|
62456
63333
|
}
|
|
@@ -62667,6 +63544,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
62667
63544
|
resetKrakenTurnMetrics();
|
|
62668
63545
|
const { registry: toolRegistry } = createBuiltinToolRegistry({
|
|
62669
63546
|
planMode: planModeFromOpts(opts),
|
|
63547
|
+
gauntletParent: Boolean(opts.gauntlet) && !planModeFromOpts(opts),
|
|
62670
63548
|
// Fase 1 (ADR-0020): anchor tentacles to the provider/model THIS run
|
|
62671
63549
|
// resolved (--provider/--model opts or Desktop's selector), mirroring
|
|
62672
63550
|
// what the kraken-graph path already does for its executor.
|