zelari-code 2.33.1 → 2.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/councilDispatcher.js +1 -0
- package/dist/cli/councilDispatcher.js.map +1 -1
- package/dist/cli/headless/liveTurnAbort.js +67 -0
- package/dist/cli/headless/liveTurnAbort.js.map +1 -0
- package/dist/cli/headless/runOneTurn.js +5 -1
- package/dist/cli/headless/runOneTurn.js.map +1 -1
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +1 -0
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +1777 -1228
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/runHeadless.js +55 -7
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/serve/askUserBridge.js +59 -0
- package/dist/cli/serve/askUserBridge.js.map +1 -0
- package/dist/cli/serve/harnessServer.js +14 -2
- package/dist/cli/serve/harnessServer.js.map +1 -1
- package/dist/cli/serve/permissionBridge.js +64 -8
- package/dist/cli/serve/permissionBridge.js.map +1 -1
- package/dist/cli/serve/sessionControl.js +5 -3
- package/dist/cli/serve/sessionControl.js.map +1 -1
- package/dist/cli/toolRegistry.js +32 -17
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenModel.js +18 -0
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/dist/cli/tools/taskTool.js +114 -9
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/dist/cli/utils/doctor.js +24 -3
- package/dist/cli/utils/doctor.js.map +1 -1
- package/dist/cli/utils/fixPath.js +18 -14
- package/dist/cli/utils/fixPath.js.map +1 -1
- package/dist/cli/utils/streamScrub.js +5 -3
- package/dist/cli/utils/streamScrub.js.map +1 -1
- package/dist/cli/zelariMission.js +14 -0
- package/dist/cli/zelariMission.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -28372,6 +28372,136 @@ var init_textLoopDetect = __esm({
|
|
|
28372
28372
|
}
|
|
28373
28373
|
});
|
|
28374
28374
|
|
|
28375
|
+
// packages/core/dist/agents/council/outputCleaning.js
|
|
28376
|
+
function extractBalancedJsonObject(s) {
|
|
28377
|
+
const start = s.indexOf("{");
|
|
28378
|
+
if (start < 0)
|
|
28379
|
+
return null;
|
|
28380
|
+
let depth = 0;
|
|
28381
|
+
let inString = false;
|
|
28382
|
+
let escape = false;
|
|
28383
|
+
for (let i = start; i < s.length; i++) {
|
|
28384
|
+
const ch = s[i];
|
|
28385
|
+
if (inString) {
|
|
28386
|
+
if (escape) {
|
|
28387
|
+
escape = false;
|
|
28388
|
+
continue;
|
|
28389
|
+
}
|
|
28390
|
+
if (ch === "\\") {
|
|
28391
|
+
escape = true;
|
|
28392
|
+
continue;
|
|
28393
|
+
}
|
|
28394
|
+
if (ch === '"')
|
|
28395
|
+
inString = false;
|
|
28396
|
+
continue;
|
|
28397
|
+
}
|
|
28398
|
+
if (ch === '"') {
|
|
28399
|
+
inString = true;
|
|
28400
|
+
continue;
|
|
28401
|
+
}
|
|
28402
|
+
if (ch === "{")
|
|
28403
|
+
depth++;
|
|
28404
|
+
else if (ch === "}") {
|
|
28405
|
+
depth--;
|
|
28406
|
+
if (depth === 0)
|
|
28407
|
+
return s.slice(start, i + 1);
|
|
28408
|
+
}
|
|
28409
|
+
}
|
|
28410
|
+
return null;
|
|
28411
|
+
}
|
|
28412
|
+
function parseClarificationRequest(text) {
|
|
28413
|
+
const start = text.indexOf(QUESTION_MARKER);
|
|
28414
|
+
if (start < 0)
|
|
28415
|
+
return null;
|
|
28416
|
+
const rest = text.slice(start + QUESTION_MARKER.length);
|
|
28417
|
+
const end = rest.indexOf(QUESTION_END_MARKER);
|
|
28418
|
+
const block = end >= 0 ? rest.slice(0, end) : rest;
|
|
28419
|
+
const cleaned = block.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
28420
|
+
const jsonText = extractBalancedJsonObject(cleaned) ?? (() => {
|
|
28421
|
+
const objStart = cleaned.indexOf("{");
|
|
28422
|
+
const objEnd = cleaned.lastIndexOf("}");
|
|
28423
|
+
return objStart >= 0 && objEnd > objStart ? cleaned.slice(objStart, objEnd + 1) : cleaned;
|
|
28424
|
+
})();
|
|
28425
|
+
try {
|
|
28426
|
+
const parsed = JSON.parse(jsonText);
|
|
28427
|
+
if (typeof parsed.question !== "string" || !parsed.question.trim())
|
|
28428
|
+
return null;
|
|
28429
|
+
return {
|
|
28430
|
+
question: parsed.question.trim(),
|
|
28431
|
+
choices: Array.isArray(parsed.choices) ? parsed.choices.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : void 0,
|
|
28432
|
+
context: typeof parsed.context === "string" ? parsed.context.trim() : void 0
|
|
28433
|
+
};
|
|
28434
|
+
} catch {
|
|
28435
|
+
return null;
|
|
28436
|
+
}
|
|
28437
|
+
}
|
|
28438
|
+
function hasInteractiveClarification(text) {
|
|
28439
|
+
const c = parseClarificationRequest(text);
|
|
28440
|
+
return !!(c && c.choices && c.choices.length >= 2);
|
|
28441
|
+
}
|
|
28442
|
+
function stripQuestionBlocks(text) {
|
|
28443
|
+
let out = "";
|
|
28444
|
+
let rest = text;
|
|
28445
|
+
while (true) {
|
|
28446
|
+
const start = rest.indexOf(QUESTION_MARKER);
|
|
28447
|
+
if (start < 0) {
|
|
28448
|
+
out += rest;
|
|
28449
|
+
break;
|
|
28450
|
+
}
|
|
28451
|
+
out += rest.slice(0, start);
|
|
28452
|
+
const afterMarker = rest.slice(start + QUESTION_MARKER.length);
|
|
28453
|
+
const trimmed = afterMarker.replace(/^\s+/, "");
|
|
28454
|
+
if (!trimmed.startsWith("{")) {
|
|
28455
|
+
out += QUESTION_MARKER;
|
|
28456
|
+
rest = afterMarker;
|
|
28457
|
+
continue;
|
|
28458
|
+
}
|
|
28459
|
+
const endIdx = afterMarker.indexOf(QUESTION_END_MARKER);
|
|
28460
|
+
if (endIdx >= 0) {
|
|
28461
|
+
rest = afterMarker.slice(endIdx + QUESTION_END_MARKER.length);
|
|
28462
|
+
continue;
|
|
28463
|
+
}
|
|
28464
|
+
const json3 = extractBalancedJsonObject(trimmed);
|
|
28465
|
+
if (json3) {
|
|
28466
|
+
const jsonAt = afterMarker.indexOf(json3);
|
|
28467
|
+
rest = afterMarker.slice(jsonAt + json3.length);
|
|
28468
|
+
continue;
|
|
28469
|
+
}
|
|
28470
|
+
break;
|
|
28471
|
+
}
|
|
28472
|
+
return out.replace(/\n{3,}/g, "\n\n").trim();
|
|
28473
|
+
}
|
|
28474
|
+
function parseThinking(text) {
|
|
28475
|
+
const complete = text.match(/<think(?:ing)?>([\s\S]*?)<\/think(?:ing)?>/i);
|
|
28476
|
+
if (complete)
|
|
28477
|
+
return complete[1].trim();
|
|
28478
|
+
const open2 = text.match(/<think(?:ing)?>([\s\S]*)$/i);
|
|
28479
|
+
return open2 ? open2[1].trim() : "";
|
|
28480
|
+
}
|
|
28481
|
+
function cleanAgentContent(text, opts = {}) {
|
|
28482
|
+
const stripQuestion = opts.stripQuestion !== false;
|
|
28483
|
+
const stripThink = opts.stripThink !== false;
|
|
28484
|
+
let out = text;
|
|
28485
|
+
if (stripThink) {
|
|
28486
|
+
out = out.replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/gi, "").replace(/<think(?:ing)?>[\s\S]*$/gi, "").replace(/<\/think(?:ing)?>/gi, "");
|
|
28487
|
+
}
|
|
28488
|
+
out = out.replace(/<minimax:tool_call>[\s\S]*?<\/minimax:tool_call>/gi, "").replace(/<\/?minimax:tool_call>/gi, "").replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, "").replace(/<\/?tool_call>/gi, "").replace(/<function_call>[\s\S]*?<\/function_call>/gi, "").replace(/<\/?function_call>/gi, "").replace(/<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<\/invoke>/gi, "").replace(/<parameter\b[^>]*>[\s\S]*?<\/parameter>/gi, "").replace(/<\/parameter>/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>\s*\[?<invoke\b[^>]*>[\s\S]*?<\/invoke>/gi, "").replace(/<minimax:tool_call>[\s\S]*$/gi, "").replace(/<tool_call>[\s\S]*$/gi, "").replace(/<function_call>[\s\S]*$/gi, "").replace(/<invoke\b[^>]*>[\s\S]*$/gi, "").replace(/\]\s*<\]\s*minimax\s*\[>[\s\S]*$/gi, "").replace(/^\s*\]\s*<\]\s*minimax\s*\[>.*$/gim, "").replace(/^\s*<\/?(?:tool_call|function_call|invoke|parameter|minimax:tool_call)\b[^>]*>\s*$/gim, "");
|
|
28489
|
+
if (stripQuestion) {
|
|
28490
|
+
out = stripQuestionBlocks(out);
|
|
28491
|
+
}
|
|
28492
|
+
out = out.replace(/\n{3,}/g, "\n\n").trim();
|
|
28493
|
+
return scrubProprietaryLeak(out);
|
|
28494
|
+
}
|
|
28495
|
+
var QUESTION_MARKER, QUESTION_END_MARKER;
|
|
28496
|
+
var init_outputCleaning = __esm({
|
|
28497
|
+
"packages/core/dist/agents/council/outputCleaning.js"() {
|
|
28498
|
+
"use strict";
|
|
28499
|
+
init_secrecyPolicy();
|
|
28500
|
+
QUESTION_MARKER = "---QUESTION---";
|
|
28501
|
+
QUESTION_END_MARKER = "---END---";
|
|
28502
|
+
}
|
|
28503
|
+
});
|
|
28504
|
+
|
|
28375
28505
|
// packages/core/dist/core/AgentHarness.js
|
|
28376
28506
|
function gateAdvice(hardLimit) {
|
|
28377
28507
|
return hardLimit ? "Finalize now with the evidence already collected; no further tool calls will run this turn." : "Prioritize verification/repair actions (test, typecheck, build, read failures) or finalize honestly.";
|
|
@@ -28668,6 +28798,7 @@ var init_AgentHarness = __esm({
|
|
|
28668
28798
|
init_requestSnapshot();
|
|
28669
28799
|
init_textLoopDetect();
|
|
28670
28800
|
init_ObserverBus();
|
|
28801
|
+
init_outputCleaning();
|
|
28671
28802
|
init_textLoopDetect();
|
|
28672
28803
|
TOOL_CALL_TRUNCATED_RECOVERY_MARKER = "[harness] Previous tool call was truncated";
|
|
28673
28804
|
TOOL_CALL_TRUNCATED_RECOVERY_USER = `${TOOL_CALL_TRUNCATED_RECOVERY_MARKER} by the provider before completion (finish_reason=tool_calls but no complete tool_call arrived). Retry with a shorter payload or split the work into smaller tool calls.`;
|
|
@@ -29562,7 +29693,7 @@ ${cached2}`
|
|
|
29562
29693
|
}
|
|
29563
29694
|
pendingNativeTools.length = 0;
|
|
29564
29695
|
}
|
|
29565
|
-
const clarificationPause =
|
|
29696
|
+
const clarificationPause = hasInteractiveClarification(turnText);
|
|
29566
29697
|
if (clarificationPause) {
|
|
29567
29698
|
finishRef.value = "stop";
|
|
29568
29699
|
finishRef.clarificationRequested = true;
|
|
@@ -30994,31 +31125,6 @@ You are the sole implementer this run. Advisors already analyzed \u2014 implemen
|
|
|
30994
31125
|
}
|
|
30995
31126
|
});
|
|
30996
31127
|
|
|
30997
|
-
// packages/core/dist/council/modeBanners.js
|
|
30998
|
-
function councilModeBanner(runMode, opts) {
|
|
30999
|
-
if (runMode === "design-phase")
|
|
31000
|
-
return DESIGN_PHASE_MODE_BANNER;
|
|
31001
|
-
if (opts?.isImplementer === true)
|
|
31002
|
-
return IMPLEMENTATION_IMPLEMENTER_BANNER;
|
|
31003
|
-
if (opts?.isImplementer === false)
|
|
31004
|
-
return IMPLEMENTATION_ADVISOR_BANNER;
|
|
31005
|
-
return IMPLEMENTATION_MODE_BANNER;
|
|
31006
|
-
}
|
|
31007
|
-
var DESIGN_PHASE_MODE_BANNER, IMPLEMENTATION_MODE_BANNER, IMPLEMENTATION_IMPLEMENTER_BANNER, IMPLEMENTATION_ADVISOR_BANNER;
|
|
31008
|
-
var init_modeBanners = __esm({
|
|
31009
|
-
"packages/core/dist/council/modeBanners.js"() {
|
|
31010
|
-
"use strict";
|
|
31011
|
-
DESIGN_PHASE_MODE_BANNER = `COUNCIL RUN MODE: design-phase.
|
|
31012
|
-
Workspace tool emissions described in your role prompt are MANDATORY in this run \u2014 prose alone does not count as a deliverable. Persist artifacts via the workspace tools listed in your AVAILABLE TOOLS section.`;
|
|
31013
|
-
IMPLEMENTATION_MODE_BANNER = `COUNCIL RUN MODE: implementation.
|
|
31014
|
-
Prefer write_file, edit_file, and bash for code changes. Design-phase mandatory workspace blocks in your role prompt are INACTIVE \u2014 .zelari/docs and draft plans are hypotheses, not product law. Ground work in the real source tree. Only call workspace tools when they add durable project value.`;
|
|
31015
|
-
IMPLEMENTATION_IMPLEMENTER_BANNER = `COUNCIL RUN MODE: implementation \u2014 you are the IMPLEMENTER.
|
|
31016
|
-
You are the only member that writes code this run. Implement the solution with write_file / edit_file and verify with bash. Reconcile specialists' analysis and Minosse's critique into working, verified changes. Design vault (.zelari/docs, draft plans) is HYPOTHESIS only \u2014 product truth is the source tree. Design-phase mandatory workspace blocks are INACTIVE.`;
|
|
31017
|
-
IMPLEMENTATION_ADVISOR_BANNER = `COUNCIL RUN MODE: implementation \u2014 you are an ADVISOR.
|
|
31018
|
-
Do NOT write or edit project files (not via write_file/edit_file, and not via bash) \u2014 Lucifero is the sole implementer. Inspect the real codebase (read_file, grep_content, list_files). Treat prior design prose and .zelari/docs as hypotheses. Flag contradictions with package.json / the tree. Design-phase mandatory workspace blocks are INACTIVE.`;
|
|
31019
|
-
}
|
|
31020
|
-
});
|
|
31021
|
-
|
|
31022
31128
|
// packages/core/dist/council/runMode.js
|
|
31023
31129
|
function resolveCouncilRunMode(input) {
|
|
31024
31130
|
if (input.forceMode) {
|
|
@@ -31880,54 +31986,6 @@ var init_microGate = __esm({
|
|
|
31880
31986
|
}
|
|
31881
31987
|
});
|
|
31882
31988
|
|
|
31883
|
-
// packages/core/dist/council/verification/completion.js
|
|
31884
|
-
function isVerifyToolCheckSkipped() {
|
|
31885
|
-
return process.env.ZELARI_VERIFY_SKIP_TOOL === "1";
|
|
31886
|
-
}
|
|
31887
|
-
function checkImplementationCompletion(emittedToolNames) {
|
|
31888
|
-
if (isVerifyToolCheckSkipped()) {
|
|
31889
|
-
return { ok: true, missing: [] };
|
|
31890
|
-
}
|
|
31891
|
-
let lastWriteIdx = -1;
|
|
31892
|
-
for (let i = 0; i < emittedToolNames.length; i++) {
|
|
31893
|
-
if (WRITE_TOOLS.has(emittedToolNames[i])) {
|
|
31894
|
-
lastWriteIdx = i;
|
|
31895
|
-
}
|
|
31896
|
-
}
|
|
31897
|
-
if (lastWriteIdx === -1) {
|
|
31898
|
-
return { ok: true, missing: [] };
|
|
31899
|
-
}
|
|
31900
|
-
const afterWrite = emittedToolNames.slice(lastWriteIdx + 1);
|
|
31901
|
-
if (afterWrite.some((t) => VERIFY_TOOLS.has(t))) {
|
|
31902
|
-
return { ok: true, missing: [] };
|
|
31903
|
-
}
|
|
31904
|
-
return {
|
|
31905
|
-
ok: false,
|
|
31906
|
-
missing: ["grep_content"],
|
|
31907
|
-
reason: "No grep_content or bash after last write_file/edit_file"
|
|
31908
|
-
};
|
|
31909
|
-
}
|
|
31910
|
-
function resolveVerifyRetryTool(executableTools) {
|
|
31911
|
-
if (!executableTools)
|
|
31912
|
-
return "grep_content";
|
|
31913
|
-
if (executableTools.has("grep_content"))
|
|
31914
|
-
return "grep_content";
|
|
31915
|
-
if (executableTools.has("bash"))
|
|
31916
|
-
return "bash";
|
|
31917
|
-
return null;
|
|
31918
|
-
}
|
|
31919
|
-
function buildImplementationVerifyRetryPrompt(toolName) {
|
|
31920
|
-
return `You wrote files but did not run ${toolName} or bash to verify them. Call ${toolName} NOW on your changed HTML (search @keyframes, transition, classList.add). No prose.`;
|
|
31921
|
-
}
|
|
31922
|
-
var WRITE_TOOLS, VERIFY_TOOLS;
|
|
31923
|
-
var init_completion = __esm({
|
|
31924
|
-
"packages/core/dist/council/verification/completion.js"() {
|
|
31925
|
-
"use strict";
|
|
31926
|
-
WRITE_TOOLS = /* @__PURE__ */ new Set(["write_file", "edit_file"]);
|
|
31927
|
-
VERIFY_TOOLS = /* @__PURE__ */ new Set(["grep_content", "bash"]);
|
|
31928
|
-
}
|
|
31929
|
-
});
|
|
31930
|
-
|
|
31931
31989
|
// packages/core/dist/council/scope/extractTaskScope.js
|
|
31932
31990
|
function normalizePath(p3) {
|
|
31933
31991
|
return p3.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
@@ -32178,13 +32236,13 @@ ${hints.map((h) => `- ${h}`).join("\n")}
|
|
|
32178
32236
|
` : "") + `Use read_file then edit_file on the listed files. No verification table \u2014 tool calls only.`;
|
|
32179
32237
|
}
|
|
32180
32238
|
function countEmittedWriteTools(emittedToolNames) {
|
|
32181
|
-
return emittedToolNames.filter((t) =>
|
|
32239
|
+
return emittedToolNames.filter((t) => WRITE_TOOLS.has(t)).length;
|
|
32182
32240
|
}
|
|
32183
|
-
var
|
|
32241
|
+
var WRITE_TOOLS, IMPLEMENTATION_WRITE_REQUIREMENTS;
|
|
32184
32242
|
var init_implementationDelivery = __esm({
|
|
32185
32243
|
"packages/core/dist/council/verification/implementationDelivery.js"() {
|
|
32186
32244
|
"use strict";
|
|
32187
|
-
|
|
32245
|
+
WRITE_TOOLS = /* @__PURE__ */ new Set(["write_file", "edit_file"]);
|
|
32188
32246
|
IMPLEMENTATION_WRITE_REQUIREMENTS = [
|
|
32189
32247
|
{ name: "write_file", min: 1 },
|
|
32190
32248
|
{ name: "edit_file", min: 1 }
|
|
@@ -32192,6 +32250,191 @@ var init_implementationDelivery = __esm({
|
|
|
32192
32250
|
}
|
|
32193
32251
|
});
|
|
32194
32252
|
|
|
32253
|
+
// packages/core/dist/agents/council/types.js
|
|
32254
|
+
var NON_RETRY_AGENTS;
|
|
32255
|
+
var init_types7 = __esm({
|
|
32256
|
+
"packages/core/dist/agents/council/types.js"() {
|
|
32257
|
+
"use strict";
|
|
32258
|
+
NON_RETRY_AGENTS = /* @__PURE__ */ new Set([]);
|
|
32259
|
+
}
|
|
32260
|
+
});
|
|
32261
|
+
|
|
32262
|
+
// packages/core/dist/agents/council/cancel.js
|
|
32263
|
+
function isCouncilCancelled(signal) {
|
|
32264
|
+
return signal?.aborted === true;
|
|
32265
|
+
}
|
|
32266
|
+
function bindHarnessAbort(harness, signal) {
|
|
32267
|
+
if (!signal)
|
|
32268
|
+
return () => void 0;
|
|
32269
|
+
if (signal.aborted) {
|
|
32270
|
+
harness.cancel();
|
|
32271
|
+
return () => void 0;
|
|
32272
|
+
}
|
|
32273
|
+
const onAbort = () => {
|
|
32274
|
+
harness.cancel();
|
|
32275
|
+
};
|
|
32276
|
+
signal.addEventListener("abort", onAbort);
|
|
32277
|
+
return () => {
|
|
32278
|
+
signal.removeEventListener("abort", onAbort);
|
|
32279
|
+
};
|
|
32280
|
+
}
|
|
32281
|
+
async function* runHarnessWithAbort(harness, signal) {
|
|
32282
|
+
const unbind = bindHarnessAbort(harness, signal);
|
|
32283
|
+
try {
|
|
32284
|
+
yield* harness.run();
|
|
32285
|
+
} finally {
|
|
32286
|
+
unbind();
|
|
32287
|
+
}
|
|
32288
|
+
}
|
|
32289
|
+
var init_cancel = __esm({
|
|
32290
|
+
"packages/core/dist/agents/council/cancel.js"() {
|
|
32291
|
+
"use strict";
|
|
32292
|
+
}
|
|
32293
|
+
});
|
|
32294
|
+
|
|
32295
|
+
// packages/core/dist/council/modeBanners.js
|
|
32296
|
+
function councilModeBanner(runMode, opts) {
|
|
32297
|
+
if (runMode === "design-phase")
|
|
32298
|
+
return DESIGN_PHASE_MODE_BANNER;
|
|
32299
|
+
if (opts?.isImplementer === true)
|
|
32300
|
+
return IMPLEMENTATION_IMPLEMENTER_BANNER;
|
|
32301
|
+
if (opts?.isImplementer === false)
|
|
32302
|
+
return IMPLEMENTATION_ADVISOR_BANNER;
|
|
32303
|
+
return IMPLEMENTATION_MODE_BANNER;
|
|
32304
|
+
}
|
|
32305
|
+
var DESIGN_PHASE_MODE_BANNER, IMPLEMENTATION_MODE_BANNER, IMPLEMENTATION_IMPLEMENTER_BANNER, IMPLEMENTATION_ADVISOR_BANNER;
|
|
32306
|
+
var init_modeBanners = __esm({
|
|
32307
|
+
"packages/core/dist/council/modeBanners.js"() {
|
|
32308
|
+
"use strict";
|
|
32309
|
+
DESIGN_PHASE_MODE_BANNER = `COUNCIL RUN MODE: design-phase.
|
|
32310
|
+
Workspace tool emissions described in your role prompt are MANDATORY in this run \u2014 prose alone does not count as a deliverable. Persist artifacts via the workspace tools listed in your AVAILABLE TOOLS section.`;
|
|
32311
|
+
IMPLEMENTATION_MODE_BANNER = `COUNCIL RUN MODE: implementation.
|
|
32312
|
+
Prefer write_file, edit_file, and bash for code changes. Design-phase mandatory workspace blocks in your role prompt are INACTIVE \u2014 .zelari/docs and draft plans are hypotheses, not product law. Ground work in the real source tree. Only call workspace tools when they add durable project value.`;
|
|
32313
|
+
IMPLEMENTATION_IMPLEMENTER_BANNER = `COUNCIL RUN MODE: implementation \u2014 you are the IMPLEMENTER.
|
|
32314
|
+
You are the only member that writes code this run. Implement the solution with write_file / edit_file and verify with bash. Reconcile specialists' analysis and Minosse's critique into working, verified changes. Design vault (.zelari/docs, draft plans) is HYPOTHESIS only \u2014 product truth is the source tree. Design-phase mandatory workspace blocks are INACTIVE.`;
|
|
32315
|
+
IMPLEMENTATION_ADVISOR_BANNER = `COUNCIL RUN MODE: implementation \u2014 you are an ADVISOR.
|
|
32316
|
+
Do NOT write or edit project files (not via write_file/edit_file, and not via bash) \u2014 Lucifero is the sole implementer. Inspect the real codebase (read_file, grep_content, list_files). Treat prior design prose and .zelari/docs as hypotheses. Flag contradictions with package.json / the tree. Design-phase mandatory workspace blocks are INACTIVE.`;
|
|
32317
|
+
}
|
|
32318
|
+
});
|
|
32319
|
+
|
|
32320
|
+
// packages/core/dist/agents/council/memberMessages.js
|
|
32321
|
+
function restrictImplementationWrites(toolNames, opts) {
|
|
32322
|
+
if (opts.runMode !== "implementation" || opts.isImplementer)
|
|
32323
|
+
return toolNames;
|
|
32324
|
+
return toolNames.filter((t) => !MUTATING_PROJECT_TOOLS.includes(t));
|
|
32325
|
+
}
|
|
32326
|
+
function buildAgentMessages(agent, userMessage, ragContext, workspaceContext, priorOutputs, aiConfig, executableTools, runMode = "implementation", languageModule) {
|
|
32327
|
+
const allToolNames = computeAgentTools(agent, aiConfig);
|
|
32328
|
+
const toolNames = executableTools ? allToolNames.filter((n) => executableTools.has(n)) : allToolNames;
|
|
32329
|
+
const mergedAiConfig = languageModule ? {
|
|
32330
|
+
enabledSkills: aiConfig?.enabledSkills ?? [],
|
|
32331
|
+
enabledTools: aiConfig?.enabledTools ?? [],
|
|
32332
|
+
agentSkillConfigs: aiConfig?.agentSkillConfigs ?? [],
|
|
32333
|
+
customSkills: aiConfig?.customSkills,
|
|
32334
|
+
customPromptModules: [
|
|
32335
|
+
...aiConfig?.customPromptModules ?? [],
|
|
32336
|
+
languageModule
|
|
32337
|
+
]
|
|
32338
|
+
} : aiConfig;
|
|
32339
|
+
const modeAwareAgent = {
|
|
32340
|
+
...agent,
|
|
32341
|
+
systemPrompt: resolveRoleSystemPrompt(agent, runMode)
|
|
32342
|
+
};
|
|
32343
|
+
const split = buildSystemPromptSplit(modeAwareAgent, {
|
|
32344
|
+
tools: getAllTools(),
|
|
32345
|
+
toolNames,
|
|
32346
|
+
aiConfig: mergedAiConfig,
|
|
32347
|
+
workspaceContext,
|
|
32348
|
+
ragContext,
|
|
32349
|
+
mode: "council",
|
|
32350
|
+
includeWorkspaceInPrompt: true
|
|
32351
|
+
});
|
|
32352
|
+
const messages = [
|
|
32353
|
+
{ role: "system", content: split.stable }
|
|
32354
|
+
];
|
|
32355
|
+
if (split.volatile.trim()) {
|
|
32356
|
+
messages.push({ role: "system", content: split.volatile });
|
|
32357
|
+
}
|
|
32358
|
+
messages.push({ role: "system", content: councilModeBanner(runMode, { isImplementer: agent.id === "lucifer" }) }, { role: "system", content: "IMPORTANT: Before making any tool calls or expensive operations, check if the information already exists in the shared context from previous agents. Avoid redundant work." });
|
|
32359
|
+
if (priorOutputs.length > 0) {
|
|
32360
|
+
const MAX_PRIOR_CHARS = 2800;
|
|
32361
|
+
const summary = priorOutputs.map((o) => {
|
|
32362
|
+
const body = o.content.length > MAX_PRIOR_CHARS ? `${o.content.slice(0, MAX_PRIOR_CHARS)}
|
|
32363
|
+
\u2026 [truncated ${o.content.length}\u2192${MAX_PRIOR_CHARS} chars; treat as hypothesis]` : o.content;
|
|
32364
|
+
return `[${o.name} - ${o.role}]: ${body}`;
|
|
32365
|
+
}).join("\n\n");
|
|
32366
|
+
messages.push({
|
|
32367
|
+
role: "user",
|
|
32368
|
+
content: `Previous council members have said (hypotheses \u2014 prefer product files on disk if they conflict):
|
|
32369
|
+
${summary}
|
|
32370
|
+
|
|
32371
|
+
Original user request: ${userMessage}`
|
|
32372
|
+
});
|
|
32373
|
+
} else {
|
|
32374
|
+
messages.push({ role: "user", content: userMessage });
|
|
32375
|
+
}
|
|
32376
|
+
return messages;
|
|
32377
|
+
}
|
|
32378
|
+
var MUTATING_PROJECT_TOOLS;
|
|
32379
|
+
var init_memberMessages = __esm({
|
|
32380
|
+
"packages/core/dist/agents/council/memberMessages.js"() {
|
|
32381
|
+
"use strict";
|
|
32382
|
+
init_roles();
|
|
32383
|
+
init_systemPromptBuilder();
|
|
32384
|
+
init_tools();
|
|
32385
|
+
init_modeBanners();
|
|
32386
|
+
MUTATING_PROJECT_TOOLS = ["write_file", "edit_file"];
|
|
32387
|
+
}
|
|
32388
|
+
});
|
|
32389
|
+
|
|
32390
|
+
// packages/core/dist/council/verification/completion.js
|
|
32391
|
+
function isVerifyToolCheckSkipped() {
|
|
32392
|
+
return process.env.ZELARI_VERIFY_SKIP_TOOL === "1";
|
|
32393
|
+
}
|
|
32394
|
+
function checkImplementationCompletion(emittedToolNames) {
|
|
32395
|
+
if (isVerifyToolCheckSkipped()) {
|
|
32396
|
+
return { ok: true, missing: [] };
|
|
32397
|
+
}
|
|
32398
|
+
let lastWriteIdx = -1;
|
|
32399
|
+
for (let i = 0; i < emittedToolNames.length; i++) {
|
|
32400
|
+
if (WRITE_TOOLS2.has(emittedToolNames[i])) {
|
|
32401
|
+
lastWriteIdx = i;
|
|
32402
|
+
}
|
|
32403
|
+
}
|
|
32404
|
+
if (lastWriteIdx === -1) {
|
|
32405
|
+
return { ok: true, missing: [] };
|
|
32406
|
+
}
|
|
32407
|
+
const afterWrite = emittedToolNames.slice(lastWriteIdx + 1);
|
|
32408
|
+
if (afterWrite.some((t) => VERIFY_TOOLS.has(t))) {
|
|
32409
|
+
return { ok: true, missing: [] };
|
|
32410
|
+
}
|
|
32411
|
+
return {
|
|
32412
|
+
ok: false,
|
|
32413
|
+
missing: ["grep_content"],
|
|
32414
|
+
reason: "No grep_content or bash after last write_file/edit_file"
|
|
32415
|
+
};
|
|
32416
|
+
}
|
|
32417
|
+
function resolveVerifyRetryTool(executableTools) {
|
|
32418
|
+
if (!executableTools)
|
|
32419
|
+
return "grep_content";
|
|
32420
|
+
if (executableTools.has("grep_content"))
|
|
32421
|
+
return "grep_content";
|
|
32422
|
+
if (executableTools.has("bash"))
|
|
32423
|
+
return "bash";
|
|
32424
|
+
return null;
|
|
32425
|
+
}
|
|
32426
|
+
function buildImplementationVerifyRetryPrompt(toolName) {
|
|
32427
|
+
return `You wrote files but did not run ${toolName} or bash to verify them. Call ${toolName} NOW on your changed HTML (search @keyframes, transition, classList.add). No prose.`;
|
|
32428
|
+
}
|
|
32429
|
+
var WRITE_TOOLS2, VERIFY_TOOLS;
|
|
32430
|
+
var init_completion = __esm({
|
|
32431
|
+
"packages/core/dist/council/verification/completion.js"() {
|
|
32432
|
+
"use strict";
|
|
32433
|
+
WRITE_TOOLS2 = /* @__PURE__ */ new Set(["write_file", "edit_file"]);
|
|
32434
|
+
VERIFY_TOOLS = /* @__PURE__ */ new Set(["grep_content", "bash"]);
|
|
32435
|
+
}
|
|
32436
|
+
});
|
|
32437
|
+
|
|
32195
32438
|
// packages/core/dist/council/verification/inlineJsAutofix.js
|
|
32196
32439
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
32197
32440
|
import { join as join7 } from "node:path";
|
|
@@ -32272,153 +32515,518 @@ var init_inlineJsAutofix = __esm({
|
|
|
32272
32515
|
}
|
|
32273
32516
|
});
|
|
32274
32517
|
|
|
32275
|
-
// packages/core/dist/agents/
|
|
32276
|
-
|
|
32277
|
-
|
|
32278
|
-
|
|
32279
|
-
|
|
32280
|
-
|
|
32281
|
-
|
|
32282
|
-
|
|
32283
|
-
|
|
32284
|
-
|
|
32285
|
-
for (
|
|
32286
|
-
const
|
|
32287
|
-
if (
|
|
32288
|
-
|
|
32289
|
-
escape = false;
|
|
32290
|
-
continue;
|
|
32291
|
-
}
|
|
32292
|
-
if (ch === "\\") {
|
|
32293
|
-
escape = true;
|
|
32294
|
-
continue;
|
|
32295
|
-
}
|
|
32296
|
-
if (ch === '"')
|
|
32297
|
-
inString = false;
|
|
32298
|
-
continue;
|
|
32518
|
+
// packages/core/dist/agents/council/toolEmission.js
|
|
32519
|
+
function checkMemberToolEmissions(_memberId, emittedToolNames, requirements) {
|
|
32520
|
+
if (requirements.length === 0) {
|
|
32521
|
+
return { ok: true, missing: [] };
|
|
32522
|
+
}
|
|
32523
|
+
const counts = /* @__PURE__ */ new Map();
|
|
32524
|
+
for (const name of emittedToolNames) {
|
|
32525
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
32526
|
+
}
|
|
32527
|
+
const missing = [];
|
|
32528
|
+
for (const req of requirements) {
|
|
32529
|
+
const got = counts.get(req.name) ?? 0;
|
|
32530
|
+
if (got < req.min) {
|
|
32531
|
+
missing.push(`${req.name} (got ${got}, need >= ${req.min})`);
|
|
32299
32532
|
}
|
|
32300
|
-
|
|
32301
|
-
|
|
32302
|
-
|
|
32533
|
+
}
|
|
32534
|
+
return { ok: missing.length === 0, missing };
|
|
32535
|
+
}
|
|
32536
|
+
function checkMemberToolEmissionSets(memberId, emittedToolNames, sets) {
|
|
32537
|
+
if (sets.length === 0) {
|
|
32538
|
+
return { ok: true, missing: [] };
|
|
32539
|
+
}
|
|
32540
|
+
const results = sets.map((set2) => checkMemberToolEmissions(memberId, emittedToolNames, set2));
|
|
32541
|
+
if (results.some((r) => r.ok)) {
|
|
32542
|
+
return { ok: true, missing: [] };
|
|
32543
|
+
}
|
|
32544
|
+
return results[0];
|
|
32545
|
+
}
|
|
32546
|
+
function enforceDesignPhaseToolEmissions(memberId, emittedToolNames) {
|
|
32547
|
+
const sets = DESIGN_PHASE_REQUIREMENT_SETS[memberId];
|
|
32548
|
+
if (!sets || sets.length === 0) {
|
|
32549
|
+
return { ok: true, missing: [] };
|
|
32550
|
+
}
|
|
32551
|
+
const result = checkMemberToolEmissionSets(memberId, emittedToolNames, sets);
|
|
32552
|
+
if (!result.ok) {
|
|
32553
|
+
console.warn(`[council] member "${memberId}" did not emit required tools: ${result.missing.join(", ")}. The downstream .zelari/ deliverable may be incomplete. (A forced retry turn scoped to the missing tools follows; the deterministic complete-design fallback covers any remaining gap.)`);
|
|
32554
|
+
}
|
|
32555
|
+
return result;
|
|
32556
|
+
}
|
|
32557
|
+
var DESIGN_PHASE_REQUIREMENT_SETS, DESIGN_PHASE_REQUIREMENTS;
|
|
32558
|
+
var init_toolEmission = __esm({
|
|
32559
|
+
"packages/core/dist/agents/council/toolEmission.js"() {
|
|
32560
|
+
"use strict";
|
|
32561
|
+
DESIGN_PHASE_REQUIREMENT_SETS = {
|
|
32562
|
+
nettun: [
|
|
32563
|
+
[{ name: "createPlan", min: 1 }],
|
|
32564
|
+
[
|
|
32565
|
+
{ name: "createPhase", min: 3 },
|
|
32566
|
+
{ name: "createTask", min: 6 },
|
|
32567
|
+
{ name: "createMilestone", min: 1 }
|
|
32568
|
+
]
|
|
32569
|
+
],
|
|
32570
|
+
geryon: [
|
|
32571
|
+
[{ name: "createDocument", min: 3 }]
|
|
32572
|
+
],
|
|
32573
|
+
pluton: [
|
|
32574
|
+
[{ name: "createDocument", min: 1 }]
|
|
32575
|
+
],
|
|
32576
|
+
minos: [
|
|
32577
|
+
[{ name: "createDocument", min: 1 }]
|
|
32578
|
+
],
|
|
32579
|
+
lucifer: [
|
|
32580
|
+
[{ name: "createDocument", min: 1 }]
|
|
32581
|
+
]
|
|
32582
|
+
};
|
|
32583
|
+
DESIGN_PHASE_REQUIREMENTS = Object.fromEntries(Object.entries(DESIGN_PHASE_REQUIREMENT_SETS).map(([id3, sets]) => [id3, sets[0]]));
|
|
32584
|
+
}
|
|
32585
|
+
});
|
|
32586
|
+
|
|
32587
|
+
// packages/core/dist/agents/council/retryTurn.js
|
|
32588
|
+
function shouldRetryMember(missingToolNames, attemptsSoFar) {
|
|
32589
|
+
if (missingToolNames.length === 0)
|
|
32590
|
+
return false;
|
|
32591
|
+
if (attemptsSoFar >= MAX_RETRY_PER_MEMBER)
|
|
32592
|
+
return false;
|
|
32593
|
+
return true;
|
|
32594
|
+
}
|
|
32595
|
+
function buildRetryPrompt(missingToolNames) {
|
|
32596
|
+
const names = missingToolNames.join(", ");
|
|
32597
|
+
return `You did not emit the required workspace tools: ${names}. Call ${names} NOW with concrete arguments. No prose. No search.`;
|
|
32598
|
+
}
|
|
32599
|
+
async function* runRetryTurnForMember(args) {
|
|
32600
|
+
if (isCouncilCancelled(args.signal))
|
|
32601
|
+
return [];
|
|
32602
|
+
const executableMissing = args.executableTools ? args.missingToolNames.filter((n) => args.executableTools.has(n)) : args.missingToolNames;
|
|
32603
|
+
if (executableMissing.length === 0) {
|
|
32604
|
+
return [];
|
|
32605
|
+
}
|
|
32606
|
+
const retryToolNames = executableMissing;
|
|
32607
|
+
const retryToolSpecs = getProviderTools(retryToolNames).map((t) => ({
|
|
32608
|
+
name: t.function.name,
|
|
32609
|
+
description: t.function.description,
|
|
32610
|
+
parameters: t.function.parameters
|
|
32611
|
+
}));
|
|
32612
|
+
const baseMessages = buildAgentMessages(args.agent, args.userMessage, args.ragContext, args.workspaceContext, args.priorOutputs, args.aiConfig, args.executableTools, args.runMode ?? "implementation", args.languageModule);
|
|
32613
|
+
const retryMessages = [
|
|
32614
|
+
...baseMessages,
|
|
32615
|
+
{
|
|
32616
|
+
role: "user",
|
|
32617
|
+
content: args.retryPrompt ?? buildRetryPrompt(executableMissing)
|
|
32303
32618
|
}
|
|
32304
|
-
|
|
32305
|
-
|
|
32306
|
-
|
|
32307
|
-
|
|
32308
|
-
|
|
32309
|
-
|
|
32619
|
+
];
|
|
32620
|
+
const maxToolCalls = args.minPerTool !== void 0 ? Object.entries(args.minPerTool).filter(([name]) => executableMissing.includes(name)).reduce((sum, [, min]) => sum + min, 0) : retryToolNames.length;
|
|
32621
|
+
const retryHarness = new AgentHarness({
|
|
32622
|
+
model: args.effectiveModel,
|
|
32623
|
+
provider: args.effectiveProvider,
|
|
32624
|
+
sessionId: args.sessionId,
|
|
32625
|
+
messages: retryMessages,
|
|
32626
|
+
tools: retryToolSpecs,
|
|
32627
|
+
eventBus: args.eventBus,
|
|
32628
|
+
toolRegistry: args.toolRegistry,
|
|
32629
|
+
// Budget the retry so the model can satisfy every requirement in
|
|
32630
|
+
// ONE tool_calls turn. For createTask min:12 this needs 12 calls.
|
|
32631
|
+
maxToolCallsPerTurn: maxToolCalls,
|
|
32632
|
+
memberId: args.agent.id,
|
|
32633
|
+
memberName: args.agent.name,
|
|
32634
|
+
providerStream: (params) => args.providerStream(params)
|
|
32635
|
+
});
|
|
32636
|
+
const retryEmitted = [];
|
|
32637
|
+
for await (const event of runHarnessWithAbort(retryHarness, args.signal)) {
|
|
32638
|
+
if (event.type === "tool_execution_start") {
|
|
32639
|
+
retryEmitted.push(event.toolName);
|
|
32310
32640
|
}
|
|
32641
|
+
yield event;
|
|
32311
32642
|
}
|
|
32312
|
-
return
|
|
32643
|
+
return retryEmitted;
|
|
32313
32644
|
}
|
|
32314
|
-
function
|
|
32315
|
-
|
|
32316
|
-
|
|
32317
|
-
|
|
32318
|
-
|
|
32319
|
-
const
|
|
32320
|
-
|
|
32321
|
-
|
|
32322
|
-
|
|
32323
|
-
|
|
32324
|
-
|
|
32325
|
-
|
|
32326
|
-
|
|
32645
|
+
async function* applyRetryIfMissing(args) {
|
|
32646
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32647
|
+
return;
|
|
32648
|
+
if (args.check.ok)
|
|
32649
|
+
return;
|
|
32650
|
+
const missingToolNames = args.check.missing.map((m) => m.split(" ")[0]);
|
|
32651
|
+
if (!shouldRetryMember(missingToolNames, 0))
|
|
32652
|
+
return;
|
|
32653
|
+
console.warn(`[council] ${args.agent.id} retrying missing tools: ${missingToolNames.join(", ")}`);
|
|
32654
|
+
const minPerTool = {};
|
|
32655
|
+
if (args.requirements) {
|
|
32656
|
+
for (const req of args.requirements) {
|
|
32657
|
+
if (missingToolNames.includes(req.name)) {
|
|
32658
|
+
minPerTool[req.name] = req.min;
|
|
32659
|
+
}
|
|
32660
|
+
}
|
|
32661
|
+
}
|
|
32327
32662
|
try {
|
|
32328
|
-
const
|
|
32329
|
-
|
|
32330
|
-
|
|
32331
|
-
|
|
32332
|
-
|
|
32333
|
-
|
|
32334
|
-
|
|
32335
|
-
|
|
32336
|
-
|
|
32337
|
-
|
|
32663
|
+
const retryGenerator = runRetryTurnForMember({
|
|
32664
|
+
agent: args.agent,
|
|
32665
|
+
missingToolNames,
|
|
32666
|
+
minPerTool,
|
|
32667
|
+
executableTools: args.executableNames,
|
|
32668
|
+
userMessage: args.userMessage,
|
|
32669
|
+
ragContext: args.config.ragContext,
|
|
32670
|
+
workspaceContext: args.config.workspaceContext,
|
|
32671
|
+
priorOutputs: args.agentOutputs,
|
|
32672
|
+
aiConfig: args.config.aiConfig,
|
|
32673
|
+
sessionId: args.sessionId,
|
|
32674
|
+
effectiveModel: args.effectiveModel,
|
|
32675
|
+
effectiveProvider: args.effectiveProvider,
|
|
32676
|
+
eventBus: args.config.eventBus,
|
|
32677
|
+
toolRegistry: args.config.tools,
|
|
32678
|
+
providerStream: args.config.providerStream,
|
|
32679
|
+
runMode: args.config.runMode,
|
|
32680
|
+
languageModule: args.languageModule,
|
|
32681
|
+
signal: args.config.signal
|
|
32682
|
+
});
|
|
32683
|
+
for await (const event of retryGenerator) {
|
|
32684
|
+
if (event.type === "tool_execution_start") {
|
|
32685
|
+
args.onToolCall();
|
|
32686
|
+
args.emittedToolNames.push(event.toolName);
|
|
32687
|
+
}
|
|
32688
|
+
yield event;
|
|
32689
|
+
}
|
|
32690
|
+
} catch (retryErr) {
|
|
32691
|
+
console.error(`[council] ${args.agent.id} retry failed:`, retryErr);
|
|
32338
32692
|
}
|
|
32693
|
+
enforceDesignPhaseToolEmissions(args.agent.id, args.emittedToolNames);
|
|
32339
32694
|
}
|
|
32340
|
-
|
|
32341
|
-
|
|
32342
|
-
|
|
32695
|
+
var MAX_RETRY_PER_MEMBER;
|
|
32696
|
+
var init_retryTurn = __esm({
|
|
32697
|
+
"packages/core/dist/agents/council/retryTurn.js"() {
|
|
32698
|
+
"use strict";
|
|
32699
|
+
init_AgentHarness();
|
|
32700
|
+
init_cancel();
|
|
32701
|
+
init_toolSchemas();
|
|
32702
|
+
init_memberMessages();
|
|
32703
|
+
init_toolEmission();
|
|
32704
|
+
MAX_RETRY_PER_MEMBER = 1;
|
|
32705
|
+
}
|
|
32706
|
+
});
|
|
32707
|
+
|
|
32708
|
+
// packages/core/dist/agents/council/chairmanDelivery.js
|
|
32709
|
+
async function* applyCompletionRetry(args) {
|
|
32710
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32711
|
+
return;
|
|
32712
|
+
const check2 = checkImplementationCompletion(args.emittedToolNames);
|
|
32713
|
+
if (check2.ok)
|
|
32714
|
+
return;
|
|
32715
|
+
const retryTool = resolveVerifyRetryTool(args.executableNames);
|
|
32716
|
+
if (!retryTool) {
|
|
32717
|
+
console.warn("[council] implementation verify retry skipped \u2014 no grep_content/bash in registry");
|
|
32718
|
+
return;
|
|
32719
|
+
}
|
|
32720
|
+
if (!shouldRetryMember([retryTool], 0))
|
|
32721
|
+
return;
|
|
32722
|
+
console.warn(`[council] ${args.agent.id} retrying missing verify tool: ${retryTool}`);
|
|
32723
|
+
try {
|
|
32724
|
+
const retryGenerator = runRetryTurnForMember({
|
|
32725
|
+
agent: args.agent,
|
|
32726
|
+
missingToolNames: [retryTool],
|
|
32727
|
+
executableTools: args.executableNames,
|
|
32728
|
+
userMessage: args.userMessage,
|
|
32729
|
+
ragContext: args.config.ragContext,
|
|
32730
|
+
workspaceContext: args.config.workspaceContext,
|
|
32731
|
+
priorOutputs: args.agentOutputs,
|
|
32732
|
+
aiConfig: args.config.aiConfig,
|
|
32733
|
+
sessionId: args.sessionId,
|
|
32734
|
+
effectiveModel: args.effectiveModel,
|
|
32735
|
+
effectiveProvider: args.effectiveProvider,
|
|
32736
|
+
eventBus: args.config.eventBus,
|
|
32737
|
+
toolRegistry: args.config.tools,
|
|
32738
|
+
providerStream: args.config.providerStream,
|
|
32739
|
+
runMode: args.config.runMode,
|
|
32740
|
+
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool),
|
|
32741
|
+
languageModule: args.languageModule,
|
|
32742
|
+
signal: args.config.signal
|
|
32743
|
+
});
|
|
32744
|
+
for await (const event of retryGenerator) {
|
|
32745
|
+
if (event.type === "tool_execution_start") {
|
|
32746
|
+
args.onToolCall();
|
|
32747
|
+
args.emittedToolNames.push(event.toolName);
|
|
32748
|
+
}
|
|
32749
|
+
yield event;
|
|
32750
|
+
}
|
|
32751
|
+
} catch (retryErr) {
|
|
32752
|
+
console.error(`[council] ${args.agent.id} verify retry failed:`, retryErr);
|
|
32753
|
+
}
|
|
32754
|
+
const after = checkImplementationCompletion(args.emittedToolNames);
|
|
32755
|
+
if (!after.ok) {
|
|
32756
|
+
console.warn(`[council] ${args.agent.id} still missing verify after retry: ${after.reason}`);
|
|
32757
|
+
}
|
|
32343
32758
|
}
|
|
32344
|
-
function
|
|
32345
|
-
const
|
|
32346
|
-
|
|
32347
|
-
|
|
32348
|
-
|
|
32349
|
-
|
|
32759
|
+
function buildMotionFixPrompt(violations) {
|
|
32760
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
32761
|
+
for (const v of violations) {
|
|
32762
|
+
const file2 = v.file || "index.html";
|
|
32763
|
+
const loc = v.line ? `${file2}:L${v.line}` : file2;
|
|
32764
|
+
const list = byFile.get(file2) ?? [];
|
|
32765
|
+
list.push(` - ${loc}: ${v.message}`);
|
|
32766
|
+
byFile.set(file2, list);
|
|
32767
|
+
}
|
|
32768
|
+
const blocks = Array.from(byFile.values()).map((lines) => lines.join("\n")).join("\n");
|
|
32769
|
+
return `Deterministic verification found ${violations.length} motion violation(s) in the file(s) you just edited. Fix ONLY these \u2014 do not add features, do not rewrite sections, do not touch anything else:
|
|
32770
|
+
${blocks}
|
|
32771
|
+
|
|
32772
|
+
Rules: animate ONLY transform and opacity. Replace any box-shadow / background / background-position / filter / color / border-color / width / height / grid-template-rows used in @keyframes or transitions with transform/opacity equivalents (e.g. render a glow via a pseudo-element that scales and fades). For every classList.add('x') in the script, add a matching '.x' CSS rule. Use read_file to see the exact lines, then edit_file. When the listed items are fixed, stop \u2014 no summary.`;
|
|
32350
32773
|
}
|
|
32351
|
-
function
|
|
32352
|
-
|
|
32353
|
-
|
|
32354
|
-
|
|
32355
|
-
|
|
32356
|
-
|
|
32774
|
+
async function* applyImplementationWriteRetry(args) {
|
|
32775
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32776
|
+
return;
|
|
32777
|
+
if (args.check.ok)
|
|
32778
|
+
return;
|
|
32779
|
+
if (!shouldRetryMember(["write_file"], 0))
|
|
32780
|
+
return;
|
|
32781
|
+
const statusMsg = `[council] ${args.chairman.id} implementation write retry: ${args.check.missing.join(", ")}`;
|
|
32782
|
+
args.onCouncilStatus?.(statusMsg);
|
|
32783
|
+
console.warn(statusMsg);
|
|
32784
|
+
try {
|
|
32785
|
+
const retryGenerator = runRetryTurnForMember({
|
|
32786
|
+
agent: args.chairman,
|
|
32787
|
+
missingToolNames: ["read_file", "write_file", "edit_file"],
|
|
32788
|
+
minPerTool: { read_file: 3, edit_file: 8, write_file: 1 },
|
|
32789
|
+
executableTools: args.executableNames,
|
|
32790
|
+
userMessage: args.userMessage,
|
|
32791
|
+
ragContext: args.config.ragContext,
|
|
32792
|
+
workspaceContext: args.config.workspaceContext,
|
|
32793
|
+
priorOutputs: args.agentOutputs,
|
|
32794
|
+
aiConfig: args.config.aiConfig,
|
|
32795
|
+
sessionId: args.sessionId,
|
|
32796
|
+
effectiveModel: args.effectiveModel,
|
|
32797
|
+
effectiveProvider: args.effectiveProvider,
|
|
32798
|
+
eventBus: args.config.eventBus,
|
|
32799
|
+
toolRegistry: args.config.tools,
|
|
32800
|
+
providerStream: args.config.providerStream,
|
|
32801
|
+
runMode: "implementation",
|
|
32802
|
+
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage),
|
|
32803
|
+
languageModule: args.languageModule,
|
|
32804
|
+
signal: args.config.signal
|
|
32805
|
+
});
|
|
32806
|
+
for await (const event of retryGenerator) {
|
|
32807
|
+
if (event.type === "tool_execution_start")
|
|
32808
|
+
args.onToolCall?.();
|
|
32809
|
+
if (event.type === "tool_execution_end" && !event.isError && typeof event.result === "string") {
|
|
32810
|
+
try {
|
|
32811
|
+
const parsed = JSON.parse(event.result);
|
|
32812
|
+
if ((parsed.bytesWritten ?? 0) > 0 || (parsed.occurrencesReplaced ?? 0) > 0) {
|
|
32813
|
+
args.onSuccessfulWrite?.();
|
|
32814
|
+
}
|
|
32815
|
+
} catch {
|
|
32816
|
+
if (event.result.includes("bytesWritten") || event.result.includes("occurrencesReplaced")) {
|
|
32817
|
+
args.onSuccessfulWrite?.();
|
|
32818
|
+
}
|
|
32819
|
+
}
|
|
32820
|
+
}
|
|
32821
|
+
yield event;
|
|
32822
|
+
}
|
|
32823
|
+
} catch (retryErr) {
|
|
32824
|
+
console.error(`[council] ${args.chairman.id} implementation write retry failed:`, retryErr);
|
|
32357
32825
|
}
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32826
|
+
}
|
|
32827
|
+
async function* runChairmanDeliveryLoop(args) {
|
|
32828
|
+
const maxAttempts = args.maxAttempts ?? MAX_DELIVERY_ATTEMPTS;
|
|
32829
|
+
const zelariRoot = `${args.projectRoot}/.zelari`;
|
|
32830
|
+
let attempt = 0;
|
|
32831
|
+
while (attempt < maxAttempts) {
|
|
32832
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32833
|
+
return false;
|
|
32834
|
+
const report = runImplementationVerification({
|
|
32835
|
+
projectRoot: args.projectRoot,
|
|
32836
|
+
zelariRoot
|
|
32837
|
+
});
|
|
32838
|
+
const blocking = filterDeliveryBlockingFails(report.results);
|
|
32839
|
+
if (blocking.length === 0)
|
|
32840
|
+
return true;
|
|
32841
|
+
if (blocking.some((b) => b.id === "inline-js.budget")) {
|
|
32842
|
+
const jsFix = applyInlineJsAutofix(args.projectRoot, report);
|
|
32843
|
+
if (jsFix.applied) {
|
|
32844
|
+
args.onCouncilStatus?.(`[council] ${args.chairman.id} inline-js autofix: ${jsFix.fixes.join("; ")}`);
|
|
32845
|
+
const afterJs = runImplementationVerification({
|
|
32846
|
+
projectRoot: args.projectRoot,
|
|
32847
|
+
zelariRoot
|
|
32848
|
+
});
|
|
32849
|
+
if (filterDeliveryBlockingFails(afterJs.results).length === 0)
|
|
32850
|
+
return true;
|
|
32851
|
+
}
|
|
32852
|
+
}
|
|
32853
|
+
attempt++;
|
|
32854
|
+
const statusMsg = `[council] ${args.chairman.id} delivery pass ${attempt}/${maxAttempts}: ${blocking.map((b) => b.id).join(", ")}`;
|
|
32855
|
+
args.onCouncilStatus?.(statusMsg);
|
|
32856
|
+
console.warn(statusMsg);
|
|
32857
|
+
try {
|
|
32858
|
+
const fixGenerator = runRetryTurnForMember({
|
|
32859
|
+
agent: args.chairman,
|
|
32860
|
+
missingToolNames: ["read_file", "edit_file"],
|
|
32861
|
+
minPerTool: { read_file: 3, edit_file: 10 },
|
|
32862
|
+
executableTools: args.executableNames,
|
|
32863
|
+
userMessage: args.userMessage,
|
|
32864
|
+
ragContext: args.config.ragContext,
|
|
32865
|
+
workspaceContext: args.config.workspaceContext,
|
|
32866
|
+
priorOutputs: args.agentOutputs,
|
|
32867
|
+
aiConfig: args.config.aiConfig,
|
|
32868
|
+
sessionId: args.sessionId,
|
|
32869
|
+
effectiveModel: args.effectiveModel,
|
|
32870
|
+
effectiveProvider: args.effectiveProvider,
|
|
32871
|
+
eventBus: args.config.eventBus,
|
|
32872
|
+
toolRegistry: args.config.tools,
|
|
32873
|
+
providerStream: args.config.providerStream,
|
|
32874
|
+
runMode: "implementation",
|
|
32875
|
+
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage),
|
|
32876
|
+
languageModule: args.languageModule,
|
|
32877
|
+
signal: args.config.signal
|
|
32878
|
+
});
|
|
32879
|
+
for await (const event of fixGenerator) {
|
|
32880
|
+
if (event.type === "tool_execution_start")
|
|
32881
|
+
args.onToolCall?.();
|
|
32882
|
+
yield event;
|
|
32883
|
+
}
|
|
32884
|
+
} catch (deliveryErr) {
|
|
32885
|
+
console.error(`[council] ${args.chairman.id} delivery pass ${attempt} failed:`, deliveryErr);
|
|
32886
|
+
break;
|
|
32887
|
+
}
|
|
32888
|
+
for (const rel2 of args.changedFiles) {
|
|
32889
|
+
for (const w of runChairmanMicroGate({ projectRoot: args.projectRoot, relPath: rel2, zelariRoot })) {
|
|
32890
|
+
args.changedFiles.add(w.file ?? rel2);
|
|
32891
|
+
}
|
|
32892
|
+
}
|
|
32893
|
+
}
|
|
32894
|
+
const finalReport = runImplementationVerification({
|
|
32895
|
+
projectRoot: args.projectRoot,
|
|
32896
|
+
zelariRoot
|
|
32897
|
+
});
|
|
32898
|
+
return filterDeliveryBlockingFails(finalReport.results).length === 0;
|
|
32899
|
+
}
|
|
32900
|
+
var MAX_DELIVERY_ATTEMPTS;
|
|
32901
|
+
var init_chairmanDelivery = __esm({
|
|
32902
|
+
"packages/core/dist/agents/council/chairmanDelivery.js"() {
|
|
32903
|
+
"use strict";
|
|
32904
|
+
init_microGate();
|
|
32905
|
+
init_completion();
|
|
32906
|
+
init_implementationDelivery();
|
|
32907
|
+
init_runChecks();
|
|
32908
|
+
init_inlineJsAutofix();
|
|
32909
|
+
init_retryTurn();
|
|
32910
|
+
init_cancel();
|
|
32911
|
+
MAX_DELIVERY_ATTEMPTS = 2;
|
|
32912
|
+
}
|
|
32913
|
+
});
|
|
32914
|
+
|
|
32915
|
+
// packages/core/dist/agents/council/chairmanFixLoop.js
|
|
32916
|
+
async function* replayChairmanTextTools(args) {
|
|
32917
|
+
const tools = parseTextToolCalls(args.synthesisText);
|
|
32918
|
+
if (tools.length === 0)
|
|
32919
|
+
return 0;
|
|
32920
|
+
let applied = 0;
|
|
32921
|
+
for (const tt of tools) {
|
|
32922
|
+
if (tt.name !== "edit_file" && tt.name !== "write_file")
|
|
32923
|
+
continue;
|
|
32924
|
+
const normalized = normalizeTextToolArgs(tt.name, tt.args);
|
|
32925
|
+
const toolCallId = `replay-${crypto.randomUUID().slice(0, 8)}`;
|
|
32926
|
+
yield createBrainEvent("tool_execution_start", args.sessionId, {
|
|
32927
|
+
toolCallId,
|
|
32928
|
+
toolName: tt.name,
|
|
32929
|
+
args: normalized,
|
|
32930
|
+
...args.memberId ? { memberId: args.memberId } : {}
|
|
32931
|
+
});
|
|
32932
|
+
const startMs = Date.now();
|
|
32933
|
+
let resultStr = "";
|
|
32934
|
+
let isError = false;
|
|
32935
|
+
try {
|
|
32936
|
+
const result = await args.toolRegistry.invoke(tt.name, normalized, {
|
|
32937
|
+
cwd: args.projectRoot,
|
|
32938
|
+
sessionId: args.sessionId
|
|
32939
|
+
});
|
|
32940
|
+
if (result.ok) {
|
|
32941
|
+
const val = result.value;
|
|
32942
|
+
if (tt.name === "edit_file" && val.occurrencesReplaced === 0) {
|
|
32943
|
+
resultStr = `edit_file: no match for oldString (replay)`;
|
|
32944
|
+
isError = true;
|
|
32945
|
+
} else {
|
|
32946
|
+
resultStr = typeof result.value === "string" ? result.value : JSON.stringify(result.value, null, 2);
|
|
32947
|
+
applied += 1;
|
|
32948
|
+
}
|
|
32949
|
+
} else {
|
|
32950
|
+
resultStr = result.error;
|
|
32951
|
+
isError = true;
|
|
32952
|
+
}
|
|
32953
|
+
} catch (err) {
|
|
32954
|
+
resultStr = err instanceof Error ? err.message : String(err);
|
|
32955
|
+
isError = true;
|
|
32956
|
+
}
|
|
32957
|
+
yield createBrainEvent("tool_execution_end", args.sessionId, {
|
|
32958
|
+
toolCallId,
|
|
32959
|
+
result: resultStr,
|
|
32960
|
+
isError,
|
|
32961
|
+
durationMs: Date.now() - startMs
|
|
32962
|
+
});
|
|
32963
|
+
}
|
|
32964
|
+
return applied;
|
|
32965
|
+
}
|
|
32966
|
+
async function* runChairmanFixLoop(args) {
|
|
32967
|
+
const maxAttempts = args.maxAttempts ?? 3;
|
|
32968
|
+
const zelariRoot = `${args.projectRoot}/.zelari`;
|
|
32969
|
+
let current = Array.from(args.violations.values());
|
|
32970
|
+
let attempt = 0;
|
|
32971
|
+
while (current.length > 0 && attempt < maxAttempts) {
|
|
32972
|
+
if (isCouncilCancelled(args.config.signal))
|
|
32973
|
+
return;
|
|
32974
|
+
attempt++;
|
|
32975
|
+
try {
|
|
32976
|
+
const fixGenerator = runRetryTurnForMember({
|
|
32977
|
+
agent: args.chairman,
|
|
32978
|
+
missingToolNames: ["read_file", "edit_file"],
|
|
32979
|
+
minPerTool: { read_file: 2, edit_file: 8 },
|
|
32980
|
+
executableTools: args.executableNames,
|
|
32981
|
+
userMessage: args.userMessage,
|
|
32982
|
+
ragContext: args.config.ragContext,
|
|
32983
|
+
workspaceContext: args.config.workspaceContext,
|
|
32984
|
+
priorOutputs: args.agentOutputs,
|
|
32985
|
+
aiConfig: args.config.aiConfig,
|
|
32986
|
+
sessionId: args.sessionId,
|
|
32987
|
+
effectiveModel: args.effectiveModel,
|
|
32988
|
+
effectiveProvider: args.effectiveProvider,
|
|
32989
|
+
eventBus: args.config.eventBus,
|
|
32990
|
+
toolRegistry: args.config.tools,
|
|
32991
|
+
providerStream: args.config.providerStream,
|
|
32992
|
+
runMode: "implementation",
|
|
32993
|
+
retryPrompt: buildMotionFixPrompt(current),
|
|
32994
|
+
languageModule: args.languageModule,
|
|
32995
|
+
signal: args.config.signal
|
|
32996
|
+
});
|
|
32997
|
+
for await (const event of fixGenerator) {
|
|
32998
|
+
if (event.type === "tool_execution_start")
|
|
32999
|
+
args.onToolCall?.();
|
|
33000
|
+
yield event;
|
|
33001
|
+
}
|
|
33002
|
+
} catch (fixErr) {
|
|
33003
|
+
console.error(`[council] chairman fix pass ${attempt} failed:`, fixErr);
|
|
33004
|
+
break;
|
|
33005
|
+
}
|
|
33006
|
+
const rescanned = /* @__PURE__ */ new Map();
|
|
33007
|
+
for (const relPath of args.changedFiles) {
|
|
33008
|
+
for (const w of runChairmanMicroGate({ projectRoot: args.projectRoot, relPath, zelariRoot })) {
|
|
33009
|
+
rescanned.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
33010
|
+
}
|
|
33011
|
+
}
|
|
33012
|
+
current = Array.from(rescanned.values());
|
|
32361
33013
|
}
|
|
32362
|
-
out = out.replace(/\n{3,}/g, "\n\n").trim();
|
|
32363
|
-
return scrubProprietaryLeak(out);
|
|
32364
|
-
}
|
|
32365
|
-
function restrictImplementationWrites(toolNames, opts) {
|
|
32366
|
-
if (opts.runMode !== "implementation" || opts.isImplementer)
|
|
32367
|
-
return toolNames;
|
|
32368
|
-
return toolNames.filter((t) => !MUTATING_PROJECT_TOOLS.includes(t));
|
|
32369
33014
|
}
|
|
32370
|
-
|
|
32371
|
-
|
|
32372
|
-
|
|
32373
|
-
|
|
32374
|
-
|
|
32375
|
-
|
|
32376
|
-
|
|
32377
|
-
|
|
32378
|
-
|
|
32379
|
-
...aiConfig?.customPromptModules ?? [],
|
|
32380
|
-
languageModule
|
|
32381
|
-
]
|
|
32382
|
-
} : aiConfig;
|
|
32383
|
-
const modeAwareAgent = {
|
|
32384
|
-
...agent,
|
|
32385
|
-
systemPrompt: resolveRoleSystemPrompt(agent, runMode)
|
|
32386
|
-
};
|
|
32387
|
-
const split = buildSystemPromptSplit(modeAwareAgent, {
|
|
32388
|
-
tools: getAllTools(),
|
|
32389
|
-
toolNames,
|
|
32390
|
-
aiConfig: mergedAiConfig,
|
|
32391
|
-
workspaceContext,
|
|
32392
|
-
ragContext,
|
|
32393
|
-
mode: "council",
|
|
32394
|
-
includeWorkspaceInPrompt: true
|
|
32395
|
-
});
|
|
32396
|
-
const messages = [
|
|
32397
|
-
{ role: "system", content: split.stable }
|
|
32398
|
-
];
|
|
32399
|
-
if (split.volatile.trim()) {
|
|
32400
|
-
messages.push({ role: "system", content: split.volatile });
|
|
33015
|
+
var init_chairmanFixLoop = __esm({
|
|
33016
|
+
"packages/core/dist/agents/council/chairmanFixLoop.js"() {
|
|
33017
|
+
"use strict";
|
|
33018
|
+
init_AgentHarness();
|
|
33019
|
+
init_events();
|
|
33020
|
+
init_microGate();
|
|
33021
|
+
init_chairmanDelivery();
|
|
33022
|
+
init_retryTurn();
|
|
33023
|
+
init_cancel();
|
|
32401
33024
|
}
|
|
32402
|
-
|
|
32403
|
-
if (priorOutputs.length > 0) {
|
|
32404
|
-
const MAX_PRIOR_CHARS = 2800;
|
|
32405
|
-
const summary = priorOutputs.map((o) => {
|
|
32406
|
-
const body = o.content.length > MAX_PRIOR_CHARS ? `${o.content.slice(0, MAX_PRIOR_CHARS)}
|
|
32407
|
-
\u2026 [truncated ${o.content.length}\u2192${MAX_PRIOR_CHARS} chars; treat as hypothesis]` : o.content;
|
|
32408
|
-
return `[${o.name} - ${o.role}]: ${body}`;
|
|
32409
|
-
}).join("\n\n");
|
|
32410
|
-
messages.push({
|
|
32411
|
-
role: "user",
|
|
32412
|
-
content: `Previous council members have said (hypotheses \u2014 prefer product files on disk if they conflict):
|
|
32413
|
-
${summary}
|
|
33025
|
+
});
|
|
32414
33026
|
|
|
32415
|
-
|
|
32416
|
-
|
|
32417
|
-
|
|
32418
|
-
messages.push({ role: "user", content: userMessage });
|
|
32419
|
-
}
|
|
32420
|
-
return messages;
|
|
32421
|
-
}
|
|
33027
|
+
// packages/core/dist/agents/councilApi.js
|
|
33028
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
33029
|
+
import { join as join8 } from "node:path";
|
|
32422
33030
|
async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
32423
33031
|
const baseAgents = getCouncilAgents(config2.councilSize);
|
|
32424
33032
|
const agents = swapMembers(baseAgents, config2.memberSwap ?? {});
|
|
@@ -32454,6 +33062,17 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32454
33062
|
model: config2.model,
|
|
32455
33063
|
provider: config2.provider ?? "minimax"
|
|
32456
33064
|
};
|
|
33065
|
+
if (isCouncilCancelled(config2.signal)) {
|
|
33066
|
+
yield {
|
|
33067
|
+
type: "agent_end",
|
|
33068
|
+
id: crypto.randomUUID(),
|
|
33069
|
+
ts: Date.now(),
|
|
33070
|
+
sessionId: sessionId2,
|
|
33071
|
+
reason: "cancelled",
|
|
33072
|
+
durationMs: 0
|
|
33073
|
+
};
|
|
33074
|
+
return;
|
|
33075
|
+
}
|
|
32457
33076
|
const emitMemberCost = (input) => {
|
|
32458
33077
|
const usage = input.usage;
|
|
32459
33078
|
const prompt = usage?.promptTokens ?? 0;
|
|
@@ -32483,6 +33102,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32483
33102
|
const oracle = agents.find((a) => a.id === "minos") ?? (config2.skipSpecialists ? getAgent("minos") : void 0);
|
|
32484
33103
|
const chairman = agents.find((a) => a.id === "lucifer") ?? (config2.skipSpecialists ? getAgent("lucifer") : void 0);
|
|
32485
33104
|
for (const agent of specialists) {
|
|
33105
|
+
if (isCouncilCancelled(config2.signal))
|
|
33106
|
+
break;
|
|
32486
33107
|
if (completedIds.has(agent.id))
|
|
32487
33108
|
continue;
|
|
32488
33109
|
callbacks.onAgentStart?.(agent);
|
|
@@ -32528,7 +33149,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32528
33149
|
const emittedToolNames = [];
|
|
32529
33150
|
const memberStart = Date.now();
|
|
32530
33151
|
try {
|
|
32531
|
-
for await (const event of harness.
|
|
33152
|
+
for await (const event of runHarnessWithAbort(harness, config2.signal)) {
|
|
32532
33153
|
yield event;
|
|
32533
33154
|
if (event.type === "tool_execution_start") {
|
|
32534
33155
|
toolCalls += 1;
|
|
@@ -32550,7 +33171,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32550
33171
|
fullText = `Error: ${err instanceof Error ? err.message : "Unknown"}`;
|
|
32551
33172
|
errored = true;
|
|
32552
33173
|
}
|
|
32553
|
-
if (isDesignPhase && !errored && !NON_RETRY_AGENTS.has(agent.id)) {
|
|
33174
|
+
if (isDesignPhase && !errored && !NON_RETRY_AGENTS.has(agent.id) && !isCouncilCancelled(config2.signal)) {
|
|
32554
33175
|
const specialistCheck = enforceDesignPhaseToolEmissions(agent.id, emittedToolNames);
|
|
32555
33176
|
yield* applyRetryIfMissing({
|
|
32556
33177
|
agent,
|
|
@@ -32633,7 +33254,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32633
33254
|
}
|
|
32634
33255
|
}
|
|
32635
33256
|
}
|
|
32636
|
-
if (oracle && !completedIds.has(oracle.id)) {
|
|
33257
|
+
if (oracle && !completedIds.has(oracle.id) && !isCouncilCancelled(config2.signal)) {
|
|
32637
33258
|
callbacks.onAgentStart?.(oracle);
|
|
32638
33259
|
const override = config2.agentModels?.[oracle.id];
|
|
32639
33260
|
const effectiveProvider = override?.providerId ?? config2.provider ?? "minimax";
|
|
@@ -32682,7 +33303,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32682
33303
|
const emittedToolNames = [];
|
|
32683
33304
|
const memberStart = Date.now();
|
|
32684
33305
|
try {
|
|
32685
|
-
for await (const event of harness.
|
|
33306
|
+
for await (const event of runHarnessWithAbort(harness, config2.signal)) {
|
|
32686
33307
|
yield event;
|
|
32687
33308
|
if (event.type === "tool_execution_start") {
|
|
32688
33309
|
toolCalls += 1;
|
|
@@ -32704,7 +33325,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32704
33325
|
fullText = `Review error: ${err instanceof Error ? err.message : "Unknown"}`;
|
|
32705
33326
|
errored = true;
|
|
32706
33327
|
}
|
|
32707
|
-
if (isDesignPhase && !errored) {
|
|
33328
|
+
if (isDesignPhase && !errored && !isCouncilCancelled(config2.signal)) {
|
|
32708
33329
|
const oracleCheck = enforceDesignPhaseToolEmissions(oracle.id, emittedToolNames);
|
|
32709
33330
|
yield* applyRetryIfMissing({
|
|
32710
33331
|
agent: oracle,
|
|
@@ -32764,7 +33385,7 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32764
33385
|
});
|
|
32765
33386
|
agentOutputs.push({ name: oracle.name, role: oracle.role, content: cleaned });
|
|
32766
33387
|
}
|
|
32767
|
-
if (chairman && !completedIds.has(chairman.id)) {
|
|
33388
|
+
if (chairman && !completedIds.has(chairman.id) && !isCouncilCancelled(config2.signal)) {
|
|
32768
33389
|
callbacks.onSynthesisStart?.();
|
|
32769
33390
|
callbacks.onAgentStart?.(chairman);
|
|
32770
33391
|
const override = config2.agentModels?.[chairman.id];
|
|
@@ -32800,702 +33421,264 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
32800
33421
|
});
|
|
32801
33422
|
let fullText = "";
|
|
32802
33423
|
let toolCalls = 0;
|
|
32803
|
-
let usage = null;
|
|
32804
|
-
let errored = false;
|
|
32805
|
-
let lastErrorMessage = "";
|
|
32806
|
-
const emittedToolNames = [];
|
|
32807
|
-
const pendingChairmanWrites = /* @__PURE__ */ new Map();
|
|
32808
|
-
let successfulWriteCount = 0;
|
|
32809
|
-
const chairmanViolations = /* @__PURE__ */ new Map();
|
|
32810
|
-
const changedTargetFiles = /* @__PURE__ */ new Set();
|
|
32811
|
-
let chairmanProjectRoot = parseProjectRootFromWorkspaceContext(config2.workspaceContext ?? "");
|
|
32812
|
-
const memberStart = Date.now();
|
|
32813
|
-
try {
|
|
32814
|
-
for await (const event of chairmanHarness.
|
|
32815
|
-
yield event;
|
|
32816
|
-
if (event.type === "tool_execution_start") {
|
|
32817
|
-
toolCalls += 1;
|
|
32818
|
-
emittedToolNames.push(event.toolName);
|
|
32819
|
-
if (!isDesignPhase && (event.toolName === "write_file" || event.toolName === "edit_file") && typeof event.args.path === "string") {
|
|
32820
|
-
pendingChairmanWrites.set(event.toolCallId, {
|
|
32821
|
-
path: event.args.path,
|
|
32822
|
-
toolName: event.toolName
|
|
32823
|
-
});
|
|
32824
|
-
}
|
|
32825
|
-
}
|
|
32826
|
-
if (!isDesignPhase && event.type === "tool_execution_end") {
|
|
32827
|
-
const pending = pendingChairmanWrites.get(event.toolCallId);
|
|
32828
|
-
if (pending) {
|
|
32829
|
-
pendingChairmanWrites.delete(event.toolCallId);
|
|
32830
|
-
if (!event.isError) {
|
|
32831
|
-
let wrote = pending.toolName === "write_file";
|
|
32832
|
-
if (pending.toolName === "edit_file" && typeof event.result === "string") {
|
|
32833
|
-
try {
|
|
32834
|
-
const parsed = JSON.parse(event.result);
|
|
32835
|
-
wrote = (parsed.occurrencesReplaced ?? 0) > 0;
|
|
32836
|
-
} catch {
|
|
32837
|
-
wrote = false;
|
|
32838
|
-
}
|
|
32839
|
-
}
|
|
32840
|
-
if (wrote) {
|
|
32841
|
-
successfulWriteCount += 1;
|
|
32842
|
-
const projectRoot = parseProjectRootFromWorkspaceContext(config2.workspaceContext);
|
|
32843
|
-
if (projectRoot) {
|
|
32844
|
-
chairmanProjectRoot = projectRoot;
|
|
32845
|
-
changedTargetFiles.add(pending.path);
|
|
32846
|
-
for (const w of runChairmanMicroGate({
|
|
32847
|
-
projectRoot,
|
|
32848
|
-
relPath: pending.path,
|
|
32849
|
-
zelariRoot: `${projectRoot}/.zelari`
|
|
32850
|
-
})) {
|
|
32851
|
-
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
32852
|
-
}
|
|
32853
|
-
}
|
|
32854
|
-
}
|
|
32855
|
-
}
|
|
32856
|
-
}
|
|
32857
|
-
}
|
|
32858
|
-
if (event.type === "message_end" && event.usage) {
|
|
32859
|
-
usage = event.usage;
|
|
32860
|
-
}
|
|
32861
|
-
if (event.type === "message_delta") {
|
|
32862
|
-
fullText += event.delta;
|
|
32863
|
-
callbacks.onSynthesisChunk?.(event.delta);
|
|
32864
|
-
callbacks.onAgentChunk?.(chairman, event.delta);
|
|
32865
|
-
}
|
|
32866
|
-
if (event.type === "error") {
|
|
32867
|
-
if (event.severity !== "cancelled" && event.code !== "text_tools_parse_failed") {
|
|
32868
|
-
errored = true;
|
|
32869
|
-
lastErrorMessage = event.message;
|
|
32870
|
-
}
|
|
32871
|
-
}
|
|
32872
|
-
}
|
|
32873
|
-
} catch (err) {
|
|
32874
|
-
console.error(`[council] chairman "${chairman.id}" failed:`, err);
|
|
32875
|
-
errored = true;
|
|
32876
|
-
lastErrorMessage = err instanceof Error ? err.message : String(err);
|
|
32877
|
-
}
|
|
32878
|
-
if (isDesignPhase && !errored) {
|
|
32879
|
-
const chairmanCheck = enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
32880
|
-
yield* applyRetryIfMissing({
|
|
32881
|
-
agent: chairman,
|
|
32882
|
-
check: chairmanCheck,
|
|
32883
|
-
requirements: DESIGN_PHASE_REQUIREMENTS[chairman.id],
|
|
32884
|
-
emittedToolNames,
|
|
32885
|
-
executableNames,
|
|
32886
|
-
sessionId: sessionId2,
|
|
32887
|
-
userMessage,
|
|
32888
|
-
agentOutputs,
|
|
32889
|
-
config: config2,
|
|
32890
|
-
effectiveProvider,
|
|
32891
|
-
effectiveModel,
|
|
32892
|
-
onToolCall: () => {
|
|
32893
|
-
toolCalls += 1;
|
|
32894
|
-
},
|
|
32895
|
-
languageModule: councilLanguageModule
|
|
32896
|
-
});
|
|
32897
|
-
} else if (isDesignPhase) {
|
|
32898
|
-
enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
32899
|
-
} else if (!errored) {
|
|
32900
|
-
if (chairmanProjectRoot) {
|
|
32901
|
-
const zelariRoot = `${chairmanProjectRoot}/.zelari`;
|
|
32902
|
-
const spec = loadNfrSpec(zelariRoot) ?? DEFAULT_NFR_SPEC;
|
|
32903
|
-
for (const rel2 of spec.targets) {
|
|
32904
|
-
if (!existsSync12(join8(chairmanProjectRoot, rel2)))
|
|
32905
|
-
continue;
|
|
32906
|
-
changedTargetFiles.add(rel2);
|
|
32907
|
-
for (const w of runChairmanMicroGate({ projectRoot: chairmanProjectRoot, relPath: rel2, zelariRoot })) {
|
|
32908
|
-
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
32909
|
-
}
|
|
32910
|
-
}
|
|
32911
|
-
}
|
|
32912
|
-
if (fullText.includes("---TOOLS---") && chairmanProjectRoot && config2.tools) {
|
|
32913
|
-
const replayed = yield* replayChairmanTextTools({
|
|
32914
|
-
synthesisText: fullText,
|
|
32915
|
-
projectRoot: chairmanProjectRoot,
|
|
32916
|
-
toolRegistry: config2.tools,
|
|
32917
|
-
sessionId: sessionId2,
|
|
32918
|
-
memberId: chairman.id
|
|
32919
|
-
});
|
|
32920
|
-
successfulWriteCount += replayed;
|
|
32921
|
-
const zelariRootReplay = `${chairmanProjectRoot}/.zelari`;
|
|
32922
|
-
const specReplay = loadNfrSpec(zelariRootReplay) ?? DEFAULT_NFR_SPEC;
|
|
32923
|
-
for (const rel2 of specReplay.targets) {
|
|
32924
|
-
if (!existsSync12(join8(chairmanProjectRoot, rel2)))
|
|
32925
|
-
continue;
|
|
32926
|
-
changedTargetFiles.add(rel2);
|
|
32927
|
-
for (const w of runChairmanMicroGate({
|
|
32928
|
-
projectRoot: chairmanProjectRoot,
|
|
32929
|
-
relPath: rel2,
|
|
32930
|
-
zelariRoot: zelariRootReplay
|
|
32931
|
-
})) {
|
|
32932
|
-
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
32933
|
-
}
|
|
32934
|
-
}
|
|
32935
|
-
}
|
|
32936
|
-
if (chairmanProjectRoot) {
|
|
32937
|
-
const deliveryCheck = checkImplementationDelivery(successfulWriteCount, countEmittedWriteTools(emittedToolNames));
|
|
32938
|
-
if (!deliveryCheck.ok) {
|
|
32939
|
-
yield* applyImplementationWriteRetry({
|
|
32940
|
-
chairman,
|
|
32941
|
-
check: deliveryCheck,
|
|
32942
|
-
sessionId: sessionId2,
|
|
32943
|
-
userMessage,
|
|
32944
|
-
agentOutputs,
|
|
32945
|
-
config: config2,
|
|
32946
|
-
effectiveProvider,
|
|
32947
|
-
effectiveModel,
|
|
32948
|
-
executableNames,
|
|
32949
|
-
onToolCall: () => {
|
|
32950
|
-
toolCalls += 1;
|
|
32951
|
-
},
|
|
32952
|
-
onSuccessfulWrite: () => {
|
|
32953
|
-
successfulWriteCount += 1;
|
|
32954
|
-
},
|
|
32955
|
-
onCouncilStatus: callbacks.onCouncilStatus,
|
|
32956
|
-
languageModule: councilLanguageModule
|
|
32957
|
-
});
|
|
32958
|
-
}
|
|
32959
|
-
}
|
|
32960
|
-
if (chairmanViolations.size > 0 && chairmanProjectRoot) {
|
|
32961
|
-
yield* runChairmanFixLoop({
|
|
32962
|
-
chairman,
|
|
32963
|
-
violations: chairmanViolations,
|
|
32964
|
-
changedFiles: changedTargetFiles,
|
|
32965
|
-
projectRoot: chairmanProjectRoot,
|
|
32966
|
-
executableNames,
|
|
32967
|
-
sessionId: sessionId2,
|
|
32968
|
-
userMessage,
|
|
32969
|
-
agentOutputs,
|
|
32970
|
-
config: config2,
|
|
32971
|
-
effectiveProvider,
|
|
32972
|
-
effectiveModel,
|
|
32973
|
-
onToolCall: () => {
|
|
32974
|
-
toolCalls += 1;
|
|
32975
|
-
},
|
|
32976
|
-
languageModule: councilLanguageModule
|
|
32977
|
-
});
|
|
32978
|
-
}
|
|
32979
|
-
if (chairmanProjectRoot) {
|
|
32980
|
-
yield* runChairmanDeliveryLoop({
|
|
32981
|
-
chairman,
|
|
32982
|
-
projectRoot: chairmanProjectRoot,
|
|
32983
|
-
changedFiles: changedTargetFiles,
|
|
32984
|
-
executableNames,
|
|
32985
|
-
sessionId: sessionId2,
|
|
32986
|
-
userMessage,
|
|
32987
|
-
agentOutputs,
|
|
32988
|
-
config: config2,
|
|
32989
|
-
effectiveProvider,
|
|
32990
|
-
effectiveModel,
|
|
32991
|
-
onToolCall: () => {
|
|
32992
|
-
toolCalls += 1;
|
|
32993
|
-
},
|
|
32994
|
-
onCouncilStatus: callbacks.onCouncilStatus,
|
|
32995
|
-
languageModule: councilLanguageModule
|
|
32996
|
-
});
|
|
32997
|
-
}
|
|
32998
|
-
}
|
|
32999
|
-
const memberDuration = Date.now() - memberStart;
|
|
33000
|
-
const finalSynthesis = errored && fullText.length === 0 ? `[Chairman synthesis failed: ${lastErrorMessage || "unknown error"}]` : fullText;
|
|
33001
|
-
callbacks.onSynthesisDone?.(finalSynthesis, void 0, void 0);
|
|
33002
|
-
emitMemberCost({
|
|
33003
|
-
memberId: chairman.id,
|
|
33004
|
-
name: chairman.name,
|
|
33005
|
-
usage,
|
|
33006
|
-
durationMs: memberDuration,
|
|
33007
|
-
toolCalls,
|
|
33008
|
-
errored
|
|
33009
|
-
});
|
|
33010
|
-
yield createBrainEvent("member_cost", sessionId2, {
|
|
33011
|
-
cost: {
|
|
33012
|
-
memberId: chairman.id,
|
|
33013
|
-
name: chairman.name,
|
|
33014
|
-
promptTokens: usage?.promptTokens ?? 0,
|
|
33015
|
-
completionTokens: usage?.completionTokens ?? 0,
|
|
33016
|
-
totalTokens: usage?.totalTokens ?? (usage?.promptTokens ?? 0) + (usage?.completionTokens ?? 0),
|
|
33017
|
-
durationMs: memberDuration,
|
|
33018
|
-
toolCalls,
|
|
33019
|
-
errored
|
|
33020
|
-
}
|
|
33021
|
-
});
|
|
33022
|
-
}
|
|
33023
|
-
yield {
|
|
33024
|
-
type: "agent_end",
|
|
33025
|
-
id: crypto.randomUUID(),
|
|
33026
|
-
ts: Date.now(),
|
|
33027
|
-
sessionId: sessionId2,
|
|
33028
|
-
reason: "completed",
|
|
33029
|
-
durationMs: 0
|
|
33030
|
-
};
|
|
33031
|
-
}
|
|
33032
|
-
async function* applyCompletionRetry(args) {
|
|
33033
|
-
const check2 = checkImplementationCompletion(args.emittedToolNames);
|
|
33034
|
-
if (check2.ok)
|
|
33035
|
-
return;
|
|
33036
|
-
const retryTool = resolveVerifyRetryTool(args.executableNames);
|
|
33037
|
-
if (!retryTool) {
|
|
33038
|
-
console.warn("[council] implementation verify retry skipped \u2014 no grep_content/bash in registry");
|
|
33039
|
-
return;
|
|
33040
|
-
}
|
|
33041
|
-
if (!shouldRetryMember([retryTool], 0))
|
|
33042
|
-
return;
|
|
33043
|
-
console.warn(`[council] ${args.agent.id} retrying missing verify tool: ${retryTool}`);
|
|
33044
|
-
try {
|
|
33045
|
-
const retryGenerator = runRetryTurnForMember({
|
|
33046
|
-
agent: args.agent,
|
|
33047
|
-
missingToolNames: [retryTool],
|
|
33048
|
-
executableTools: args.executableNames,
|
|
33049
|
-
userMessage: args.userMessage,
|
|
33050
|
-
ragContext: args.config.ragContext,
|
|
33051
|
-
workspaceContext: args.config.workspaceContext,
|
|
33052
|
-
priorOutputs: args.agentOutputs,
|
|
33053
|
-
aiConfig: args.config.aiConfig,
|
|
33054
|
-
sessionId: args.sessionId,
|
|
33055
|
-
effectiveModel: args.effectiveModel,
|
|
33056
|
-
effectiveProvider: args.effectiveProvider,
|
|
33057
|
-
eventBus: args.config.eventBus,
|
|
33058
|
-
toolRegistry: args.config.tools,
|
|
33059
|
-
providerStream: args.config.providerStream,
|
|
33060
|
-
runMode: args.config.runMode,
|
|
33061
|
-
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool),
|
|
33062
|
-
languageModule: args.languageModule
|
|
33063
|
-
});
|
|
33064
|
-
for await (const event of retryGenerator) {
|
|
33065
|
-
if (event.type === "tool_execution_start") {
|
|
33066
|
-
args.onToolCall();
|
|
33067
|
-
args.emittedToolNames.push(event.toolName);
|
|
33068
|
-
}
|
|
33069
|
-
yield event;
|
|
33070
|
-
}
|
|
33071
|
-
} catch (retryErr) {
|
|
33072
|
-
console.error(`[council] ${args.agent.id} verify retry failed:`, retryErr);
|
|
33073
|
-
}
|
|
33074
|
-
const after = checkImplementationCompletion(args.emittedToolNames);
|
|
33075
|
-
if (!after.ok) {
|
|
33076
|
-
console.warn(`[council] ${args.agent.id} still missing verify after retry: ${after.reason}`);
|
|
33077
|
-
}
|
|
33078
|
-
}
|
|
33079
|
-
function buildMotionFixPrompt(violations) {
|
|
33080
|
-
const byFile = /* @__PURE__ */ new Map();
|
|
33081
|
-
for (const v of violations) {
|
|
33082
|
-
const file2 = v.file || "index.html";
|
|
33083
|
-
const loc = v.line ? `${file2}:L${v.line}` : file2;
|
|
33084
|
-
const list = byFile.get(file2) ?? [];
|
|
33085
|
-
list.push(` - ${loc}: ${v.message}`);
|
|
33086
|
-
byFile.set(file2, list);
|
|
33087
|
-
}
|
|
33088
|
-
const blocks = Array.from(byFile.values()).map((lines) => lines.join("\n")).join("\n");
|
|
33089
|
-
return `Deterministic verification found ${violations.length} motion violation(s) in the file(s) you just edited. Fix ONLY these \u2014 do not add features, do not rewrite sections, do not touch anything else:
|
|
33090
|
-
${blocks}
|
|
33091
|
-
|
|
33092
|
-
Rules: animate ONLY transform and opacity. Replace any box-shadow / background / background-position / filter / color / border-color / width / height / grid-template-rows used in @keyframes or transitions with transform/opacity equivalents (e.g. render a glow via a pseudo-element that scales and fades). For every classList.add('x') in the script, add a matching '.x' CSS rule. Use read_file to see the exact lines, then edit_file. When the listed items are fixed, stop \u2014 no summary.`;
|
|
33093
|
-
}
|
|
33094
|
-
async function* applyImplementationWriteRetry(args) {
|
|
33095
|
-
if (args.check.ok)
|
|
33096
|
-
return;
|
|
33097
|
-
if (!shouldRetryMember(["write_file"], 0))
|
|
33098
|
-
return;
|
|
33099
|
-
const statusMsg = `[council] ${args.chairman.id} implementation write retry: ${args.check.missing.join(", ")}`;
|
|
33100
|
-
args.onCouncilStatus?.(statusMsg);
|
|
33101
|
-
console.warn(statusMsg);
|
|
33102
|
-
try {
|
|
33103
|
-
const retryGenerator = runRetryTurnForMember({
|
|
33104
|
-
agent: args.chairman,
|
|
33105
|
-
missingToolNames: ["read_file", "write_file", "edit_file"],
|
|
33106
|
-
minPerTool: { read_file: 3, edit_file: 8, write_file: 1 },
|
|
33107
|
-
executableTools: args.executableNames,
|
|
33108
|
-
userMessage: args.userMessage,
|
|
33109
|
-
ragContext: args.config.ragContext,
|
|
33110
|
-
workspaceContext: args.config.workspaceContext,
|
|
33111
|
-
priorOutputs: args.agentOutputs,
|
|
33112
|
-
aiConfig: args.config.aiConfig,
|
|
33113
|
-
sessionId: args.sessionId,
|
|
33114
|
-
effectiveModel: args.effectiveModel,
|
|
33115
|
-
effectiveProvider: args.effectiveProvider,
|
|
33116
|
-
eventBus: args.config.eventBus,
|
|
33117
|
-
toolRegistry: args.config.tools,
|
|
33118
|
-
providerStream: args.config.providerStream,
|
|
33119
|
-
runMode: "implementation",
|
|
33120
|
-
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage),
|
|
33121
|
-
languageModule: args.languageModule
|
|
33122
|
-
});
|
|
33123
|
-
for await (const event of retryGenerator) {
|
|
33124
|
-
if (event.type === "tool_execution_start")
|
|
33125
|
-
args.onToolCall?.();
|
|
33126
|
-
if (event.type === "tool_execution_end" && !event.isError && typeof event.result === "string") {
|
|
33127
|
-
try {
|
|
33128
|
-
const parsed = JSON.parse(event.result);
|
|
33129
|
-
if ((parsed.bytesWritten ?? 0) > 0 || (parsed.occurrencesReplaced ?? 0) > 0) {
|
|
33130
|
-
args.onSuccessfulWrite?.();
|
|
33131
|
-
}
|
|
33132
|
-
} catch {
|
|
33133
|
-
if (event.result.includes("bytesWritten") || event.result.includes("occurrencesReplaced")) {
|
|
33134
|
-
args.onSuccessfulWrite?.();
|
|
33135
|
-
}
|
|
33136
|
-
}
|
|
33137
|
-
}
|
|
33138
|
-
yield event;
|
|
33139
|
-
}
|
|
33140
|
-
} catch (retryErr) {
|
|
33141
|
-
console.error(`[council] ${args.chairman.id} implementation write retry failed:`, retryErr);
|
|
33142
|
-
}
|
|
33143
|
-
}
|
|
33144
|
-
async function* runChairmanDeliveryLoop(args) {
|
|
33145
|
-
const maxAttempts = args.maxAttempts ?? MAX_DELIVERY_ATTEMPTS;
|
|
33146
|
-
const zelariRoot = `${args.projectRoot}/.zelari`;
|
|
33147
|
-
let attempt = 0;
|
|
33148
|
-
while (attempt < maxAttempts) {
|
|
33149
|
-
const report = runImplementationVerification({
|
|
33150
|
-
projectRoot: args.projectRoot,
|
|
33151
|
-
zelariRoot
|
|
33152
|
-
});
|
|
33153
|
-
const blocking = filterDeliveryBlockingFails(report.results);
|
|
33154
|
-
if (blocking.length === 0)
|
|
33155
|
-
return true;
|
|
33156
|
-
if (blocking.some((b) => b.id === "inline-js.budget")) {
|
|
33157
|
-
const jsFix = applyInlineJsAutofix(args.projectRoot, report);
|
|
33158
|
-
if (jsFix.applied) {
|
|
33159
|
-
args.onCouncilStatus?.(`[council] ${args.chairman.id} inline-js autofix: ${jsFix.fixes.join("; ")}`);
|
|
33160
|
-
const afterJs = runImplementationVerification({
|
|
33161
|
-
projectRoot: args.projectRoot,
|
|
33162
|
-
zelariRoot
|
|
33163
|
-
});
|
|
33164
|
-
if (filterDeliveryBlockingFails(afterJs.results).length === 0)
|
|
33165
|
-
return true;
|
|
33166
|
-
}
|
|
33167
|
-
}
|
|
33168
|
-
attempt++;
|
|
33169
|
-
const statusMsg = `[council] ${args.chairman.id} delivery pass ${attempt}/${maxAttempts}: ${blocking.map((b) => b.id).join(", ")}`;
|
|
33170
|
-
args.onCouncilStatus?.(statusMsg);
|
|
33171
|
-
console.warn(statusMsg);
|
|
33172
|
-
try {
|
|
33173
|
-
const fixGenerator = runRetryTurnForMember({
|
|
33174
|
-
agent: args.chairman,
|
|
33175
|
-
missingToolNames: ["read_file", "edit_file"],
|
|
33176
|
-
minPerTool: { read_file: 3, edit_file: 10 },
|
|
33177
|
-
executableTools: args.executableNames,
|
|
33178
|
-
userMessage: args.userMessage,
|
|
33179
|
-
ragContext: args.config.ragContext,
|
|
33180
|
-
workspaceContext: args.config.workspaceContext,
|
|
33181
|
-
priorOutputs: args.agentOutputs,
|
|
33182
|
-
aiConfig: args.config.aiConfig,
|
|
33183
|
-
sessionId: args.sessionId,
|
|
33184
|
-
effectiveModel: args.effectiveModel,
|
|
33185
|
-
effectiveProvider: args.effectiveProvider,
|
|
33186
|
-
eventBus: args.config.eventBus,
|
|
33187
|
-
toolRegistry: args.config.tools,
|
|
33188
|
-
providerStream: args.config.providerStream,
|
|
33189
|
-
runMode: "implementation",
|
|
33190
|
-
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage),
|
|
33191
|
-
languageModule: args.languageModule
|
|
33192
|
-
});
|
|
33193
|
-
for await (const event of fixGenerator) {
|
|
33194
|
-
if (event.type === "tool_execution_start")
|
|
33195
|
-
args.onToolCall?.();
|
|
33196
|
-
yield event;
|
|
33197
|
-
}
|
|
33198
|
-
} catch (deliveryErr) {
|
|
33199
|
-
console.error(`[council] ${args.chairman.id} delivery pass ${attempt} failed:`, deliveryErr);
|
|
33200
|
-
break;
|
|
33201
|
-
}
|
|
33202
|
-
for (const rel2 of args.changedFiles) {
|
|
33203
|
-
for (const w of runChairmanMicroGate({ projectRoot: args.projectRoot, relPath: rel2, zelariRoot })) {
|
|
33204
|
-
args.changedFiles.add(w.file ?? rel2);
|
|
33205
|
-
}
|
|
33206
|
-
}
|
|
33207
|
-
}
|
|
33208
|
-
const finalReport = runImplementationVerification({
|
|
33209
|
-
projectRoot: args.projectRoot,
|
|
33210
|
-
zelariRoot
|
|
33211
|
-
});
|
|
33212
|
-
return filterDeliveryBlockingFails(finalReport.results).length === 0;
|
|
33213
|
-
}
|
|
33214
|
-
async function* replayChairmanTextTools(args) {
|
|
33215
|
-
const tools = parseTextToolCalls(args.synthesisText);
|
|
33216
|
-
if (tools.length === 0)
|
|
33217
|
-
return 0;
|
|
33218
|
-
let applied = 0;
|
|
33219
|
-
for (const tt of tools) {
|
|
33220
|
-
if (tt.name !== "edit_file" && tt.name !== "write_file")
|
|
33221
|
-
continue;
|
|
33222
|
-
const normalized = normalizeTextToolArgs(tt.name, tt.args);
|
|
33223
|
-
const toolCallId = `replay-${crypto.randomUUID().slice(0, 8)}`;
|
|
33224
|
-
yield createBrainEvent("tool_execution_start", args.sessionId, {
|
|
33225
|
-
toolCallId,
|
|
33226
|
-
toolName: tt.name,
|
|
33227
|
-
args: normalized,
|
|
33228
|
-
...args.memberId ? { memberId: args.memberId } : {}
|
|
33229
|
-
});
|
|
33230
|
-
const startMs = Date.now();
|
|
33231
|
-
let resultStr = "";
|
|
33232
|
-
let isError = false;
|
|
33233
|
-
try {
|
|
33234
|
-
const result = await args.toolRegistry.invoke(tt.name, normalized, {
|
|
33235
|
-
cwd: args.projectRoot,
|
|
33236
|
-
sessionId: args.sessionId
|
|
33237
|
-
});
|
|
33238
|
-
if (result.ok) {
|
|
33239
|
-
const val = result.value;
|
|
33240
|
-
if (tt.name === "edit_file" && val.occurrencesReplaced === 0) {
|
|
33241
|
-
resultStr = `edit_file: no match for oldString (replay)`;
|
|
33242
|
-
isError = true;
|
|
33243
|
-
} else {
|
|
33244
|
-
resultStr = typeof result.value === "string" ? result.value : JSON.stringify(result.value, null, 2);
|
|
33245
|
-
applied += 1;
|
|
33424
|
+
let usage = null;
|
|
33425
|
+
let errored = false;
|
|
33426
|
+
let lastErrorMessage = "";
|
|
33427
|
+
const emittedToolNames = [];
|
|
33428
|
+
const pendingChairmanWrites = /* @__PURE__ */ new Map();
|
|
33429
|
+
let successfulWriteCount = 0;
|
|
33430
|
+
const chairmanViolations = /* @__PURE__ */ new Map();
|
|
33431
|
+
const changedTargetFiles = /* @__PURE__ */ new Set();
|
|
33432
|
+
let chairmanProjectRoot = parseProjectRootFromWorkspaceContext(config2.workspaceContext ?? "");
|
|
33433
|
+
const memberStart = Date.now();
|
|
33434
|
+
try {
|
|
33435
|
+
for await (const event of runHarnessWithAbort(chairmanHarness, config2.signal)) {
|
|
33436
|
+
yield event;
|
|
33437
|
+
if (event.type === "tool_execution_start") {
|
|
33438
|
+
toolCalls += 1;
|
|
33439
|
+
emittedToolNames.push(event.toolName);
|
|
33440
|
+
if (!isDesignPhase && (event.toolName === "write_file" || event.toolName === "edit_file") && typeof event.args.path === "string") {
|
|
33441
|
+
pendingChairmanWrites.set(event.toolCallId, {
|
|
33442
|
+
path: event.args.path,
|
|
33443
|
+
toolName: event.toolName
|
|
33444
|
+
});
|
|
33445
|
+
}
|
|
33446
|
+
}
|
|
33447
|
+
if (!isDesignPhase && event.type === "tool_execution_end") {
|
|
33448
|
+
const pending = pendingChairmanWrites.get(event.toolCallId);
|
|
33449
|
+
if (pending) {
|
|
33450
|
+
pendingChairmanWrites.delete(event.toolCallId);
|
|
33451
|
+
if (!event.isError) {
|
|
33452
|
+
let wrote = pending.toolName === "write_file";
|
|
33453
|
+
if (pending.toolName === "edit_file" && typeof event.result === "string") {
|
|
33454
|
+
try {
|
|
33455
|
+
const parsed = JSON.parse(event.result);
|
|
33456
|
+
wrote = (parsed.occurrencesReplaced ?? 0) > 0;
|
|
33457
|
+
} catch {
|
|
33458
|
+
wrote = false;
|
|
33459
|
+
}
|
|
33460
|
+
}
|
|
33461
|
+
if (wrote) {
|
|
33462
|
+
successfulWriteCount += 1;
|
|
33463
|
+
const projectRoot = parseProjectRootFromWorkspaceContext(config2.workspaceContext);
|
|
33464
|
+
if (projectRoot) {
|
|
33465
|
+
chairmanProjectRoot = projectRoot;
|
|
33466
|
+
changedTargetFiles.add(pending.path);
|
|
33467
|
+
for (const w of runChairmanMicroGate({
|
|
33468
|
+
projectRoot,
|
|
33469
|
+
relPath: pending.path,
|
|
33470
|
+
zelariRoot: `${projectRoot}/.zelari`
|
|
33471
|
+
})) {
|
|
33472
|
+
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
33473
|
+
}
|
|
33474
|
+
}
|
|
33475
|
+
}
|
|
33476
|
+
}
|
|
33477
|
+
}
|
|
33478
|
+
}
|
|
33479
|
+
if (event.type === "message_end" && event.usage) {
|
|
33480
|
+
usage = event.usage;
|
|
33481
|
+
}
|
|
33482
|
+
if (event.type === "message_delta") {
|
|
33483
|
+
fullText += event.delta;
|
|
33484
|
+
callbacks.onSynthesisChunk?.(event.delta);
|
|
33485
|
+
callbacks.onAgentChunk?.(chairman, event.delta);
|
|
33486
|
+
}
|
|
33487
|
+
if (event.type === "error") {
|
|
33488
|
+
if (event.severity !== "cancelled" && event.code !== "text_tools_parse_failed") {
|
|
33489
|
+
errored = true;
|
|
33490
|
+
lastErrorMessage = event.message;
|
|
33491
|
+
}
|
|
33246
33492
|
}
|
|
33247
|
-
} else {
|
|
33248
|
-
resultStr = result.error;
|
|
33249
|
-
isError = true;
|
|
33250
33493
|
}
|
|
33251
33494
|
} catch (err) {
|
|
33252
|
-
|
|
33253
|
-
|
|
33495
|
+
console.error(`[council] chairman "${chairman.id}" failed:`, err);
|
|
33496
|
+
errored = true;
|
|
33497
|
+
lastErrorMessage = err instanceof Error ? err.message : String(err);
|
|
33254
33498
|
}
|
|
33255
|
-
|
|
33256
|
-
|
|
33257
|
-
|
|
33258
|
-
|
|
33259
|
-
|
|
33260
|
-
|
|
33261
|
-
|
|
33262
|
-
|
|
33263
|
-
|
|
33264
|
-
|
|
33265
|
-
|
|
33266
|
-
|
|
33267
|
-
|
|
33268
|
-
|
|
33269
|
-
|
|
33270
|
-
|
|
33271
|
-
|
|
33272
|
-
|
|
33273
|
-
agent: args.chairman,
|
|
33274
|
-
missingToolNames: ["read_file", "edit_file"],
|
|
33275
|
-
minPerTool: { read_file: 2, edit_file: 8 },
|
|
33276
|
-
executableTools: args.executableNames,
|
|
33277
|
-
userMessage: args.userMessage,
|
|
33278
|
-
ragContext: args.config.ragContext,
|
|
33279
|
-
workspaceContext: args.config.workspaceContext,
|
|
33280
|
-
priorOutputs: args.agentOutputs,
|
|
33281
|
-
aiConfig: args.config.aiConfig,
|
|
33282
|
-
sessionId: args.sessionId,
|
|
33283
|
-
effectiveModel: args.effectiveModel,
|
|
33284
|
-
effectiveProvider: args.effectiveProvider,
|
|
33285
|
-
eventBus: args.config.eventBus,
|
|
33286
|
-
toolRegistry: args.config.tools,
|
|
33287
|
-
providerStream: args.config.providerStream,
|
|
33288
|
-
runMode: "implementation",
|
|
33289
|
-
retryPrompt: buildMotionFixPrompt(current),
|
|
33290
|
-
languageModule: args.languageModule
|
|
33499
|
+
if (isDesignPhase && !errored && !isCouncilCancelled(config2.signal)) {
|
|
33500
|
+
const chairmanCheck = enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
33501
|
+
yield* applyRetryIfMissing({
|
|
33502
|
+
agent: chairman,
|
|
33503
|
+
check: chairmanCheck,
|
|
33504
|
+
requirements: DESIGN_PHASE_REQUIREMENTS[chairman.id],
|
|
33505
|
+
emittedToolNames,
|
|
33506
|
+
executableNames,
|
|
33507
|
+
sessionId: sessionId2,
|
|
33508
|
+
userMessage,
|
|
33509
|
+
agentOutputs,
|
|
33510
|
+
config: config2,
|
|
33511
|
+
effectiveProvider,
|
|
33512
|
+
effectiveModel,
|
|
33513
|
+
onToolCall: () => {
|
|
33514
|
+
toolCalls += 1;
|
|
33515
|
+
},
|
|
33516
|
+
languageModule: councilLanguageModule
|
|
33291
33517
|
});
|
|
33292
|
-
|
|
33293
|
-
|
|
33294
|
-
|
|
33295
|
-
|
|
33518
|
+
} else if (isDesignPhase) {
|
|
33519
|
+
enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
33520
|
+
} else if (!errored && !isCouncilCancelled(config2.signal)) {
|
|
33521
|
+
if (chairmanProjectRoot) {
|
|
33522
|
+
const zelariRoot = `${chairmanProjectRoot}/.zelari`;
|
|
33523
|
+
const spec = loadNfrSpec(zelariRoot) ?? DEFAULT_NFR_SPEC;
|
|
33524
|
+
for (const rel2 of spec.targets) {
|
|
33525
|
+
if (!existsSync12(join8(chairmanProjectRoot, rel2)))
|
|
33526
|
+
continue;
|
|
33527
|
+
changedTargetFiles.add(rel2);
|
|
33528
|
+
for (const w of runChairmanMicroGate({ projectRoot: chairmanProjectRoot, relPath: rel2, zelariRoot })) {
|
|
33529
|
+
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
33530
|
+
}
|
|
33531
|
+
}
|
|
33296
33532
|
}
|
|
33297
|
-
|
|
33298
|
-
|
|
33299
|
-
|
|
33300
|
-
|
|
33301
|
-
|
|
33302
|
-
|
|
33303
|
-
|
|
33304
|
-
|
|
33533
|
+
if (fullText.includes("---TOOLS---") && chairmanProjectRoot && config2.tools) {
|
|
33534
|
+
const replayed = yield* replayChairmanTextTools({
|
|
33535
|
+
synthesisText: fullText,
|
|
33536
|
+
projectRoot: chairmanProjectRoot,
|
|
33537
|
+
toolRegistry: config2.tools,
|
|
33538
|
+
sessionId: sessionId2,
|
|
33539
|
+
memberId: chairman.id
|
|
33540
|
+
});
|
|
33541
|
+
successfulWriteCount += replayed;
|
|
33542
|
+
const zelariRootReplay = `${chairmanProjectRoot}/.zelari`;
|
|
33543
|
+
const specReplay = loadNfrSpec(zelariRootReplay) ?? DEFAULT_NFR_SPEC;
|
|
33544
|
+
for (const rel2 of specReplay.targets) {
|
|
33545
|
+
if (!existsSync12(join8(chairmanProjectRoot, rel2)))
|
|
33546
|
+
continue;
|
|
33547
|
+
changedTargetFiles.add(rel2);
|
|
33548
|
+
for (const w of runChairmanMicroGate({
|
|
33549
|
+
projectRoot: chairmanProjectRoot,
|
|
33550
|
+
relPath: rel2,
|
|
33551
|
+
zelariRoot: zelariRootReplay
|
|
33552
|
+
})) {
|
|
33553
|
+
chairmanViolations.set(`${w.id}|${w.file}|${w.line ?? ""}`, w);
|
|
33554
|
+
}
|
|
33555
|
+
}
|
|
33305
33556
|
}
|
|
33306
|
-
|
|
33307
|
-
|
|
33308
|
-
|
|
33309
|
-
|
|
33310
|
-
|
|
33311
|
-
|
|
33312
|
-
|
|
33313
|
-
|
|
33314
|
-
|
|
33315
|
-
|
|
33316
|
-
|
|
33317
|
-
|
|
33318
|
-
|
|
33319
|
-
|
|
33320
|
-
|
|
33321
|
-
|
|
33322
|
-
|
|
33323
|
-
|
|
33324
|
-
|
|
33325
|
-
|
|
33326
|
-
|
|
33327
|
-
|
|
33328
|
-
|
|
33329
|
-
|
|
33330
|
-
|
|
33331
|
-
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
|
|
33335
|
-
|
|
33336
|
-
|
|
33337
|
-
|
|
33338
|
-
|
|
33339
|
-
|
|
33340
|
-
|
|
33341
|
-
|
|
33342
|
-
|
|
33343
|
-
|
|
33344
|
-
|
|
33345
|
-
|
|
33346
|
-
|
|
33347
|
-
}
|
|
33348
|
-
|
|
33349
|
-
|
|
33350
|
-
|
|
33351
|
-
|
|
33352
|
-
|
|
33353
|
-
|
|
33354
|
-
|
|
33355
|
-
|
|
33356
|
-
|
|
33357
|
-
|
|
33358
|
-
|
|
33359
|
-
|
|
33360
|
-
|
|
33361
|
-
|
|
33362
|
-
|
|
33363
|
-
|
|
33364
|
-
|
|
33365
|
-
|
|
33366
|
-
|
|
33367
|
-
description: t.function.description,
|
|
33368
|
-
parameters: t.function.parameters
|
|
33369
|
-
}));
|
|
33370
|
-
const baseMessages = buildAgentMessages(args.agent, args.userMessage, args.ragContext, args.workspaceContext, args.priorOutputs, args.aiConfig, args.executableTools, args.runMode ?? "implementation", args.languageModule);
|
|
33371
|
-
const retryMessages = [
|
|
33372
|
-
...baseMessages,
|
|
33373
|
-
{
|
|
33374
|
-
role: "user",
|
|
33375
|
-
content: args.retryPrompt ?? buildRetryPrompt(executableMissing)
|
|
33376
|
-
}
|
|
33377
|
-
];
|
|
33378
|
-
const maxToolCalls = args.minPerTool !== void 0 ? Object.entries(args.minPerTool).filter(([name]) => executableMissing.includes(name)).reduce((sum, [, min]) => sum + min, 0) : retryToolNames.length;
|
|
33379
|
-
const retryHarness = new AgentHarness({
|
|
33380
|
-
model: args.effectiveModel,
|
|
33381
|
-
provider: args.effectiveProvider,
|
|
33382
|
-
sessionId: args.sessionId,
|
|
33383
|
-
messages: retryMessages,
|
|
33384
|
-
tools: retryToolSpecs,
|
|
33385
|
-
eventBus: args.eventBus,
|
|
33386
|
-
toolRegistry: args.toolRegistry,
|
|
33387
|
-
// Budget the retry so the model can satisfy every requirement in
|
|
33388
|
-
// ONE tool_calls turn. For createTask min:12 this needs 12 calls.
|
|
33389
|
-
maxToolCallsPerTurn: maxToolCalls,
|
|
33390
|
-
memberId: args.agent.id,
|
|
33391
|
-
memberName: args.agent.name,
|
|
33392
|
-
providerStream: (params) => args.providerStream(params)
|
|
33393
|
-
});
|
|
33394
|
-
const retryEmitted = [];
|
|
33395
|
-
for await (const event of retryHarness.run()) {
|
|
33396
|
-
if (event.type === "tool_execution_start") {
|
|
33397
|
-
retryEmitted.push(event.toolName);
|
|
33398
|
-
}
|
|
33399
|
-
yield event;
|
|
33400
|
-
}
|
|
33401
|
-
return retryEmitted;
|
|
33402
|
-
}
|
|
33403
|
-
async function* applyRetryIfMissing(args) {
|
|
33404
|
-
if (args.check.ok)
|
|
33405
|
-
return;
|
|
33406
|
-
const missingToolNames = args.check.missing.map((m) => m.split(" ")[0]);
|
|
33407
|
-
if (!shouldRetryMember(missingToolNames, 0))
|
|
33408
|
-
return;
|
|
33409
|
-
console.warn(`[council] ${args.agent.id} retrying missing tools: ${missingToolNames.join(", ")}`);
|
|
33410
|
-
const minPerTool = {};
|
|
33411
|
-
if (args.requirements) {
|
|
33412
|
-
for (const req of args.requirements) {
|
|
33413
|
-
if (missingToolNames.includes(req.name)) {
|
|
33414
|
-
minPerTool[req.name] = req.min;
|
|
33557
|
+
if (chairmanProjectRoot) {
|
|
33558
|
+
const deliveryCheck = checkImplementationDelivery(successfulWriteCount, countEmittedWriteTools(emittedToolNames));
|
|
33559
|
+
if (!deliveryCheck.ok) {
|
|
33560
|
+
yield* applyImplementationWriteRetry({
|
|
33561
|
+
chairman,
|
|
33562
|
+
check: deliveryCheck,
|
|
33563
|
+
sessionId: sessionId2,
|
|
33564
|
+
userMessage,
|
|
33565
|
+
agentOutputs,
|
|
33566
|
+
config: config2,
|
|
33567
|
+
effectiveProvider,
|
|
33568
|
+
effectiveModel,
|
|
33569
|
+
executableNames,
|
|
33570
|
+
onToolCall: () => {
|
|
33571
|
+
toolCalls += 1;
|
|
33572
|
+
},
|
|
33573
|
+
onSuccessfulWrite: () => {
|
|
33574
|
+
successfulWriteCount += 1;
|
|
33575
|
+
},
|
|
33576
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
33577
|
+
languageModule: councilLanguageModule
|
|
33578
|
+
});
|
|
33579
|
+
}
|
|
33580
|
+
}
|
|
33581
|
+
if (chairmanViolations.size > 0 && chairmanProjectRoot) {
|
|
33582
|
+
yield* runChairmanFixLoop({
|
|
33583
|
+
chairman,
|
|
33584
|
+
violations: chairmanViolations,
|
|
33585
|
+
changedFiles: changedTargetFiles,
|
|
33586
|
+
projectRoot: chairmanProjectRoot,
|
|
33587
|
+
executableNames,
|
|
33588
|
+
sessionId: sessionId2,
|
|
33589
|
+
userMessage,
|
|
33590
|
+
agentOutputs,
|
|
33591
|
+
config: config2,
|
|
33592
|
+
effectiveProvider,
|
|
33593
|
+
effectiveModel,
|
|
33594
|
+
onToolCall: () => {
|
|
33595
|
+
toolCalls += 1;
|
|
33596
|
+
},
|
|
33597
|
+
languageModule: councilLanguageModule
|
|
33598
|
+
});
|
|
33599
|
+
}
|
|
33600
|
+
if (chairmanProjectRoot) {
|
|
33601
|
+
yield* runChairmanDeliveryLoop({
|
|
33602
|
+
chairman,
|
|
33603
|
+
projectRoot: chairmanProjectRoot,
|
|
33604
|
+
changedFiles: changedTargetFiles,
|
|
33605
|
+
executableNames,
|
|
33606
|
+
sessionId: sessionId2,
|
|
33607
|
+
userMessage,
|
|
33608
|
+
agentOutputs,
|
|
33609
|
+
config: config2,
|
|
33610
|
+
effectiveProvider,
|
|
33611
|
+
effectiveModel,
|
|
33612
|
+
onToolCall: () => {
|
|
33613
|
+
toolCalls += 1;
|
|
33614
|
+
},
|
|
33615
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
33616
|
+
languageModule: councilLanguageModule
|
|
33617
|
+
});
|
|
33415
33618
|
}
|
|
33416
33619
|
}
|
|
33417
|
-
|
|
33418
|
-
|
|
33419
|
-
|
|
33420
|
-
|
|
33421
|
-
|
|
33422
|
-
|
|
33423
|
-
|
|
33424
|
-
|
|
33425
|
-
|
|
33426
|
-
|
|
33427
|
-
priorOutputs: args.agentOutputs,
|
|
33428
|
-
aiConfig: args.config.aiConfig,
|
|
33429
|
-
sessionId: args.sessionId,
|
|
33430
|
-
effectiveModel: args.effectiveModel,
|
|
33431
|
-
effectiveProvider: args.effectiveProvider,
|
|
33432
|
-
eventBus: args.config.eventBus,
|
|
33433
|
-
toolRegistry: args.config.tools,
|
|
33434
|
-
providerStream: args.config.providerStream,
|
|
33435
|
-
runMode: args.config.runMode,
|
|
33436
|
-
languageModule: args.languageModule
|
|
33620
|
+
const memberDuration = Date.now() - memberStart;
|
|
33621
|
+
const finalSynthesis = errored && fullText.length === 0 ? `[Chairman synthesis failed: ${lastErrorMessage || "unknown error"}]` : fullText;
|
|
33622
|
+
callbacks.onSynthesisDone?.(finalSynthesis, void 0, void 0);
|
|
33623
|
+
emitMemberCost({
|
|
33624
|
+
memberId: chairman.id,
|
|
33625
|
+
name: chairman.name,
|
|
33626
|
+
usage,
|
|
33627
|
+
durationMs: memberDuration,
|
|
33628
|
+
toolCalls,
|
|
33629
|
+
errored
|
|
33437
33630
|
});
|
|
33438
|
-
|
|
33439
|
-
|
|
33440
|
-
|
|
33441
|
-
|
|
33631
|
+
yield createBrainEvent("member_cost", sessionId2, {
|
|
33632
|
+
cost: {
|
|
33633
|
+
memberId: chairman.id,
|
|
33634
|
+
name: chairman.name,
|
|
33635
|
+
promptTokens: usage?.promptTokens ?? 0,
|
|
33636
|
+
completionTokens: usage?.completionTokens ?? 0,
|
|
33637
|
+
totalTokens: usage?.totalTokens ?? (usage?.promptTokens ?? 0) + (usage?.completionTokens ?? 0),
|
|
33638
|
+
durationMs: memberDuration,
|
|
33639
|
+
toolCalls,
|
|
33640
|
+
errored
|
|
33442
33641
|
}
|
|
33443
|
-
|
|
33444
|
-
}
|
|
33445
|
-
} catch (retryErr) {
|
|
33446
|
-
console.error(`[council] ${args.agent.id} retry failed:`, retryErr);
|
|
33642
|
+
});
|
|
33447
33643
|
}
|
|
33448
|
-
|
|
33644
|
+
yield {
|
|
33645
|
+
type: "agent_end",
|
|
33646
|
+
id: crypto.randomUUID(),
|
|
33647
|
+
ts: Date.now(),
|
|
33648
|
+
sessionId: sessionId2,
|
|
33649
|
+
reason: isCouncilCancelled(config2.signal) ? "cancelled" : "completed",
|
|
33650
|
+
durationMs: 0
|
|
33651
|
+
};
|
|
33449
33652
|
}
|
|
33450
|
-
var NON_RETRY_AGENTS, QUESTION_MARKER, QUESTION_END_MARKER, MUTATING_PROJECT_TOOLS, MAX_DELIVERY_ATTEMPTS, DESIGN_PHASE_REQUIREMENT_SETS, DESIGN_PHASE_REQUIREMENTS, MAX_RETRY_PER_MEMBER;
|
|
33451
33653
|
var init_councilApi = __esm({
|
|
33452
33654
|
"packages/core/dist/agents/councilApi.js"() {
|
|
33453
33655
|
"use strict";
|
|
33454
33656
|
init_roles();
|
|
33455
33657
|
init_toolSchemas();
|
|
33456
33658
|
init_systemPromptBuilder();
|
|
33457
|
-
init_tools();
|
|
33458
33659
|
init_languagePolicy();
|
|
33459
|
-
init_secrecyPolicy();
|
|
33460
33660
|
init_events();
|
|
33461
33661
|
init_AgentHarness();
|
|
33462
|
-
init_modeBanners();
|
|
33463
33662
|
init_runMode();
|
|
33464
33663
|
init_microGate();
|
|
33465
|
-
init_completion();
|
|
33466
33664
|
init_nfrSpecWarn();
|
|
33467
33665
|
init_runChecks();
|
|
33468
33666
|
init_implementationDelivery();
|
|
33469
|
-
|
|
33470
|
-
|
|
33471
|
-
|
|
33472
|
-
|
|
33473
|
-
|
|
33474
|
-
|
|
33475
|
-
|
|
33476
|
-
|
|
33477
|
-
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
|
|
33482
|
-
|
|
33483
|
-
|
|
33484
|
-
geryon: [
|
|
33485
|
-
[{ name: "createDocument", min: 3 }]
|
|
33486
|
-
],
|
|
33487
|
-
pluton: [
|
|
33488
|
-
[{ name: "createDocument", min: 1 }]
|
|
33489
|
-
],
|
|
33490
|
-
minos: [
|
|
33491
|
-
[{ name: "createDocument", min: 1 }]
|
|
33492
|
-
],
|
|
33493
|
-
lucifer: [
|
|
33494
|
-
[{ name: "createDocument", min: 1 }]
|
|
33495
|
-
]
|
|
33496
|
-
};
|
|
33497
|
-
DESIGN_PHASE_REQUIREMENTS = Object.fromEntries(Object.entries(DESIGN_PHASE_REQUIREMENT_SETS).map(([id3, sets]) => [id3, sets[0]]));
|
|
33498
|
-
MAX_RETRY_PER_MEMBER = 1;
|
|
33667
|
+
init_types7();
|
|
33668
|
+
init_cancel();
|
|
33669
|
+
init_types7();
|
|
33670
|
+
init_outputCleaning();
|
|
33671
|
+
init_outputCleaning();
|
|
33672
|
+
init_memberMessages();
|
|
33673
|
+
init_memberMessages();
|
|
33674
|
+
init_chairmanDelivery();
|
|
33675
|
+
init_chairmanDelivery();
|
|
33676
|
+
init_chairmanFixLoop();
|
|
33677
|
+
init_chairmanFixLoop();
|
|
33678
|
+
init_toolEmission();
|
|
33679
|
+
init_toolEmission();
|
|
33680
|
+
init_retryTurn();
|
|
33681
|
+
init_retryTurn();
|
|
33499
33682
|
}
|
|
33500
33683
|
});
|
|
33501
33684
|
|
|
@@ -33632,7 +33815,7 @@ var init_missionBrief = __esm({
|
|
|
33632
33815
|
});
|
|
33633
33816
|
|
|
33634
33817
|
// packages/core/dist/council/verification/types.js
|
|
33635
|
-
var
|
|
33818
|
+
var init_types8 = __esm({
|
|
33636
33819
|
"packages/core/dist/council/verification/types.js"() {
|
|
33637
33820
|
"use strict";
|
|
33638
33821
|
}
|
|
@@ -33836,7 +34019,7 @@ var init_autofix = __esm({
|
|
|
33836
34019
|
var init_verification2 = __esm({
|
|
33837
34020
|
"packages/core/dist/council/verification/index.js"() {
|
|
33838
34021
|
"use strict";
|
|
33839
|
-
|
|
34022
|
+
init_types8();
|
|
33840
34023
|
init_runChecks();
|
|
33841
34024
|
init_honesty();
|
|
33842
34025
|
init_parseCssMotion();
|
|
@@ -33854,7 +34037,7 @@ var init_verification2 = __esm({
|
|
|
33854
34037
|
});
|
|
33855
34038
|
|
|
33856
34039
|
// packages/core/dist/council/lessons/types.js
|
|
33857
|
-
var
|
|
34040
|
+
var init_types9 = __esm({
|
|
33858
34041
|
"packages/core/dist/council/lessons/types.js"() {
|
|
33859
34042
|
"use strict";
|
|
33860
34043
|
}
|
|
@@ -34107,7 +34290,7 @@ var init_recallLessons = __esm({
|
|
|
34107
34290
|
var init_lessons = __esm({
|
|
34108
34291
|
"packages/core/dist/council/lessons/index.js"() {
|
|
34109
34292
|
"use strict";
|
|
34110
|
-
|
|
34293
|
+
init_types9();
|
|
34111
34294
|
init_io();
|
|
34112
34295
|
init_isAnswerLeak();
|
|
34113
34296
|
init_signatures();
|
|
@@ -34117,7 +34300,7 @@ var init_lessons = __esm({
|
|
|
34117
34300
|
});
|
|
34118
34301
|
|
|
34119
34302
|
// packages/core/dist/council/completion/types.js
|
|
34120
|
-
var
|
|
34303
|
+
var init_types10 = __esm({
|
|
34121
34304
|
"packages/core/dist/council/completion/types.js"() {
|
|
34122
34305
|
"use strict";
|
|
34123
34306
|
}
|
|
@@ -34198,7 +34381,7 @@ var init_buildCompletion = __esm({
|
|
|
34198
34381
|
var init_completion2 = __esm({
|
|
34199
34382
|
"packages/core/dist/council/completion/index.js"() {
|
|
34200
34383
|
"use strict";
|
|
34201
|
-
|
|
34384
|
+
init_types10();
|
|
34202
34385
|
init_buildCompletion();
|
|
34203
34386
|
}
|
|
34204
34387
|
});
|
|
@@ -34489,6 +34672,7 @@ __export(council_exports, {
|
|
|
34489
34672
|
shouldRetryMember: () => shouldRetryMember,
|
|
34490
34673
|
slugify: () => slugify2,
|
|
34491
34674
|
stripClarificationProtocol: () => stripClarificationProtocol,
|
|
34675
|
+
stripQuestionBlocks: () => stripQuestionBlocks,
|
|
34492
34676
|
swapMembers: () => swapMembers,
|
|
34493
34677
|
systemMessagesFromSplit: () => systemMessagesFromSplit,
|
|
34494
34678
|
taskMatchesNfrKeywords: () => taskMatchesNfrKeywords,
|
|
@@ -34521,7 +34705,7 @@ var init_council = __esm({
|
|
|
34521
34705
|
|
|
34522
34706
|
// packages/core/dist/memory/types.js
|
|
34523
34707
|
var MEMORY_SCHEMA_VERSION, MEMORY_KINDS, MEMORY_STATUSES, MEMORY_RELATIONS, MEMORY_VISIBILITIES;
|
|
34524
|
-
var
|
|
34708
|
+
var init_types11 = __esm({
|
|
34525
34709
|
"packages/core/dist/memory/types.js"() {
|
|
34526
34710
|
"use strict";
|
|
34527
34711
|
MEMORY_SCHEMA_VERSION = 1;
|
|
@@ -34572,7 +34756,7 @@ var init_schemas3 = __esm({
|
|
|
34572
34756
|
"packages/core/dist/memory/schemas.js"() {
|
|
34573
34757
|
"use strict";
|
|
34574
34758
|
init_zod();
|
|
34575
|
-
|
|
34759
|
+
init_types11();
|
|
34576
34760
|
isoDate = external_exports.string().datetime({ offset: true });
|
|
34577
34761
|
unit = external_exports.number().finite().min(0).max(1);
|
|
34578
34762
|
metadata = external_exports.record(external_exports.string(), external_exports.unknown()).refine((value) => {
|
|
@@ -35864,7 +36048,7 @@ var init_noop = __esm({
|
|
|
35864
36048
|
var init_memory = __esm({
|
|
35865
36049
|
"packages/core/dist/memory/index.js"() {
|
|
35866
36050
|
"use strict";
|
|
35867
|
-
|
|
36051
|
+
init_types11();
|
|
35868
36052
|
init_schemas3();
|
|
35869
36053
|
init_scoring();
|
|
35870
36054
|
init_policies();
|
|
@@ -36586,7 +36770,7 @@ var init_personas = __esm({
|
|
|
36586
36770
|
|
|
36587
36771
|
// packages/core/dist/kraken/runtime/types.js
|
|
36588
36772
|
var PlanError;
|
|
36589
|
-
var
|
|
36773
|
+
var init_types12 = __esm({
|
|
36590
36774
|
"packages/core/dist/kraken/runtime/types.js"() {
|
|
36591
36775
|
"use strict";
|
|
36592
36776
|
PlanError = class extends Error {
|
|
@@ -36684,7 +36868,7 @@ var MAX_BUNDLE_BYTES, FORBIDDEN_TOKENS;
|
|
|
36684
36868
|
var init_sandbox = __esm({
|
|
36685
36869
|
"packages/core/dist/kraken/runtime/sandbox.js"() {
|
|
36686
36870
|
"use strict";
|
|
36687
|
-
|
|
36871
|
+
init_types12();
|
|
36688
36872
|
MAX_BUNDLE_BYTES = 256 * 1024;
|
|
36689
36873
|
FORBIDDEN_TOKENS = [
|
|
36690
36874
|
/\bprocess\b/,
|
|
@@ -36747,7 +36931,7 @@ var init_runner = __esm({
|
|
|
36747
36931
|
"use strict";
|
|
36748
36932
|
init_verdict();
|
|
36749
36933
|
init_personas();
|
|
36750
|
-
|
|
36934
|
+
init_types12();
|
|
36751
36935
|
DEFAULT_MAX_TENTACLES = 200;
|
|
36752
36936
|
DEFAULT_PLAN_TIMEOUT_MS = 30 * 6e4;
|
|
36753
36937
|
ScriptRunner = class {
|
|
@@ -36931,7 +37115,7 @@ var init_runner = __esm({
|
|
|
36931
37115
|
var init_runtime2 = __esm({
|
|
36932
37116
|
"packages/core/dist/kraken/runtime/index.js"() {
|
|
36933
37117
|
"use strict";
|
|
36934
|
-
|
|
37118
|
+
init_types12();
|
|
36935
37119
|
init_sandbox();
|
|
36936
37120
|
init_runner();
|
|
36937
37121
|
}
|
|
@@ -38031,7 +38215,7 @@ var CORE_VERSION;
|
|
|
38031
38215
|
var init_version = __esm({
|
|
38032
38216
|
"packages/core/dist/version.js"() {
|
|
38033
38217
|
"use strict";
|
|
38034
|
-
CORE_VERSION = "2.
|
|
38218
|
+
CORE_VERSION = "2.34.1";
|
|
38035
38219
|
}
|
|
38036
38220
|
});
|
|
38037
38221
|
|
|
@@ -38543,6 +38727,7 @@ __export(dist_exports, {
|
|
|
38543
38727
|
strictBuildGate: () => strictBuildGate,
|
|
38544
38728
|
stripAnsi: () => stripAnsi,
|
|
38545
38729
|
stripClarificationProtocol: () => stripClarificationProtocol,
|
|
38730
|
+
stripQuestionBlocks: () => stripQuestionBlocks,
|
|
38546
38731
|
swapMembers: () => swapMembers,
|
|
38547
38732
|
systemMessagesFromSplit: () => systemMessagesFromSplit,
|
|
38548
38733
|
taskMatchesNfrKeywords: () => taskMatchesNfrKeywords,
|
|
@@ -44033,6 +44218,7 @@ __export(krakenModel_exports, {
|
|
|
44033
44218
|
inferModelFamily: () => inferModelFamily,
|
|
44034
44219
|
isCheapModelId: () => isCheapModelId,
|
|
44035
44220
|
isKrakenAutoModelEnabled: () => isKrakenAutoModelEnabled,
|
|
44221
|
+
isUnknownModelError: () => isUnknownModelError,
|
|
44036
44222
|
parseQualifiedModelRef: () => parseQualifiedModelRef,
|
|
44037
44223
|
pickCheapModel: () => pickCheapModel,
|
|
44038
44224
|
pickDifferentFamily: () => pickDifferentFamily,
|
|
@@ -44144,6 +44330,12 @@ function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {})
|
|
|
44144
44330
|
}
|
|
44145
44331
|
return parentModel;
|
|
44146
44332
|
}
|
|
44333
|
+
function isUnknownModelError(message) {
|
|
44334
|
+
if (!message) return false;
|
|
44335
|
+
const m = message.toLowerCase();
|
|
44336
|
+
if (!/model/.test(m)) return false;
|
|
44337
|
+
return /http\s*404/.test(m) || /not-found/.test(m) || /not_found/.test(m) || /does not exist/.test(m) || /unknown model/.test(m) || /model_not_found/.test(m);
|
|
44338
|
+
}
|
|
44147
44339
|
function resolveKrakenPlannerModel(parentModel, env = process.env) {
|
|
44148
44340
|
const specific = env.ZELARI_KRAKEN_PLANNER_MODEL?.trim();
|
|
44149
44341
|
if (specific) return specific;
|
|
@@ -45943,6 +46135,12 @@ ${failed.error ?? "unknown error"}`,
|
|
|
45943
46135
|
// src/cli/tools/taskTool.ts
|
|
45944
46136
|
import { existsSync as existsSync26 } from "node:fs";
|
|
45945
46137
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
46138
|
+
function permissionsForTaskAgent(agent) {
|
|
46139
|
+
const kind2 = agent ?? "explore";
|
|
46140
|
+
if (kind2 === "general") return ["read", "write", "execute", "network"];
|
|
46141
|
+
if (kind2 === "verify") return ["read", "execute", "network"];
|
|
46142
|
+
return ["read"];
|
|
46143
|
+
}
|
|
45946
46144
|
function resetTaskSpawnCount() {
|
|
45947
46145
|
const g = globalThis;
|
|
45948
46146
|
g.__zelariTaskSpawnCount = 0;
|
|
@@ -46009,6 +46207,27 @@ ${findings || "(the reviewer reported FAIL without detail)"}`;
|
|
|
46009
46207
|
async function runAutoVerifyAfterGeneral(opts) {
|
|
46010
46208
|
const g = globalThis;
|
|
46011
46209
|
g.__zelariGeneralVerifyDebt = { description: opts.original.description };
|
|
46210
|
+
const emitVerifyPhase = (detail2, ok) => {
|
|
46211
|
+
const agentId = opts.general.agentId;
|
|
46212
|
+
if (agentId) {
|
|
46213
|
+
opts.deps.onTentacleEvent?.({
|
|
46214
|
+
type: "agent_status",
|
|
46215
|
+
agentId,
|
|
46216
|
+
status: "running",
|
|
46217
|
+
message: detail2,
|
|
46218
|
+
id: randomUUID4(),
|
|
46219
|
+
sessionId: opts.sessionId,
|
|
46220
|
+
ts: Date.now()
|
|
46221
|
+
});
|
|
46222
|
+
}
|
|
46223
|
+
appendKrakenRadio(opts.parentCwd, opts.sessionId, {
|
|
46224
|
+
kind: "progress",
|
|
46225
|
+
agent: "verify",
|
|
46226
|
+
description: `verify: ${opts.original.description}`,
|
|
46227
|
+
detail: detail2,
|
|
46228
|
+
...ok === void 0 ? {} : { ok }
|
|
46229
|
+
});
|
|
46230
|
+
};
|
|
46012
46231
|
const inheritedCwd = opts.general.worktreePath && existsSync26(opts.general.worktreePath) ? opts.general.worktreePath : void 0;
|
|
46013
46232
|
const runVerify = (label) => runTentacle({
|
|
46014
46233
|
deps: opts.deps,
|
|
@@ -46025,6 +46244,7 @@ async function runAutoVerifyAfterGeneral(opts) {
|
|
|
46025
46244
|
sessionId: opts.sessionId,
|
|
46026
46245
|
...opts.signal ? { signal: opts.signal } : {}
|
|
46027
46246
|
});
|
|
46247
|
+
emitVerifyPhase("verifying\u2026");
|
|
46028
46248
|
let verify = await runVerify(`verify: ${opts.original.description}`);
|
|
46029
46249
|
let verdict = verify.ok ? parseVerifyVerdict(verify.result).verdict : "unknown";
|
|
46030
46250
|
let findings = verify.ok ? parseVerifyVerdict(verify.result).findings : "";
|
|
@@ -46072,10 +46292,15 @@ async function runAutoVerifyAfterGeneral(opts) {
|
|
|
46072
46292
|
}
|
|
46073
46293
|
if (verdict === "pass") {
|
|
46074
46294
|
g.__zelariGeneralVerifyDebt = null;
|
|
46295
|
+
emitVerifyPhase("verify PASS", true);
|
|
46075
46296
|
return `
|
|
46076
46297
|
|
|
46077
46298
|
[kraken:auto-verify] verify PASS \u2014 general\u21D2verify obligation satisfied.`;
|
|
46078
46299
|
}
|
|
46300
|
+
emitVerifyPhase(
|
|
46301
|
+
verdict === "fail" ? "verify FAIL" : verify.ok ? "verify unknown" : "verify failed",
|
|
46302
|
+
verdict === "fail" || !verify.ok ? false : void 0
|
|
46303
|
+
);
|
|
46079
46304
|
const detail = verdict === "fail" ? `verify FAIL unresolved (rework budget spent): ${findings || "no findings reported"}` : verify.ok ? "verify produced no parseable VERDICT \u2014 unverified" : `verify tentacle failed: ${verify.error}`;
|
|
46080
46305
|
g.__zelariGeneralVerifyDebt = { description: opts.original.description, detail };
|
|
46081
46306
|
appendKrakenRadio(opts.parentCwd, opts.sessionId, {
|
|
@@ -46231,6 +46456,11 @@ async function runSubAgent(harness, opts = {}) {
|
|
|
46231
46456
|
signal?.removeEventListener("abort", onAbort);
|
|
46232
46457
|
}
|
|
46233
46458
|
}
|
|
46459
|
+
function shortWorktreeCaption(p3) {
|
|
46460
|
+
const parts = p3.split(/[\\/]/).filter(Boolean);
|
|
46461
|
+
const short2 = parts.length > 2 ? `.../${parts.slice(-2).join("/")}` : p3;
|
|
46462
|
+
return short2.length > 50 ? `...${short2.slice(-47)}` : short2;
|
|
46463
|
+
}
|
|
46234
46464
|
async function runTentacle(opts) {
|
|
46235
46465
|
const { deps, args, agent, thoroughness, parentCwd, sessionId: sessionId2 } = opts;
|
|
46236
46466
|
const started = Date.now();
|
|
@@ -46327,6 +46557,18 @@ async function runTentacle(opts) {
|
|
|
46327
46557
|
ts: Date.now()
|
|
46328
46558
|
});
|
|
46329
46559
|
emitActivity({ type: "agent_status", agentId: liveId, status: "running", ts: Date.now() });
|
|
46560
|
+
const emitPhase = (message) => {
|
|
46561
|
+
emitActivity({ type: "agent_status", agentId: liveId, status: "running", message, ts: Date.now() });
|
|
46562
|
+
appendKrakenRadio(parentCwd, sessionId2, {
|
|
46563
|
+
kind: "progress",
|
|
46564
|
+
agent,
|
|
46565
|
+
thoroughness,
|
|
46566
|
+
description: args.description,
|
|
46567
|
+
detail: message
|
|
46568
|
+
});
|
|
46569
|
+
};
|
|
46570
|
+
emitPhase(`phase: ${agent}`);
|
|
46571
|
+
if (worktree) emitPhase(`worktree: ${shortWorktreeCaption(worktree.path)}`);
|
|
46330
46572
|
const taskUserContent = buildTaskUserPrompt({
|
|
46331
46573
|
prompt: args.prompt,
|
|
46332
46574
|
scope: args.scope,
|
|
@@ -46380,17 +46622,45 @@ ${taskUserContent}`,
|
|
|
46380
46622
|
};
|
|
46381
46623
|
}
|
|
46382
46624
|
const startedTools = /* @__PURE__ */ new Map();
|
|
46383
|
-
const
|
|
46625
|
+
const onHarnessEvent = (ev) => {
|
|
46626
|
+
if (ev.type === "tool_execution_start") {
|
|
46627
|
+
startedTools.set(ev.toolCallId, ev.toolName);
|
|
46628
|
+
emitActivity({ type: "agent_tool", agentId: liveId, toolCallId: ev.toolCallId, tool: ev.toolName, status: "started", ...ev.args ? { summary: toolCommandHint(ev.args) } : {}, ts: Date.now() });
|
|
46629
|
+
} else if (ev.type === "tool_execution_end") {
|
|
46630
|
+
emitActivity({ type: "agent_tool", agentId: liveId, toolCallId: ev.toolCallId, tool: startedTools.get(ev.toolCallId) ?? "unknown", status: ev.isError ? "failed" : "completed", durationMs: ev.durationMs, ts: Date.now() });
|
|
46631
|
+
}
|
|
46632
|
+
};
|
|
46633
|
+
let { result, error: error51, aborted: aborted2, usage, toolTrace } = await runSubAgent(harness, {
|
|
46384
46634
|
...opts.signal ? { signal: opts.signal } : {},
|
|
46385
|
-
onEvent:
|
|
46386
|
-
|
|
46387
|
-
|
|
46388
|
-
|
|
46389
|
-
|
|
46390
|
-
|
|
46635
|
+
onEvent: onHarnessEvent
|
|
46636
|
+
});
|
|
46637
|
+
if (!aborted2 && !result && sub.fallback && sub.fallback.model !== sub.model) {
|
|
46638
|
+
const { isUnknownModelError: isUnknownModelError2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
46639
|
+
if (isUnknownModelError2(error51)) {
|
|
46640
|
+
emitPhase(`model ${sub.model} unavailable \u2014 retrying with ${sub.fallback.model}`);
|
|
46641
|
+
const retryConfig = {
|
|
46642
|
+
...config2,
|
|
46643
|
+
model: sub.fallback.model,
|
|
46644
|
+
provider: sub.fallback.provider,
|
|
46645
|
+
providerStream: sub.fallback.providerStream
|
|
46646
|
+
};
|
|
46647
|
+
try {
|
|
46648
|
+
harness = deps.harnessFactory ? deps.harnessFactory(retryConfig) : new (await Promise.resolve().then(() => (init_harness(), harness_exports))).AgentHarness(retryConfig);
|
|
46649
|
+
const retry = await runSubAgent(harness, {
|
|
46650
|
+
...opts.signal ? { signal: opts.signal } : {},
|
|
46651
|
+
onEvent: onHarnessEvent
|
|
46652
|
+
});
|
|
46653
|
+
result = retry.result;
|
|
46654
|
+
error51 = retry.error;
|
|
46655
|
+
aborted2 = retry.aborted;
|
|
46656
|
+
usage = retry.usage;
|
|
46657
|
+
toolTrace = retry.toolTrace;
|
|
46658
|
+
sub = { ...sub, model: sub.fallback.model, provider: sub.fallback.provider };
|
|
46659
|
+
} catch (err) {
|
|
46660
|
+
error51 = err instanceof Error ? err.message : String(err);
|
|
46391
46661
|
}
|
|
46392
46662
|
}
|
|
46393
|
-
}
|
|
46663
|
+
}
|
|
46394
46664
|
const durationMs = Date.now() - started;
|
|
46395
46665
|
if (aborted2) {
|
|
46396
46666
|
if (worktree && !shouldKeepWorktree()) await cleanupKrakenWorktree(worktree);
|
|
@@ -46441,6 +46711,7 @@ worktree deferred: branch=${worktree.branch} path=${worktree.path} (executor mer
|
|
|
46441
46711
|
} else if (worktree) {
|
|
46442
46712
|
let merge2 = null;
|
|
46443
46713
|
if (!kept && isKrakenWorktreeAutoMergeEnabled()) {
|
|
46714
|
+
emitPhase("merging\u2026");
|
|
46444
46715
|
try {
|
|
46445
46716
|
merge2 = await mergeKrakenWorktree(
|
|
46446
46717
|
worktree,
|
|
@@ -46454,6 +46725,7 @@ worktree deferred: branch=${worktree.branch} path=${worktree.path} (executor mer
|
|
|
46454
46725
|
message: `merge threw: ${err instanceof Error ? err.message : String(err)}`
|
|
46455
46726
|
};
|
|
46456
46727
|
}
|
|
46728
|
+
emitPhase(merge2.ok ? "merge ok" : "merge failed");
|
|
46457
46729
|
} else if (!kept) {
|
|
46458
46730
|
await cleanupKrakenWorktree(worktree);
|
|
46459
46731
|
}
|
|
@@ -46517,6 +46789,7 @@ ${verifyHintForGeneral(args.acceptance)}`;
|
|
|
46517
46789
|
ok: true,
|
|
46518
46790
|
agent,
|
|
46519
46791
|
thoroughness,
|
|
46792
|
+
agentId: liveId,
|
|
46520
46793
|
model: sub.model,
|
|
46521
46794
|
result,
|
|
46522
46795
|
footer,
|
|
@@ -53952,6 +54225,7 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
53952
54225
|
// registry's own policy (permPolicy above) — they can never
|
|
53953
54226
|
// exceed it.
|
|
53954
54227
|
parentPolicy: permPolicy,
|
|
54228
|
+
...options.onPermissionAsk ? { onPermissionAsk: options.onPermissionAsk } : {},
|
|
53955
54229
|
...options.subAgentProvider ? { provider: options.subAgentProvider } : {},
|
|
53956
54230
|
...options.subAgentModel ? { model: options.subAgentModel } : {}
|
|
53957
54231
|
}),
|
|
@@ -54051,12 +54325,13 @@ function taskAgentToProfile(agent) {
|
|
|
54051
54325
|
return "explore";
|
|
54052
54326
|
}
|
|
54053
54327
|
function createKrakenSubAgentContextFactory(opts) {
|
|
54054
|
-
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy } = opts;
|
|
54328
|
+
const { root, audit, sessionId: sessionId2, provider: providerOverride, model: modelOverride, parentPolicy, onPermissionAsk } = opts;
|
|
54055
54329
|
return async ({ agent, cwd: subCwd }) => {
|
|
54056
54330
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
54057
54331
|
if (!cfg) return null;
|
|
54058
54332
|
const { resolveKrakenSubModel: resolveKrakenSubModel2, parseQualifiedModelRef: parseQualifiedModelRef2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
54059
|
-
const
|
|
54333
|
+
const parentModel = modelOverride || cfg.model;
|
|
54334
|
+
const resolvedModel = resolveKrakenSubModel2(agent, parentModel);
|
|
54060
54335
|
let effCfg = cfg;
|
|
54061
54336
|
let model = resolvedModel;
|
|
54062
54337
|
const ref = parseQualifiedModelRef2(resolvedModel);
|
|
@@ -54085,6 +54360,7 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
54085
54360
|
diagnostics: false,
|
|
54086
54361
|
lspProvider: null,
|
|
54087
54362
|
permissionPolicy: effectiveSubPolicy,
|
|
54363
|
+
...onPermissionAsk ? { onPermissionAsk } : {},
|
|
54088
54364
|
// P0.5: the tentacle's agent identity drives per-agent policy rules.
|
|
54089
54365
|
policyAgent: agent
|
|
54090
54366
|
});
|
|
@@ -54092,6 +54368,13 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
54092
54368
|
providerStream: buildProviderStream(subCfg),
|
|
54093
54369
|
model,
|
|
54094
54370
|
provider: subCfg.providerId,
|
|
54371
|
+
...model !== parentModel ? {
|
|
54372
|
+
fallback: {
|
|
54373
|
+
model: parentModel,
|
|
54374
|
+
provider: cfg.providerId,
|
|
54375
|
+
providerStream: buildProviderStream({ ...cfg, model: parentModel })
|
|
54376
|
+
}
|
|
54377
|
+
} : {},
|
|
54095
54378
|
registry: subRegistry,
|
|
54096
54379
|
tools: subRegistry.toOpenAITools().map((t) => ({
|
|
54097
54380
|
name: t.function.name,
|
|
@@ -54111,11 +54394,14 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54111
54394
|
return {
|
|
54112
54395
|
...original,
|
|
54113
54396
|
execute: async (input, ctx) => {
|
|
54114
|
-
const
|
|
54397
|
+
const requiredNow = original.name === "task" ? permissionsForTaskAgent(
|
|
54398
|
+
input?.agent
|
|
54399
|
+
) : required2;
|
|
54400
|
+
const decision = resolveToolPermission(original.name, requiredNow, policy);
|
|
54115
54401
|
const rule = agentLayers ? matchAgentPolicyRuleLayered(
|
|
54116
54402
|
agentLayers,
|
|
54117
54403
|
precedence,
|
|
54118
|
-
|
|
54404
|
+
requiredNow,
|
|
54119
54405
|
input ?? {},
|
|
54120
54406
|
root ?? process.cwd()
|
|
54121
54407
|
) : null;
|
|
@@ -54127,25 +54413,25 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54127
54413
|
root ?? process.cwd()
|
|
54128
54414
|
) : void 0;
|
|
54129
54415
|
const contractRule = matchContractCapabilityRule(
|
|
54130
|
-
|
|
54416
|
+
requiredNow,
|
|
54131
54417
|
input ?? {},
|
|
54132
54418
|
root ?? process.cwd()
|
|
54133
54419
|
);
|
|
54134
54420
|
let action = intersectEffects(mergeRuleEffect(decision.action, rule), claims?.effect, contractRule?.effect);
|
|
54135
54421
|
let actionReason = decision.reason;
|
|
54136
|
-
if (action !== "deny" && (
|
|
54422
|
+
if (action !== "deny" && (requiredNow.includes("write") || requiredNow.includes("execute"))) {
|
|
54137
54423
|
const provHit = provenanceMatchIn(JSON.stringify(input ?? {}));
|
|
54138
|
-
if (provHit && provenanceAppliesTo(provHit.source,
|
|
54424
|
+
if (provHit && provenanceAppliesTo(provHit.source, requiredNow)) {
|
|
54139
54425
|
const provNote = `[provenance] args embed non-user ${provHit.source} content (via ${provHit.tool})`;
|
|
54140
54426
|
if (action === "allow") {
|
|
54141
54427
|
action = "ask";
|
|
54142
|
-
actionReason = `${provNote} \u2014 confirm before ${
|
|
54428
|
+
actionReason = `${provNote} \u2014 confirm before ${requiredNow.join("+")}`;
|
|
54143
54429
|
} else {
|
|
54144
54430
|
actionReason = `${decision.reason} \xB7 ${provNote}`;
|
|
54145
54431
|
}
|
|
54146
54432
|
}
|
|
54147
54433
|
}
|
|
54148
|
-
if (action === "allow" &&
|
|
54434
|
+
if (action === "allow" && requiredNow.includes("execute") && activePermissionPreset() !== "yolo" && !isSessionGranted(original.name, requiredNow)) {
|
|
54149
54435
|
const destructiveHit = destructiveCommandHit(input ?? {});
|
|
54150
54436
|
if (destructiveHit) {
|
|
54151
54437
|
action = "ask";
|
|
@@ -54188,7 +54474,7 @@ function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence =
|
|
|
54188
54474
|
}
|
|
54189
54475
|
}
|
|
54190
54476
|
const outcome = await original.execute(input, ctx);
|
|
54191
|
-
recordResultForProvenance(original.name,
|
|
54477
|
+
recordResultForProvenance(original.name, requiredNow, outcome);
|
|
54192
54478
|
return outcome;
|
|
54193
54479
|
}
|
|
54194
54480
|
};
|
|
@@ -55524,6 +55810,25 @@ var init_spineTelemetry = __esm({
|
|
|
55524
55810
|
}
|
|
55525
55811
|
});
|
|
55526
55812
|
|
|
55813
|
+
// src/cli/hooks/askUserTimeout.ts
|
|
55814
|
+
function askUserTimeoutMs() {
|
|
55815
|
+
const raw = process.env.ZELARI_ASK_USER_TIMEOUT_MS?.trim();
|
|
55816
|
+
if (!raw) return 3e5;
|
|
55817
|
+
const n = Number.parseInt(raw, 10);
|
|
55818
|
+
if (!Number.isFinite(n) || n < 0) return 3e5;
|
|
55819
|
+
return n;
|
|
55820
|
+
}
|
|
55821
|
+
function armPickerTimeout(onFire, ms) {
|
|
55822
|
+
if (ms <= 0) return () => void 0;
|
|
55823
|
+
const id3 = setTimeout(onFire, ms);
|
|
55824
|
+
return () => clearTimeout(id3);
|
|
55825
|
+
}
|
|
55826
|
+
var init_askUserTimeout = __esm({
|
|
55827
|
+
"src/cli/hooks/askUserTimeout.ts"() {
|
|
55828
|
+
"use strict";
|
|
55829
|
+
}
|
|
55830
|
+
});
|
|
55831
|
+
|
|
55527
55832
|
// src/cli/state/fileStateStore.ts
|
|
55528
55833
|
import { createHash as createHash17, randomUUID as randomUUID5 } from "node:crypto";
|
|
55529
55834
|
import { promises as fs26 } from "node:fs";
|
|
@@ -60910,7 +61215,8 @@ async function* dispatchCouncil(userMessage, options) {
|
|
|
60910
61215
|
maxToolLoopIterations: options.maxToolLoopIterations,
|
|
60911
61216
|
maxToolLoopHardCap: options.maxToolLoopHardCap,
|
|
60912
61217
|
skipSpecialists: options.skipSpecialists,
|
|
60913
|
-
feedbackStore: options.feedbackStore
|
|
61218
|
+
feedbackStore: options.feedbackStore,
|
|
61219
|
+
signal: options.signal
|
|
60914
61220
|
};
|
|
60915
61221
|
if (!options.disableWorkspaceTools) {
|
|
60916
61222
|
const { setWorkspaceStubs: setWorkspaceStubs2 } = await Promise.resolve().then(() => (init_skills2(), skills_exports));
|
|
@@ -62668,6 +62974,13 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
62668
62974
|
let forcePivot = false;
|
|
62669
62975
|
const missionStartMs = now().getTime();
|
|
62670
62976
|
while (true) {
|
|
62977
|
+
if (deps.signal?.aborted) {
|
|
62978
|
+
state3.status = "cancelled";
|
|
62979
|
+
state3.updatedAt = now().toISOString();
|
|
62980
|
+
await persist();
|
|
62981
|
+
deps.emit("[zelari] missione cancellata.");
|
|
62982
|
+
return state3;
|
|
62983
|
+
}
|
|
62671
62984
|
const runMode = pendingDesign ? "design-phase" : "implementation";
|
|
62672
62985
|
if (runMode === "implementation") {
|
|
62673
62986
|
deps.onMissionPhase?.("build", `impl-${implStep + 1}`);
|
|
@@ -62724,6 +63037,13 @@ async function runZelariMission(userMessage, brief, deps) {
|
|
|
62724
63037
|
);
|
|
62725
63038
|
return state3;
|
|
62726
63039
|
}
|
|
63040
|
+
if (deps.signal?.aborted) {
|
|
63041
|
+
state3.status = "cancelled";
|
|
63042
|
+
state3.updatedAt = now().toISOString();
|
|
63043
|
+
await persist();
|
|
63044
|
+
deps.emit("[zelari] missione cancellata.");
|
|
63045
|
+
return state3;
|
|
63046
|
+
}
|
|
62727
63047
|
if (typeof result.costUsd === "number") cumulativeCostUsd += result.costUsd;
|
|
62728
63048
|
if (typeof result.costTokens === "number") cumulativeTokens += result.costTokens;
|
|
62729
63049
|
await deps.memory.add(
|
|
@@ -65842,11 +66162,12 @@ var init_facts = __esm({
|
|
|
65842
66162
|
});
|
|
65843
66163
|
|
|
65844
66164
|
// src/cli/utils/streamScrub.ts
|
|
65845
|
-
function createStreamScrubber2() {
|
|
66165
|
+
function createStreamScrubber2(opts = {}) {
|
|
66166
|
+
const stripQuestion = opts.stripQuestion !== false;
|
|
65846
66167
|
let rawBuf = "";
|
|
65847
66168
|
let emittedLen = 0;
|
|
65848
66169
|
const snapshot = () => {
|
|
65849
|
-
const cleaned = cleanAgentContent(rawBuf);
|
|
66170
|
+
const cleaned = cleanAgentContent(rawBuf, { stripQuestion });
|
|
65850
66171
|
if (cleaned.length <= emittedLen) return "";
|
|
65851
66172
|
const delta = cleaned.slice(emittedLen);
|
|
65852
66173
|
emittedLen = cleaned.length;
|
|
@@ -66084,6 +66405,330 @@ var init_harnessStateEmit = __esm({
|
|
|
66084
66405
|
}
|
|
66085
66406
|
});
|
|
66086
66407
|
|
|
66408
|
+
// src/cli/serve/sessionControl.ts
|
|
66409
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
66410
|
+
function runWithSession(sessionId2, fn) {
|
|
66411
|
+
return dispatchContext.run({ sessionId: sessionId2, token: {} }, fn);
|
|
66412
|
+
}
|
|
66413
|
+
function registerLiveTurnControl(control) {
|
|
66414
|
+
const store6 = dispatchContext.getStore();
|
|
66415
|
+
if (!store6) return void 0;
|
|
66416
|
+
const registered = { ...control, token: store6.token };
|
|
66417
|
+
liveTurns.set(store6.sessionId, registered);
|
|
66418
|
+
return () => {
|
|
66419
|
+
if (liveTurns.get(store6.sessionId) === registered) {
|
|
66420
|
+
liveTurns.delete(store6.sessionId);
|
|
66421
|
+
}
|
|
66422
|
+
};
|
|
66423
|
+
}
|
|
66424
|
+
function getLiveTurnControl(sessionId2) {
|
|
66425
|
+
return liveTurns.get(sessionId2);
|
|
66426
|
+
}
|
|
66427
|
+
function clearSessionTurnControl(sessionId2) {
|
|
66428
|
+
const store6 = dispatchContext.getStore();
|
|
66429
|
+
if (!store6 || store6.sessionId !== sessionId2) return;
|
|
66430
|
+
const registered = liveTurns.get(sessionId2);
|
|
66431
|
+
if (registered && registered.token === store6.token) {
|
|
66432
|
+
liveTurns.delete(sessionId2);
|
|
66433
|
+
}
|
|
66434
|
+
}
|
|
66435
|
+
var dispatchContext, liveTurns;
|
|
66436
|
+
var init_sessionControl = __esm({
|
|
66437
|
+
"src/cli/serve/sessionControl.ts"() {
|
|
66438
|
+
"use strict";
|
|
66439
|
+
dispatchContext = new AsyncLocalStorage();
|
|
66440
|
+
liveTurns = /* @__PURE__ */ new Map();
|
|
66441
|
+
}
|
|
66442
|
+
});
|
|
66443
|
+
|
|
66444
|
+
// src/cli/headless/controlReader.ts
|
|
66445
|
+
function parseControlEvent(raw) {
|
|
66446
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
66447
|
+
return { ok: false, id: "", reason: "control event must be a JSON object" };
|
|
66448
|
+
}
|
|
66449
|
+
const candidate = raw;
|
|
66450
|
+
const type = candidate["type"];
|
|
66451
|
+
if (typeof type !== "string" || !CONTROL_TYPES.has(type)) {
|
|
66452
|
+
return {
|
|
66453
|
+
ok: false,
|
|
66454
|
+
id: typeof candidate["id"] === "string" ? candidate["id"] : "",
|
|
66455
|
+
reason: `unknown control type: ${String(type)}`
|
|
66456
|
+
};
|
|
66457
|
+
}
|
|
66458
|
+
if (typeof candidate["id"] !== "string" || candidate["id"].length === 0) {
|
|
66459
|
+
return { ok: false, id: "", reason: "missing control id" };
|
|
66460
|
+
}
|
|
66461
|
+
if (type === "steer" || type === "follow_up") {
|
|
66462
|
+
if (typeof candidate["text"] !== "string" || candidate["text"].trim().length === 0) {
|
|
66463
|
+
return {
|
|
66464
|
+
ok: false,
|
|
66465
|
+
id: candidate["id"],
|
|
66466
|
+
reason: `${type} requires a non-empty "text" field`
|
|
66467
|
+
};
|
|
66468
|
+
}
|
|
66469
|
+
}
|
|
66470
|
+
if (type === "cancel" && "reason" in candidate && candidate["reason"] !== void 0 && typeof candidate["reason"] !== "string") {
|
|
66471
|
+
return {
|
|
66472
|
+
ok: false,
|
|
66473
|
+
id: candidate["id"],
|
|
66474
|
+
reason: "cancel reason must be a string"
|
|
66475
|
+
};
|
|
66476
|
+
}
|
|
66477
|
+
return {
|
|
66478
|
+
ok: true,
|
|
66479
|
+
event: {
|
|
66480
|
+
...candidate,
|
|
66481
|
+
ts: typeof candidate["ts"] === "number" ? candidate["ts"] : Date.now()
|
|
66482
|
+
}
|
|
66483
|
+
};
|
|
66484
|
+
}
|
|
66485
|
+
function parseControlLine(line) {
|
|
66486
|
+
const trimmed = line.trim();
|
|
66487
|
+
if (trimmed.length === 0) return null;
|
|
66488
|
+
try {
|
|
66489
|
+
return parseControlEvent(JSON.parse(trimmed));
|
|
66490
|
+
} catch (e) {
|
|
66491
|
+
return { ok: false, id: "", reason: `malformed JSON: ${e.message}` };
|
|
66492
|
+
}
|
|
66493
|
+
}
|
|
66494
|
+
function startControlReader(input, onLine) {
|
|
66495
|
+
let buffer = "";
|
|
66496
|
+
const onData = (chunk) => {
|
|
66497
|
+
buffer += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
66498
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
66499
|
+
while (newlineIndex !== -1) {
|
|
66500
|
+
const line = buffer.slice(0, newlineIndex);
|
|
66501
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
66502
|
+
if (line.trim().length > 0) onLine(line.replace(/\r$/, ""));
|
|
66503
|
+
newlineIndex = buffer.indexOf("\n");
|
|
66504
|
+
}
|
|
66505
|
+
};
|
|
66506
|
+
input.on("data", onData);
|
|
66507
|
+
return () => {
|
|
66508
|
+
input.removeListener("data", onData);
|
|
66509
|
+
buffer = "";
|
|
66510
|
+
};
|
|
66511
|
+
}
|
|
66512
|
+
var CONTROL_TYPES;
|
|
66513
|
+
var init_controlReader = __esm({
|
|
66514
|
+
"src/cli/headless/controlReader.ts"() {
|
|
66515
|
+
"use strict";
|
|
66516
|
+
CONTROL_TYPES = /* @__PURE__ */ new Set([
|
|
66517
|
+
"steer",
|
|
66518
|
+
"follow_up",
|
|
66519
|
+
"cancel",
|
|
66520
|
+
"pause",
|
|
66521
|
+
"resume"
|
|
66522
|
+
]);
|
|
66523
|
+
}
|
|
66524
|
+
});
|
|
66525
|
+
|
|
66526
|
+
// src/cli/headless/protocol.ts
|
|
66527
|
+
function protocolInfoEvent() {
|
|
66528
|
+
return {
|
|
66529
|
+
type: "protocol_info",
|
|
66530
|
+
version: HEADLESS_PROTOCOL_VERSION,
|
|
66531
|
+
capabilities: HEADLESS_PROTOCOL_CAPABILITIES,
|
|
66532
|
+
ts: Date.now()
|
|
66533
|
+
};
|
|
66534
|
+
}
|
|
66535
|
+
function controlAcceptedEvent(controlId, controlType) {
|
|
66536
|
+
return {
|
|
66537
|
+
type: "control_accepted",
|
|
66538
|
+
controlId,
|
|
66539
|
+
controlType,
|
|
66540
|
+
ts: Date.now()
|
|
66541
|
+
};
|
|
66542
|
+
}
|
|
66543
|
+
function controlAppliedEvent(controlId, controlType, boundary) {
|
|
66544
|
+
return {
|
|
66545
|
+
type: "control_applied",
|
|
66546
|
+
controlId,
|
|
66547
|
+
controlType,
|
|
66548
|
+
boundary,
|
|
66549
|
+
ts: Date.now()
|
|
66550
|
+
};
|
|
66551
|
+
}
|
|
66552
|
+
function controlRejectedEvent(controlId, reason) {
|
|
66553
|
+
return {
|
|
66554
|
+
type: "control_rejected",
|
|
66555
|
+
controlId,
|
|
66556
|
+
reason,
|
|
66557
|
+
ts: Date.now()
|
|
66558
|
+
};
|
|
66559
|
+
}
|
|
66560
|
+
var HEADLESS_PROTOCOL_VERSION, HEADLESS_PROTOCOL_CAPABILITIES;
|
|
66561
|
+
var init_protocol2 = __esm({
|
|
66562
|
+
"src/cli/headless/protocol.ts"() {
|
|
66563
|
+
"use strict";
|
|
66564
|
+
HEADLESS_PROTOCOL_VERSION = 2;
|
|
66565
|
+
HEADLESS_PROTOCOL_CAPABILITIES = [
|
|
66566
|
+
"stdin-control",
|
|
66567
|
+
"steer",
|
|
66568
|
+
"follow_up",
|
|
66569
|
+
"cancel"
|
|
66570
|
+
];
|
|
66571
|
+
}
|
|
66572
|
+
});
|
|
66573
|
+
|
|
66574
|
+
// src/cli/headless/controlBridge.ts
|
|
66575
|
+
function attachControlPlane(opts) {
|
|
66576
|
+
const { input, queue, emit, onCancel } = opts;
|
|
66577
|
+
let finalized = false;
|
|
66578
|
+
queue.onDrained = (events) => {
|
|
66579
|
+
for (const event of events) {
|
|
66580
|
+
emit(
|
|
66581
|
+
controlAppliedEvent(
|
|
66582
|
+
event.id,
|
|
66583
|
+
event.type,
|
|
66584
|
+
APPLIED_BOUNDARY[event.type] ?? "unknown"
|
|
66585
|
+
)
|
|
66586
|
+
);
|
|
66587
|
+
}
|
|
66588
|
+
const cancels = events.filter((e) => e.type === "cancel");
|
|
66589
|
+
if (cancels.length > 0 && onCancel) {
|
|
66590
|
+
const last = cancels[cancels.length - 1];
|
|
66591
|
+
onCancel(last.type === "cancel" ? last.reason : void 0);
|
|
66592
|
+
}
|
|
66593
|
+
};
|
|
66594
|
+
const disposeReader = startControlReader(input, (line) => {
|
|
66595
|
+
const outcome = parseControlLine(line);
|
|
66596
|
+
if (outcome === null) return;
|
|
66597
|
+
if (!outcome.ok) {
|
|
66598
|
+
emit(controlRejectedEvent(outcome.id, outcome.reason));
|
|
66599
|
+
return;
|
|
66600
|
+
}
|
|
66601
|
+
const event = outcome.event;
|
|
66602
|
+
if (event.type === "pause" || event.type === "resume") {
|
|
66603
|
+
emit(
|
|
66604
|
+
controlRejectedEvent(event.id, `${event.type} is not supported yet`)
|
|
66605
|
+
);
|
|
66606
|
+
return;
|
|
66607
|
+
}
|
|
66608
|
+
if (finalized) {
|
|
66609
|
+
if (event.type === "steer") {
|
|
66610
|
+
const converted = toFollowUp(event);
|
|
66611
|
+
queue.enqueue(converted);
|
|
66612
|
+
emit(controlAppliedEvent(event.id, "steer", "converted-to-follow-up"));
|
|
66613
|
+
emit(controlAcceptedEvent(converted.id, "follow_up"));
|
|
66614
|
+
} else if (event.type === "follow_up") {
|
|
66615
|
+
queue.enqueue(event);
|
|
66616
|
+
emit(controlAcceptedEvent(event.id, "follow_up"));
|
|
66617
|
+
} else {
|
|
66618
|
+
emit(controlRejectedEvent(event.id, "run already finished"));
|
|
66619
|
+
}
|
|
66620
|
+
return;
|
|
66621
|
+
}
|
|
66622
|
+
queue.enqueue(event);
|
|
66623
|
+
emit(controlAcceptedEvent(event.id, event.type));
|
|
66624
|
+
});
|
|
66625
|
+
return {
|
|
66626
|
+
dispose() {
|
|
66627
|
+
disposeReader();
|
|
66628
|
+
queue.onDrained = void 0;
|
|
66629
|
+
},
|
|
66630
|
+
finalize() {
|
|
66631
|
+
finalized = true;
|
|
66632
|
+
const lateSteers = queue.drainSteers();
|
|
66633
|
+
for (const steer of lateSteers) {
|
|
66634
|
+
queue.enqueue(toFollowUp(steer));
|
|
66635
|
+
emit(controlAppliedEvent(steer.id, "steer", "converted-to-follow-up"));
|
|
66636
|
+
}
|
|
66637
|
+
const followUps = queue.drainFollowUps();
|
|
66638
|
+
for (const followUp of followUps) {
|
|
66639
|
+
emit(controlAppliedEvent(followUp.id, "follow_up", "run-end"));
|
|
66640
|
+
}
|
|
66641
|
+
return followUps.map((f) => f.text);
|
|
66642
|
+
},
|
|
66643
|
+
get finalized() {
|
|
66644
|
+
return finalized;
|
|
66645
|
+
}
|
|
66646
|
+
};
|
|
66647
|
+
}
|
|
66648
|
+
function toFollowUp(steer) {
|
|
66649
|
+
return {
|
|
66650
|
+
type: "follow_up",
|
|
66651
|
+
id: `fu-${steer.id}`,
|
|
66652
|
+
text: steer.text,
|
|
66653
|
+
ts: steer.ts
|
|
66654
|
+
};
|
|
66655
|
+
}
|
|
66656
|
+
var APPLIED_BOUNDARY;
|
|
66657
|
+
var init_controlBridge = __esm({
|
|
66658
|
+
"src/cli/headless/controlBridge.ts"() {
|
|
66659
|
+
"use strict";
|
|
66660
|
+
init_controlReader();
|
|
66661
|
+
init_protocol2();
|
|
66662
|
+
APPLIED_BOUNDARY = {
|
|
66663
|
+
steer: "turn-end",
|
|
66664
|
+
follow_up: "run-end",
|
|
66665
|
+
cancel: "cancel"
|
|
66666
|
+
};
|
|
66667
|
+
}
|
|
66668
|
+
});
|
|
66669
|
+
|
|
66670
|
+
// src/cli/headless/liveTurnAbort.ts
|
|
66671
|
+
function attachHeadlessLiveCancel(opts) {
|
|
66672
|
+
const abort = new AbortController();
|
|
66673
|
+
const controlQueue = new RuntimeControlQueue();
|
|
66674
|
+
const cancel = () => {
|
|
66675
|
+
if (!abort.signal.aborted) abort.abort();
|
|
66676
|
+
return true;
|
|
66677
|
+
};
|
|
66678
|
+
const controlPlane = opts?.output === "json" && process.stdin.isTTY !== true && process.env.ZELARI_SERVE_HARNESS !== "1" ? (() => {
|
|
66679
|
+
emitEvent(protocolInfoEvent());
|
|
66680
|
+
return attachControlPlane({
|
|
66681
|
+
input: process.stdin,
|
|
66682
|
+
queue: controlQueue,
|
|
66683
|
+
emit: emitEvent,
|
|
66684
|
+
onCancel: () => {
|
|
66685
|
+
cancel();
|
|
66686
|
+
}
|
|
66687
|
+
});
|
|
66688
|
+
})() : void 0;
|
|
66689
|
+
const unregister = process.env.ZELARI_SERVE_HARNESS === "1" ? registerLiveTurnControl({
|
|
66690
|
+
queue: controlQueue,
|
|
66691
|
+
cancel
|
|
66692
|
+
}) : void 0;
|
|
66693
|
+
if (unregister) {
|
|
66694
|
+
const appliedBoundary = {
|
|
66695
|
+
steer: "turn-end",
|
|
66696
|
+
follow_up: "run-end",
|
|
66697
|
+
cancel: "cancel"
|
|
66698
|
+
};
|
|
66699
|
+
controlQueue.onDrained = (events) => {
|
|
66700
|
+
for (const event of events) {
|
|
66701
|
+
emitEvent(
|
|
66702
|
+
controlAppliedEvent(
|
|
66703
|
+
event.id,
|
|
66704
|
+
event.type,
|
|
66705
|
+
appliedBoundary[event.type] ?? "unknown"
|
|
66706
|
+
)
|
|
66707
|
+
);
|
|
66708
|
+
}
|
|
66709
|
+
};
|
|
66710
|
+
}
|
|
66711
|
+
return {
|
|
66712
|
+
signal: abort.signal,
|
|
66713
|
+
cancel,
|
|
66714
|
+
dispose() {
|
|
66715
|
+
controlPlane?.finalize();
|
|
66716
|
+
controlPlane?.dispose();
|
|
66717
|
+
unregister?.();
|
|
66718
|
+
}
|
|
66719
|
+
};
|
|
66720
|
+
}
|
|
66721
|
+
var init_liveTurnAbort = __esm({
|
|
66722
|
+
"src/cli/headless/liveTurnAbort.ts"() {
|
|
66723
|
+
"use strict";
|
|
66724
|
+
init_runtime();
|
|
66725
|
+
init_sessionControl();
|
|
66726
|
+
init_controlBridge();
|
|
66727
|
+
init_protocol2();
|
|
66728
|
+
init_headless();
|
|
66729
|
+
}
|
|
66730
|
+
});
|
|
66731
|
+
|
|
66087
66732
|
// src/cli/headless/policyGate.ts
|
|
66088
66733
|
import { isAbsolute as isAbsolute5, resolve as resolve7 } from "node:path";
|
|
66089
66734
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
@@ -66296,268 +66941,6 @@ var init_verifierLifecycle = __esm({
|
|
|
66296
66941
|
}
|
|
66297
66942
|
});
|
|
66298
66943
|
|
|
66299
|
-
// src/cli/headless/controlReader.ts
|
|
66300
|
-
function parseControlEvent(raw) {
|
|
66301
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
66302
|
-
return { ok: false, id: "", reason: "control event must be a JSON object" };
|
|
66303
|
-
}
|
|
66304
|
-
const candidate = raw;
|
|
66305
|
-
const type = candidate["type"];
|
|
66306
|
-
if (typeof type !== "string" || !CONTROL_TYPES.has(type)) {
|
|
66307
|
-
return {
|
|
66308
|
-
ok: false,
|
|
66309
|
-
id: typeof candidate["id"] === "string" ? candidate["id"] : "",
|
|
66310
|
-
reason: `unknown control type: ${String(type)}`
|
|
66311
|
-
};
|
|
66312
|
-
}
|
|
66313
|
-
if (typeof candidate["id"] !== "string" || candidate["id"].length === 0) {
|
|
66314
|
-
return { ok: false, id: "", reason: "missing control id" };
|
|
66315
|
-
}
|
|
66316
|
-
if (type === "steer" || type === "follow_up") {
|
|
66317
|
-
if (typeof candidate["text"] !== "string" || candidate["text"].trim().length === 0) {
|
|
66318
|
-
return {
|
|
66319
|
-
ok: false,
|
|
66320
|
-
id: candidate["id"],
|
|
66321
|
-
reason: `${type} requires a non-empty "text" field`
|
|
66322
|
-
};
|
|
66323
|
-
}
|
|
66324
|
-
}
|
|
66325
|
-
if (type === "cancel" && "reason" in candidate && candidate["reason"] !== void 0 && typeof candidate["reason"] !== "string") {
|
|
66326
|
-
return {
|
|
66327
|
-
ok: false,
|
|
66328
|
-
id: candidate["id"],
|
|
66329
|
-
reason: "cancel reason must be a string"
|
|
66330
|
-
};
|
|
66331
|
-
}
|
|
66332
|
-
return {
|
|
66333
|
-
ok: true,
|
|
66334
|
-
event: {
|
|
66335
|
-
...candidate,
|
|
66336
|
-
ts: typeof candidate["ts"] === "number" ? candidate["ts"] : Date.now()
|
|
66337
|
-
}
|
|
66338
|
-
};
|
|
66339
|
-
}
|
|
66340
|
-
function parseControlLine(line) {
|
|
66341
|
-
const trimmed = line.trim();
|
|
66342
|
-
if (trimmed.length === 0) return null;
|
|
66343
|
-
try {
|
|
66344
|
-
return parseControlEvent(JSON.parse(trimmed));
|
|
66345
|
-
} catch (e) {
|
|
66346
|
-
return { ok: false, id: "", reason: `malformed JSON: ${e.message}` };
|
|
66347
|
-
}
|
|
66348
|
-
}
|
|
66349
|
-
function startControlReader(input, onLine) {
|
|
66350
|
-
let buffer = "";
|
|
66351
|
-
const onData = (chunk) => {
|
|
66352
|
-
buffer += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
66353
|
-
let newlineIndex = buffer.indexOf("\n");
|
|
66354
|
-
while (newlineIndex !== -1) {
|
|
66355
|
-
const line = buffer.slice(0, newlineIndex);
|
|
66356
|
-
buffer = buffer.slice(newlineIndex + 1);
|
|
66357
|
-
if (line.trim().length > 0) onLine(line.replace(/\r$/, ""));
|
|
66358
|
-
newlineIndex = buffer.indexOf("\n");
|
|
66359
|
-
}
|
|
66360
|
-
};
|
|
66361
|
-
input.on("data", onData);
|
|
66362
|
-
return () => {
|
|
66363
|
-
input.removeListener("data", onData);
|
|
66364
|
-
buffer = "";
|
|
66365
|
-
};
|
|
66366
|
-
}
|
|
66367
|
-
var CONTROL_TYPES;
|
|
66368
|
-
var init_controlReader = __esm({
|
|
66369
|
-
"src/cli/headless/controlReader.ts"() {
|
|
66370
|
-
"use strict";
|
|
66371
|
-
CONTROL_TYPES = /* @__PURE__ */ new Set([
|
|
66372
|
-
"steer",
|
|
66373
|
-
"follow_up",
|
|
66374
|
-
"cancel",
|
|
66375
|
-
"pause",
|
|
66376
|
-
"resume"
|
|
66377
|
-
]);
|
|
66378
|
-
}
|
|
66379
|
-
});
|
|
66380
|
-
|
|
66381
|
-
// src/cli/headless/protocol.ts
|
|
66382
|
-
function protocolInfoEvent() {
|
|
66383
|
-
return {
|
|
66384
|
-
type: "protocol_info",
|
|
66385
|
-
version: HEADLESS_PROTOCOL_VERSION,
|
|
66386
|
-
capabilities: HEADLESS_PROTOCOL_CAPABILITIES,
|
|
66387
|
-
ts: Date.now()
|
|
66388
|
-
};
|
|
66389
|
-
}
|
|
66390
|
-
function controlAcceptedEvent(controlId, controlType) {
|
|
66391
|
-
return {
|
|
66392
|
-
type: "control_accepted",
|
|
66393
|
-
controlId,
|
|
66394
|
-
controlType,
|
|
66395
|
-
ts: Date.now()
|
|
66396
|
-
};
|
|
66397
|
-
}
|
|
66398
|
-
function controlAppliedEvent(controlId, controlType, boundary) {
|
|
66399
|
-
return {
|
|
66400
|
-
type: "control_applied",
|
|
66401
|
-
controlId,
|
|
66402
|
-
controlType,
|
|
66403
|
-
boundary,
|
|
66404
|
-
ts: Date.now()
|
|
66405
|
-
};
|
|
66406
|
-
}
|
|
66407
|
-
function controlRejectedEvent(controlId, reason) {
|
|
66408
|
-
return {
|
|
66409
|
-
type: "control_rejected",
|
|
66410
|
-
controlId,
|
|
66411
|
-
reason,
|
|
66412
|
-
ts: Date.now()
|
|
66413
|
-
};
|
|
66414
|
-
}
|
|
66415
|
-
var HEADLESS_PROTOCOL_VERSION, HEADLESS_PROTOCOL_CAPABILITIES;
|
|
66416
|
-
var init_protocol2 = __esm({
|
|
66417
|
-
"src/cli/headless/protocol.ts"() {
|
|
66418
|
-
"use strict";
|
|
66419
|
-
HEADLESS_PROTOCOL_VERSION = 2;
|
|
66420
|
-
HEADLESS_PROTOCOL_CAPABILITIES = [
|
|
66421
|
-
"stdin-control",
|
|
66422
|
-
"steer",
|
|
66423
|
-
"follow_up",
|
|
66424
|
-
"cancel"
|
|
66425
|
-
];
|
|
66426
|
-
}
|
|
66427
|
-
});
|
|
66428
|
-
|
|
66429
|
-
// src/cli/headless/controlBridge.ts
|
|
66430
|
-
function attachControlPlane(opts) {
|
|
66431
|
-
const { input, queue, emit, onCancel } = opts;
|
|
66432
|
-
let finalized = false;
|
|
66433
|
-
queue.onDrained = (events) => {
|
|
66434
|
-
for (const event of events) {
|
|
66435
|
-
emit(
|
|
66436
|
-
controlAppliedEvent(
|
|
66437
|
-
event.id,
|
|
66438
|
-
event.type,
|
|
66439
|
-
APPLIED_BOUNDARY[event.type] ?? "unknown"
|
|
66440
|
-
)
|
|
66441
|
-
);
|
|
66442
|
-
}
|
|
66443
|
-
const cancels = events.filter((e) => e.type === "cancel");
|
|
66444
|
-
if (cancels.length > 0 && onCancel) {
|
|
66445
|
-
const last = cancels[cancels.length - 1];
|
|
66446
|
-
onCancel(last.type === "cancel" ? last.reason : void 0);
|
|
66447
|
-
}
|
|
66448
|
-
};
|
|
66449
|
-
const disposeReader = startControlReader(input, (line) => {
|
|
66450
|
-
const outcome = parseControlLine(line);
|
|
66451
|
-
if (outcome === null) return;
|
|
66452
|
-
if (!outcome.ok) {
|
|
66453
|
-
emit(controlRejectedEvent(outcome.id, outcome.reason));
|
|
66454
|
-
return;
|
|
66455
|
-
}
|
|
66456
|
-
const event = outcome.event;
|
|
66457
|
-
if (event.type === "pause" || event.type === "resume") {
|
|
66458
|
-
emit(
|
|
66459
|
-
controlRejectedEvent(event.id, `${event.type} is not supported yet`)
|
|
66460
|
-
);
|
|
66461
|
-
return;
|
|
66462
|
-
}
|
|
66463
|
-
if (finalized) {
|
|
66464
|
-
if (event.type === "steer") {
|
|
66465
|
-
const converted = toFollowUp(event);
|
|
66466
|
-
queue.enqueue(converted);
|
|
66467
|
-
emit(controlAppliedEvent(event.id, "steer", "converted-to-follow-up"));
|
|
66468
|
-
emit(controlAcceptedEvent(converted.id, "follow_up"));
|
|
66469
|
-
} else if (event.type === "follow_up") {
|
|
66470
|
-
queue.enqueue(event);
|
|
66471
|
-
emit(controlAcceptedEvent(event.id, "follow_up"));
|
|
66472
|
-
} else {
|
|
66473
|
-
emit(controlRejectedEvent(event.id, "run already finished"));
|
|
66474
|
-
}
|
|
66475
|
-
return;
|
|
66476
|
-
}
|
|
66477
|
-
queue.enqueue(event);
|
|
66478
|
-
emit(controlAcceptedEvent(event.id, event.type));
|
|
66479
|
-
});
|
|
66480
|
-
return {
|
|
66481
|
-
dispose() {
|
|
66482
|
-
disposeReader();
|
|
66483
|
-
queue.onDrained = void 0;
|
|
66484
|
-
},
|
|
66485
|
-
finalize() {
|
|
66486
|
-
finalized = true;
|
|
66487
|
-
const lateSteers = queue.drainSteers();
|
|
66488
|
-
for (const steer of lateSteers) {
|
|
66489
|
-
queue.enqueue(toFollowUp(steer));
|
|
66490
|
-
emit(controlAppliedEvent(steer.id, "steer", "converted-to-follow-up"));
|
|
66491
|
-
}
|
|
66492
|
-
const followUps = queue.drainFollowUps();
|
|
66493
|
-
for (const followUp of followUps) {
|
|
66494
|
-
emit(controlAppliedEvent(followUp.id, "follow_up", "run-end"));
|
|
66495
|
-
}
|
|
66496
|
-
return followUps.map((f) => f.text);
|
|
66497
|
-
},
|
|
66498
|
-
get finalized() {
|
|
66499
|
-
return finalized;
|
|
66500
|
-
}
|
|
66501
|
-
};
|
|
66502
|
-
}
|
|
66503
|
-
function toFollowUp(steer) {
|
|
66504
|
-
return {
|
|
66505
|
-
type: "follow_up",
|
|
66506
|
-
id: `fu-${steer.id}`,
|
|
66507
|
-
text: steer.text,
|
|
66508
|
-
ts: steer.ts
|
|
66509
|
-
};
|
|
66510
|
-
}
|
|
66511
|
-
var APPLIED_BOUNDARY;
|
|
66512
|
-
var init_controlBridge = __esm({
|
|
66513
|
-
"src/cli/headless/controlBridge.ts"() {
|
|
66514
|
-
"use strict";
|
|
66515
|
-
init_controlReader();
|
|
66516
|
-
init_protocol2();
|
|
66517
|
-
APPLIED_BOUNDARY = {
|
|
66518
|
-
steer: "turn-end",
|
|
66519
|
-
follow_up: "run-end",
|
|
66520
|
-
cancel: "cancel"
|
|
66521
|
-
};
|
|
66522
|
-
}
|
|
66523
|
-
});
|
|
66524
|
-
|
|
66525
|
-
// src/cli/serve/sessionControl.ts
|
|
66526
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
66527
|
-
function runWithSession(sessionId2, fn) {
|
|
66528
|
-
return dispatchContext.run({ sessionId: sessionId2, token: {} }, fn);
|
|
66529
|
-
}
|
|
66530
|
-
function registerLiveTurnControl(control) {
|
|
66531
|
-
const store6 = dispatchContext.getStore();
|
|
66532
|
-
if (!store6) return void 0;
|
|
66533
|
-
const registered = { ...control, token: store6.token };
|
|
66534
|
-
liveTurns.set(store6.sessionId, registered);
|
|
66535
|
-
return () => {
|
|
66536
|
-
if (liveTurns.get(store6.sessionId) === registered) {
|
|
66537
|
-
liveTurns.delete(store6.sessionId);
|
|
66538
|
-
}
|
|
66539
|
-
};
|
|
66540
|
-
}
|
|
66541
|
-
function getLiveTurnControl(sessionId2) {
|
|
66542
|
-
return liveTurns.get(sessionId2);
|
|
66543
|
-
}
|
|
66544
|
-
function clearSessionTurnControl(sessionId2) {
|
|
66545
|
-
const store6 = dispatchContext.getStore();
|
|
66546
|
-
if (!store6 || store6.sessionId !== sessionId2) return;
|
|
66547
|
-
const registered = liveTurns.get(sessionId2);
|
|
66548
|
-
if (registered && registered.token === store6.token) {
|
|
66549
|
-
liveTurns.delete(sessionId2);
|
|
66550
|
-
}
|
|
66551
|
-
}
|
|
66552
|
-
var dispatchContext, liveTurns;
|
|
66553
|
-
var init_sessionControl = __esm({
|
|
66554
|
-
"src/cli/serve/sessionControl.ts"() {
|
|
66555
|
-
"use strict";
|
|
66556
|
-
dispatchContext = new AsyncLocalStorage();
|
|
66557
|
-
liveTurns = /* @__PURE__ */ new Map();
|
|
66558
|
-
}
|
|
66559
|
-
});
|
|
66560
|
-
|
|
66561
66944
|
// src/cli/extensions/sandboxedFs.ts
|
|
66562
66945
|
import { promises as fsp } from "node:fs";
|
|
66563
66946
|
import path89 from "node:path";
|
|
@@ -66916,6 +67299,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
66916
67299
|
// an interactive approval (permission.request over NDJSON) instead of
|
|
66917
67300
|
// the fail-closed typedErr. Absent handler ⇒ unchanged fail-closed.
|
|
66918
67301
|
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
67302
|
+
...opts.onAskUser ? { onAskUser: opts.onAskUser } : {},
|
|
66919
67303
|
permissionPolicy: defaultPermissionPolicy2(),
|
|
66920
67304
|
...nativeMemory ? { memoryService: nativeMemory } : {},
|
|
66921
67305
|
memoryAutoWrite,
|
|
@@ -67142,7 +67526,7 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
67142
67526
|
let finalReason = "completed";
|
|
67143
67527
|
let exitCode = 0;
|
|
67144
67528
|
const textBuffer = [];
|
|
67145
|
-
const scrub = createStreamScrubber2();
|
|
67529
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
67146
67530
|
try {
|
|
67147
67531
|
for await (const event of harness.run()) {
|
|
67148
67532
|
progressRuntime.observe(event);
|
|
@@ -68684,6 +69068,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
68684
69068
|
// ask without a UI fails closed), so this intersection actually
|
|
68685
69069
|
// bites: tentacles can never exceed the preset.
|
|
68686
69070
|
parentPolicy: defaultPermissionPolicy2(),
|
|
69071
|
+
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
68687
69072
|
// Anchor every tentacle to the SAME provider/model this run
|
|
68688
69073
|
// resolved (Desktop's selector, or --provider/--model), instead
|
|
68689
69074
|
// of the persisted provider.json default the factory falls back
|
|
@@ -68800,6 +69185,8 @@ async function buildCouncilToolRegistry(planMode, opts, memoryService, memoryAut
|
|
|
68800
69185
|
planMode,
|
|
68801
69186
|
...extras?.lspProvider ? { lspProvider: extras.lspProvider } : {},
|
|
68802
69187
|
permissionPolicy: defaultPermissionPolicy2(),
|
|
69188
|
+
...opts?.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
69189
|
+
...opts?.onAskUser ? { onAskUser: opts.onAskUser } : {},
|
|
68803
69190
|
...memoryService ? { memoryService } : {},
|
|
68804
69191
|
memoryAutoWrite
|
|
68805
69192
|
});
|
|
@@ -68819,6 +69206,14 @@ async function buildCouncilToolRegistry(planMode, opts, memoryService, memoryAut
|
|
|
68819
69206
|
return { toolRegistry, workspaceCtx: realCtx };
|
|
68820
69207
|
}
|
|
68821
69208
|
async function runHeadlessCouncil(opts, provider, model, providerStream, extras) {
|
|
69209
|
+
const live = attachHeadlessLiveCancel({ output: opts.output });
|
|
69210
|
+
try {
|
|
69211
|
+
return await runHeadlessCouncilBody(opts, provider, model, providerStream, extras, live.signal);
|
|
69212
|
+
} finally {
|
|
69213
|
+
live.dispose();
|
|
69214
|
+
}
|
|
69215
|
+
}
|
|
69216
|
+
async function runHeadlessCouncilBody(opts, provider, model, providerStream, extras, signal) {
|
|
68822
69217
|
const { dispatchCouncil: dispatchCouncil2 } = await Promise.resolve().then(() => (init_councilDispatcher(), councilDispatcher_exports));
|
|
68823
69218
|
const sessionId2 = crypto.randomUUID();
|
|
68824
69219
|
const cwd = resolveHeadlessCwd(opts);
|
|
@@ -68894,7 +69289,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
68894
69289
|
const effectiveTask = buildCouncilTaskWithHistory(opts.task, historySeed);
|
|
68895
69290
|
if (opts.task) spine.userMessage(effectiveTask);
|
|
68896
69291
|
let exitCode = 0;
|
|
68897
|
-
const scrub = createStreamScrubber2();
|
|
69292
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
68898
69293
|
let lastAssistantText = "";
|
|
68899
69294
|
let currentAssistantText = "";
|
|
68900
69295
|
try {
|
|
@@ -68929,6 +69324,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
68929
69324
|
tools: toolRegistry,
|
|
68930
69325
|
feedbackStore,
|
|
68931
69326
|
runMode: councilRunMode,
|
|
69327
|
+
signal,
|
|
68932
69328
|
// t23: an auto-SELECTED council runs the LITE tier (3 members) unless
|
|
68933
69329
|
// ZELARI_COUNCIL_TIER / ZELARI_COUNCIL_SIZE explicitly opt into full.
|
|
68934
69330
|
...opts.orchestrationDecision?.strategy === "council" && process.env["ZELARI_COUNCIL_TIER"] === void 0 && process.env["ZELARI_COUNCIL_SIZE"] === void 0 ? { councilSize: COUNCIL_TIER_SIZES.lite } : {},
|
|
@@ -68987,7 +69383,9 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
68987
69383
|
return 2;
|
|
68988
69384
|
}
|
|
68989
69385
|
try {
|
|
68990
|
-
await spine.close(
|
|
69386
|
+
await spine.close(
|
|
69387
|
+
signal.aborted ? "stopped" : exitCode === 0 ? "completed" : "error"
|
|
69388
|
+
);
|
|
68991
69389
|
} catch {
|
|
68992
69390
|
}
|
|
68993
69391
|
try {
|
|
@@ -68999,7 +69397,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
68999
69397
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69000
69398
|
mode: "shadow",
|
|
69001
69399
|
taskClass: classifyTask2({ prompt: effectiveTask }).taskClass,
|
|
69002
|
-
verdict: exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
69400
|
+
verdict: signal.aborted ? "UNKNOWN" : exitCode === 0 ? "PASS" : exitCode === 3 ? "FAIL" : "UNKNOWN"
|
|
69003
69401
|
});
|
|
69004
69402
|
}
|
|
69005
69403
|
} catch {
|
|
@@ -69018,7 +69416,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69018
69416
|
} catch {
|
|
69019
69417
|
}
|
|
69020
69418
|
}
|
|
69021
|
-
if (nativeMemory && memoryAutoWrite && lastAssistantText) {
|
|
69419
|
+
if (nativeMemory && memoryAutoWrite && lastAssistantText && !signal.aborted) {
|
|
69022
69420
|
try {
|
|
69023
69421
|
await nativeMemory.remember({
|
|
69024
69422
|
kind: councilRunMode === "design-phase" ? "decision" : "outcome",
|
|
@@ -69045,6 +69443,14 @@ async function runHeadlessCouncil(opts, provider, model, providerStream, extras)
|
|
|
69045
69443
|
return exitCode;
|
|
69046
69444
|
}
|
|
69047
69445
|
async function runHeadlessZelari(opts, provider, model, providerStream, extras) {
|
|
69446
|
+
const live = attachHeadlessLiveCancel({ output: opts.output });
|
|
69447
|
+
try {
|
|
69448
|
+
return await runHeadlessZelariBody(opts, provider, model, providerStream, extras, live.signal);
|
|
69449
|
+
} finally {
|
|
69450
|
+
live.dispose();
|
|
69451
|
+
}
|
|
69452
|
+
}
|
|
69453
|
+
async function runHeadlessZelariBody(opts, provider, model, providerStream, extras, signal) {
|
|
69048
69454
|
const projectRoot = resolveHeadlessCwd(opts);
|
|
69049
69455
|
const sessionId2 = opts.resumeSessionId ?? crypto.randomUUID();
|
|
69050
69456
|
const spine = await openHeadlessSpine({
|
|
@@ -69155,6 +69561,7 @@ ${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMv
|
|
|
69155
69561
|
memory,
|
|
69156
69562
|
emit,
|
|
69157
69563
|
buildViaAgent,
|
|
69564
|
+
signal,
|
|
69158
69565
|
onMissionPhase: (phase2, note) => spine.missionPhase(phase2, note),
|
|
69159
69566
|
onMissionProgress: (advice, iteration) => spine.missionProgress({
|
|
69160
69567
|
recommendation: advice.recommendation,
|
|
@@ -69180,7 +69587,7 @@ ${ragContext}` : slicePrompt;
|
|
|
69180
69587
|
let writeCount = 0;
|
|
69181
69588
|
let chairmanErrored = false;
|
|
69182
69589
|
let membersCompleted = 0;
|
|
69183
|
-
const scrub = createStreamScrubber2();
|
|
69590
|
+
const scrub = createStreamScrubber2({ stripQuestion: opts.output !== "json" });
|
|
69184
69591
|
const { composeProjectContext: composeProjectContext3 } = await Promise.resolve().then(() => (init_composeContext(), composeContext_exports));
|
|
69185
69592
|
const { loadDurableContext: loadDurableContext3 } = await Promise.resolve().then(() => (init_loadDurableContext(), loadDurableContext_exports));
|
|
69186
69593
|
const memOnly = ragContext?.trim() ? ragContext : void 0;
|
|
@@ -69203,6 +69610,7 @@ ${ragContext}` : slicePrompt;
|
|
|
69203
69610
|
tools: toolRegistry,
|
|
69204
69611
|
feedbackStore,
|
|
69205
69612
|
runMode: effectiveRunMode,
|
|
69613
|
+
signal,
|
|
69206
69614
|
maxToolCallsChairman: chairmanBudget,
|
|
69207
69615
|
...implementerRetry ? { skipSpecialists: true } : {},
|
|
69208
69616
|
workspaceContext: composed2.workspaceContext,
|
|
@@ -69250,11 +69658,20 @@ ${ragContext}` : slicePrompt;
|
|
|
69250
69658
|
}
|
|
69251
69659
|
let completionOk = false;
|
|
69252
69660
|
let degraded = false;
|
|
69661
|
+
if (signal.aborted) {
|
|
69662
|
+
return {
|
|
69663
|
+
completionOk: false,
|
|
69664
|
+
ran: membersCompleted > 0 || synthesisText.length > 0,
|
|
69665
|
+
synthesisText: synthesisText || void 0,
|
|
69666
|
+
writeCount,
|
|
69667
|
+
degraded: true
|
|
69668
|
+
};
|
|
69669
|
+
}
|
|
69253
69670
|
try {
|
|
69254
69671
|
const { detectDegradedRun: detectDegradedRun3 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
69255
69672
|
const d = detectDegradedRun3({
|
|
69256
69673
|
chairmanErrored,
|
|
69257
|
-
councilAborted:
|
|
69674
|
+
councilAborted: signal.aborted,
|
|
69258
69675
|
luciferWriteCount: writeCount,
|
|
69259
69676
|
synthesisText,
|
|
69260
69677
|
runMode: effectiveRunMode
|
|
@@ -69321,7 +69738,9 @@ ${ragContext}` : slicePrompt;
|
|
|
69321
69738
|
const { registry: agentRegistry } = createBuiltinToolRegistry2({
|
|
69322
69739
|
root: projectRoot,
|
|
69323
69740
|
planMode: false,
|
|
69324
|
-
permissionPolicy: defaultPermissionPolicy2()
|
|
69741
|
+
permissionPolicy: defaultPermissionPolicy2(),
|
|
69742
|
+
...opts.onPermissionAsk ? { onPermissionAsk: opts.onPermissionAsk } : {},
|
|
69743
|
+
...opts.onAskUser ? { onAskUser: opts.onAskUser } : {}
|
|
69325
69744
|
});
|
|
69326
69745
|
await registerHeadlessMcp(agentRegistry, opts);
|
|
69327
69746
|
const durableState = await loadDurableContext2(projectRoot);
|
|
@@ -69388,7 +69807,10 @@ ${ragContext}` : slicePrompt;
|
|
|
69388
69807
|
}
|
|
69389
69808
|
});
|
|
69390
69809
|
if (state3.status === "error") exitCode = exitCode || 3;
|
|
69391
|
-
else if (state3.status === "
|
|
69810
|
+
else if (state3.status === "cancelled") {
|
|
69811
|
+
exitCode = 0;
|
|
69812
|
+
spine.missionPhase("verification", "mission-cancelled");
|
|
69813
|
+
} else if (state3.status === "success") {
|
|
69392
69814
|
const missionGate = await evaluateStrictBuildGate("build", {
|
|
69393
69815
|
emit: (input) => spine.appendEvent(input),
|
|
69394
69816
|
surface: "mission",
|
|
@@ -69426,7 +69848,8 @@ ${ragContext}` : slicePrompt;
|
|
|
69426
69848
|
}
|
|
69427
69849
|
await memory.close().catch(() => void 0);
|
|
69428
69850
|
try {
|
|
69429
|
-
if (
|
|
69851
|
+
if (signal.aborted) await spine.close("stopped");
|
|
69852
|
+
else if (exitCode === 0) await spine.close("completed");
|
|
69430
69853
|
else await spine.close(exitCode === 2 ? "error" : "stopped");
|
|
69431
69854
|
} catch {
|
|
69432
69855
|
}
|
|
@@ -69473,6 +69896,7 @@ var init_runHeadless = __esm({
|
|
|
69473
69896
|
init_metrics3();
|
|
69474
69897
|
init_headlessSpine();
|
|
69475
69898
|
init_harnessStateEmit();
|
|
69899
|
+
init_liveTurnAbort();
|
|
69476
69900
|
init_policyGate();
|
|
69477
69901
|
init_policyLoadMode();
|
|
69478
69902
|
init_runOneTurn();
|
|
@@ -71060,38 +71484,61 @@ function applyTurnPermissionPreset(input) {
|
|
|
71060
71484
|
process.env[PRESET_ENV] = value;
|
|
71061
71485
|
return true;
|
|
71062
71486
|
}
|
|
71487
|
+
function isPermissionDecision(value) {
|
|
71488
|
+
return typeof value === "string" && PERMISSION_DECISIONS.includes(value);
|
|
71489
|
+
}
|
|
71063
71490
|
function createServePermissionBridge(write, timeoutMs2 = 12e4) {
|
|
71064
71491
|
const pending = /* @__PURE__ */ new Map();
|
|
71065
71492
|
let seq = 0;
|
|
71066
|
-
const settle = (requestId, decision) => {
|
|
71493
|
+
const settle = (requestId, decision, timedOut = false) => {
|
|
71067
71494
|
const entry = pending.get(requestId);
|
|
71068
71495
|
if (!entry) return false;
|
|
71069
71496
|
pending.delete(requestId);
|
|
71070
71497
|
clearTimeout(entry.timer);
|
|
71498
|
+
write(
|
|
71499
|
+
JSON.stringify({
|
|
71500
|
+
type: "permission.settled",
|
|
71501
|
+
requestId,
|
|
71502
|
+
decision,
|
|
71503
|
+
...timedOut ? { timedOut: true } : {}
|
|
71504
|
+
})
|
|
71505
|
+
);
|
|
71071
71506
|
entry.resolve(decision);
|
|
71072
71507
|
return true;
|
|
71073
71508
|
};
|
|
71074
71509
|
return {
|
|
71075
71510
|
onPermissionAsk(payload) {
|
|
71076
71511
|
const requestId = `perm-${Date.now()}-${++seq}`;
|
|
71512
|
+
const categories = payload.categories && payload.categories.length > 0 ? payload.categories : payload.category ? payload.category.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
71077
71513
|
return new Promise((resolve9) => {
|
|
71078
71514
|
const timer = setTimeout(() => {
|
|
71079
|
-
settle(requestId, "deny");
|
|
71515
|
+
settle(requestId, "deny", true);
|
|
71080
71516
|
}, timeoutMs2);
|
|
71081
|
-
pending.set(requestId, { resolve: resolve9, timer });
|
|
71517
|
+
pending.set(requestId, { resolve: resolve9, timer, payload });
|
|
71082
71518
|
write(
|
|
71083
71519
|
JSON.stringify({
|
|
71084
71520
|
type: "permission.request",
|
|
71085
71521
|
requestId,
|
|
71086
71522
|
tool: payload.tool,
|
|
71087
71523
|
category: payload.category,
|
|
71524
|
+
categories,
|
|
71088
71525
|
...payload.inputPreview !== void 0 ? { inputPreview: payload.inputPreview } : {},
|
|
71089
71526
|
...payload.reason !== void 0 ? { reason: payload.reason } : {}
|
|
71090
71527
|
})
|
|
71091
71528
|
);
|
|
71092
71529
|
});
|
|
71093
71530
|
},
|
|
71094
|
-
respond: settle,
|
|
71531
|
+
respond: (requestId, decision) => settle(requestId, decision, false),
|
|
71532
|
+
releaseGranted() {
|
|
71533
|
+
let n = 0;
|
|
71534
|
+
for (const [id3, entry] of [...pending]) {
|
|
71535
|
+
const cats = entry.payload.categories && entry.payload.categories.length > 0 ? entry.payload.categories : entry.payload.category ? entry.payload.category.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
71536
|
+
if (isSessionGranted(entry.payload.tool, cats)) {
|
|
71537
|
+
if (settle(id3, "allow", false)) n += 1;
|
|
71538
|
+
}
|
|
71539
|
+
}
|
|
71540
|
+
return n;
|
|
71541
|
+
},
|
|
71095
71542
|
pendingCount: () => pending.size
|
|
71096
71543
|
};
|
|
71097
71544
|
}
|
|
@@ -71103,8 +71550,11 @@ function servePermissionRespond(bridge, params) {
|
|
|
71103
71550
|
if (typeof requestId !== "string" || requestId.length === 0) {
|
|
71104
71551
|
return { accepted: false, reason: "permission.respond requires a non-empty string requestId" };
|
|
71105
71552
|
}
|
|
71106
|
-
if (decision
|
|
71107
|
-
return {
|
|
71553
|
+
if (!isPermissionDecision(decision)) {
|
|
71554
|
+
return {
|
|
71555
|
+
accepted: false,
|
|
71556
|
+
reason: "permission.respond decision must be 'allow' | 'deny' | 'always-tool' | 'always-category'"
|
|
71557
|
+
};
|
|
71108
71558
|
}
|
|
71109
71559
|
return { accepted: bridge.respond(requestId, decision) };
|
|
71110
71560
|
}
|
|
@@ -71114,18 +71564,104 @@ function asRegistryAskHandler(bridge) {
|
|
|
71114
71564
|
const decision = await bridge.onPermissionAsk({
|
|
71115
71565
|
tool: req.toolName,
|
|
71116
71566
|
category: req.categories.join(",") || "other",
|
|
71567
|
+
categories: req.categories,
|
|
71117
71568
|
reason,
|
|
71118
71569
|
...req.claims && req.claims.length > 0 ? { inputPreview: req.claims.map((c) => c.summary).join(" \xB7 ") } : {}
|
|
71119
71570
|
});
|
|
71120
|
-
|
|
71571
|
+
if (decision === "deny") return false;
|
|
71572
|
+
if (decision === "always-tool") {
|
|
71573
|
+
grantSessionTool(req.toolName);
|
|
71574
|
+
bridge.releaseGranted();
|
|
71575
|
+
} else if (decision === "always-category") {
|
|
71576
|
+
for (const cat of req.categories) {
|
|
71577
|
+
grantSessionCategory(cat);
|
|
71578
|
+
}
|
|
71579
|
+
grantSessionTool(req.toolName);
|
|
71580
|
+
bridge.releaseGranted();
|
|
71581
|
+
}
|
|
71582
|
+
return true;
|
|
71121
71583
|
};
|
|
71122
71584
|
}
|
|
71123
|
-
var SERVE_PERMISSION_PRESETS, PRESET_ENV;
|
|
71585
|
+
var SERVE_PERMISSION_PRESETS, PRESET_ENV, PERMISSION_DECISIONS;
|
|
71124
71586
|
var init_permissionBridge = __esm({
|
|
71125
71587
|
"src/cli/serve/permissionBridge.ts"() {
|
|
71126
71588
|
"use strict";
|
|
71589
|
+
init_toolPermissions();
|
|
71127
71590
|
SERVE_PERMISSION_PRESETS = ["standard", "strict", "yolo"];
|
|
71128
71591
|
PRESET_ENV = "ZELARI_PERMISSION_PRESET";
|
|
71592
|
+
PERMISSION_DECISIONS = [
|
|
71593
|
+
"allow",
|
|
71594
|
+
"deny",
|
|
71595
|
+
"always-tool",
|
|
71596
|
+
"always-category"
|
|
71597
|
+
];
|
|
71598
|
+
}
|
|
71599
|
+
});
|
|
71600
|
+
|
|
71601
|
+
// src/cli/serve/askUserBridge.ts
|
|
71602
|
+
function createServeAskUserBridge(write, timeoutMs2 = askUserTimeoutMs()) {
|
|
71603
|
+
const pending = /* @__PURE__ */ new Map();
|
|
71604
|
+
let seq = 0;
|
|
71605
|
+
const settle = (requestId, answer, timedOut = false) => {
|
|
71606
|
+
const entry = pending.get(requestId);
|
|
71607
|
+
if (!entry) return false;
|
|
71608
|
+
pending.delete(requestId);
|
|
71609
|
+
clearTimeout(entry.timer);
|
|
71610
|
+
write(
|
|
71611
|
+
JSON.stringify({
|
|
71612
|
+
type: "ask_user.settled",
|
|
71613
|
+
requestId,
|
|
71614
|
+
answer,
|
|
71615
|
+
...timedOut ? { timedOut: true } : {}
|
|
71616
|
+
})
|
|
71617
|
+
);
|
|
71618
|
+
entry.resolve(answer);
|
|
71619
|
+
return true;
|
|
71620
|
+
};
|
|
71621
|
+
return {
|
|
71622
|
+
onAskUser(req) {
|
|
71623
|
+
const question = req.question.trim();
|
|
71624
|
+
const choices = req.choices.map((c) => c.trim()).filter(Boolean);
|
|
71625
|
+
if (choices.length < 2) return Promise.resolve(null);
|
|
71626
|
+
const requestId = `ask-${Date.now()}-${++seq}`;
|
|
71627
|
+
return new Promise((resolve9) => {
|
|
71628
|
+
const timer = setTimeout(() => {
|
|
71629
|
+
settle(requestId, null, true);
|
|
71630
|
+
}, timeoutMs2);
|
|
71631
|
+
pending.set(requestId, { resolve: resolve9, timer });
|
|
71632
|
+
write(
|
|
71633
|
+
JSON.stringify({
|
|
71634
|
+
type: "ask_user.request",
|
|
71635
|
+
requestId,
|
|
71636
|
+
question,
|
|
71637
|
+
choices,
|
|
71638
|
+
...req.context ? { context: req.context } : {}
|
|
71639
|
+
})
|
|
71640
|
+
);
|
|
71641
|
+
});
|
|
71642
|
+
},
|
|
71643
|
+
respond: (requestId, answer) => settle(requestId, answer, false),
|
|
71644
|
+
pendingCount: () => pending.size
|
|
71645
|
+
};
|
|
71646
|
+
}
|
|
71647
|
+
function serveAskUserRespond(bridge, params) {
|
|
71648
|
+
if (!params || typeof params !== "object") {
|
|
71649
|
+
return { accepted: false, reason: "ask_user.respond requires an object params" };
|
|
71650
|
+
}
|
|
71651
|
+
const { requestId, answer } = params;
|
|
71652
|
+
if (typeof requestId !== "string" || requestId.length === 0) {
|
|
71653
|
+
return { accepted: false, reason: "ask_user.respond requires a non-empty string requestId" };
|
|
71654
|
+
}
|
|
71655
|
+
if (answer !== null && typeof answer !== "string") {
|
|
71656
|
+
return { accepted: false, reason: "ask_user.respond answer must be a string or null" };
|
|
71657
|
+
}
|
|
71658
|
+
const text = typeof answer === "string" ? answer.trim() : null;
|
|
71659
|
+
return { accepted: bridge.respond(requestId, text && text.length > 0 ? text : null) };
|
|
71660
|
+
}
|
|
71661
|
+
var init_askUserBridge = __esm({
|
|
71662
|
+
"src/cli/serve/askUserBridge.ts"() {
|
|
71663
|
+
"use strict";
|
|
71664
|
+
init_askUserTimeout();
|
|
71129
71665
|
}
|
|
71130
71666
|
});
|
|
71131
71667
|
|
|
@@ -71242,7 +71778,7 @@ function resolveTurnLspProvider(services) {
|
|
|
71242
71778
|
const candidate = services?.lspManager;
|
|
71243
71779
|
return candidate instanceof LspManager ? candidate : void 0;
|
|
71244
71780
|
}
|
|
71245
|
-
function createCliRunTurn(onPermissionAsk) {
|
|
71781
|
+
function createCliRunTurn(onPermissionAsk, onAskUser) {
|
|
71246
71782
|
let streamPromise = null;
|
|
71247
71783
|
const ensureStream = () => {
|
|
71248
71784
|
if (!streamPromise) {
|
|
@@ -71269,6 +71805,7 @@ function createCliRunTurn(onPermissionAsk) {
|
|
|
71269
71805
|
const { provider, model, stream } = await ensureStream();
|
|
71270
71806
|
const opts = bindHarnessTurnOptions(input, deps.session.workspaceRoot);
|
|
71271
71807
|
if (onPermissionAsk) opts.onPermissionAsk = onPermissionAsk;
|
|
71808
|
+
if (onAskUser) opts.onAskUser = onAskUser;
|
|
71272
71809
|
applyTurnPermissionPreset(input);
|
|
71273
71810
|
const lspProvider = resolveTurnLspProvider(deps.services);
|
|
71274
71811
|
const exitCode = await dispatchHeadlessTurn(
|
|
@@ -71304,6 +71841,7 @@ function startHarnessServer(options = {}) {
|
|
|
71304
71841
|
write(JSON.stringify(envelope));
|
|
71305
71842
|
};
|
|
71306
71843
|
const permissionBridge = createServePermissionBridge(write);
|
|
71844
|
+
const askUserBridge = createServeAskUserBridge(write);
|
|
71307
71845
|
const dispatch = async (req) => {
|
|
71308
71846
|
if (typeof req.method !== "string") {
|
|
71309
71847
|
return { id: req.id ?? null, ok: false, error: { code: "bad_request", message: "missing method" } };
|
|
@@ -71317,11 +71855,21 @@ function startHarnessServer(options = {}) {
|
|
|
71317
71855
|
result: servePermissionRespond(permissionBridge, params)
|
|
71318
71856
|
};
|
|
71319
71857
|
}
|
|
71858
|
+
case "ask_user.respond": {
|
|
71859
|
+
return {
|
|
71860
|
+
id: req.id ?? null,
|
|
71861
|
+
ok: true,
|
|
71862
|
+
result: serveAskUserRespond(askUserBridge, params)
|
|
71863
|
+
};
|
|
71864
|
+
}
|
|
71320
71865
|
case "session.create": {
|
|
71321
71866
|
const root = typeof params.workspaceRoot === "string" ? params.workspaceRoot : process.cwd();
|
|
71322
71867
|
const session = server.createSession({
|
|
71323
71868
|
workspaceRoot: root,
|
|
71324
|
-
runTurn: options.runTurn ?? createCliRunTurn(
|
|
71869
|
+
runTurn: options.runTurn ?? createCliRunTurn(
|
|
71870
|
+
asRegistryAskHandler(permissionBridge),
|
|
71871
|
+
askUserBridge.onAskUser
|
|
71872
|
+
)
|
|
71325
71873
|
});
|
|
71326
71874
|
return { id: req.id ?? null, ok: true, result: { sessionId: session.id, workspaceRoot: session.workspaceRoot } };
|
|
71327
71875
|
}
|
|
@@ -71475,6 +72023,7 @@ var init_harnessServer = __esm({
|
|
|
71475
72023
|
init_policyGate();
|
|
71476
72024
|
init_policyLoadMode();
|
|
71477
72025
|
init_permissionBridge();
|
|
72026
|
+
init_askUserBridge();
|
|
71478
72027
|
init_spineLockSweep();
|
|
71479
72028
|
}
|
|
71480
72029
|
});
|
|
@@ -72517,7 +73066,12 @@ function readPackageJson4() {
|
|
|
72517
73066
|
}
|
|
72518
73067
|
}
|
|
72519
73068
|
function getGlobalPrefix() {
|
|
72520
|
-
|
|
73069
|
+
const fromNpm = tryExec("npm prefix -g");
|
|
73070
|
+
if (fromNpm) return fromNpm;
|
|
73071
|
+
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
73072
|
+
}
|
|
73073
|
+
function isSourceCheckout() {
|
|
73074
|
+
return existsSync62(path95.join(packageRoot, "src", "cli", "main.ts")) && existsSync62(path95.join(packageRoot, "apps", "desktop", "package.json"));
|
|
72521
73075
|
}
|
|
72522
73076
|
function checkShim(pkgName) {
|
|
72523
73077
|
const prefix = getGlobalPrefix();
|
|
@@ -72528,6 +73082,14 @@ function checkShim(pkgName) {
|
|
|
72528
73082
|
const shimName = isWin ? "zelari-code.cmd" : "zelari-code";
|
|
72529
73083
|
const shimPath = path95.join(prefix, shimName);
|
|
72530
73084
|
if (!existsSync62(shimPath)) {
|
|
73085
|
+
const localBin = path95.join(packageRoot, "bin", "zelari-code.js");
|
|
73086
|
+
if (isSourceCheckout() && existsSync62(localBin)) {
|
|
73087
|
+
return WARN(
|
|
73088
|
+
`global shim not found at ${shimPath}
|
|
73089
|
+
source checkout \u2014 using ${localBin}
|
|
73090
|
+
optional: npm install -g ${pkgName}@latest --force`
|
|
73091
|
+
);
|
|
73092
|
+
}
|
|
72531
73093
|
return FAIL(
|
|
72532
73094
|
`shim not found at ${shimPath}
|
|
72533
73095
|
fix: npm install -g ${pkgName}@latest --force`
|
|
@@ -72922,16 +73484,15 @@ __export(fixPath_exports, {
|
|
|
72922
73484
|
});
|
|
72923
73485
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
72924
73486
|
function getGlobalPrefix2() {
|
|
72925
|
-
|
|
72926
|
-
|
|
72927
|
-
|
|
72928
|
-
|
|
72929
|
-
|
|
72930
|
-
|
|
72931
|
-
|
|
72932
|
-
|
|
72933
|
-
|
|
72934
|
-
})();
|
|
73487
|
+
try {
|
|
73488
|
+
const fromNpm = spawnSync3("npm", ["prefix", "-g"], {
|
|
73489
|
+
encoding: "utf8",
|
|
73490
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
73491
|
+
}).stdout?.trim() ?? "";
|
|
73492
|
+
if (fromNpm) return fromNpm;
|
|
73493
|
+
} catch {
|
|
73494
|
+
}
|
|
73495
|
+
return (process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX || "").trim();
|
|
72935
73496
|
}
|
|
72936
73497
|
function powershell(script) {
|
|
72937
73498
|
try {
|
|
@@ -76570,22 +77131,7 @@ init_spineTelemetry();
|
|
|
76570
77131
|
|
|
76571
77132
|
// src/cli/hooks/permissionPicker.ts
|
|
76572
77133
|
init_toolPermissions();
|
|
76573
|
-
|
|
76574
|
-
// src/cli/hooks/askUserTimeout.ts
|
|
76575
|
-
function askUserTimeoutMs() {
|
|
76576
|
-
const raw = process.env.ZELARI_ASK_USER_TIMEOUT_MS?.trim();
|
|
76577
|
-
if (!raw) return 3e5;
|
|
76578
|
-
const n = Number.parseInt(raw, 10);
|
|
76579
|
-
if (!Number.isFinite(n) || n < 0) return 3e5;
|
|
76580
|
-
return n;
|
|
76581
|
-
}
|
|
76582
|
-
function armPickerTimeout(onFire, ms) {
|
|
76583
|
-
if (ms <= 0) return () => void 0;
|
|
76584
|
-
const id3 = setTimeout(onFire, ms);
|
|
76585
|
-
return () => clearTimeout(id3);
|
|
76586
|
-
}
|
|
76587
|
-
|
|
76588
|
-
// src/cli/hooks/permissionPicker.ts
|
|
77134
|
+
init_askUserTimeout();
|
|
76589
77135
|
function createPermissionAskHandler(opts) {
|
|
76590
77136
|
const { setPicker: setPicker2, appendSystem: appendSystem2 } = opts;
|
|
76591
77137
|
return (req) => new Promise((resolve9) => {
|
|
@@ -76678,6 +77224,7 @@ ${detail}${note}${claimsBlock}
|
|
|
76678
77224
|
}
|
|
76679
77225
|
|
|
76680
77226
|
// src/cli/hooks/useChatTurn.ts
|
|
77227
|
+
init_askUserTimeout();
|
|
76681
77228
|
init_toolPermissions();
|
|
76682
77229
|
init_skills2();
|
|
76683
77230
|
init_fileStateStore();
|
|
@@ -78577,6 +79124,7 @@ async function runZelariMissionInTui(userMessage, deps, emit) {
|
|
|
78577
79124
|
const hook = await runPostCouncilHook2(workspaceCtx, {
|
|
78578
79125
|
runMode: "implementation",
|
|
78579
79126
|
userMessage,
|
|
79127
|
+
sessionId: deps.sessionId,
|
|
78580
79128
|
synthesisText: synthesisText || void 0,
|
|
78581
79129
|
degradedRun: d.degraded,
|
|
78582
79130
|
degradedReasons: d.reasons
|
|
@@ -78606,6 +79154,7 @@ init_permissionBroker();
|
|
|
78606
79154
|
init_brokerHandlers();
|
|
78607
79155
|
import { useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
78608
79156
|
init_messageHelpers();
|
|
79157
|
+
init_askUserTimeout();
|
|
78609
79158
|
function usePermissionBroker(opts) {
|
|
78610
79159
|
const { setPicker: setPicker2, setMessages } = opts;
|
|
78611
79160
|
const handleRef = useRef5(null);
|