zelari-code 2.0.0-alpha.4 → 2.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli/headless.js.map +1 -1
- package/dist/cli/headlessHistorySeed.test.js +158 -0
- package/dist/cli/headlessHistorySeed.test.js.map +1 -0
- package/dist/cli/headlessSessionEvent.test.js +83 -0
- package/dist/cli/headlessSessionEvent.test.js.map +1 -0
- package/dist/cli/headlessSpine.js +106 -1
- package/dist/cli/headlessSpine.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +58 -7
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.js +38 -3
- package/dist/cli/kraken/verificationBridge.js.map +1 -1
- package/dist/cli/kraken/verificationBridge.session.test.js +104 -0
- package/dist/cli/kraken/verificationBridge.session.test.js.map +1 -0
- package/dist/cli/kraken/verificationBridge.test.js +31 -1
- package/dist/cli/kraken/verificationBridge.test.js.map +1 -1
- package/dist/cli/legacyContextIsolation.test.js +64 -0
- package/dist/cli/legacyContextIsolation.test.js.map +1 -0
- package/dist/cli/main.bundled.js +853 -580
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/providerConfig.js +58 -49
- package/dist/cli/providerConfig.js.map +1 -1
- package/dist/cli/providerConfig.test.js +85 -0
- package/dist/cli/providerConfig.test.js.map +1 -0
- package/dist/cli/runHeadless.js +57 -45
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/sessionManager.js +7 -0
- package/dist/cli/sessionManager.js.map +1 -1
- package/dist/cli/sessionReplayInvariant.test.js +187 -0
- package/dist/cli/sessionReplayInvariant.test.js.map +1 -0
- package/dist/cli/sessionSpine.js +42 -0
- package/dist/cli/sessionSpine.js.map +1 -1
- package/package.json +3 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -1939,40 +1939,47 @@ import os3 from "node:os";
|
|
|
1939
1939
|
function getProviderConfigPath() {
|
|
1940
1940
|
return process.env.ANATHEMA_PROVIDER_CONFIG_FILE ?? path4.join(os3.homedir(), ".tmp", "zelari-code", "provider.json");
|
|
1941
1941
|
}
|
|
1942
|
-
function
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
|
|
1952
|
-
stored = {
|
|
1953
|
-
activeProviderId: parsed.activeProviderId,
|
|
1954
|
-
modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
|
|
1955
|
-
thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
|
|
1956
|
-
customEndpoints: mergeCustomEndpoints(parsed.customEndpoints),
|
|
1957
|
-
krakenVerifier: mergeKrakenVerifier(parsed.krakenVerifier)
|
|
1958
|
-
};
|
|
1959
|
-
}
|
|
1960
|
-
} catch {
|
|
1961
|
-
}
|
|
1942
|
+
function mergeStoredProviderConfig(parsed) {
|
|
1943
|
+
if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
|
|
1944
|
+
return {
|
|
1945
|
+
activeProviderId: parsed.activeProviderId,
|
|
1946
|
+
modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
|
|
1947
|
+
thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
|
|
1948
|
+
customEndpoints: mergeCustomEndpoints(parsed.customEndpoints),
|
|
1949
|
+
krakenVerifier: mergeKrakenVerifier(parsed.krakenVerifier)
|
|
1950
|
+
};
|
|
1962
1951
|
}
|
|
1963
|
-
|
|
1952
|
+
return cloneDefaults();
|
|
1953
|
+
}
|
|
1954
|
+
function cloneDefaults() {
|
|
1955
|
+
return {
|
|
1964
1956
|
...DEFAULTS,
|
|
1965
1957
|
modelByProvider: { ...DEFAULTS.modelByProvider },
|
|
1966
1958
|
thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
|
|
1967
1959
|
customEndpoints: { ...DEFAULTS.customEndpoints }
|
|
1968
1960
|
};
|
|
1961
|
+
}
|
|
1962
|
+
function applyEnvOverrides(config2) {
|
|
1963
|
+
const envActive = process.env.ANATHEMA_ACTIVE_PROVIDER;
|
|
1964
|
+
const envModel = process.env.OPENAI_MODEL;
|
|
1969
1965
|
if (envActive && PROVIDERS.some((p3) => p3.id === envActive)) {
|
|
1970
|
-
|
|
1966
|
+
config2.activeProviderId = envActive;
|
|
1971
1967
|
}
|
|
1972
1968
|
if (envModel && envModel.trim().length > 0) {
|
|
1973
|
-
|
|
1969
|
+
config2.modelByProvider[config2.activeProviderId] = envModel;
|
|
1974
1970
|
}
|
|
1975
|
-
return
|
|
1971
|
+
return config2;
|
|
1972
|
+
}
|
|
1973
|
+
function getProviderConfig() {
|
|
1974
|
+
const file2 = getProviderConfigPath();
|
|
1975
|
+
let parsed = null;
|
|
1976
|
+
if (existsSync3(file2)) {
|
|
1977
|
+
try {
|
|
1978
|
+
parsed = JSON.parse(readFileSync3(file2, "utf-8"));
|
|
1979
|
+
} catch {
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return applyEnvOverrides(mergeStoredProviderConfig(parsed));
|
|
1976
1983
|
}
|
|
1977
1984
|
function writeProviderConfig(config2) {
|
|
1978
1985
|
const file2 = getProviderConfigPath();
|
|
@@ -2105,25 +2112,12 @@ function getActiveModel() {
|
|
|
2105
2112
|
}
|
|
2106
2113
|
async function loadProviderConfig() {
|
|
2107
2114
|
const file2 = getProviderConfigPath();
|
|
2115
|
+
let parsed = null;
|
|
2108
2116
|
try {
|
|
2109
|
-
|
|
2110
|
-
const parsed = JSON.parse(raw);
|
|
2111
|
-
if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
|
|
2112
|
-
return {
|
|
2113
|
-
activeProviderId: parsed.activeProviderId,
|
|
2114
|
-
modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
|
|
2115
|
-
thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
|
|
2116
|
-
customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
|
|
2117
|
-
};
|
|
2118
|
-
}
|
|
2117
|
+
parsed = JSON.parse(await fs2.readFile(file2, "utf-8"));
|
|
2119
2118
|
} catch {
|
|
2120
2119
|
}
|
|
2121
|
-
return
|
|
2122
|
-
...DEFAULTS,
|
|
2123
|
-
modelByProvider: { ...DEFAULTS.modelByProvider },
|
|
2124
|
-
thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
|
|
2125
|
-
customEndpoints: { ...DEFAULTS.customEndpoints }
|
|
2126
|
-
};
|
|
2120
|
+
return applyEnvOverrides(mergeStoredProviderConfig(parsed));
|
|
2127
2121
|
}
|
|
2128
2122
|
var DEFAULTS;
|
|
2129
2123
|
var init_providerConfig = __esm({
|
|
@@ -28387,6 +28381,23 @@ var init_modelSurface = __esm({
|
|
|
28387
28381
|
}
|
|
28388
28382
|
});
|
|
28389
28383
|
|
|
28384
|
+
// packages/core/dist/session/agentAdapter.js
|
|
28385
|
+
function derivedToAgentMessages(messages) {
|
|
28386
|
+
const out = [];
|
|
28387
|
+
for (const m of messages) {
|
|
28388
|
+
const agent = { role: m.role, content: m.content };
|
|
28389
|
+
if (m.toolCallId !== void 0)
|
|
28390
|
+
agent.toolCallId = m.toolCallId;
|
|
28391
|
+
out.push(agent);
|
|
28392
|
+
}
|
|
28393
|
+
return out;
|
|
28394
|
+
}
|
|
28395
|
+
var init_agentAdapter = __esm({
|
|
28396
|
+
"packages/core/dist/session/agentAdapter.js"() {
|
|
28397
|
+
"use strict";
|
|
28398
|
+
}
|
|
28399
|
+
});
|
|
28400
|
+
|
|
28390
28401
|
// packages/core/dist/session/writer.js
|
|
28391
28402
|
import { promises as fs9 } from "node:fs";
|
|
28392
28403
|
import path14 from "node:path";
|
|
@@ -28841,6 +28852,7 @@ var init_session = __esm({
|
|
|
28841
28852
|
"use strict";
|
|
28842
28853
|
init_types8();
|
|
28843
28854
|
init_modelSurface();
|
|
28855
|
+
init_agentAdapter();
|
|
28844
28856
|
init_writer();
|
|
28845
28857
|
init_replay();
|
|
28846
28858
|
init_store();
|
|
@@ -29633,6 +29645,16 @@ function evaluateCompletion(criteria, results, policy = STRICT_ALL_POLICY) {
|
|
|
29633
29645
|
});
|
|
29634
29646
|
continue;
|
|
29635
29647
|
}
|
|
29648
|
+
const admissible = policy.admissibleTiers;
|
|
29649
|
+
if (admissible && !result.evidence.some((e) => admissible.includes(e.tier))) {
|
|
29650
|
+
const tiers = [...new Set(result.evidence.map((e) => e.tier))].join(", ");
|
|
29651
|
+
unsatisfied.push({
|
|
29652
|
+
id,
|
|
29653
|
+
status: "unknown",
|
|
29654
|
+
reason: `pass with inadmissible evidence tiers only (${tiers}) \u2014 not acceptable for completion`
|
|
29655
|
+
});
|
|
29656
|
+
continue;
|
|
29657
|
+
}
|
|
29636
29658
|
satisfied.push(id);
|
|
29637
29659
|
}
|
|
29638
29660
|
const verdict = unsatisfied.length === 0 ? "PASS" : unsatisfied.some((u) => u.status === "fail") ? "REPAIR_REQUIRED" : "BLOCKED";
|
|
@@ -29644,15 +29666,113 @@ function evaluateCompletion(criteria, results, policy = STRICT_ALL_POLICY) {
|
|
|
29644
29666
|
summary: verdict === "PASS" ? `complete: ${satisfied.length}/${ids.length} required criteria pass with evidence` : `incomplete (${verdict}): ${unsatisfied.map((u) => `${u.id}=${u.status}`).join(", ")}`
|
|
29645
29667
|
};
|
|
29646
29668
|
}
|
|
29647
|
-
var STRICT_ALL_POLICY, strictBuildGate;
|
|
29669
|
+
var STRICT_ALL_POLICY, DETERMINISTIC_EVIDENCE_TIERS, STRICT_BUILD_POLICY, strictBuildGate;
|
|
29648
29670
|
var init_completionPolicy = __esm({
|
|
29649
29671
|
"packages/core/dist/verification/completionPolicy.js"() {
|
|
29650
29672
|
"use strict";
|
|
29651
29673
|
STRICT_ALL_POLICY = { mode: "strict", required: "*" };
|
|
29674
|
+
DETERMINISTIC_EVIDENCE_TIERS = [
|
|
29675
|
+
"tool-output",
|
|
29676
|
+
"command-output",
|
|
29677
|
+
"fs-observation",
|
|
29678
|
+
"human"
|
|
29679
|
+
];
|
|
29680
|
+
STRICT_BUILD_POLICY = {
|
|
29681
|
+
mode: "strict",
|
|
29682
|
+
required: "*",
|
|
29683
|
+
admissibleTiers: DETERMINISTIC_EVIDENCE_TIERS
|
|
29684
|
+
};
|
|
29652
29685
|
strictBuildGate = evaluateCompletion;
|
|
29653
29686
|
}
|
|
29654
29687
|
});
|
|
29655
29688
|
|
|
29689
|
+
// packages/core/dist/verification/sessionEvidence.js
|
|
29690
|
+
function asString2(v) {
|
|
29691
|
+
return typeof v === "string" ? v : null;
|
|
29692
|
+
}
|
|
29693
|
+
function asStringArray(v) {
|
|
29694
|
+
if (!Array.isArray(v))
|
|
29695
|
+
return [];
|
|
29696
|
+
return v.filter((x) => typeof x === "string");
|
|
29697
|
+
}
|
|
29698
|
+
function asUnsatisfied(v) {
|
|
29699
|
+
if (!Array.isArray(v))
|
|
29700
|
+
return [];
|
|
29701
|
+
const out = [];
|
|
29702
|
+
for (const item of v) {
|
|
29703
|
+
if (!item || typeof item !== "object")
|
|
29704
|
+
continue;
|
|
29705
|
+
const rec = item;
|
|
29706
|
+
const id = asString2(rec.id);
|
|
29707
|
+
if (id === null)
|
|
29708
|
+
continue;
|
|
29709
|
+
out.push({
|
|
29710
|
+
id,
|
|
29711
|
+
status: asString2(rec.status) ?? "unknown",
|
|
29712
|
+
reason: asString2(rec.reason) ?? ""
|
|
29713
|
+
});
|
|
29714
|
+
}
|
|
29715
|
+
return out;
|
|
29716
|
+
}
|
|
29717
|
+
function parseVerificationRunPayload(ev) {
|
|
29718
|
+
const data = ev.data;
|
|
29719
|
+
if (!data || typeof data !== "object")
|
|
29720
|
+
return null;
|
|
29721
|
+
const rec = data;
|
|
29722
|
+
const verdictRaw = asString2(rec.verdict);
|
|
29723
|
+
const verdict = verdictRaw !== null && VERDICTS.has(verdictRaw) ? verdictRaw : "unknown";
|
|
29724
|
+
const evidence = rec.evidence && typeof rec.evidence === "object" ? rec.evidence : null;
|
|
29725
|
+
const satisfied = asStringArray(evidence?.satisfied);
|
|
29726
|
+
const unsatisfied = asUnsatisfied(evidence?.unsatisfied);
|
|
29727
|
+
const completeRaw = evidence?.complete;
|
|
29728
|
+
return {
|
|
29729
|
+
seq: ev.seq,
|
|
29730
|
+
ts: ev.ts,
|
|
29731
|
+
engine: asString2(rec.engine),
|
|
29732
|
+
strict: rec.strict === true,
|
|
29733
|
+
verdict,
|
|
29734
|
+
satisfied,
|
|
29735
|
+
unsatisfied,
|
|
29736
|
+
evidenceComplete: typeof completeRaw === "boolean" ? completeRaw : verdict === "PASS" && satisfied.length > 0 && unsatisfied.length === 0,
|
|
29737
|
+
summary: asString2(rec.summary) ?? ""
|
|
29738
|
+
};
|
|
29739
|
+
}
|
|
29740
|
+
function lastVerificationRun(events) {
|
|
29741
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
29742
|
+
const ev = events[i];
|
|
29743
|
+
if (ev.kind !== "verification.run")
|
|
29744
|
+
continue;
|
|
29745
|
+
const snap = parseVerificationRunPayload(ev);
|
|
29746
|
+
if (snap)
|
|
29747
|
+
return snap;
|
|
29748
|
+
}
|
|
29749
|
+
return null;
|
|
29750
|
+
}
|
|
29751
|
+
function snapshotToCompletionEvaluation(snap) {
|
|
29752
|
+
if (!snap.strict)
|
|
29753
|
+
return null;
|
|
29754
|
+
const unsatisfied = snap.unsatisfied.map((u) => ({
|
|
29755
|
+
id: u.id,
|
|
29756
|
+
status: u.status === "fail" || u.status === "missing" ? u.status : "unknown",
|
|
29757
|
+
reason: u.reason
|
|
29758
|
+
}));
|
|
29759
|
+
const verdict = snap.verdict === "PASS" || snap.verdict === "REPAIR_REQUIRED" || snap.verdict === "BLOCKED" ? snap.verdict : "BLOCKED";
|
|
29760
|
+
return {
|
|
29761
|
+
verdict,
|
|
29762
|
+
satisfied: [...snap.satisfied],
|
|
29763
|
+
unsatisfied,
|
|
29764
|
+
evidenceComplete: snap.evidenceComplete && unsatisfied.length === 0 && verdict === "PASS",
|
|
29765
|
+
summary: snap.summary
|
|
29766
|
+
};
|
|
29767
|
+
}
|
|
29768
|
+
var VERDICTS;
|
|
29769
|
+
var init_sessionEvidence = __esm({
|
|
29770
|
+
"packages/core/dist/verification/sessionEvidence.js"() {
|
|
29771
|
+
"use strict";
|
|
29772
|
+
VERDICTS = /* @__PURE__ */ new Set(["PASS", "REPAIR_REQUIRED", "BLOCKED"]);
|
|
29773
|
+
}
|
|
29774
|
+
});
|
|
29775
|
+
|
|
29656
29776
|
// packages/core/dist/verification/criteriaPack.v1.js
|
|
29657
29777
|
function codingCriteriaPack(options = {}) {
|
|
29658
29778
|
const timeoutMs = options.commandTimeoutMs ?? 6e5;
|
|
@@ -29942,6 +30062,7 @@ var init_verification2 = __esm({
|
|
|
29942
30062
|
init_types9();
|
|
29943
30063
|
init_engine();
|
|
29944
30064
|
init_completionPolicy();
|
|
30065
|
+
init_sessionEvidence();
|
|
29945
30066
|
init_criteriaPack_v1();
|
|
29946
30067
|
init_metrics();
|
|
29947
30068
|
init_verifier();
|
|
@@ -30033,6 +30154,7 @@ __export(dist_exports, {
|
|
|
30033
30154
|
DESIGN_PHASE_MODE_BANNER: () => DESIGN_PHASE_MODE_BANNER,
|
|
30034
30155
|
DESIGN_PHASE_REQUIREMENTS: () => DESIGN_PHASE_REQUIREMENTS,
|
|
30035
30156
|
DESIGN_PHASE_REQUIREMENT_SETS: () => DESIGN_PHASE_REQUIREMENT_SETS,
|
|
30157
|
+
DETERMINISTIC_EVIDENCE_TIERS: () => DETERMINISTIC_EVIDENCE_TIERS,
|
|
30036
30158
|
DOOM_LOOP_THRESHOLD: () => DOOM_LOOP_THRESHOLD,
|
|
30037
30159
|
DeterministicCheckSchema: () => DeterministicCheckSchema,
|
|
30038
30160
|
EXPERIMENTAL_FLAGS: () => EXPERIMENTAL_FLAGS,
|
|
@@ -30088,6 +30210,7 @@ __export(dist_exports, {
|
|
|
30088
30210
|
SINGLE_AGENT_IDENTITY_MODULE: () => SINGLE_AGENT_IDENTITY_MODULE,
|
|
30089
30211
|
SKILL_CATALOG: () => SKILL_CATALOG,
|
|
30090
30212
|
STRICT_ALL_POLICY: () => STRICT_ALL_POLICY,
|
|
30213
|
+
STRICT_BUILD_POLICY: () => STRICT_BUILD_POLICY,
|
|
30091
30214
|
STRUCTURED_REASONING_DIRECTIVE: () => STRUCTURED_REASONING_DIRECTIVE,
|
|
30092
30215
|
ScriptRunner: () => ScriptRunner,
|
|
30093
30216
|
SessionActorSchema: () => SessionActorSchema,
|
|
@@ -30170,6 +30293,7 @@ __export(dist_exports, {
|
|
|
30170
30293
|
defaultPersonaParse: () => defaultPersonaParse,
|
|
30171
30294
|
deriveMessages: () => deriveMessages,
|
|
30172
30295
|
deriveMissionState: () => deriveMissionState,
|
|
30296
|
+
derivedToAgentMessages: () => derivedToAgentMessages,
|
|
30173
30297
|
detectAssistantTextLoop: () => detectAssistantTextLoop,
|
|
30174
30298
|
detectAssistantTextLoopWindow: () => detectAssistantTextLoopWindow,
|
|
30175
30299
|
detectDegradedRun: () => detectDegradedRun,
|
|
@@ -30242,6 +30366,7 @@ __export(dist_exports, {
|
|
|
30242
30366
|
isVerifyToolCheckSkipped: () => isVerifyToolCheckSkipped,
|
|
30243
30367
|
jaccardSimilarity: () => jaccardSimilarity,
|
|
30244
30368
|
jsonBytes: () => jsonBytes,
|
|
30369
|
+
lastVerificationRun: () => lastVerificationRun,
|
|
30245
30370
|
lineageOf: () => lineageOf,
|
|
30246
30371
|
lintSynthesisHonesty: () => lintSynthesisHonesty,
|
|
30247
30372
|
listCodingSkills: () => listCodingSkills,
|
|
@@ -30263,6 +30388,7 @@ __export(dist_exports, {
|
|
|
30263
30388
|
parseProjectRootFromWorkspaceContext: () => parseProjectRootFromWorkspaceContext,
|
|
30264
30389
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
30265
30390
|
parseThinking: () => parseThinking,
|
|
30391
|
+
parseVerificationRunPayload: () => parseVerificationRunPayload,
|
|
30266
30392
|
parseVerificationTable: () => parseVerificationTable,
|
|
30267
30393
|
parseVerifyVerdict: () => parseVerifyVerdict,
|
|
30268
30394
|
pathsOverlap: () => pathsOverlap,
|
|
@@ -30312,6 +30438,7 @@ __export(dist_exports, {
|
|
|
30312
30438
|
sha256Hex: () => sha256Hex,
|
|
30313
30439
|
shouldRetryMember: () => shouldRetryMember,
|
|
30314
30440
|
slugify: () => slugify2,
|
|
30441
|
+
snapshotToCompletionEvaluation: () => snapshotToCompletionEvaluation,
|
|
30315
30442
|
specificityFromAssumptions: () => specificityFromAssumptions,
|
|
30316
30443
|
stableStringify: () => stableStringify,
|
|
30317
30444
|
strictBuildGate: () => strictBuildGate,
|
|
@@ -30681,6 +30808,7 @@ var init_sessionSpine = __esm({
|
|
|
30681
30808
|
"use strict";
|
|
30682
30809
|
init_session();
|
|
30683
30810
|
init_session();
|
|
30811
|
+
init_verification2();
|
|
30684
30812
|
MAX_STREAM_BUFFERS = 32;
|
|
30685
30813
|
SessionSpineMirror = class _SessionSpineMirror {
|
|
30686
30814
|
constructor(sessionId2, options) {
|
|
@@ -30740,6 +30868,47 @@ var init_sessionSpine = __esm({
|
|
|
30740
30868
|
userMessage(text) {
|
|
30741
30869
|
void this.append({ kind: "user.message", actor: ACTOR_USER, data: { text } });
|
|
30742
30870
|
}
|
|
30871
|
+
/**
|
|
30872
|
+
* Log an assistant message outside the streaming path — legacy
|
|
30873
|
+
* `--history` import (Exit-1/E1.2). Same event shape the message_end
|
|
30874
|
+
* coalescer emits, so deriveMessages() treats both identically.
|
|
30875
|
+
*/
|
|
30876
|
+
assistantMessage(text, extra) {
|
|
30877
|
+
void this.append({
|
|
30878
|
+
kind: "assistant.message",
|
|
30879
|
+
actor: ACTOR_AGENT,
|
|
30880
|
+
data: { text, ...extra }
|
|
30881
|
+
});
|
|
30882
|
+
}
|
|
30883
|
+
/** Await all pending appends (import → derive read-back needs this). */
|
|
30884
|
+
async flush() {
|
|
30885
|
+
await this.chain;
|
|
30886
|
+
}
|
|
30887
|
+
/**
|
|
30888
|
+
* Derive prior-turn model context from the on-disk log. Null when the
|
|
30889
|
+
* log is missing/empty — callers decide whether that means "fresh".
|
|
30890
|
+
*/
|
|
30891
|
+
async derivedPriorTurns() {
|
|
30892
|
+
if (this.status !== "active" && this.status !== "closed") return null;
|
|
30893
|
+
const report = await readSessionLog(
|
|
30894
|
+
path21.join(this.sessionsDir, this.sessionId, "events.jsonl")
|
|
30895
|
+
).catch(() => null);
|
|
30896
|
+
if (!report || report.events.length === 0) return null;
|
|
30897
|
+
return deriveMessages(report.events);
|
|
30898
|
+
}
|
|
30899
|
+
/**
|
|
30900
|
+
* E2.1 (ADR-0023 × ADR-0021): last recognizable strict verification record
|
|
30901
|
+
* in this session's log — the completion verdict is reconstructible from
|
|
30902
|
+
* the spine alone (null when degraded/disabled or no record).
|
|
30903
|
+
*/
|
|
30904
|
+
async lastVerificationRun() {
|
|
30905
|
+
if (this.status !== "active" && this.status !== "closed") return null;
|
|
30906
|
+
const report = await readSessionLog(
|
|
30907
|
+
path21.join(this.sessionsDir, this.sessionId, "events.jsonl")
|
|
30908
|
+
).catch(() => null);
|
|
30909
|
+
if (!report) return null;
|
|
30910
|
+
return lastVerificationRun(report.events);
|
|
30911
|
+
}
|
|
30743
30912
|
/** Mirror one BrainEvent (coalescing message deltas until message_end). */
|
|
30744
30913
|
mirrorBrainEvent(ev) {
|
|
30745
30914
|
if (this.status !== "active" || !this.writer) return;
|
|
@@ -39550,6 +39719,537 @@ var init_toolRegistry = __esm({
|
|
|
39550
39719
|
}
|
|
39551
39720
|
});
|
|
39552
39721
|
|
|
39722
|
+
// src/cli/phase.ts
|
|
39723
|
+
var phase_exports = {};
|
|
39724
|
+
__export(phase_exports, {
|
|
39725
|
+
PHASES: () => PHASES,
|
|
39726
|
+
PLAN_ALLOWED_WRITE_TOOLS: () => PLAN_ALLOWED_WRITE_TOOLS,
|
|
39727
|
+
PLAN_BLOCKED_TOOLS: () => PLAN_BLOCKED_TOOLS,
|
|
39728
|
+
describePhase: () => describePhase,
|
|
39729
|
+
nextPhase: () => nextPhase,
|
|
39730
|
+
parsePhase: () => parsePhase
|
|
39731
|
+
});
|
|
39732
|
+
function parsePhase(input) {
|
|
39733
|
+
const v = input.trim().toLowerCase();
|
|
39734
|
+
return PHASES.includes(v) ? v : null;
|
|
39735
|
+
}
|
|
39736
|
+
function nextPhase(current) {
|
|
39737
|
+
return current === "plan" ? "build" : "plan";
|
|
39738
|
+
}
|
|
39739
|
+
function describePhase(phase2) {
|
|
39740
|
+
switch (phase2) {
|
|
39741
|
+
case "plan":
|
|
39742
|
+
return "plan \u2014 explore & design only (no project writes; plan files allowed)";
|
|
39743
|
+
default:
|
|
39744
|
+
return "build \u2014 implement with full tools";
|
|
39745
|
+
}
|
|
39746
|
+
}
|
|
39747
|
+
var PHASES, PLAN_ALLOWED_WRITE_TOOLS, PLAN_BLOCKED_TOOLS;
|
|
39748
|
+
var init_phase = __esm({
|
|
39749
|
+
"src/cli/phase.ts"() {
|
|
39750
|
+
"use strict";
|
|
39751
|
+
PHASES = ["plan", "build"];
|
|
39752
|
+
PLAN_ALLOWED_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
39753
|
+
// Workspace plan/docs — intentional plan-mode outputs
|
|
39754
|
+
"createPlan",
|
|
39755
|
+
"createTask",
|
|
39756
|
+
"updateTask",
|
|
39757
|
+
"createMilestone",
|
|
39758
|
+
"createDocument",
|
|
39759
|
+
"createDecision",
|
|
39760
|
+
"linkDocuments"
|
|
39761
|
+
// Soft writes that only touch .zelari / plan paths are still gated in
|
|
39762
|
+
// toolRegistry by path when needed; write_file/edit_file stay DENIED.
|
|
39763
|
+
]);
|
|
39764
|
+
PLAN_BLOCKED_TOOLS = /* @__PURE__ */ new Set([
|
|
39765
|
+
"write_file",
|
|
39766
|
+
"edit_file",
|
|
39767
|
+
"apply_diff",
|
|
39768
|
+
"bash"
|
|
39769
|
+
]);
|
|
39770
|
+
}
|
|
39771
|
+
});
|
|
39772
|
+
|
|
39773
|
+
// src/cli/mode.ts
|
|
39774
|
+
function nextMode(current) {
|
|
39775
|
+
const i = MODES.indexOf(current);
|
|
39776
|
+
return MODES[(i + 1) % MODES.length] ?? "kraken";
|
|
39777
|
+
}
|
|
39778
|
+
function parseMode(input) {
|
|
39779
|
+
const v = input.trim().toLowerCase();
|
|
39780
|
+
if (MODES.includes(v)) return v;
|
|
39781
|
+
return MODE_ALIASES[v] ?? null;
|
|
39782
|
+
}
|
|
39783
|
+
function describeMode(mode) {
|
|
39784
|
+
switch (mode) {
|
|
39785
|
+
case "council":
|
|
39786
|
+
return "council \u2014 multi-member plan/design (Caronte\u2026Lucifero; build needs ZELARI_COUNCIL_CAN_BUILD=1)";
|
|
39787
|
+
case "zelari":
|
|
39788
|
+
return "zelari \u2014 mission: plan@council \u2192 build@kraken (legacy: ZELARI_BUILD_VIA_AGENT=0)";
|
|
39789
|
+
default:
|
|
39790
|
+
return "kraken \u2014 super-agent lead (spawns explore/general/verify tentacles; default implementer)";
|
|
39791
|
+
}
|
|
39792
|
+
}
|
|
39793
|
+
var MODES, MODE_ALIASES;
|
|
39794
|
+
var init_mode = __esm({
|
|
39795
|
+
"src/cli/mode.ts"() {
|
|
39796
|
+
"use strict";
|
|
39797
|
+
MODES = ["kraken", "council", "zelari"];
|
|
39798
|
+
MODE_ALIASES = {
|
|
39799
|
+
agent: "kraken",
|
|
39800
|
+
single: "kraken"
|
|
39801
|
+
};
|
|
39802
|
+
}
|
|
39803
|
+
});
|
|
39804
|
+
|
|
39805
|
+
// src/cli/headless.ts
|
|
39806
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
39807
|
+
function defaultProfileForMode(mode) {
|
|
39808
|
+
switch (mode) {
|
|
39809
|
+
case "council":
|
|
39810
|
+
return "council/v1";
|
|
39811
|
+
case "zelari":
|
|
39812
|
+
return "mission/v1";
|
|
39813
|
+
default:
|
|
39814
|
+
return "kraken/v1";
|
|
39815
|
+
}
|
|
39816
|
+
}
|
|
39817
|
+
function parseHeadlessFlags(argv) {
|
|
39818
|
+
if (!argv.includes("--headless")) {
|
|
39819
|
+
return { options: null };
|
|
39820
|
+
}
|
|
39821
|
+
let task;
|
|
39822
|
+
let output = "json";
|
|
39823
|
+
let mode = "kraken";
|
|
39824
|
+
let phase2 = "build";
|
|
39825
|
+
let modeExplicit = false;
|
|
39826
|
+
let councilFlag = false;
|
|
39827
|
+
let provider;
|
|
39828
|
+
let model;
|
|
39829
|
+
let history2;
|
|
39830
|
+
let todos2;
|
|
39831
|
+
let once = false;
|
|
39832
|
+
let profile;
|
|
39833
|
+
let resumeSessionId;
|
|
39834
|
+
let exportSessionPath;
|
|
39835
|
+
let strictDone = false;
|
|
39836
|
+
let krakenGraph;
|
|
39837
|
+
let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
|
|
39838
|
+
let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
|
|
39839
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39840
|
+
const arg = argv[i];
|
|
39841
|
+
if (arg === "--headless") continue;
|
|
39842
|
+
if (arg === "--output") {
|
|
39843
|
+
const next = argv[i + 1];
|
|
39844
|
+
if (next === "json" || next === "plain") {
|
|
39845
|
+
output = next;
|
|
39846
|
+
i++;
|
|
39847
|
+
} else {
|
|
39848
|
+
return {
|
|
39849
|
+
options: null,
|
|
39850
|
+
error: `--output requires 'json' or 'plain', got '${next ?? "(missing)"}'`
|
|
39851
|
+
};
|
|
39852
|
+
}
|
|
39853
|
+
} else if (arg === "--task") {
|
|
39854
|
+
task = argv[i + 1];
|
|
39855
|
+
i++;
|
|
39856
|
+
} else if (arg === "--task-file") {
|
|
39857
|
+
const next = argv[i + 1];
|
|
39858
|
+
if (next) {
|
|
39859
|
+
try {
|
|
39860
|
+
const fromFile = readFileSync22(next, "utf-8");
|
|
39861
|
+
if (fromFile.trim()) task = fromFile;
|
|
39862
|
+
} catch {
|
|
39863
|
+
}
|
|
39864
|
+
}
|
|
39865
|
+
i++;
|
|
39866
|
+
} else if (arg === "--council") {
|
|
39867
|
+
councilFlag = true;
|
|
39868
|
+
} else if (arg === "--mode") {
|
|
39869
|
+
const next = argv[i + 1];
|
|
39870
|
+
const parsed = next ? parseMode(next) : null;
|
|
39871
|
+
if (!parsed) {
|
|
39872
|
+
return {
|
|
39873
|
+
options: null,
|
|
39874
|
+
error: `--mode requires 'kraken', 'council', or 'zelari' (agent=alias), got '${next ?? "(missing)"}'`
|
|
39875
|
+
};
|
|
39876
|
+
}
|
|
39877
|
+
mode = parsed;
|
|
39878
|
+
modeExplicit = true;
|
|
39879
|
+
i++;
|
|
39880
|
+
} else if (arg === "--phase") {
|
|
39881
|
+
const next = argv[i + 1];
|
|
39882
|
+
const parsed = next ? parsePhase(next) : null;
|
|
39883
|
+
if (!parsed) {
|
|
39884
|
+
return {
|
|
39885
|
+
options: null,
|
|
39886
|
+
error: `--phase requires 'plan' or 'build', got '${next ?? "(missing)"}'`
|
|
39887
|
+
};
|
|
39888
|
+
}
|
|
39889
|
+
phase2 = parsed;
|
|
39890
|
+
i++;
|
|
39891
|
+
} else if (arg === "--provider") {
|
|
39892
|
+
provider = argv[i + 1];
|
|
39893
|
+
i++;
|
|
39894
|
+
} else if (arg === "--model") {
|
|
39895
|
+
model = argv[i + 1];
|
|
39896
|
+
i++;
|
|
39897
|
+
} else if (arg === "--history" || arg === "--history-file") {
|
|
39898
|
+
const next = argv[i + 1];
|
|
39899
|
+
if (next) {
|
|
39900
|
+
let raw = null;
|
|
39901
|
+
if (arg === "--history-file") {
|
|
39902
|
+
try {
|
|
39903
|
+
raw = readFileSync22(next, "utf-8");
|
|
39904
|
+
} catch {
|
|
39905
|
+
raw = null;
|
|
39906
|
+
}
|
|
39907
|
+
} else {
|
|
39908
|
+
raw = next;
|
|
39909
|
+
}
|
|
39910
|
+
if (raw) {
|
|
39911
|
+
try {
|
|
39912
|
+
const parsedHist = JSON.parse(raw);
|
|
39913
|
+
if (Array.isArray(parsedHist)) {
|
|
39914
|
+
history2 = parsedHist.filter(
|
|
39915
|
+
(m) => !!m && typeof m === "object" && typeof m.role === "string"
|
|
39916
|
+
).map((m) => {
|
|
39917
|
+
const role = String(m.role);
|
|
39918
|
+
const raw2 = m.content;
|
|
39919
|
+
const content = typeof raw2 === "string" ? raw2 : raw2 == null ? "" : typeof raw2 === "object" ? JSON.stringify(raw2) : String(raw2);
|
|
39920
|
+
const msg = {
|
|
39921
|
+
role,
|
|
39922
|
+
content
|
|
39923
|
+
};
|
|
39924
|
+
if (typeof m.toolCallId === "string") {
|
|
39925
|
+
msg.toolCallId = m.toolCallId;
|
|
39926
|
+
}
|
|
39927
|
+
return msg;
|
|
39928
|
+
}).filter(
|
|
39929
|
+
(m) => m.role === "user" || m.role === "assistant" || m.role === "tool" || m.role === "system"
|
|
39930
|
+
);
|
|
39931
|
+
}
|
|
39932
|
+
} catch {
|
|
39933
|
+
}
|
|
39934
|
+
}
|
|
39935
|
+
i++;
|
|
39936
|
+
}
|
|
39937
|
+
} else if (arg === "--todos") {
|
|
39938
|
+
const next = argv[i + 1];
|
|
39939
|
+
if (next) {
|
|
39940
|
+
try {
|
|
39941
|
+
const parsed = JSON.parse(next);
|
|
39942
|
+
if (Array.isArray(parsed)) {
|
|
39943
|
+
todos2 = parsed.filter(
|
|
39944
|
+
(t) => !!t && typeof t === "object" && typeof t.content === "string"
|
|
39945
|
+
).map((t) => ({
|
|
39946
|
+
id: typeof t.id === "string" ? t.id : void 0,
|
|
39947
|
+
content: String(t.content).slice(0, 500),
|
|
39948
|
+
status: t.status
|
|
39949
|
+
}));
|
|
39950
|
+
}
|
|
39951
|
+
} catch {
|
|
39952
|
+
}
|
|
39953
|
+
i++;
|
|
39954
|
+
}
|
|
39955
|
+
} else if (arg === "--once") {
|
|
39956
|
+
once = true;
|
|
39957
|
+
} else if (arg === "--profile") {
|
|
39958
|
+
const next = argv[i + 1];
|
|
39959
|
+
if (!next || next.startsWith("--")) {
|
|
39960
|
+
return { options: null, error: `--profile requires a profile id (e.g. kraken/v1), got '${next ?? "(missing)"}'` };
|
|
39961
|
+
}
|
|
39962
|
+
try {
|
|
39963
|
+
resolveProfile(next);
|
|
39964
|
+
} catch (err) {
|
|
39965
|
+
return {
|
|
39966
|
+
options: null,
|
|
39967
|
+
error: err instanceof Error ? err.message : String(err)
|
|
39968
|
+
};
|
|
39969
|
+
}
|
|
39970
|
+
profile = next;
|
|
39971
|
+
i++;
|
|
39972
|
+
} else if (arg === "--resume") {
|
|
39973
|
+
const next = argv[i + 1];
|
|
39974
|
+
if (!next || next.startsWith("--")) {
|
|
39975
|
+
return { options: null, error: `--resume requires a session id, got '${next ?? "(missing)"}'` };
|
|
39976
|
+
}
|
|
39977
|
+
resumeSessionId = next;
|
|
39978
|
+
i++;
|
|
39979
|
+
} else if (arg === "--export-session") {
|
|
39980
|
+
const next = argv[i + 1];
|
|
39981
|
+
if (!next || next.startsWith("--")) {
|
|
39982
|
+
return { options: null, error: `--export-session requires a path (or - for stdout), got '${next ?? "(missing)"}'` };
|
|
39983
|
+
}
|
|
39984
|
+
exportSessionPath = next;
|
|
39985
|
+
i++;
|
|
39986
|
+
} else if (arg === "--strict-done") {
|
|
39987
|
+
strictDone = true;
|
|
39988
|
+
} else if (arg === "--kraken-graph") {
|
|
39989
|
+
krakenGraph = argv[i + 1];
|
|
39990
|
+
i++;
|
|
39991
|
+
} else if (arg === "--kraken-graph-file") {
|
|
39992
|
+
const next = argv[i + 1];
|
|
39993
|
+
if (next) {
|
|
39994
|
+
try {
|
|
39995
|
+
const fromFile = readFileSync22(next, "utf-8");
|
|
39996
|
+
if (fromFile.trim()) krakenGraph = fromFile;
|
|
39997
|
+
} catch {
|
|
39998
|
+
}
|
|
39999
|
+
}
|
|
40000
|
+
i++;
|
|
40001
|
+
} else if (arg === "--plan-only") {
|
|
40002
|
+
planOnly = true;
|
|
40003
|
+
} else if (arg === "--run-plan") {
|
|
40004
|
+
runPlan = argv[i + 1];
|
|
40005
|
+
i++;
|
|
40006
|
+
}
|
|
40007
|
+
}
|
|
40008
|
+
if (councilFlag && !modeExplicit) {
|
|
40009
|
+
mode = "council";
|
|
40010
|
+
} else if (councilFlag && modeExplicit && mode !== "council") {
|
|
40011
|
+
return {
|
|
40012
|
+
options: null,
|
|
40013
|
+
error: `--council conflicts with --mode ${mode}`
|
|
40014
|
+
};
|
|
40015
|
+
}
|
|
40016
|
+
if (task && krakenGraph) {
|
|
40017
|
+
return { options: null, error: "--task and --kraken-graph are mutually exclusive" };
|
|
40018
|
+
}
|
|
40019
|
+
if ((!task || task.trim().length === 0) && (!krakenGraph || krakenGraph.trim().length === 0)) {
|
|
40020
|
+
return { options: null, error: "--headless requires --task <prompt> or --kraken-graph <goal>" };
|
|
40021
|
+
}
|
|
40022
|
+
return {
|
|
40023
|
+
options: {
|
|
40024
|
+
task: task ?? "",
|
|
40025
|
+
output,
|
|
40026
|
+
mode,
|
|
40027
|
+
phase: phase2,
|
|
40028
|
+
useCouncil: mode === "council",
|
|
40029
|
+
provider,
|
|
40030
|
+
model,
|
|
40031
|
+
...history2 && history2.length > 0 ? { history: history2 } : {},
|
|
40032
|
+
...todos2 && todos2.length > 0 ? { todos: todos2 } : {},
|
|
40033
|
+
...once ? { once: true } : {},
|
|
40034
|
+
...profile ? { profile } : {},
|
|
40035
|
+
...resumeSessionId ? { resumeSessionId } : {},
|
|
40036
|
+
...exportSessionPath ? { exportSessionPath } : {},
|
|
40037
|
+
...strictDone ? { strictDone: true } : {},
|
|
40038
|
+
...krakenGraph ? { krakenGraph } : {},
|
|
40039
|
+
...planOnly ? { planOnly: true } : {},
|
|
40040
|
+
...runPlan ? { runPlan } : {}
|
|
40041
|
+
}
|
|
40042
|
+
};
|
|
40043
|
+
}
|
|
40044
|
+
async function resolveHeadlessKey(providerId) {
|
|
40045
|
+
const spec = PROVIDERS.find((p3) => p3.id === providerId);
|
|
40046
|
+
if (!spec) {
|
|
40047
|
+
return { error: `unknown provider: '${providerId}'` };
|
|
40048
|
+
}
|
|
40049
|
+
const resolved = await resolveApiKeyWithMeta(providerId);
|
|
40050
|
+
if (!resolved || !resolved.apiKey) {
|
|
40051
|
+
return {
|
|
40052
|
+
error: `no API key for provider '${providerId}'.
|
|
40053
|
+
Set the env var ${spec.envVar} or save a key via /login.`
|
|
40054
|
+
};
|
|
40055
|
+
}
|
|
40056
|
+
const { resolveBaseUrl: resolveBaseUrl2 } = await Promise.resolve().then(() => (init_openai_compatible(), openai_compatible_exports));
|
|
40057
|
+
return {
|
|
40058
|
+
apiKey: resolved.apiKey,
|
|
40059
|
+
baseUrl: resolveBaseUrl2(providerId)
|
|
40060
|
+
};
|
|
40061
|
+
}
|
|
40062
|
+
function resolveHeadlessProvider(opts) {
|
|
40063
|
+
const provider = opts.provider ?? getActiveProvider().id;
|
|
40064
|
+
const model = opts.model ?? getModelForProvider(provider);
|
|
40065
|
+
return { provider, model };
|
|
40066
|
+
}
|
|
40067
|
+
function emitEvent(event) {
|
|
40068
|
+
process.stdout.write(JSON.stringify(event) + "\n");
|
|
40069
|
+
}
|
|
40070
|
+
var init_headless = __esm({
|
|
40071
|
+
"src/cli/headless.ts"() {
|
|
40072
|
+
"use strict";
|
|
40073
|
+
init_keyStore();
|
|
40074
|
+
init_providerConfig();
|
|
40075
|
+
init_openai_compatible();
|
|
40076
|
+
init_phase();
|
|
40077
|
+
init_mode();
|
|
40078
|
+
init_runtime2();
|
|
40079
|
+
}
|
|
40080
|
+
});
|
|
40081
|
+
|
|
40082
|
+
// src/cli/headlessSpine.ts
|
|
40083
|
+
var headlessSpine_exports = {};
|
|
40084
|
+
__export(headlessSpine_exports, {
|
|
40085
|
+
derivedModelSeed: () => derivedModelSeed,
|
|
40086
|
+
exportSessionById: () => exportSessionById,
|
|
40087
|
+
missionStateFromSpine: () => missionStateFromSpine,
|
|
40088
|
+
openHeadlessSpine: () => openHeadlessSpine,
|
|
40089
|
+
resolveHeadlessProfileId: () => resolveHeadlessProfileId,
|
|
40090
|
+
seedHeadlessModelHistory: () => seedHeadlessModelHistory,
|
|
40091
|
+
sessionStartedEvent: () => sessionStartedEvent
|
|
40092
|
+
});
|
|
40093
|
+
function sessionStartedEvent(handle) {
|
|
40094
|
+
return {
|
|
40095
|
+
type: "session_started",
|
|
40096
|
+
sessionId: handle.sessionId,
|
|
40097
|
+
spine: handle.spine.status
|
|
40098
|
+
};
|
|
40099
|
+
}
|
|
40100
|
+
function resolveHeadlessProfileId(mode, explicit) {
|
|
40101
|
+
if (explicit) return resolveProfile(explicit).id;
|
|
40102
|
+
return defaultProfileForMode(mode ?? "kraken");
|
|
40103
|
+
}
|
|
40104
|
+
async function openHeadlessSpine(opts) {
|
|
40105
|
+
const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
|
|
40106
|
+
let profileTools = [];
|
|
40107
|
+
try {
|
|
40108
|
+
profileTools = resolveProfile(profileId).tools;
|
|
40109
|
+
} catch {
|
|
40110
|
+
profileTools = [];
|
|
40111
|
+
}
|
|
40112
|
+
const extra = {
|
|
40113
|
+
profile: profileId,
|
|
40114
|
+
workspace: opts.workspace ?? process.cwd(),
|
|
40115
|
+
toolManifestHash: profileTools.length > 0 ? toolManifestHash(profileTools) : void 0
|
|
40116
|
+
};
|
|
40117
|
+
const mirrorOpts = {
|
|
40118
|
+
baseDir: opts.baseDir,
|
|
40119
|
+
quiet: opts.quiet,
|
|
40120
|
+
extraStarted: extra
|
|
40121
|
+
};
|
|
40122
|
+
const spine = await SessionSpineMirror.adopt(opts.sessionId, mirrorOpts);
|
|
40123
|
+
if (spine.status === "active") {
|
|
40124
|
+
spine.note("headless.profile", { profile: profileId, mode: opts.mode ?? "kraken" });
|
|
40125
|
+
}
|
|
40126
|
+
return {
|
|
40127
|
+
sessionId: opts.sessionId,
|
|
40128
|
+
profileId,
|
|
40129
|
+
spine,
|
|
40130
|
+
observe(ev) {
|
|
40131
|
+
if (ev && typeof ev === "object" && "type" in ev) {
|
|
40132
|
+
spine.mirrorBrainEvent(ev);
|
|
40133
|
+
}
|
|
40134
|
+
},
|
|
40135
|
+
userMessage(text) {
|
|
40136
|
+
spine.userMessage(text);
|
|
40137
|
+
},
|
|
40138
|
+
verificationRun(payload) {
|
|
40139
|
+
spine.verificationRun(payload);
|
|
40140
|
+
},
|
|
40141
|
+
lastVerificationRun() {
|
|
40142
|
+
return spine.lastVerificationRun();
|
|
40143
|
+
},
|
|
40144
|
+
missionPhase(phase2, note) {
|
|
40145
|
+
spine.missionPhase(phase2, note);
|
|
40146
|
+
},
|
|
40147
|
+
note(text, data) {
|
|
40148
|
+
spine.note(text, data);
|
|
40149
|
+
},
|
|
40150
|
+
async close(reason = "host-exit") {
|
|
40151
|
+
await spine.close(reason);
|
|
40152
|
+
},
|
|
40153
|
+
async interrupt(note) {
|
|
40154
|
+
if (note) spine.note("headless.interrupt", { note });
|
|
40155
|
+
await spine.release();
|
|
40156
|
+
},
|
|
40157
|
+
async exportJson() {
|
|
40158
|
+
try {
|
|
40159
|
+
const store6 = new SessionStore(resolveSessionsDir({ baseDir: opts.baseDir }));
|
|
40160
|
+
if (!await store6.exists(opts.sessionId)) return null;
|
|
40161
|
+
return await exportSessionJson(store6, opts.sessionId);
|
|
40162
|
+
} catch {
|
|
40163
|
+
return null;
|
|
40164
|
+
}
|
|
40165
|
+
}
|
|
40166
|
+
};
|
|
40167
|
+
}
|
|
40168
|
+
async function exportSessionById(sessionId2, baseDir) {
|
|
40169
|
+
try {
|
|
40170
|
+
const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
|
|
40171
|
+
if (!await store6.exists(sessionId2)) {
|
|
40172
|
+
return { ok: false, error: `session not found: ${sessionId2}` };
|
|
40173
|
+
}
|
|
40174
|
+
return { ok: true, json: await exportSessionJson(store6, sessionId2) };
|
|
40175
|
+
} catch (err) {
|
|
40176
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
40177
|
+
}
|
|
40178
|
+
}
|
|
40179
|
+
async function missionStateFromSpine(sessionId2, baseDir) {
|
|
40180
|
+
try {
|
|
40181
|
+
const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
|
|
40182
|
+
if (!await store6.exists(sessionId2)) return null;
|
|
40183
|
+
const projection = await store6.projection(sessionId2);
|
|
40184
|
+
return deriveMissionState(projection);
|
|
40185
|
+
} catch {
|
|
40186
|
+
return null;
|
|
40187
|
+
}
|
|
40188
|
+
}
|
|
40189
|
+
async function seedHeadlessModelHistory(handle, legacy) {
|
|
40190
|
+
const mirror = handle.spine;
|
|
40191
|
+
const legacySeed = filterLegacySeed(legacy);
|
|
40192
|
+
if (mirror.status !== "active") {
|
|
40193
|
+
return { history: legacySeed, importedCount: 0, source: "legacy-fallback" };
|
|
40194
|
+
}
|
|
40195
|
+
const existing = await mirror.derivedPriorTurns();
|
|
40196
|
+
if (existing && existing.length > 0) {
|
|
40197
|
+
return { history: derivedModelSeed(existing), importedCount: 0, source: "spine" };
|
|
40198
|
+
}
|
|
40199
|
+
if (legacySeed.length === 0) {
|
|
40200
|
+
return { history: [], importedCount: 0, source: "spine" };
|
|
40201
|
+
}
|
|
40202
|
+
for (const m of legacySeed) {
|
|
40203
|
+
if (m.role === "user") {
|
|
40204
|
+
mirror.userMessage(m.content);
|
|
40205
|
+
} else {
|
|
40206
|
+
mirror.assistantMessage(m.content, { imported: "legacy-history" });
|
|
40207
|
+
}
|
|
40208
|
+
}
|
|
40209
|
+
await mirror.flush();
|
|
40210
|
+
const derived = await mirror.derivedPriorTurns() ?? [];
|
|
40211
|
+
return {
|
|
40212
|
+
history: derivedModelSeed(derived),
|
|
40213
|
+
importedCount: legacySeed.length,
|
|
40214
|
+
source: "spine-import"
|
|
40215
|
+
};
|
|
40216
|
+
}
|
|
40217
|
+
function filterLegacySeed(legacy) {
|
|
40218
|
+
return (legacy ?? []).filter((m) => m.role === "user" || m.role === "assistant").map(
|
|
40219
|
+
(m) => m.role === "assistant" && m.content ? {
|
|
40220
|
+
role: "assistant",
|
|
40221
|
+
content: cleanAgentContent(m.content, {
|
|
40222
|
+
stripQuestion: false,
|
|
40223
|
+
stripThink: false
|
|
40224
|
+
})
|
|
40225
|
+
} : { role: m.role, content: m.content ?? "" }
|
|
40226
|
+
).filter((m) => (m.content ?? "").trim().length > 0);
|
|
40227
|
+
}
|
|
40228
|
+
function derivedModelSeed(derived) {
|
|
40229
|
+
return derivedToAgentMessages(derived).map(
|
|
40230
|
+
(m) => m.role === "system" ? { role: "user", content: m.content } : m
|
|
40231
|
+
).map(
|
|
40232
|
+
(m) => m.role === "assistant" && m.content ? {
|
|
40233
|
+
role: "assistant",
|
|
40234
|
+
content: cleanAgentContent(m.content, {
|
|
40235
|
+
stripQuestion: false,
|
|
40236
|
+
stripThink: false
|
|
40237
|
+
})
|
|
40238
|
+
} : m
|
|
40239
|
+
).filter((m) => m.role === "user" || m.role === "assistant").filter((m) => (m.content ?? "").trim().length > 0);
|
|
40240
|
+
}
|
|
40241
|
+
var init_headlessSpine = __esm({
|
|
40242
|
+
"src/cli/headlessSpine.ts"() {
|
|
40243
|
+
"use strict";
|
|
40244
|
+
init_dist();
|
|
40245
|
+
init_session();
|
|
40246
|
+
init_mission2();
|
|
40247
|
+
init_runtime2();
|
|
40248
|
+
init_sessionSpine();
|
|
40249
|
+
init_headless();
|
|
40250
|
+
}
|
|
40251
|
+
});
|
|
40252
|
+
|
|
39553
40253
|
// src/cli/state/fileStateStore.ts
|
|
39554
40254
|
import { createHash as createHash10, randomUUID as randomUUID2 } from "node:crypto";
|
|
39555
40255
|
import { promises as fs21 } from "node:fs";
|
|
@@ -40502,57 +41202,6 @@ var init_phaseState = __esm({
|
|
|
40502
41202
|
}
|
|
40503
41203
|
});
|
|
40504
41204
|
|
|
40505
|
-
// src/cli/phase.ts
|
|
40506
|
-
var phase_exports = {};
|
|
40507
|
-
__export(phase_exports, {
|
|
40508
|
-
PHASES: () => PHASES,
|
|
40509
|
-
PLAN_ALLOWED_WRITE_TOOLS: () => PLAN_ALLOWED_WRITE_TOOLS,
|
|
40510
|
-
PLAN_BLOCKED_TOOLS: () => PLAN_BLOCKED_TOOLS,
|
|
40511
|
-
describePhase: () => describePhase,
|
|
40512
|
-
nextPhase: () => nextPhase,
|
|
40513
|
-
parsePhase: () => parsePhase
|
|
40514
|
-
});
|
|
40515
|
-
function parsePhase(input) {
|
|
40516
|
-
const v = input.trim().toLowerCase();
|
|
40517
|
-
return PHASES.includes(v) ? v : null;
|
|
40518
|
-
}
|
|
40519
|
-
function nextPhase(current) {
|
|
40520
|
-
return current === "plan" ? "build" : "plan";
|
|
40521
|
-
}
|
|
40522
|
-
function describePhase(phase2) {
|
|
40523
|
-
switch (phase2) {
|
|
40524
|
-
case "plan":
|
|
40525
|
-
return "plan \u2014 explore & design only (no project writes; plan files allowed)";
|
|
40526
|
-
default:
|
|
40527
|
-
return "build \u2014 implement with full tools";
|
|
40528
|
-
}
|
|
40529
|
-
}
|
|
40530
|
-
var PHASES, PLAN_ALLOWED_WRITE_TOOLS, PLAN_BLOCKED_TOOLS;
|
|
40531
|
-
var init_phase = __esm({
|
|
40532
|
-
"src/cli/phase.ts"() {
|
|
40533
|
-
"use strict";
|
|
40534
|
-
PHASES = ["plan", "build"];
|
|
40535
|
-
PLAN_ALLOWED_WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
40536
|
-
// Workspace plan/docs — intentional plan-mode outputs
|
|
40537
|
-
"createPlan",
|
|
40538
|
-
"createTask",
|
|
40539
|
-
"updateTask",
|
|
40540
|
-
"createMilestone",
|
|
40541
|
-
"createDocument",
|
|
40542
|
-
"createDecision",
|
|
40543
|
-
"linkDocuments"
|
|
40544
|
-
// Soft writes that only touch .zelari / plan paths are still gated in
|
|
40545
|
-
// toolRegistry by path when needed; write_file/edit_file stay DENIED.
|
|
40546
|
-
]);
|
|
40547
|
-
PLAN_BLOCKED_TOOLS = /* @__PURE__ */ new Set([
|
|
40548
|
-
"write_file",
|
|
40549
|
-
"edit_file",
|
|
40550
|
-
"apply_diff",
|
|
40551
|
-
"bash"
|
|
40552
|
-
]);
|
|
40553
|
-
}
|
|
40554
|
-
});
|
|
40555
|
-
|
|
40556
41205
|
// src/cli/provider/localCli/claudeStreamJson.ts
|
|
40557
41206
|
function textBlock(text) {
|
|
40558
41207
|
return { type: "text", text };
|
|
@@ -40816,14 +41465,14 @@ var init_claudeProvider = __esm({
|
|
|
40816
41465
|
});
|
|
40817
41466
|
|
|
40818
41467
|
// src/cli/workspace/projectInstructions.ts
|
|
40819
|
-
import { existsSync as existsSync26, readFileSync as
|
|
41468
|
+
import { existsSync as existsSync26, readFileSync as readFileSync23 } from "node:fs";
|
|
40820
41469
|
import { join as join20 } from "node:path";
|
|
40821
41470
|
function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
|
|
40822
41471
|
for (const name of CANDIDATES) {
|
|
40823
41472
|
const full = join20(projectRoot, name);
|
|
40824
41473
|
if (!existsSync26(full)) continue;
|
|
40825
41474
|
try {
|
|
40826
|
-
let raw =
|
|
41475
|
+
let raw = readFileSync23(full, "utf8");
|
|
40827
41476
|
raw = raw.replace(/\r\n/g, "\n").trim();
|
|
40828
41477
|
if (!raw) continue;
|
|
40829
41478
|
if (raw.length <= maxChars) {
|
|
@@ -40867,7 +41516,7 @@ __export(workspaceSummary_exports, {
|
|
|
40867
41516
|
buildWorkspaceSummary: () => buildWorkspaceSummary,
|
|
40868
41517
|
buildZelariReadHint: () => buildZelariReadHint
|
|
40869
41518
|
});
|
|
40870
|
-
import { existsSync as existsSync27, readFileSync as
|
|
41519
|
+
import { existsSync as existsSync27, readFileSync as readFileSync24, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
|
|
40871
41520
|
import { join as join21, relative } from "node:path";
|
|
40872
41521
|
function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
|
|
40873
41522
|
const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
|
|
@@ -40905,7 +41554,7 @@ function buildPlanSummary(projectRoot = process.cwd(), options) {
|
|
|
40905
41554
|
if (!existsSync27(planPath)) return null;
|
|
40906
41555
|
let plan;
|
|
40907
41556
|
try {
|
|
40908
|
-
plan = JSON.parse(
|
|
41557
|
+
plan = JSON.parse(readFileSync24(planPath, "utf8"));
|
|
40909
41558
|
} catch {
|
|
40910
41559
|
return null;
|
|
40911
41560
|
}
|
|
@@ -41063,7 +41712,7 @@ function readPackageJson(projectRoot) {
|
|
|
41063
41712
|
const p3 = join21(projectRoot, "package.json");
|
|
41064
41713
|
if (!existsSync27(p3)) return null;
|
|
41065
41714
|
try {
|
|
41066
|
-
return JSON.parse(
|
|
41715
|
+
return JSON.parse(readFileSync24(p3, "utf8"));
|
|
41067
41716
|
} catch {
|
|
41068
41717
|
return null;
|
|
41069
41718
|
}
|
|
@@ -41191,7 +41840,7 @@ var composeContext_exports = {};
|
|
|
41191
41840
|
__export(composeContext_exports, {
|
|
41192
41841
|
composeProjectContext: () => composeProjectContext
|
|
41193
41842
|
});
|
|
41194
|
-
import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as
|
|
41843
|
+
import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as readFileSync25 } from "node:fs";
|
|
41195
41844
|
import { join as join23 } from "node:path";
|
|
41196
41845
|
function cap2(text, max, label) {
|
|
41197
41846
|
if (!text || text.length <= max) return { text: text || "", truncated: false };
|
|
@@ -41332,15 +41981,15 @@ function readDurableHeadSync(projectRoot) {
|
|
|
41332
41981
|
try {
|
|
41333
41982
|
const headPath = join23(projectRoot, ".zelari", "state", "HEAD.json");
|
|
41334
41983
|
if (!existsSync29(headPath)) return "";
|
|
41335
|
-
const head = JSON.parse(
|
|
41984
|
+
const head = JSON.parse(readFileSync25(headPath, "utf8"));
|
|
41336
41985
|
if (!head?.id) return "";
|
|
41337
41986
|
const metaPath = join23(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
|
|
41338
41987
|
if (!existsSync29(metaPath)) return "";
|
|
41339
|
-
const meta3 = JSON.parse(
|
|
41988
|
+
const meta3 = JSON.parse(readFileSync25(metaPath, "utf8"));
|
|
41340
41989
|
const discPath = meta3.artifactDir ? join23(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join23(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
|
|
41341
41990
|
let discoveries = [];
|
|
41342
41991
|
if (existsSync29(discPath)) {
|
|
41343
|
-
discoveries = JSON.parse(
|
|
41992
|
+
discoveries = JSON.parse(readFileSync25(discPath, "utf8"));
|
|
41344
41993
|
}
|
|
41345
41994
|
const reusable = discoveries.filter((d) => d.reusable !== false);
|
|
41346
41995
|
const lines = [
|
|
@@ -41373,13 +42022,13 @@ var planDetect_exports = {};
|
|
|
41373
42022
|
__export(planDetect_exports, {
|
|
41374
42023
|
hasWorkspacePlan: () => hasWorkspacePlan
|
|
41375
42024
|
});
|
|
41376
|
-
import { existsSync as existsSync30, readFileSync as
|
|
42025
|
+
import { existsSync as existsSync30, readFileSync as readFileSync26 } from "node:fs";
|
|
41377
42026
|
import { join as join24 } from "node:path";
|
|
41378
42027
|
function hasWorkspacePlan(projectRoot = process.cwd()) {
|
|
41379
42028
|
const planPath = join24(resolveWorkspaceRoot(projectRoot), "plan.json");
|
|
41380
42029
|
if (!existsSync30(planPath)) return false;
|
|
41381
42030
|
try {
|
|
41382
|
-
const parsed = JSON.parse(
|
|
42031
|
+
const parsed = JSON.parse(readFileSync26(planPath, "utf8"));
|
|
41383
42032
|
return Array.isArray(parsed.phases) && parsed.phases.length > 0;
|
|
41384
42033
|
} catch {
|
|
41385
42034
|
return false;
|
|
@@ -41441,7 +42090,7 @@ import {
|
|
|
41441
42090
|
existsSync as existsSync31,
|
|
41442
42091
|
readdirSync as readdirSync8,
|
|
41443
42092
|
writeFileSync as writeFileSync17,
|
|
41444
|
-
readFileSync as
|
|
42093
|
+
readFileSync as readFileSync27,
|
|
41445
42094
|
mkdirSync as mkdirSync15,
|
|
41446
42095
|
renameSync as renameSync4
|
|
41447
42096
|
} from "node:fs";
|
|
@@ -41462,7 +42111,7 @@ function readPlan(ctx) {
|
|
|
41462
42111
|
if (existsSync31(jsonPath)) {
|
|
41463
42112
|
try {
|
|
41464
42113
|
const parsed = JSON.parse(
|
|
41465
|
-
|
|
42114
|
+
readFileSync27(jsonPath, "utf8")
|
|
41466
42115
|
);
|
|
41467
42116
|
const { phases, tasks, milestones, ...root } = parsed;
|
|
41468
42117
|
return {
|
|
@@ -42026,7 +42675,7 @@ function searchDocumentsStub(ctx) {
|
|
|
42026
42675
|
const results = [];
|
|
42027
42676
|
for (const file2 of files) {
|
|
42028
42677
|
if (!existsSync31(file2)) continue;
|
|
42029
|
-
const raw =
|
|
42678
|
+
const raw = readFileSync27(file2, "utf8");
|
|
42030
42679
|
const content = raw.toLowerCase();
|
|
42031
42680
|
let idx = -1;
|
|
42032
42681
|
let matchLen = 0;
|
|
@@ -42535,7 +43184,7 @@ var init_mcpClient = __esm({
|
|
|
42535
43184
|
import {
|
|
42536
43185
|
existsSync as existsSync33,
|
|
42537
43186
|
mkdirSync as mkdirSync16,
|
|
42538
|
-
readFileSync as
|
|
43187
|
+
readFileSync as readFileSync28,
|
|
42539
43188
|
writeFileSync as writeFileSync18
|
|
42540
43189
|
} from "node:fs";
|
|
42541
43190
|
import { dirname as dirname7, join as join26 } from "node:path";
|
|
@@ -42549,7 +43198,7 @@ function getProjectMcpPath(projectRoot) {
|
|
|
42549
43198
|
function readFile2(path63) {
|
|
42550
43199
|
if (!existsSync33(path63)) return {};
|
|
42551
43200
|
try {
|
|
42552
|
-
const parsed = JSON.parse(
|
|
43201
|
+
const parsed = JSON.parse(readFileSync28(path63, "utf8"));
|
|
42553
43202
|
const out = {};
|
|
42554
43203
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
42555
43204
|
if (!cfg || typeof cfg.command !== "string" || !cfg.command.trim()) continue;
|
|
@@ -42777,7 +43426,7 @@ __export(mcpManager_exports, {
|
|
|
42777
43426
|
readMcpConfig: () => readMcpConfig,
|
|
42778
43427
|
registerMcpTools: () => registerMcpTools
|
|
42779
43428
|
});
|
|
42780
|
-
import { existsSync as existsSync34, readFileSync as
|
|
43429
|
+
import { existsSync as existsSync34, readFileSync as readFileSync29 } from "node:fs";
|
|
42781
43430
|
import { join as join27 } from "node:path";
|
|
42782
43431
|
import { homedir as homedir11 } from "node:os";
|
|
42783
43432
|
function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
@@ -42792,7 +43441,7 @@ function readMcpConfig(projectRoot = process.cwd(), opts) {
|
|
|
42792
43441
|
for (const p3 of paths) {
|
|
42793
43442
|
if (!existsSync34(p3)) continue;
|
|
42794
43443
|
try {
|
|
42795
|
-
const parsed = JSON.parse(
|
|
43444
|
+
const parsed = JSON.parse(readFileSync29(p3, "utf8"));
|
|
42796
43445
|
for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
|
|
42797
43446
|
if (!cfg || typeof cfg.command !== "string" || cfg.command.length === 0) continue;
|
|
42798
43447
|
merged[name] = cfg;
|
|
@@ -43031,7 +43680,7 @@ __export(agentsMd_exports, {
|
|
|
43031
43680
|
serializeAgentsMd: () => serializeAgentsMd,
|
|
43032
43681
|
updateAgentsMd: () => updateAgentsMd
|
|
43033
43682
|
});
|
|
43034
|
-
import { existsSync as existsSync35, readFileSync as
|
|
43683
|
+
import { existsSync as existsSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync19 } from "node:fs";
|
|
43035
43684
|
import { createHash as createHash11 } from "node:crypto";
|
|
43036
43685
|
import { join as join28 } from "node:path";
|
|
43037
43686
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
@@ -43089,7 +43738,7 @@ async function genConventions(ctx) {
|
|
|
43089
43738
|
const lines = [];
|
|
43090
43739
|
const claudeMd = join28(ctx.projectRoot, "CLAUDE.MD");
|
|
43091
43740
|
if (existsSync35(claudeMd)) {
|
|
43092
|
-
const content =
|
|
43741
|
+
const content = readFileSync30(claudeMd, "utf8");
|
|
43093
43742
|
const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
|
|
43094
43743
|
if (match) {
|
|
43095
43744
|
lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
|
|
@@ -43123,7 +43772,7 @@ async function genBuild(ctx) {
|
|
|
43123
43772
|
async function genOpenQuestions(ctx) {
|
|
43124
43773
|
const path63 = join28(ctx.rootDir, "risks.md");
|
|
43125
43774
|
if (!existsSync35(path63)) return "_No open questions._";
|
|
43126
|
-
const content =
|
|
43775
|
+
const content = readFileSync30(path63, "utf8");
|
|
43127
43776
|
const lines = content.split("\n");
|
|
43128
43777
|
const questions = [];
|
|
43129
43778
|
let currentTitle = "";
|
|
@@ -43199,7 +43848,7 @@ function titleCase(id) {
|
|
|
43199
43848
|
async function updateAgentsMd(ctx, projectRoot) {
|
|
43200
43849
|
const agentsPath = join28(projectRoot, "AGENTS.MD");
|
|
43201
43850
|
if (existsSync35(agentsPath)) {
|
|
43202
|
-
const content =
|
|
43851
|
+
const content = readFileSync30(agentsPath, "utf8");
|
|
43203
43852
|
const hasAnyMarker = AUTO_SECTIONS.some((id) => content.includes(MARKER_OPEN(id)));
|
|
43204
43853
|
if (!hasAnyMarker) {
|
|
43205
43854
|
return {
|
|
@@ -43215,7 +43864,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
43215
43864
|
}
|
|
43216
43865
|
let manualContent = "";
|
|
43217
43866
|
if (existsSync35(agentsPath)) {
|
|
43218
|
-
const { manualBlocks } = parseAgentsMd(
|
|
43867
|
+
const { manualBlocks } = parseAgentsMd(readFileSync30(agentsPath, "utf8"));
|
|
43219
43868
|
manualContent = manualBlocks.after;
|
|
43220
43869
|
} else {
|
|
43221
43870
|
const projectName2 = projectName(projectRoot);
|
|
@@ -43231,7 +43880,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
43231
43880
|
""
|
|
43232
43881
|
].join("\n");
|
|
43233
43882
|
}
|
|
43234
|
-
const oldContent = existsSync35(agentsPath) ?
|
|
43883
|
+
const oldContent = existsSync35(agentsPath) ? readFileSync30(agentsPath, "utf8") : "";
|
|
43235
43884
|
const { sections: oldSections } = parseAgentsMd(oldContent);
|
|
43236
43885
|
const changedSections = [];
|
|
43237
43886
|
for (const id of AUTO_SECTIONS) {
|
|
@@ -43368,7 +44017,7 @@ var init_completeDesign = __esm({
|
|
|
43368
44017
|
});
|
|
43369
44018
|
|
|
43370
44019
|
// src/cli/workspace/planDriftCheck.ts
|
|
43371
|
-
import { existsSync as existsSync36, readFileSync as
|
|
44020
|
+
import { existsSync as existsSync36, readFileSync as readFileSync31, readdirSync as readdirSync9, statSync as statSync6, writeFileSync as writeFileSync20 } from "node:fs";
|
|
43372
44021
|
import { join as join29 } from "node:path";
|
|
43373
44022
|
function findCanonicalDoc(rootDir) {
|
|
43374
44023
|
const docsDir = join29(rootDir, "docs");
|
|
@@ -43399,7 +44048,7 @@ function firstString2(v) {
|
|
|
43399
44048
|
}
|
|
43400
44049
|
function readFileSyncSafe(path63) {
|
|
43401
44050
|
try {
|
|
43402
|
-
return
|
|
44051
|
+
return readFileSync31(path63, "utf8");
|
|
43403
44052
|
} catch {
|
|
43404
44053
|
return null;
|
|
43405
44054
|
}
|
|
@@ -43414,7 +44063,7 @@ async function runPlanDriftCheck(rootDir) {
|
|
|
43414
44063
|
}
|
|
43415
44064
|
let plan;
|
|
43416
44065
|
try {
|
|
43417
|
-
plan = JSON.parse(
|
|
44066
|
+
plan = JSON.parse(readFileSync31(planPath, "utf8"));
|
|
43418
44067
|
} catch {
|
|
43419
44068
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
43420
44069
|
}
|
|
@@ -43540,7 +44189,7 @@ var init_planDriftCheck = __esm({
|
|
|
43540
44189
|
|
|
43541
44190
|
// src/cli/workspace/projectSmoke.ts
|
|
43542
44191
|
import { spawn as spawn14 } from "node:child_process";
|
|
43543
|
-
import { existsSync as existsSync37, readFileSync as
|
|
44192
|
+
import { existsSync as existsSync37, readFileSync as readFileSync32 } from "node:fs";
|
|
43544
44193
|
import { join as join30 } from "node:path";
|
|
43545
44194
|
function pickSmokeScript(scripts) {
|
|
43546
44195
|
if (!scripts) return null;
|
|
@@ -43559,7 +44208,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
43559
44208
|
}
|
|
43560
44209
|
let scripts = {};
|
|
43561
44210
|
try {
|
|
43562
|
-
const pkg = JSON.parse(
|
|
44211
|
+
const pkg = JSON.parse(readFileSync32(pkgPath, "utf8"));
|
|
43563
44212
|
scripts = pkg.scripts ?? {};
|
|
43564
44213
|
} catch {
|
|
43565
44214
|
return { ran: false, reason: "package.json unreadable (skipped)" };
|
|
@@ -43647,7 +44296,7 @@ __export(postCouncilHook_exports, {
|
|
|
43647
44296
|
runPostCouncilHook: () => runPostCouncilHook
|
|
43648
44297
|
});
|
|
43649
44298
|
import { spawn as spawn15 } from "node:child_process";
|
|
43650
|
-
import { existsSync as existsSync38, readFileSync as
|
|
44299
|
+
import { existsSync as existsSync38, readFileSync as readFileSync33 } from "node:fs";
|
|
43651
44300
|
import { join as join31 } from "node:path";
|
|
43652
44301
|
async function runCompleteDesignPostProcessor(ctx, options) {
|
|
43653
44302
|
if (options?.runMode === "implementation") {
|
|
@@ -43669,7 +44318,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
|
|
|
43669
44318
|
}
|
|
43670
44319
|
let phaseCount = 0;
|
|
43671
44320
|
try {
|
|
43672
|
-
const parsed = JSON.parse(
|
|
44321
|
+
const parsed = JSON.parse(readFileSync33(planJsonPath2, "utf8"));
|
|
43673
44322
|
phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
|
|
43674
44323
|
} catch {
|
|
43675
44324
|
return { ran: false, reason: ".zelari/plan.json corrupt" };
|
|
@@ -43904,7 +44553,7 @@ __export(councilFeedback_exports, {
|
|
|
43904
44553
|
import {
|
|
43905
44554
|
promises as fs22,
|
|
43906
44555
|
existsSync as existsSync39,
|
|
43907
|
-
readFileSync as
|
|
44556
|
+
readFileSync as readFileSync34,
|
|
43908
44557
|
writeFileSync as writeFileSync21,
|
|
43909
44558
|
mkdirSync as mkdirSync17
|
|
43910
44559
|
} from "node:fs";
|
|
@@ -44014,7 +44663,7 @@ var init_councilFeedback = __esm({
|
|
|
44014
44663
|
load() {
|
|
44015
44664
|
if (!existsSync39(this.file)) return;
|
|
44016
44665
|
try {
|
|
44017
|
-
const raw =
|
|
44666
|
+
const raw = readFileSync34(this.file, "utf-8");
|
|
44018
44667
|
const parsed = JSON.parse(raw);
|
|
44019
44668
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
44020
44669
|
this.entries = parsed.entries.filter(
|
|
@@ -45388,38 +46037,6 @@ var init_brokerHandlers = __esm({
|
|
|
45388
46037
|
}
|
|
45389
46038
|
});
|
|
45390
46039
|
|
|
45391
|
-
// src/cli/mode.ts
|
|
45392
|
-
function nextMode(current) {
|
|
45393
|
-
const i = MODES.indexOf(current);
|
|
45394
|
-
return MODES[(i + 1) % MODES.length] ?? "kraken";
|
|
45395
|
-
}
|
|
45396
|
-
function parseMode(input) {
|
|
45397
|
-
const v = input.trim().toLowerCase();
|
|
45398
|
-
if (MODES.includes(v)) return v;
|
|
45399
|
-
return MODE_ALIASES[v] ?? null;
|
|
45400
|
-
}
|
|
45401
|
-
function describeMode(mode) {
|
|
45402
|
-
switch (mode) {
|
|
45403
|
-
case "council":
|
|
45404
|
-
return "council \u2014 multi-member plan/design (Caronte\u2026Lucifero; build needs ZELARI_COUNCIL_CAN_BUILD=1)";
|
|
45405
|
-
case "zelari":
|
|
45406
|
-
return "zelari \u2014 mission: plan@council \u2192 build@kraken (legacy: ZELARI_BUILD_VIA_AGENT=0)";
|
|
45407
|
-
default:
|
|
45408
|
-
return "kraken \u2014 super-agent lead (spawns explore/general/verify tentacles; default implementer)";
|
|
45409
|
-
}
|
|
45410
|
-
}
|
|
45411
|
-
var MODES, MODE_ALIASES;
|
|
45412
|
-
var init_mode = __esm({
|
|
45413
|
-
"src/cli/mode.ts"() {
|
|
45414
|
-
"use strict";
|
|
45415
|
-
MODES = ["kraken", "council", "zelari"];
|
|
45416
|
-
MODE_ALIASES = {
|
|
45417
|
-
agent: "kraken",
|
|
45418
|
-
single: "kraken"
|
|
45419
|
-
};
|
|
45420
|
-
}
|
|
45421
|
-
});
|
|
45422
|
-
|
|
45423
46040
|
// src/cli/kraken/planner.ts
|
|
45424
46041
|
var planner_exports = {};
|
|
45425
46042
|
__export(planner_exports, {
|
|
@@ -47891,7 +48508,7 @@ var init_prereqChecks = __esm({
|
|
|
47891
48508
|
});
|
|
47892
48509
|
|
|
47893
48510
|
// src/cli/plugins/prefs.ts
|
|
47894
|
-
import { existsSync as existsSync42, readFileSync as
|
|
48511
|
+
import { existsSync as existsSync42, readFileSync as readFileSync35, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18 } from "node:fs";
|
|
47895
48512
|
import path53 from "node:path";
|
|
47896
48513
|
import os11 from "node:os";
|
|
47897
48514
|
function getPluginPrefsPath() {
|
|
@@ -47901,7 +48518,7 @@ function getPluginPrefs() {
|
|
|
47901
48518
|
const file2 = getPluginPrefsPath();
|
|
47902
48519
|
try {
|
|
47903
48520
|
if (!existsSync42(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
|
|
47904
|
-
const raw =
|
|
48521
|
+
const raw = readFileSync35(file2, "utf-8");
|
|
47905
48522
|
const parsed = JSON.parse(raw);
|
|
47906
48523
|
if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
|
|
47907
48524
|
const clean = {};
|
|
@@ -48703,7 +49320,7 @@ __export(atMentions_exports, {
|
|
|
48703
49320
|
extractAtMentions: () => extractAtMentions,
|
|
48704
49321
|
hasAtMentions: () => hasAtMentions
|
|
48705
49322
|
});
|
|
48706
|
-
import { existsSync as existsSync46, readFileSync as
|
|
49323
|
+
import { existsSync as existsSync46, readFileSync as readFileSync37, statSync as statSync9 } from "node:fs";
|
|
48707
49324
|
import { basename as basename3, isAbsolute as isAbsolute2, relative as relative3, resolve, sep } from "node:path";
|
|
48708
49325
|
function isImagePath(abs) {
|
|
48709
49326
|
const ext = abs.split(".").pop()?.toLowerCase() ?? "";
|
|
@@ -48809,7 +49426,7 @@ function resolveMention(token, cwd) {
|
|
|
48809
49426
|
note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
|
|
48810
49427
|
};
|
|
48811
49428
|
}
|
|
48812
|
-
const dataBase64 =
|
|
49429
|
+
const dataBase64 = readFileSync37(abs).toString("base64");
|
|
48813
49430
|
return {
|
|
48814
49431
|
raw: token,
|
|
48815
49432
|
path: rel2,
|
|
@@ -48820,7 +49437,7 @@ function resolveMention(token, cwd) {
|
|
|
48820
49437
|
};
|
|
48821
49438
|
}
|
|
48822
49439
|
try {
|
|
48823
|
-
const buf =
|
|
49440
|
+
const buf = readFileSync37(abs);
|
|
48824
49441
|
const head = buf.subarray(0, 800).toString("utf8");
|
|
48825
49442
|
if (!isProbablyText(abs, head)) {
|
|
48826
49443
|
return {
|
|
@@ -48910,388 +49527,6 @@ var init_atMentions = __esm({
|
|
|
48910
49527
|
}
|
|
48911
49528
|
});
|
|
48912
49529
|
|
|
48913
|
-
// src/cli/headless.ts
|
|
48914
|
-
import { readFileSync as readFileSync37 } from "node:fs";
|
|
48915
|
-
function defaultProfileForMode(mode) {
|
|
48916
|
-
switch (mode) {
|
|
48917
|
-
case "council":
|
|
48918
|
-
return "council/v1";
|
|
48919
|
-
case "zelari":
|
|
48920
|
-
return "mission/v1";
|
|
48921
|
-
default:
|
|
48922
|
-
return "kraken/v1";
|
|
48923
|
-
}
|
|
48924
|
-
}
|
|
48925
|
-
function parseHeadlessFlags(argv) {
|
|
48926
|
-
if (!argv.includes("--headless")) {
|
|
48927
|
-
return { options: null };
|
|
48928
|
-
}
|
|
48929
|
-
let task;
|
|
48930
|
-
let output = "json";
|
|
48931
|
-
let mode = "kraken";
|
|
48932
|
-
let phase2 = "build";
|
|
48933
|
-
let modeExplicit = false;
|
|
48934
|
-
let councilFlag = false;
|
|
48935
|
-
let provider;
|
|
48936
|
-
let model;
|
|
48937
|
-
let history2;
|
|
48938
|
-
let todos2;
|
|
48939
|
-
let once = false;
|
|
48940
|
-
let profile;
|
|
48941
|
-
let resumeSessionId;
|
|
48942
|
-
let exportSessionPath;
|
|
48943
|
-
let strictDone = false;
|
|
48944
|
-
let krakenGraph;
|
|
48945
|
-
let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
|
|
48946
|
-
let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
|
|
48947
|
-
for (let i = 0; i < argv.length; i++) {
|
|
48948
|
-
const arg = argv[i];
|
|
48949
|
-
if (arg === "--headless") continue;
|
|
48950
|
-
if (arg === "--output") {
|
|
48951
|
-
const next = argv[i + 1];
|
|
48952
|
-
if (next === "json" || next === "plain") {
|
|
48953
|
-
output = next;
|
|
48954
|
-
i++;
|
|
48955
|
-
} else {
|
|
48956
|
-
return {
|
|
48957
|
-
options: null,
|
|
48958
|
-
error: `--output requires 'json' or 'plain', got '${next ?? "(missing)"}'`
|
|
48959
|
-
};
|
|
48960
|
-
}
|
|
48961
|
-
} else if (arg === "--task") {
|
|
48962
|
-
task = argv[i + 1];
|
|
48963
|
-
i++;
|
|
48964
|
-
} else if (arg === "--task-file") {
|
|
48965
|
-
const next = argv[i + 1];
|
|
48966
|
-
if (next) {
|
|
48967
|
-
try {
|
|
48968
|
-
const fromFile = readFileSync37(next, "utf-8");
|
|
48969
|
-
if (fromFile.trim()) task = fromFile;
|
|
48970
|
-
} catch {
|
|
48971
|
-
}
|
|
48972
|
-
}
|
|
48973
|
-
i++;
|
|
48974
|
-
} else if (arg === "--council") {
|
|
48975
|
-
councilFlag = true;
|
|
48976
|
-
} else if (arg === "--mode") {
|
|
48977
|
-
const next = argv[i + 1];
|
|
48978
|
-
const parsed = next ? parseMode(next) : null;
|
|
48979
|
-
if (!parsed) {
|
|
48980
|
-
return {
|
|
48981
|
-
options: null,
|
|
48982
|
-
error: `--mode requires 'kraken', 'council', or 'zelari' (agent=alias), got '${next ?? "(missing)"}'`
|
|
48983
|
-
};
|
|
48984
|
-
}
|
|
48985
|
-
mode = parsed;
|
|
48986
|
-
modeExplicit = true;
|
|
48987
|
-
i++;
|
|
48988
|
-
} else if (arg === "--phase") {
|
|
48989
|
-
const next = argv[i + 1];
|
|
48990
|
-
const parsed = next ? parsePhase(next) : null;
|
|
48991
|
-
if (!parsed) {
|
|
48992
|
-
return {
|
|
48993
|
-
options: null,
|
|
48994
|
-
error: `--phase requires 'plan' or 'build', got '${next ?? "(missing)"}'`
|
|
48995
|
-
};
|
|
48996
|
-
}
|
|
48997
|
-
phase2 = parsed;
|
|
48998
|
-
i++;
|
|
48999
|
-
} else if (arg === "--provider") {
|
|
49000
|
-
provider = argv[i + 1];
|
|
49001
|
-
i++;
|
|
49002
|
-
} else if (arg === "--model") {
|
|
49003
|
-
model = argv[i + 1];
|
|
49004
|
-
i++;
|
|
49005
|
-
} else if (arg === "--history" || arg === "--history-file") {
|
|
49006
|
-
const next = argv[i + 1];
|
|
49007
|
-
if (next) {
|
|
49008
|
-
let raw = null;
|
|
49009
|
-
if (arg === "--history-file") {
|
|
49010
|
-
try {
|
|
49011
|
-
raw = readFileSync37(next, "utf-8");
|
|
49012
|
-
} catch {
|
|
49013
|
-
raw = null;
|
|
49014
|
-
}
|
|
49015
|
-
} else {
|
|
49016
|
-
raw = next;
|
|
49017
|
-
}
|
|
49018
|
-
if (raw) {
|
|
49019
|
-
try {
|
|
49020
|
-
const parsedHist = JSON.parse(raw);
|
|
49021
|
-
if (Array.isArray(parsedHist)) {
|
|
49022
|
-
history2 = parsedHist.filter(
|
|
49023
|
-
(m) => !!m && typeof m === "object" && typeof m.role === "string"
|
|
49024
|
-
).map((m) => {
|
|
49025
|
-
const role = String(m.role);
|
|
49026
|
-
const raw2 = m.content;
|
|
49027
|
-
const content = typeof raw2 === "string" ? raw2 : raw2 == null ? "" : typeof raw2 === "object" ? JSON.stringify(raw2) : String(raw2);
|
|
49028
|
-
const msg = {
|
|
49029
|
-
role,
|
|
49030
|
-
content
|
|
49031
|
-
};
|
|
49032
|
-
if (typeof m.toolCallId === "string") {
|
|
49033
|
-
msg.toolCallId = m.toolCallId;
|
|
49034
|
-
}
|
|
49035
|
-
return msg;
|
|
49036
|
-
}).filter(
|
|
49037
|
-
(m) => m.role === "user" || m.role === "assistant" || m.role === "tool" || m.role === "system"
|
|
49038
|
-
);
|
|
49039
|
-
}
|
|
49040
|
-
} catch {
|
|
49041
|
-
}
|
|
49042
|
-
}
|
|
49043
|
-
i++;
|
|
49044
|
-
}
|
|
49045
|
-
} else if (arg === "--todos") {
|
|
49046
|
-
const next = argv[i + 1];
|
|
49047
|
-
if (next) {
|
|
49048
|
-
try {
|
|
49049
|
-
const parsed = JSON.parse(next);
|
|
49050
|
-
if (Array.isArray(parsed)) {
|
|
49051
|
-
todos2 = parsed.filter(
|
|
49052
|
-
(t) => !!t && typeof t === "object" && typeof t.content === "string"
|
|
49053
|
-
).map((t) => ({
|
|
49054
|
-
id: typeof t.id === "string" ? t.id : void 0,
|
|
49055
|
-
content: String(t.content).slice(0, 500),
|
|
49056
|
-
status: t.status
|
|
49057
|
-
}));
|
|
49058
|
-
}
|
|
49059
|
-
} catch {
|
|
49060
|
-
}
|
|
49061
|
-
i++;
|
|
49062
|
-
}
|
|
49063
|
-
} else if (arg === "--once") {
|
|
49064
|
-
once = true;
|
|
49065
|
-
} else if (arg === "--profile") {
|
|
49066
|
-
const next = argv[i + 1];
|
|
49067
|
-
if (!next || next.startsWith("--")) {
|
|
49068
|
-
return { options: null, error: `--profile requires a profile id (e.g. kraken/v1), got '${next ?? "(missing)"}'` };
|
|
49069
|
-
}
|
|
49070
|
-
try {
|
|
49071
|
-
resolveProfile(next);
|
|
49072
|
-
} catch (err) {
|
|
49073
|
-
return {
|
|
49074
|
-
options: null,
|
|
49075
|
-
error: err instanceof Error ? err.message : String(err)
|
|
49076
|
-
};
|
|
49077
|
-
}
|
|
49078
|
-
profile = next;
|
|
49079
|
-
i++;
|
|
49080
|
-
} else if (arg === "--resume") {
|
|
49081
|
-
const next = argv[i + 1];
|
|
49082
|
-
if (!next || next.startsWith("--")) {
|
|
49083
|
-
return { options: null, error: `--resume requires a session id, got '${next ?? "(missing)"}'` };
|
|
49084
|
-
}
|
|
49085
|
-
resumeSessionId = next;
|
|
49086
|
-
i++;
|
|
49087
|
-
} else if (arg === "--export-session") {
|
|
49088
|
-
const next = argv[i + 1];
|
|
49089
|
-
if (!next || next.startsWith("--")) {
|
|
49090
|
-
return { options: null, error: `--export-session requires a path (or - for stdout), got '${next ?? "(missing)"}'` };
|
|
49091
|
-
}
|
|
49092
|
-
exportSessionPath = next;
|
|
49093
|
-
i++;
|
|
49094
|
-
} else if (arg === "--strict-done") {
|
|
49095
|
-
strictDone = true;
|
|
49096
|
-
} else if (arg === "--kraken-graph") {
|
|
49097
|
-
krakenGraph = argv[i + 1];
|
|
49098
|
-
i++;
|
|
49099
|
-
} else if (arg === "--kraken-graph-file") {
|
|
49100
|
-
const next = argv[i + 1];
|
|
49101
|
-
if (next) {
|
|
49102
|
-
try {
|
|
49103
|
-
const fromFile = readFileSync37(next, "utf-8");
|
|
49104
|
-
if (fromFile.trim()) krakenGraph = fromFile;
|
|
49105
|
-
} catch {
|
|
49106
|
-
}
|
|
49107
|
-
}
|
|
49108
|
-
i++;
|
|
49109
|
-
} else if (arg === "--plan-only") {
|
|
49110
|
-
planOnly = true;
|
|
49111
|
-
} else if (arg === "--run-plan") {
|
|
49112
|
-
runPlan = argv[i + 1];
|
|
49113
|
-
i++;
|
|
49114
|
-
}
|
|
49115
|
-
}
|
|
49116
|
-
if (councilFlag && !modeExplicit) {
|
|
49117
|
-
mode = "council";
|
|
49118
|
-
} else if (councilFlag && modeExplicit && mode !== "council") {
|
|
49119
|
-
return {
|
|
49120
|
-
options: null,
|
|
49121
|
-
error: `--council conflicts with --mode ${mode}`
|
|
49122
|
-
};
|
|
49123
|
-
}
|
|
49124
|
-
if (task && krakenGraph) {
|
|
49125
|
-
return { options: null, error: "--task and --kraken-graph are mutually exclusive" };
|
|
49126
|
-
}
|
|
49127
|
-
if ((!task || task.trim().length === 0) && (!krakenGraph || krakenGraph.trim().length === 0)) {
|
|
49128
|
-
return { options: null, error: "--headless requires --task <prompt> or --kraken-graph <goal>" };
|
|
49129
|
-
}
|
|
49130
|
-
return {
|
|
49131
|
-
options: {
|
|
49132
|
-
task: task ?? "",
|
|
49133
|
-
output,
|
|
49134
|
-
mode,
|
|
49135
|
-
phase: phase2,
|
|
49136
|
-
useCouncil: mode === "council",
|
|
49137
|
-
provider,
|
|
49138
|
-
model,
|
|
49139
|
-
...history2 && history2.length > 0 ? { history: history2 } : {},
|
|
49140
|
-
...todos2 && todos2.length > 0 ? { todos: todos2 } : {},
|
|
49141
|
-
...once ? { once: true } : {},
|
|
49142
|
-
...profile ? { profile } : {},
|
|
49143
|
-
...resumeSessionId ? { resumeSessionId } : {},
|
|
49144
|
-
...exportSessionPath ? { exportSessionPath } : {},
|
|
49145
|
-
...strictDone ? { strictDone: true } : {},
|
|
49146
|
-
...krakenGraph ? { krakenGraph } : {},
|
|
49147
|
-
...planOnly ? { planOnly: true } : {},
|
|
49148
|
-
...runPlan ? { runPlan } : {}
|
|
49149
|
-
}
|
|
49150
|
-
};
|
|
49151
|
-
}
|
|
49152
|
-
async function resolveHeadlessKey(providerId) {
|
|
49153
|
-
const spec = PROVIDERS.find((p3) => p3.id === providerId);
|
|
49154
|
-
if (!spec) {
|
|
49155
|
-
return { error: `unknown provider: '${providerId}'` };
|
|
49156
|
-
}
|
|
49157
|
-
const resolved = await resolveApiKeyWithMeta(providerId);
|
|
49158
|
-
if (!resolved || !resolved.apiKey) {
|
|
49159
|
-
return {
|
|
49160
|
-
error: `no API key for provider '${providerId}'.
|
|
49161
|
-
Set the env var ${spec.envVar} or save a key via /login.`
|
|
49162
|
-
};
|
|
49163
|
-
}
|
|
49164
|
-
const { resolveBaseUrl: resolveBaseUrl2 } = await Promise.resolve().then(() => (init_openai_compatible(), openai_compatible_exports));
|
|
49165
|
-
return {
|
|
49166
|
-
apiKey: resolved.apiKey,
|
|
49167
|
-
baseUrl: resolveBaseUrl2(providerId)
|
|
49168
|
-
};
|
|
49169
|
-
}
|
|
49170
|
-
function resolveHeadlessProvider(opts) {
|
|
49171
|
-
const provider = opts.provider ?? getActiveProvider().id;
|
|
49172
|
-
const model = opts.model ?? getModelForProvider(provider);
|
|
49173
|
-
return { provider, model };
|
|
49174
|
-
}
|
|
49175
|
-
function emitEvent(event) {
|
|
49176
|
-
process.stdout.write(JSON.stringify(event) + "\n");
|
|
49177
|
-
}
|
|
49178
|
-
var init_headless = __esm({
|
|
49179
|
-
"src/cli/headless.ts"() {
|
|
49180
|
-
"use strict";
|
|
49181
|
-
init_keyStore();
|
|
49182
|
-
init_providerConfig();
|
|
49183
|
-
init_openai_compatible();
|
|
49184
|
-
init_phase();
|
|
49185
|
-
init_mode();
|
|
49186
|
-
init_runtime2();
|
|
49187
|
-
}
|
|
49188
|
-
});
|
|
49189
|
-
|
|
49190
|
-
// src/cli/headlessSpine.ts
|
|
49191
|
-
var headlessSpine_exports = {};
|
|
49192
|
-
__export(headlessSpine_exports, {
|
|
49193
|
-
exportSessionById: () => exportSessionById,
|
|
49194
|
-
missionStateFromSpine: () => missionStateFromSpine,
|
|
49195
|
-
openHeadlessSpine: () => openHeadlessSpine,
|
|
49196
|
-
resolveHeadlessProfileId: () => resolveHeadlessProfileId
|
|
49197
|
-
});
|
|
49198
|
-
function resolveHeadlessProfileId(mode, explicit) {
|
|
49199
|
-
if (explicit) return resolveProfile(explicit).id;
|
|
49200
|
-
return defaultProfileForMode(mode ?? "kraken");
|
|
49201
|
-
}
|
|
49202
|
-
async function openHeadlessSpine(opts) {
|
|
49203
|
-
const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
|
|
49204
|
-
let profileTools = [];
|
|
49205
|
-
try {
|
|
49206
|
-
profileTools = resolveProfile(profileId).tools;
|
|
49207
|
-
} catch {
|
|
49208
|
-
profileTools = [];
|
|
49209
|
-
}
|
|
49210
|
-
const extra = {
|
|
49211
|
-
profile: profileId,
|
|
49212
|
-
workspace: opts.workspace ?? process.cwd(),
|
|
49213
|
-
toolManifestHash: profileTools.length > 0 ? toolManifestHash(profileTools) : void 0
|
|
49214
|
-
};
|
|
49215
|
-
const mirrorOpts = {
|
|
49216
|
-
baseDir: opts.baseDir,
|
|
49217
|
-
quiet: opts.quiet,
|
|
49218
|
-
extraStarted: extra
|
|
49219
|
-
};
|
|
49220
|
-
const spine = await SessionSpineMirror.adopt(opts.sessionId, mirrorOpts);
|
|
49221
|
-
if (spine.status === "active") {
|
|
49222
|
-
spine.note("headless.profile", { profile: profileId, mode: opts.mode ?? "kraken" });
|
|
49223
|
-
}
|
|
49224
|
-
return {
|
|
49225
|
-
sessionId: opts.sessionId,
|
|
49226
|
-
profileId,
|
|
49227
|
-
spine,
|
|
49228
|
-
observe(ev) {
|
|
49229
|
-
if (ev && typeof ev === "object" && "type" in ev) {
|
|
49230
|
-
spine.mirrorBrainEvent(ev);
|
|
49231
|
-
}
|
|
49232
|
-
},
|
|
49233
|
-
userMessage(text) {
|
|
49234
|
-
spine.userMessage(text);
|
|
49235
|
-
},
|
|
49236
|
-
verificationRun(payload) {
|
|
49237
|
-
spine.verificationRun(payload);
|
|
49238
|
-
},
|
|
49239
|
-
missionPhase(phase2, note) {
|
|
49240
|
-
spine.missionPhase(phase2, note);
|
|
49241
|
-
},
|
|
49242
|
-
note(text, data) {
|
|
49243
|
-
spine.note(text, data);
|
|
49244
|
-
},
|
|
49245
|
-
async close(reason = "host-exit") {
|
|
49246
|
-
await spine.close(reason);
|
|
49247
|
-
},
|
|
49248
|
-
async interrupt(note) {
|
|
49249
|
-
if (note) spine.note("headless.interrupt", { note });
|
|
49250
|
-
await spine.release();
|
|
49251
|
-
},
|
|
49252
|
-
async exportJson() {
|
|
49253
|
-
try {
|
|
49254
|
-
const store6 = new SessionStore(resolveSessionsDir({ baseDir: opts.baseDir }));
|
|
49255
|
-
if (!await store6.exists(opts.sessionId)) return null;
|
|
49256
|
-
return await exportSessionJson(store6, opts.sessionId);
|
|
49257
|
-
} catch {
|
|
49258
|
-
return null;
|
|
49259
|
-
}
|
|
49260
|
-
}
|
|
49261
|
-
};
|
|
49262
|
-
}
|
|
49263
|
-
async function exportSessionById(sessionId2, baseDir) {
|
|
49264
|
-
try {
|
|
49265
|
-
const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
|
|
49266
|
-
if (!await store6.exists(sessionId2)) {
|
|
49267
|
-
return { ok: false, error: `session not found: ${sessionId2}` };
|
|
49268
|
-
}
|
|
49269
|
-
return { ok: true, json: await exportSessionJson(store6, sessionId2) };
|
|
49270
|
-
} catch (err) {
|
|
49271
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
49272
|
-
}
|
|
49273
|
-
}
|
|
49274
|
-
async function missionStateFromSpine(sessionId2, baseDir) {
|
|
49275
|
-
try {
|
|
49276
|
-
const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
|
|
49277
|
-
if (!await store6.exists(sessionId2)) return null;
|
|
49278
|
-
const projection = await store6.projection(sessionId2);
|
|
49279
|
-
return deriveMissionState(projection);
|
|
49280
|
-
} catch {
|
|
49281
|
-
return null;
|
|
49282
|
-
}
|
|
49283
|
-
}
|
|
49284
|
-
var init_headlessSpine = __esm({
|
|
49285
|
-
"src/cli/headlessSpine.ts"() {
|
|
49286
|
-
"use strict";
|
|
49287
|
-
init_session();
|
|
49288
|
-
init_mission2();
|
|
49289
|
-
init_runtime2();
|
|
49290
|
-
init_sessionSpine();
|
|
49291
|
-
init_headless();
|
|
49292
|
-
}
|
|
49293
|
-
});
|
|
49294
|
-
|
|
49295
49530
|
// src/cli/triggerLock.ts
|
|
49296
49531
|
var triggerLock_exports = {};
|
|
49297
49532
|
__export(triggerLock_exports, {
|
|
@@ -54998,7 +55233,7 @@ function evaluateStrictBuildGate(mode) {
|
|
|
54998
55233
|
}
|
|
54999
55234
|
const checks = krakenRequiredChecks();
|
|
55000
55235
|
const contract = krakenResultsToContract(checks, getKrakenCheckResults());
|
|
55001
|
-
const evaluation = evaluateCompletion(contract.criteria, contract.results,
|
|
55236
|
+
const evaluation = evaluateCompletion(contract.criteria, contract.results, STRICT_BUILD_POLICY);
|
|
55002
55237
|
const blocked = gate.blocked || evaluation.verdict !== "PASS";
|
|
55003
55238
|
return {
|
|
55004
55239
|
gate,
|
|
@@ -55008,6 +55243,10 @@ function evaluateStrictBuildGate(mode) {
|
|
|
55008
55243
|
summary: blocked ? `blocked (strict ${evaluation?.verdict ?? "n/a"}): ${gate.passed}/${gate.total} legacy-pass, evidence ${evaluation?.evidenceComplete ? "complete" : "incomplete"}` : `open (strict PASS): ${evaluation?.satisfied.length ?? 0}/${gate.total} criteria pass with evidence`
|
|
55009
55244
|
};
|
|
55010
55245
|
}
|
|
55246
|
+
var STRICT_DONE_EXIT_CODE = 4;
|
|
55247
|
+
function strictGateExitCode(evaluation) {
|
|
55248
|
+
return evaluation.strict && evaluation.blocked ? STRICT_DONE_EXIT_CODE : 0;
|
|
55249
|
+
}
|
|
55011
55250
|
function strictGateEventPayload(evaluation) {
|
|
55012
55251
|
return {
|
|
55013
55252
|
engine: "kraken-legacy+completion-policy",
|
|
@@ -55028,6 +55267,9 @@ function strictGateEventPayload(evaluation) {
|
|
|
55028
55267
|
};
|
|
55029
55268
|
}
|
|
55030
55269
|
|
|
55270
|
+
// src/cli/hooks/useChatTurn.ts
|
|
55271
|
+
init_headlessSpine();
|
|
55272
|
+
|
|
55031
55273
|
// src/cli/hooks/permissionPicker.ts
|
|
55032
55274
|
init_toolPermissions();
|
|
55033
55275
|
|
|
@@ -55391,6 +55633,18 @@ function useChatTurn(params) {
|
|
|
55391
55633
|
try {
|
|
55392
55634
|
const anchored = maybeAnchorShortAnswer(userText);
|
|
55393
55635
|
const effectiveUserText = anchored ?? userText;
|
|
55636
|
+
let historyForModel;
|
|
55637
|
+
{
|
|
55638
|
+
const mirror = writerRef.current?.spine ?? null;
|
|
55639
|
+
let spineSeed = null;
|
|
55640
|
+
if (mirror && mirror.status === "active") {
|
|
55641
|
+
const derived = await mirror.derivedPriorTurns();
|
|
55642
|
+
if (derived && derived.length > 0) {
|
|
55643
|
+
spineSeed = derivedModelSeed(derived);
|
|
55644
|
+
}
|
|
55645
|
+
}
|
|
55646
|
+
historyForModel = spineSeed ?? getHistory();
|
|
55647
|
+
}
|
|
55394
55648
|
writerRef.current?.spine?.userMessage(effectiveUserText);
|
|
55395
55649
|
const localCli = (process.env.ZELARI_LOCAL_CLI ?? "").trim();
|
|
55396
55650
|
let localCliProvider = null;
|
|
@@ -55520,7 +55774,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
55520
55774
|
});
|
|
55521
55775
|
}
|
|
55522
55776
|
const cwd = process.cwd();
|
|
55523
|
-
const budget = await applyBudgetPolicyAsync(
|
|
55777
|
+
const budget = await applyBudgetPolicyAsync(historyForModel, getPhase(), {
|
|
55524
55778
|
model: getActiveModel(),
|
|
55525
55779
|
sessionId: sessionId2,
|
|
55526
55780
|
// v1.36.0: envelope for full-request metering + cache-aware
|
|
@@ -55546,7 +55800,8 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
55546
55800
|
});
|
|
55547
55801
|
void writerRef.current?.append(compactionEvent);
|
|
55548
55802
|
}
|
|
55549
|
-
|
|
55803
|
+
historyForModel = budget.history;
|
|
55804
|
+
historySeedLen = historyForModel.length;
|
|
55550
55805
|
let composedWorkspace = "";
|
|
55551
55806
|
let composedInstructions = "";
|
|
55552
55807
|
let hasPlan = false;
|
|
@@ -55729,7 +55984,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
55729
55984
|
// v1.8.0: shared rolling history (agent/council/zelari) so short
|
|
55730
55985
|
// answers bind to prior ---QUESTION--- blocks. Possibly empty
|
|
55731
55986
|
// when ZELARI_HISTORY_TURNS=0.
|
|
55732
|
-
...
|
|
55987
|
+
...historyForModel,
|
|
55733
55988
|
{ role: "user", content: effectiveUserText }
|
|
55734
55989
|
],
|
|
55735
55990
|
tools: toolRegistry.toOpenAITools().map((t) => ({
|
|
@@ -55781,6 +56036,15 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
55781
56036
|
}
|
|
55782
56037
|
if (event.reason === "completed" && krakenRepairEnqueued && !evaluateStrictBuildGate("build").blocked) {
|
|
55783
56038
|
markRepairSucceeded();
|
|
56039
|
+
} else if (event.reason === "completed" && krakenRepairEnqueued) {
|
|
56040
|
+
const still = evaluateStrictBuildGate("build");
|
|
56041
|
+
if (still.blocked) {
|
|
56042
|
+
appendSystem(
|
|
56043
|
+
setMessages,
|
|
56044
|
+
`[kraken] strict done: evidence still incomplete after repair (${still.evaluation?.unsatisfied.length ?? "?"} unresolved) \u2014 turn is NOT verified-complete`,
|
|
56045
|
+
Date.now()
|
|
56046
|
+
);
|
|
56047
|
+
}
|
|
55784
56048
|
}
|
|
55785
56049
|
if (!krakenSuppressFinish) progressRuntime.finish(event.reason);
|
|
55786
56050
|
}
|
|
@@ -56174,14 +56438,31 @@ async function dispatchCouncilPromptImpl(text, deps, overrides = {}) {
|
|
|
56174
56438
|
return { completionOk: false, ran: false };
|
|
56175
56439
|
}
|
|
56176
56440
|
setBusy(true);
|
|
56177
|
-
|
|
56178
|
-
|
|
56441
|
+
let councilHistory = getHistory();
|
|
56442
|
+
{
|
|
56443
|
+
const mirror = writerRef.current?.spine ?? null;
|
|
56444
|
+
if (mirror && mirror.status === "active") {
|
|
56445
|
+
const derived = await mirror.derivedPriorTurns();
|
|
56446
|
+
if (derived && derived.length > 0) {
|
|
56447
|
+
councilHistory = derivedModelSeed(derived);
|
|
56448
|
+
}
|
|
56449
|
+
}
|
|
56450
|
+
}
|
|
56451
|
+
const councilBudget = await applyBudgetPolicyAsync(councilHistory, getPhase(), {
|
|
56179
56452
|
model: envConfig.model
|
|
56180
56453
|
});
|
|
56181
56454
|
setHistory(councilBudget.history);
|
|
56182
56455
|
for (const w of councilBudget.warnings) {
|
|
56183
56456
|
appendSystem(setMessages, w, Date.now());
|
|
56184
56457
|
}
|
|
56458
|
+
if ((councilBudget.messagesRemoved ?? 0) > 0) {
|
|
56459
|
+
void writerRef.current?.append(
|
|
56460
|
+
createBrainEvent("session_compacted", sessionId2, {
|
|
56461
|
+
summary: councilBudget.compactSummary ?? "",
|
|
56462
|
+
messagesRemoved: councilBudget.messagesRemoved ?? 0
|
|
56463
|
+
})
|
|
56464
|
+
);
|
|
56465
|
+
}
|
|
56185
56466
|
const anchored = maybeAnchorShortAnswer(text);
|
|
56186
56467
|
const effectiveText = anchored ?? text;
|
|
56187
56468
|
appendSystem(
|
|
@@ -59103,7 +59384,7 @@ async function handlePromoteMember(ctx, memberId) {
|
|
|
59103
59384
|
}
|
|
59104
59385
|
|
|
59105
59386
|
// src/cli/branchManager.ts
|
|
59106
|
-
import { promises as fs32, existsSync as existsSync44, readFileSync as
|
|
59387
|
+
import { promises as fs32, existsSync as existsSync44, readFileSync as readFileSync36, writeFileSync as writeFileSync23, mkdirSync as mkdirSync19, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
59107
59388
|
import path56 from "node:path";
|
|
59108
59389
|
import os13 from "node:os";
|
|
59109
59390
|
var META_FILENAME = "meta.json";
|
|
@@ -59129,7 +59410,7 @@ function readBranchMeta(name, baseDir) {
|
|
|
59129
59410
|
throw new BranchNotFoundError(`Branch "${name}" not found`);
|
|
59130
59411
|
}
|
|
59131
59412
|
try {
|
|
59132
|
-
const raw =
|
|
59413
|
+
const raw = readFileSync36(metaPath, "utf-8");
|
|
59133
59414
|
const parsed = JSON.parse(raw);
|
|
59134
59415
|
if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
|
|
59135
59416
|
throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
|
|
@@ -61438,6 +61719,8 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61438
61719
|
profile: opts.profile,
|
|
61439
61720
|
workspace: process.cwd()
|
|
61440
61721
|
});
|
|
61722
|
+
const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
|
|
61723
|
+
emitEvent(sessionStartedEvent(spine));
|
|
61441
61724
|
if (opts.task) spine.userMessage(opts.task);
|
|
61442
61725
|
resetKrakenCandidates();
|
|
61443
61726
|
resetKrakenTurnMetrics();
|
|
@@ -61587,15 +61870,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61587
61870
|
}
|
|
61588
61871
|
];
|
|
61589
61872
|
}
|
|
61590
|
-
const historySeed =
|
|
61591
|
-
(m) => m.role === "assistant" && m.content ? {
|
|
61592
|
-
role: "assistant",
|
|
61593
|
-
content: cleanAgentContent(m.content, {
|
|
61594
|
-
stripQuestion: false,
|
|
61595
|
-
stripThink: false
|
|
61596
|
-
})
|
|
61597
|
-
} : { role: m.role, content: m.content ?? "" }
|
|
61598
|
-
).filter((m) => (m.content ?? "").trim().length > 0);
|
|
61873
|
+
const historySeed = seededHistory.history;
|
|
61599
61874
|
const effectiveTask = buildAgentUserWithHistory(opts.task, historySeed);
|
|
61600
61875
|
const maxToolLoop = (() => {
|
|
61601
61876
|
const n = envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
|
|
@@ -61758,6 +62033,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61758
62033
|
emittedWrites: pass.emittedWrites + retry.emittedWrites
|
|
61759
62034
|
};
|
|
61760
62035
|
}
|
|
62036
|
+
let strictExit = 0;
|
|
61761
62037
|
if (pass.finalReason === "completed" && pass.exitCode === 0 && opts.mode === "kraken" && isKrakenSelectionEnabled() && !planModeFromOpts(opts)) {
|
|
61762
62038
|
const strictGate = evaluateStrictBuildGate("build");
|
|
61763
62039
|
const gate = strictGate.gate;
|
|
@@ -61799,6 +62075,13 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61799
62075
|
emitEvent({ type: "verification_run", ...afterPayload });
|
|
61800
62076
|
}
|
|
61801
62077
|
if (!after.blocked) markRepairSucceeded();
|
|
62078
|
+
else {
|
|
62079
|
+
strictExit = strictGateExitCode(after);
|
|
62080
|
+
const gateMsg = `[headless] Kraken BUILD: strict completion gate still blocked after repair pass \u2014 closing non-success (exit ${strictExit}): ${after.summary}`;
|
|
62081
|
+
if (opts.output === "json") emitEvent({ type: "log", message: gateMsg });
|
|
62082
|
+
else process.stderr.write(`[zelari-code --headless] ${gateMsg}
|
|
62083
|
+
`);
|
|
62084
|
+
}
|
|
61802
62085
|
}
|
|
61803
62086
|
}
|
|
61804
62087
|
progressRuntime.finish(pass.finalReason);
|
|
@@ -61847,7 +62130,8 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61847
62130
|
}
|
|
61848
62131
|
}
|
|
61849
62132
|
try {
|
|
61850
|
-
|
|
62133
|
+
const closeStatus = pass.finalReason === "error" ? "error" : strictExit !== 0 ? "stopped" : "completed";
|
|
62134
|
+
await spine.close(closeStatus);
|
|
61851
62135
|
} catch {
|
|
61852
62136
|
}
|
|
61853
62137
|
if (opts.exportSessionPath) {
|
|
@@ -61864,6 +62148,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
61864
62148
|
}
|
|
61865
62149
|
}
|
|
61866
62150
|
if (pass.finalReason === "error") return 3;
|
|
62151
|
+
if (strictExit !== 0) return strictExit;
|
|
61867
62152
|
return pass.exitCode;
|
|
61868
62153
|
}
|
|
61869
62154
|
async function buildCouncilToolRegistry(planMode, opts) {
|
|
@@ -61902,6 +62187,8 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
61902
62187
|
profile: opts.profile,
|
|
61903
62188
|
workspace: process.cwd()
|
|
61904
62189
|
});
|
|
62190
|
+
const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
|
|
62191
|
+
emitEvent(sessionStartedEvent(spine));
|
|
61905
62192
|
if (opts.task) spine.userMessage(opts.task);
|
|
61906
62193
|
const { shouldAllowCouncilBuild: shouldAllowCouncilBuild2 } = await Promise.resolve().then(() => (init_buildPolicy(), buildPolicy_exports));
|
|
61907
62194
|
let councilRunMode = planModeFromOpts(opts) ? "design-phase" : "implementation";
|
|
@@ -61919,15 +62206,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
61919
62206
|
);
|
|
61920
62207
|
const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
|
|
61921
62208
|
const feedbackStore = new FeedbackStore2();
|
|
61922
|
-
const historySeed =
|
|
61923
|
-
(m) => m.role === "assistant" && m.content ? {
|
|
61924
|
-
...m,
|
|
61925
|
-
content: cleanAgentContent(m.content, {
|
|
61926
|
-
stripQuestion: false,
|
|
61927
|
-
stripThink: false
|
|
61928
|
-
})
|
|
61929
|
-
} : m
|
|
61930
|
-
);
|
|
62209
|
+
const historySeed = seededHistory.history;
|
|
61931
62210
|
const effectiveTask = buildCouncilTaskWithHistory(opts.task, historySeed);
|
|
61932
62211
|
let exitCode = 0;
|
|
61933
62212
|
const scrub = createStreamScrubber2();
|
|
@@ -62046,6 +62325,8 @@ async function runHeadlessZelari(opts, provider, model, providerStream) {
|
|
|
62046
62325
|
profile: opts.profile ?? "mission/v1",
|
|
62047
62326
|
workspace: projectRoot
|
|
62048
62327
|
});
|
|
62328
|
+
const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
|
|
62329
|
+
emitEvent(sessionStartedEvent(spine));
|
|
62049
62330
|
if (opts.task) spine.userMessage(opts.task);
|
|
62050
62331
|
spine.missionPhase("design", "mission-start");
|
|
62051
62332
|
const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
@@ -62078,15 +62359,7 @@ async function runHeadlessZelari(opts, provider, model, providerStream) {
|
|
|
62078
62359
|
process.stderr.write(message + "\n");
|
|
62079
62360
|
}
|
|
62080
62361
|
};
|
|
62081
|
-
const historySeed =
|
|
62082
|
-
(m) => m.role === "assistant" && m.content ? {
|
|
62083
|
-
...m,
|
|
62084
|
-
content: cleanAgentContent(m.content, {
|
|
62085
|
-
stripQuestion: false,
|
|
62086
|
-
stripThink: false
|
|
62087
|
-
})
|
|
62088
|
-
} : m
|
|
62089
|
-
);
|
|
62362
|
+
const historySeed = seededHistory.history;
|
|
62090
62363
|
const missionTask = buildCouncilTaskWithHistory(opts.task, historySeed);
|
|
62091
62364
|
emit(`[zelari] mission brief
|
|
62092
62365
|
${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMvp?.title }, null, 0)}`);
|