zelari-code 2.37.3 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/asyncLimit.js +53 -0
- package/dist/cli/asyncLimit.js.map +1 -0
- package/dist/cli/budget/restoreRuntime.js +10 -5
- package/dist/cli/budget/restoreRuntime.js.map +1 -1
- package/dist/cli/crossProviderFailover.js +32 -0
- package/dist/cli/crossProviderFailover.js.map +1 -1
- package/dist/cli/harnessState.js +7 -3
- package/dist/cli/harnessState.js.map +1 -1
- package/dist/cli/headlessSpine.js +7 -3
- package/dist/cli/headlessSpine.js.map +1 -1
- package/dist/cli/kraken/cachedShell.js +162 -0
- package/dist/cli/kraken/cachedShell.js.map +1 -0
- package/dist/cli/kraken/contractCompiler.js +6 -1
- package/dist/cli/kraken/contractCompiler.js.map +1 -1
- package/dist/cli/kraken/executor.js +27 -17
- package/dist/cli/kraken/executor.js.map +1 -1
- package/dist/cli/kraken/nativeVerification.js +9 -1
- package/dist/cli/kraken/nativeVerification.js.map +1 -1
- package/dist/cli/kraken/worktreeCleanupBatch.js +110 -0
- package/dist/cli/kraken/worktreeCleanupBatch.js.map +1 -0
- package/dist/cli/main.bundled.js +1204 -468
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/memory/legacyImport.js +66 -14
- package/dist/cli/memory/legacyImport.js.map +1 -1
- package/dist/cli/memory/sqliteBackend.js +19 -5
- package/dist/cli/memory/sqliteBackend.js.map +1 -1
- package/dist/cli/providerFailover.js +21 -2
- package/dist/cli/providerFailover.js.map +1 -1
- package/dist/cli/runHeadless.js +32 -1
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/sessionSpine.js +26 -10
- package/dist/cli/sessionSpine.js.map +1 -1
- package/dist/cli/toolRegistry.js +23 -4
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenModel.js +72 -9
- package/dist/cli/tools/krakenModel.js.map +1 -1
- package/dist/cli/tools/krakenRadio.js +60 -3
- package/dist/cli/tools/krakenRadio.js.map +1 -1
- package/dist/cli/tools/krakenWorktree.js +105 -4
- package/dist/cli/tools/krakenWorktree.js.map +1 -1
- package/package.json +3 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -19560,11 +19560,11 @@ var init_listFiles = __esm({
|
|
|
19560
19560
|
return 1;
|
|
19561
19561
|
return a.name.localeCompare(b.name);
|
|
19562
19562
|
});
|
|
19563
|
-
const
|
|
19564
|
-
const truncated = entries.length >
|
|
19563
|
+
const MAX_ENTRIES3 = 500;
|
|
19564
|
+
const truncated = entries.length > MAX_ENTRIES3;
|
|
19565
19565
|
const warnings = entries.length === 0 ? ["DIR_EMPTY"] : [];
|
|
19566
19566
|
const status = entries.length === 0 ? "empty" : truncated ? "partial" : "complete";
|
|
19567
|
-
return typedOk({ dir: target, entries: truncated ? entries.slice(0,
|
|
19567
|
+
return typedOk({ dir: target, entries: truncated ? entries.slice(0, MAX_ENTRIES3) : entries, truncated }, {
|
|
19568
19568
|
status,
|
|
19569
19569
|
counts: { filesWalked: entries.length },
|
|
19570
19570
|
...warnings.length > 0 ? { warnings } : {},
|
|
@@ -22452,6 +22452,12 @@ var init_worktreeWorkspace = __esm({
|
|
|
22452
22452
|
|
|
22453
22453
|
// packages/core/dist/core/requestSnapshot.js
|
|
22454
22454
|
import { createHash as createHash3 } from "node:crypto";
|
|
22455
|
+
function resolveRequestSnapshotMode(env = process.env) {
|
|
22456
|
+
const raw = env.ZELARI_REQUEST_SNAPSHOT?.trim().toLowerCase();
|
|
22457
|
+
if (raw === "lite" || raw === "off")
|
|
22458
|
+
return raw;
|
|
22459
|
+
return "full";
|
|
22460
|
+
}
|
|
22455
22461
|
function stableStringify(value) {
|
|
22456
22462
|
if (value === null || typeof value !== "object")
|
|
22457
22463
|
return JSON.stringify(value) ?? "null";
|
|
@@ -22467,43 +22473,96 @@ function stableStringify(value) {
|
|
|
22467
22473
|
function sha256Hex(input) {
|
|
22468
22474
|
return createHash3("sha256").update(input, "utf8").digest("hex").slice(0, 32);
|
|
22469
22475
|
}
|
|
22470
|
-
function
|
|
22476
|
+
function cloneMessagesDeep(messages) {
|
|
22471
22477
|
return structuredClone(messages);
|
|
22472
22478
|
}
|
|
22479
|
+
function cloneMessagesLite(messages) {
|
|
22480
|
+
return messages.map((m) => ({ ...m }));
|
|
22481
|
+
}
|
|
22473
22482
|
function canonicalTools(tools) {
|
|
22474
22483
|
return [...tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
22475
22484
|
}
|
|
22485
|
+
function cloneToolsDeep(tools) {
|
|
22486
|
+
return canonicalTools(tools).map((t) => structuredClone(t));
|
|
22487
|
+
}
|
|
22488
|
+
function cloneToolsLite(tools) {
|
|
22489
|
+
return canonicalTools(tools).map((t) => ({ ...t }));
|
|
22490
|
+
}
|
|
22491
|
+
function __resetRequestSnapshotMemoForTests() {
|
|
22492
|
+
headerMemo = null;
|
|
22493
|
+
}
|
|
22476
22494
|
function createRoutedRequestSnapshot(params) {
|
|
22495
|
+
const mode = params.mode ?? resolveRequestSnapshotMode();
|
|
22477
22496
|
let split = 0;
|
|
22478
22497
|
while (split < params.messages.length && params.messages[split].role === "system") {
|
|
22479
22498
|
split++;
|
|
22480
22499
|
}
|
|
22481
|
-
const
|
|
22482
|
-
const
|
|
22483
|
-
const
|
|
22484
|
-
const
|
|
22485
|
-
|
|
22486
|
-
|
|
22487
|
-
|
|
22488
|
-
tools
|
|
22489
|
-
|
|
22490
|
-
|
|
22491
|
-
|
|
22492
|
-
|
|
22493
|
-
|
|
22494
|
-
|
|
22495
|
-
|
|
22496
|
-
|
|
22497
|
-
|
|
22498
|
-
|
|
22499
|
-
|
|
22500
|
+
const lite = mode === "lite";
|
|
22501
|
+
const cloneMsg = lite ? cloneMessagesLite : cloneMessagesDeep;
|
|
22502
|
+
const systemMessages = cloneMsg(params.messages.slice(0, split));
|
|
22503
|
+
const conversation = cloneMsg(params.messages.slice(split));
|
|
22504
|
+
const createdAt = Date.now();
|
|
22505
|
+
const { provider, model } = params;
|
|
22506
|
+
if (!lite) {
|
|
22507
|
+
const tools2 = cloneToolsDeep(params.tools);
|
|
22508
|
+
const header = stableStringify({ provider, model, systemMessages, tools: tools2 });
|
|
22509
|
+
const request = stableStringify({
|
|
22510
|
+
provider,
|
|
22511
|
+
model,
|
|
22512
|
+
systemMessages,
|
|
22513
|
+
tools: tools2,
|
|
22514
|
+
conversation
|
|
22515
|
+
});
|
|
22516
|
+
return {
|
|
22517
|
+
provider,
|
|
22518
|
+
model,
|
|
22519
|
+
systemMessages,
|
|
22520
|
+
conversation,
|
|
22521
|
+
tools: tools2,
|
|
22522
|
+
headerFingerprint: sha256Hex(header),
|
|
22523
|
+
requestFingerprint: sha256Hex(request),
|
|
22524
|
+
createdAt
|
|
22525
|
+
};
|
|
22526
|
+
}
|
|
22527
|
+
const systemKey = sha256Hex(stableStringify(systemMessages));
|
|
22528
|
+
let tools;
|
|
22529
|
+
let headerFp;
|
|
22530
|
+
if (headerMemo && headerMemo.toolsRef === params.tools && headerMemo.provider === provider && headerMemo.model === model && headerMemo.systemKey === systemKey) {
|
|
22531
|
+
tools = headerMemo.tools;
|
|
22532
|
+
headerFp = headerMemo.headerFingerprint;
|
|
22533
|
+
} else {
|
|
22534
|
+
tools = cloneToolsLite(params.tools);
|
|
22535
|
+
}
|
|
22536
|
+
let requestFp;
|
|
22537
|
+
const snap = {
|
|
22538
|
+
provider,
|
|
22539
|
+
model,
|
|
22500
22540
|
systemMessages,
|
|
22501
22541
|
conversation,
|
|
22502
22542
|
tools,
|
|
22503
|
-
|
|
22504
|
-
|
|
22505
|
-
|
|
22543
|
+
createdAt,
|
|
22544
|
+
get headerFingerprint() {
|
|
22545
|
+
if (headerFp === void 0) {
|
|
22546
|
+
headerFp = sha256Hex(stableStringify({ provider, model, systemMessages, tools }));
|
|
22547
|
+
headerMemo = {
|
|
22548
|
+
toolsRef: params.tools,
|
|
22549
|
+
provider,
|
|
22550
|
+
model,
|
|
22551
|
+
systemKey,
|
|
22552
|
+
tools,
|
|
22553
|
+
headerFingerprint: headerFp
|
|
22554
|
+
};
|
|
22555
|
+
}
|
|
22556
|
+
return headerFp;
|
|
22557
|
+
},
|
|
22558
|
+
get requestFingerprint() {
|
|
22559
|
+
if (requestFp === void 0) {
|
|
22560
|
+
requestFp = sha256Hex(stableStringify({ provider, model, systemMessages, tools, conversation }));
|
|
22561
|
+
}
|
|
22562
|
+
return requestFp;
|
|
22563
|
+
}
|
|
22506
22564
|
};
|
|
22565
|
+
return snap;
|
|
22507
22566
|
}
|
|
22508
22567
|
function compareReplayPrefix(snapshot, messages) {
|
|
22509
22568
|
const base2 = snapshot.conversation;
|
|
@@ -22517,9 +22576,11 @@ function compareReplayPrefix(snapshot, messages) {
|
|
|
22517
22576
|
}
|
|
22518
22577
|
return { exact: true, matchingMessages: matching };
|
|
22519
22578
|
}
|
|
22579
|
+
var headerMemo;
|
|
22520
22580
|
var init_requestSnapshot = __esm({
|
|
22521
22581
|
"packages/core/dist/core/requestSnapshot.js"() {
|
|
22522
22582
|
"use strict";
|
|
22583
|
+
headerMemo = null;
|
|
22523
22584
|
}
|
|
22524
22585
|
});
|
|
22525
22586
|
|
|
@@ -23520,15 +23581,22 @@ async function readSessionLog(filePath) {
|
|
|
23520
23581
|
}
|
|
23521
23582
|
throw err;
|
|
23522
23583
|
}
|
|
23584
|
+
return parseSessionLogText(filePath, content);
|
|
23585
|
+
}
|
|
23586
|
+
function parseSessionLogText(filePath, content) {
|
|
23587
|
+
const { events, issues } = parseSessionLogLines(content.split("\n"));
|
|
23588
|
+
return { path: filePath, events, issues, ok: issues.length === 0 };
|
|
23589
|
+
}
|
|
23590
|
+
function parseSessionLogLines(lines, opts = {}) {
|
|
23523
23591
|
const events = [];
|
|
23524
23592
|
const issues = [];
|
|
23525
|
-
|
|
23526
|
-
|
|
23593
|
+
const base2 = opts.linesConsumed ?? 0;
|
|
23594
|
+
let expected = opts.expected ?? 1;
|
|
23527
23595
|
for (let i = 0; i < lines.length; i++) {
|
|
23528
23596
|
const trimmed = lines[i].trim();
|
|
23529
23597
|
if (!trimmed)
|
|
23530
23598
|
continue;
|
|
23531
|
-
const lineNo = i + 1;
|
|
23599
|
+
const lineNo = base2 + i + 1;
|
|
23532
23600
|
let parsed;
|
|
23533
23601
|
try {
|
|
23534
23602
|
parsed = JSON.parse(trimmed);
|
|
@@ -23562,7 +23630,7 @@ async function readSessionLog(filePath) {
|
|
|
23562
23630
|
expected = envelope.seq + 1;
|
|
23563
23631
|
}
|
|
23564
23632
|
}
|
|
23565
|
-
return {
|
|
23633
|
+
return { events, issues, expected, linesConsumed: base2 + lines.length };
|
|
23566
23634
|
}
|
|
23567
23635
|
function parseVerification(e) {
|
|
23568
23636
|
const raw = Array.isArray(e.data.results) ? e.data.results : [];
|
|
@@ -23810,7 +23878,7 @@ async function createExecutionContext(options = {}) {
|
|
|
23810
23878
|
workspaceKind: workspace.kind
|
|
23811
23879
|
}
|
|
23812
23880
|
});
|
|
23813
|
-
const
|
|
23881
|
+
const fs49 = options.fs ?? new NodeFsProvider(workspace);
|
|
23814
23882
|
const shell = options.shell ?? new NodeShellProvider(workspace);
|
|
23815
23883
|
const subagent = options.subagent ?? NOOP_SUBAGENT_PROVIDER;
|
|
23816
23884
|
const env = options.env ?? process.env;
|
|
@@ -23818,7 +23886,7 @@ async function createExecutionContext(options = {}) {
|
|
|
23818
23886
|
sessionId: sessionId2,
|
|
23819
23887
|
profile,
|
|
23820
23888
|
workspace,
|
|
23821
|
-
fs:
|
|
23889
|
+
fs: fs49,
|
|
23822
23890
|
shell,
|
|
23823
23891
|
subagent,
|
|
23824
23892
|
appendSessionEvent: (input) => writer.append(input),
|
|
@@ -25589,6 +25657,60 @@ var init_scopeDiscipline = __esm({
|
|
|
25589
25657
|
}
|
|
25590
25658
|
});
|
|
25591
25659
|
|
|
25660
|
+
// packages/core/dist/verification/commandConcurrency.js
|
|
25661
|
+
function isVerifyParallelEnabled(env = process.env) {
|
|
25662
|
+
const raw = env.ZELARI_VERIFY_PARALLEL?.trim().toLowerCase();
|
|
25663
|
+
return raw !== void 0 && PARALLEL_TRUTHY.has(raw);
|
|
25664
|
+
}
|
|
25665
|
+
function resolveCommandConcurrency(env = process.env) {
|
|
25666
|
+
if (!isVerifyParallelEnabled(env))
|
|
25667
|
+
return 1;
|
|
25668
|
+
const raw = Number(env.ZELARI_VERIFY_CONCURRENCY);
|
|
25669
|
+
if (!Number.isFinite(raw) || raw <= 0)
|
|
25670
|
+
return DEFAULT_COMMAND_CONCURRENCY;
|
|
25671
|
+
return Math.floor(raw);
|
|
25672
|
+
}
|
|
25673
|
+
var DEFAULT_COMMAND_CONCURRENCY, PARALLEL_TRUTHY;
|
|
25674
|
+
var init_commandConcurrency = __esm({
|
|
25675
|
+
"packages/core/dist/verification/commandConcurrency.js"() {
|
|
25676
|
+
"use strict";
|
|
25677
|
+
DEFAULT_COMMAND_CONCURRENCY = 3;
|
|
25678
|
+
PARALLEL_TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
25679
|
+
}
|
|
25680
|
+
});
|
|
25681
|
+
|
|
25682
|
+
// packages/core/dist/verification/runWithLimit.js
|
|
25683
|
+
async function runWithLimit(items, limit, fn) {
|
|
25684
|
+
const slots = Math.min(items.length, Math.max(1, Number.isFinite(limit) ? Math.floor(limit) : 1));
|
|
25685
|
+
if (slots <= 0)
|
|
25686
|
+
return;
|
|
25687
|
+
let cursor = 0;
|
|
25688
|
+
let failed = false;
|
|
25689
|
+
let firstError;
|
|
25690
|
+
const worker = async () => {
|
|
25691
|
+
while (!failed && cursor < items.length) {
|
|
25692
|
+
const index = cursor;
|
|
25693
|
+
cursor += 1;
|
|
25694
|
+
try {
|
|
25695
|
+
await fn(items[index], index);
|
|
25696
|
+
} catch (err) {
|
|
25697
|
+
if (!failed) {
|
|
25698
|
+
failed = true;
|
|
25699
|
+
firstError = err;
|
|
25700
|
+
}
|
|
25701
|
+
}
|
|
25702
|
+
}
|
|
25703
|
+
};
|
|
25704
|
+
await Promise.all(Array.from({ length: slots }, () => worker()));
|
|
25705
|
+
if (failed)
|
|
25706
|
+
throw firstError;
|
|
25707
|
+
}
|
|
25708
|
+
var init_runWithLimit = __esm({
|
|
25709
|
+
"packages/core/dist/verification/runWithLimit.js"() {
|
|
25710
|
+
"use strict";
|
|
25711
|
+
}
|
|
25712
|
+
});
|
|
25713
|
+
|
|
25592
25714
|
// packages/core/dist/verification/engine.js
|
|
25593
25715
|
import { createHash as createHash8 } from "node:crypto";
|
|
25594
25716
|
function defaultSha256(input) {
|
|
@@ -25597,11 +25719,14 @@ function defaultSha256(input) {
|
|
|
25597
25719
|
function tail(text, max = 400) {
|
|
25598
25720
|
return text.length > max ? `\u2026${text.slice(text.length - max)}` : text;
|
|
25599
25721
|
}
|
|
25600
|
-
var VerificationEngine;
|
|
25722
|
+
var CACHED_DETAIL_NOTE, VerificationEngine;
|
|
25601
25723
|
var init_engine = __esm({
|
|
25602
25724
|
"packages/core/dist/verification/engine.js"() {
|
|
25603
25725
|
"use strict";
|
|
25604
25726
|
init_scopeDiscipline();
|
|
25727
|
+
init_commandConcurrency();
|
|
25728
|
+
init_runWithLimit();
|
|
25729
|
+
CACHED_DETAIL_NOTE = "cached \u2014 tree unchanged since last run";
|
|
25605
25730
|
VerificationEngine = class {
|
|
25606
25731
|
services;
|
|
25607
25732
|
options;
|
|
@@ -25612,8 +25737,15 @@ var init_engine = __esm({
|
|
|
25612
25737
|
/** Evaluate criteria deterministically; optionally emit the spine event. */
|
|
25613
25738
|
async evaluate(criteria, context = {}) {
|
|
25614
25739
|
const results = [];
|
|
25615
|
-
|
|
25616
|
-
|
|
25740
|
+
const limit = this.options.commandConcurrency ?? resolveCommandConcurrency();
|
|
25741
|
+
if (limit <= 1) {
|
|
25742
|
+
for (const criterion of criteria) {
|
|
25743
|
+
results.push(await this.evaluateOne(criterion, context.scope));
|
|
25744
|
+
}
|
|
25745
|
+
} else {
|
|
25746
|
+
await runWithLimit(criteria, limit, async (criterion, index) => {
|
|
25747
|
+
results[index] = await this.evaluateOne(criterion, context.scope);
|
|
25748
|
+
});
|
|
25617
25749
|
}
|
|
25618
25750
|
if (this.options.emit) {
|
|
25619
25751
|
try {
|
|
@@ -25704,13 +25836,18 @@ var init_engine = __esm({
|
|
|
25704
25836
|
}
|
|
25705
25837
|
}
|
|
25706
25838
|
async evalCommand(check2, done) {
|
|
25707
|
-
const
|
|
25839
|
+
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
25708
25840
|
const shell = this.services.shell;
|
|
25709
25841
|
if (!shell) {
|
|
25710
25842
|
return done({ status: "unknown", evidence: [], detail: "shell provider unavailable" });
|
|
25711
25843
|
}
|
|
25712
25844
|
const result = await shell.exec(check2.command, { timeoutMs: check2.timeoutMs });
|
|
25713
|
-
const digest =
|
|
25845
|
+
const digest = sha2562(result.stdout);
|
|
25846
|
+
const cached2 = result.cached === true;
|
|
25847
|
+
const finish2 = (patch) => cached2 ? done({
|
|
25848
|
+
...patch,
|
|
25849
|
+
detail: patch.detail ? `${patch.detail} (${CACHED_DETAIL_NOTE})` : CACHED_DETAIL_NOTE
|
|
25850
|
+
}) : done(patch);
|
|
25714
25851
|
const seq = await this.emitEvidence({
|
|
25715
25852
|
observation: "command",
|
|
25716
25853
|
command: check2.command,
|
|
@@ -25718,7 +25855,9 @@ var init_engine = __esm({
|
|
|
25718
25855
|
timedOut: result.timedOut,
|
|
25719
25856
|
digest,
|
|
25720
25857
|
stdoutTail: tail(result.stdout),
|
|
25721
|
-
stderrTail: tail(result.stderr)
|
|
25858
|
+
stderrTail: tail(result.stderr),
|
|
25859
|
+
// Additive (optional) field: replay of older logs without it still parses.
|
|
25860
|
+
...cached2 ? { cached: true } : {}
|
|
25722
25861
|
});
|
|
25723
25862
|
const evidence = [
|
|
25724
25863
|
{
|
|
@@ -25730,32 +25869,32 @@ var init_engine = __esm({
|
|
|
25730
25869
|
}
|
|
25731
25870
|
];
|
|
25732
25871
|
if (result.timedOut) {
|
|
25733
|
-
return
|
|
25872
|
+
return finish2({ status: "unknown", evidence, detail: `command timed out (${check2.timeoutMs ?? "default"}ms)` });
|
|
25734
25873
|
}
|
|
25735
25874
|
const expectExit = check2.expectExit ?? 0;
|
|
25736
25875
|
if (result.exitCode !== expectExit) {
|
|
25737
|
-
return
|
|
25876
|
+
return finish2({
|
|
25738
25877
|
status: "fail",
|
|
25739
25878
|
evidence,
|
|
25740
25879
|
detail: `exit ${result.exitCode} (expected ${expectExit}) \u2014 stderr: ${tail(result.stderr)}`
|
|
25741
25880
|
});
|
|
25742
25881
|
}
|
|
25743
25882
|
if (check2.expectStdoutIncludes && !result.stdout.includes(check2.expectStdoutIncludes)) {
|
|
25744
|
-
return
|
|
25883
|
+
return finish2({
|
|
25745
25884
|
status: "fail",
|
|
25746
25885
|
evidence,
|
|
25747
25886
|
detail: `stdout missing "${check2.expectStdoutIncludes}" \u2014 got: ${tail(result.stdout)}`
|
|
25748
25887
|
});
|
|
25749
25888
|
}
|
|
25750
|
-
return
|
|
25889
|
+
return finish2({ status: "pass", evidence });
|
|
25751
25890
|
}
|
|
25752
25891
|
/**
|
|
25753
25892
|
* F3: the fs observation is logged to the spine (path, existence, optional
|
|
25754
25893
|
* content digest) and the returned ref carries the event seq when the
|
|
25755
25894
|
* emitter resolved one.
|
|
25756
25895
|
*/
|
|
25757
|
-
async fsEvidence(observation, path101,
|
|
25758
|
-
const digest =
|
|
25896
|
+
async fsEvidence(observation, path101, sha2562, content, extra = {}) {
|
|
25897
|
+
const digest = sha2562 && content !== void 0 ? sha2562(content) : void 0;
|
|
25759
25898
|
const seq = await this.emitEvidence({ observation, path: path101, ...extra, ...digest ? { digest } : {} });
|
|
25760
25899
|
return {
|
|
25761
25900
|
tier: "fs-observation",
|
|
@@ -25766,26 +25905,26 @@ var init_engine = __esm({
|
|
|
25766
25905
|
};
|
|
25767
25906
|
}
|
|
25768
25907
|
async evalFileExists(check2, done) {
|
|
25769
|
-
const
|
|
25770
|
-
const
|
|
25771
|
-
if (!
|
|
25908
|
+
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
25909
|
+
const fs49 = this.services.fs;
|
|
25910
|
+
if (!fs49)
|
|
25772
25911
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25773
|
-
const exists = await
|
|
25912
|
+
const exists = await fs49.exists(check2.path);
|
|
25774
25913
|
if (!exists) {
|
|
25775
25914
|
await this.emitEvidence({ observation: "file-exists", path: check2.path, exists: false });
|
|
25776
25915
|
return done({ status: "fail", evidence: [], detail: `file not found: ${check2.path}` });
|
|
25777
25916
|
}
|
|
25778
|
-
const content = await
|
|
25917
|
+
const content = await fs49.readFile(check2.path).catch(() => "");
|
|
25779
25918
|
return done({
|
|
25780
25919
|
status: "pass",
|
|
25781
|
-
evidence: [await this.fsEvidence("file-exists", check2.path,
|
|
25920
|
+
evidence: [await this.fsEvidence("file-exists", check2.path, sha2562, content, { exists: true })]
|
|
25782
25921
|
});
|
|
25783
25922
|
}
|
|
25784
25923
|
async evalFileAbsent(check2, done) {
|
|
25785
|
-
const
|
|
25786
|
-
if (!
|
|
25924
|
+
const fs49 = this.services.fs;
|
|
25925
|
+
if (!fs49)
|
|
25787
25926
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25788
|
-
const exists = await
|
|
25927
|
+
const exists = await fs49.exists(check2.path);
|
|
25789
25928
|
if (exists) {
|
|
25790
25929
|
await this.emitEvidence({ observation: "file-absent", path: check2.path, exists: true });
|
|
25791
25930
|
return done({ status: "fail", evidence: [], detail: `file still present: ${check2.path}` });
|
|
@@ -25796,18 +25935,18 @@ var init_engine = __esm({
|
|
|
25796
25935
|
});
|
|
25797
25936
|
}
|
|
25798
25937
|
async evalFileContains(check2, done) {
|
|
25799
|
-
const
|
|
25800
|
-
const
|
|
25801
|
-
if (!
|
|
25938
|
+
const sha2562 = this.options.sha256 ?? defaultSha256;
|
|
25939
|
+
const fs49 = this.services.fs;
|
|
25940
|
+
if (!fs49)
|
|
25802
25941
|
return done({ status: "unknown", evidence: [], detail: "fs provider unavailable" });
|
|
25803
25942
|
let content;
|
|
25804
25943
|
try {
|
|
25805
|
-
content = await
|
|
25944
|
+
content = await fs49.readFile(check2.path);
|
|
25806
25945
|
} catch {
|
|
25807
25946
|
await this.emitEvidence({ observation: "file-contains", path: check2.path, readable: false });
|
|
25808
25947
|
return done({ status: "fail", evidence: [], detail: `file not readable: ${check2.path}` });
|
|
25809
25948
|
}
|
|
25810
|
-
const evidence = [await this.fsEvidence("file-contains", check2.path,
|
|
25949
|
+
const evidence = [await this.fsEvidence("file-contains", check2.path, sha2562, content)];
|
|
25811
25950
|
let hit;
|
|
25812
25951
|
try {
|
|
25813
25952
|
hit = new RegExp(check2.pattern, "m").test(content);
|
|
@@ -26355,6 +26494,7 @@ __export(verification_exports, {
|
|
|
26355
26494
|
CommandCheckSchema: () => CommandCheckSchema,
|
|
26356
26495
|
CriterionSchema: () => CriterionSchema,
|
|
26357
26496
|
CriterionSourceSchema: () => CriterionSourceSchema,
|
|
26497
|
+
DEFAULT_COMMAND_CONCURRENCY: () => DEFAULT_COMMAND_CONCURRENCY,
|
|
26358
26498
|
DEFAULT_VERIFIER_CONFIG: () => DEFAULT_VERIFIER_CONFIG,
|
|
26359
26499
|
DETERMINISTIC_EVIDENCE_TIERS: () => DETERMINISTIC_EVIDENCE_TIERS,
|
|
26360
26500
|
DeterministicCheckSchema: () => DeterministicCheckSchema,
|
|
@@ -26383,9 +26523,11 @@ __export(verification_exports, {
|
|
|
26383
26523
|
evaluateResourceReserveGate: () => evaluateResourceReserveGate,
|
|
26384
26524
|
isEventBackedEvidence: () => isEventBackedEvidence,
|
|
26385
26525
|
isGeneratedPath: () => isGeneratedPath,
|
|
26526
|
+
isVerifyParallelEnabled: () => isVerifyParallelEnabled,
|
|
26386
26527
|
lastVerificationRun: () => lastVerificationRun,
|
|
26387
26528
|
parseNameOnlyDiff: () => parseNameOnlyDiff,
|
|
26388
26529
|
parseVerificationRunPayload: () => parseVerificationRunPayload,
|
|
26530
|
+
resolveCommandConcurrency: () => resolveCommandConcurrency,
|
|
26389
26531
|
snapshotToCompletionEvaluation: () => snapshotToCompletionEvaluation,
|
|
26390
26532
|
strictBuildGate: () => strictBuildGate,
|
|
26391
26533
|
verificationCostRatio: () => verificationCostRatio,
|
|
@@ -26402,6 +26544,7 @@ var init_verification = __esm({
|
|
|
26402
26544
|
init_metrics();
|
|
26403
26545
|
init_verifier();
|
|
26404
26546
|
init_scopeDiscipline();
|
|
26547
|
+
init_commandConcurrency();
|
|
26405
26548
|
init_resourceReserveGate();
|
|
26406
26549
|
}
|
|
26407
26550
|
});
|
|
@@ -26749,6 +26892,102 @@ var init_verificationAdapters = __esm({
|
|
|
26749
26892
|
}
|
|
26750
26893
|
});
|
|
26751
26894
|
|
|
26895
|
+
// src/cli/kraken/cachedShell.ts
|
|
26896
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
26897
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
26898
|
+
import { promisify } from "node:util";
|
|
26899
|
+
function verifyCacheEnabled(env = process.env) {
|
|
26900
|
+
const v = env.ZELARI_VERIFY_CACHE?.toLowerCase();
|
|
26901
|
+
if (v === "0" || v === "off" || v === "false") return false;
|
|
26902
|
+
return true;
|
|
26903
|
+
}
|
|
26904
|
+
function sha256(input) {
|
|
26905
|
+
return createHash9("sha256").update(input).digest("hex");
|
|
26906
|
+
}
|
|
26907
|
+
async function readTreeState(root) {
|
|
26908
|
+
try {
|
|
26909
|
+
const opts = { maxBuffer: GIT_MAX_BUFFER, timeout: GIT_TIMEOUT_MS, windowsHide: true };
|
|
26910
|
+
const [head, status] = await Promise.all([
|
|
26911
|
+
execFileAsync("git", ["-C", root, "rev-parse", "HEAD"], opts),
|
|
26912
|
+
execFileAsync("git", ["-C", root, "status", "--porcelain", "--untracked-files=all"], opts)
|
|
26913
|
+
]);
|
|
26914
|
+
return `HEAD:${String(head.stdout).trim()}|${sha256(String(status.stdout))}`;
|
|
26915
|
+
} catch {
|
|
26916
|
+
return null;
|
|
26917
|
+
}
|
|
26918
|
+
}
|
|
26919
|
+
function wrapWithVerifyCache(shell, options = {}) {
|
|
26920
|
+
const env = options.env ?? process.env;
|
|
26921
|
+
if (!verifyCacheEnabled(env)) return shell;
|
|
26922
|
+
return new CachedShellProvider(shell, options);
|
|
26923
|
+
}
|
|
26924
|
+
var execFileAsync, MAX_ENTRIES, TREE_TTL_MS, GIT_MAX_BUFFER, GIT_TIMEOUT_MS, cache, CachedShellProvider;
|
|
26925
|
+
var init_cachedShell = __esm({
|
|
26926
|
+
"src/cli/kraken/cachedShell.ts"() {
|
|
26927
|
+
"use strict";
|
|
26928
|
+
execFileAsync = promisify(execFile2);
|
|
26929
|
+
MAX_ENTRIES = 32;
|
|
26930
|
+
TREE_TTL_MS = 5e3;
|
|
26931
|
+
GIT_MAX_BUFFER = 8 * 1024 * 1024;
|
|
26932
|
+
GIT_TIMEOUT_MS = 1e4;
|
|
26933
|
+
cache = /* @__PURE__ */ new Map();
|
|
26934
|
+
CachedShellProvider = class {
|
|
26935
|
+
constructor(inner, options = {}) {
|
|
26936
|
+
this.inner = inner;
|
|
26937
|
+
this.root = options.root ?? process.cwd();
|
|
26938
|
+
}
|
|
26939
|
+
root;
|
|
26940
|
+
/**
|
|
26941
|
+
* Tree token memo, PER INSTANCE (5 s TTL). Deliberately not module-level: a
|
|
26942
|
+
* stale token would keep matching the pre-write key for up to the TTL and
|
|
26943
|
+
* serve the PRE-repair result after the repair wrote files — a false PASS
|
|
26944
|
+
* window on the gate. Every evaluation builds its own decorator, so a write
|
|
26945
|
+
* made between evaluations is always observed; the memo only avoids
|
|
26946
|
+
* re-running git for the sibling criteria of the SAME evaluation.
|
|
26947
|
+
*/
|
|
26948
|
+
treeMemo;
|
|
26949
|
+
async treeState() {
|
|
26950
|
+
const now = Date.now();
|
|
26951
|
+
if (this.treeMemo && now - this.treeMemo.at < TREE_TTL_MS) return this.treeMemo.value;
|
|
26952
|
+
const value = await readTreeState(this.root);
|
|
26953
|
+
this.treeMemo = { at: now, value };
|
|
26954
|
+
return value;
|
|
26955
|
+
}
|
|
26956
|
+
async exec(command, options = {}) {
|
|
26957
|
+
const tree = await this.treeState();
|
|
26958
|
+
if (tree === null) return await this.inner.exec(command, options);
|
|
26959
|
+
const key = sha256(
|
|
26960
|
+
JSON.stringify({
|
|
26961
|
+
command,
|
|
26962
|
+
cwd: options.cwd ?? "",
|
|
26963
|
+
timeoutMs: options.timeoutMs ?? null,
|
|
26964
|
+
tree,
|
|
26965
|
+
// Additive safety field: two evaluation roots in ONE process must
|
|
26966
|
+
// never collide on the same relative cwd.
|
|
26967
|
+
root: this.root
|
|
26968
|
+
})
|
|
26969
|
+
);
|
|
26970
|
+
const started = Date.now();
|
|
26971
|
+
const hit = cache.get(key);
|
|
26972
|
+
if (hit !== void 0) {
|
|
26973
|
+
cache.delete(key);
|
|
26974
|
+
cache.set(key, hit);
|
|
26975
|
+
return { ...hit, cached: true, durationMs: Date.now() - started };
|
|
26976
|
+
}
|
|
26977
|
+
const result = await this.inner.exec(command, options);
|
|
26978
|
+
if (!result.timedOut && result.exitCode !== null) {
|
|
26979
|
+
cache.set(key, { ...result });
|
|
26980
|
+
if (cache.size > MAX_ENTRIES) {
|
|
26981
|
+
const oldest = cache.keys().next().value;
|
|
26982
|
+
if (oldest !== void 0) cache.delete(oldest);
|
|
26983
|
+
}
|
|
26984
|
+
}
|
|
26985
|
+
return result;
|
|
26986
|
+
}
|
|
26987
|
+
};
|
|
26988
|
+
}
|
|
26989
|
+
});
|
|
26990
|
+
|
|
26752
26991
|
// src/cli/kraken/nativeVerification.ts
|
|
26753
26992
|
var nativeVerification_exports = {};
|
|
26754
26993
|
__export(nativeVerification_exports, {
|
|
@@ -26829,7 +27068,7 @@ async function evaluateNativePack(deps = {}) {
|
|
|
26829
27068
|
if (!commands.typecheckCommand && !commands.testCommand && !commands.buildCommand) return null;
|
|
26830
27069
|
const criteria = buildNativeCriteria(commands, packTimeoutMs(env));
|
|
26831
27070
|
if (criteria.length === 0) return null;
|
|
26832
|
-
const shell = deps.shell ?? new NodeShellProvider(new LocalWorkspace(cwd));
|
|
27071
|
+
const shell = deps.shell ?? wrapWithVerifyCache(new NodeShellProvider(new LocalWorkspace(cwd)), { root: cwd, env });
|
|
26833
27072
|
const engine = deps.emit ? new VerificationEngine({ shell }, { emit: deps.emit }) : new VerificationEngine({ shell });
|
|
26834
27073
|
const results = await engine.evaluate(criteria, { packId: ZELARI_CODING_PACK_ID });
|
|
26835
27074
|
return { packId: ZELARI_CODING_PACK_ID, criteria, results };
|
|
@@ -26841,6 +27080,7 @@ var init_nativeVerification = __esm({
|
|
|
26841
27080
|
init_runtime();
|
|
26842
27081
|
init_verification();
|
|
26843
27082
|
init_verificationAdapters();
|
|
27083
|
+
init_cachedShell();
|
|
26844
27084
|
EMPTY_PLAN = {
|
|
26845
27085
|
typecheckCommand: null,
|
|
26846
27086
|
testCommand: null,
|
|
@@ -27207,7 +27447,7 @@ async function evaluateContractCriteria(contract, deps = {}) {
|
|
|
27207
27447
|
const cwd = deps.cwd ?? process.cwd();
|
|
27208
27448
|
const criteria = compileVerificationCriteria(contract, { timeoutMs: deps.timeoutMs });
|
|
27209
27449
|
if (criteria.length === 0) return null;
|
|
27210
|
-
const shell = deps.shell ?? new NodeShellProvider(new LocalWorkspace(cwd));
|
|
27450
|
+
const shell = deps.shell ?? wrapWithVerifyCache(new NodeShellProvider(new LocalWorkspace(cwd)), { root: cwd });
|
|
27211
27451
|
const engine = deps.emit ? new VerificationEngine({ shell }, { emit: deps.emit }) : new VerificationEngine({ shell });
|
|
27212
27452
|
const results = await engine.evaluate(criteria, { packId: CONTRACT_CRITERIA_PACK_ID });
|
|
27213
27453
|
return { criteria, results };
|
|
@@ -27219,6 +27459,7 @@ var init_contractCompiler = __esm({
|
|
|
27219
27459
|
init_runtime();
|
|
27220
27460
|
init_verification();
|
|
27221
27461
|
init_policyEngine();
|
|
27462
|
+
init_cachedShell();
|
|
27222
27463
|
CONTRACT_CRITERIA_PACK_ID = "task-contract/v1";
|
|
27223
27464
|
CONTRACT_COMMAND_TIMEOUT_MS = 6e5;
|
|
27224
27465
|
MAX_COMMAND_LENGTH = 512;
|
|
@@ -27242,7 +27483,7 @@ __export(verificationBridge_exports, {
|
|
|
27242
27483
|
strictGateEventPayload: () => strictGateEventPayload,
|
|
27243
27484
|
strictGateExitCode: () => strictGateExitCode
|
|
27244
27485
|
});
|
|
27245
|
-
import { createHash as
|
|
27486
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
27246
27487
|
function strictDoneEnabled(surface = "kraken", env = process.env) {
|
|
27247
27488
|
if (surface === "mission") {
|
|
27248
27489
|
const v2 = env.ZELARI_MISSION_STRICT;
|
|
@@ -27318,7 +27559,7 @@ function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
|
27318
27559
|
return { criteria, results: verifications };
|
|
27319
27560
|
}
|
|
27320
27561
|
function sha256Hex2(input) {
|
|
27321
|
-
return
|
|
27562
|
+
return createHash10("sha256").update(input).digest("hex");
|
|
27322
27563
|
}
|
|
27323
27564
|
function matchNoteToToolTrace(note, trace) {
|
|
27324
27565
|
const n = normalize3(note);
|
|
@@ -29729,6 +29970,8 @@ ${shared.content}`,
|
|
|
29729
29970
|
emitSnapshot(tools, generation, messages = this.messagesForProvider()) {
|
|
29730
29971
|
if (!this.config.onRequestSnapshot)
|
|
29731
29972
|
return;
|
|
29973
|
+
if (resolveRequestSnapshotMode() === "off")
|
|
29974
|
+
return;
|
|
29732
29975
|
try {
|
|
29733
29976
|
this.config.onRequestSnapshot(createRoutedRequestSnapshot({
|
|
29734
29977
|
messages,
|
|
@@ -31022,6 +31265,7 @@ __export(harness_exports, {
|
|
|
31022
31265
|
TEXT_TOOLS_PARTIAL_USER: () => TEXT_TOOLS_PARTIAL_USER,
|
|
31023
31266
|
TOOL_CALL_TRUNCATED_RECOVERY_MARKER: () => TOOL_CALL_TRUNCATED_RECOVERY_MARKER,
|
|
31024
31267
|
TOOL_CALL_TRUNCATED_RECOVERY_USER: () => TOOL_CALL_TRUNCATED_RECOVERY_USER,
|
|
31268
|
+
__resetRequestSnapshotMemoForTests: () => __resetRequestSnapshotMemoForTests,
|
|
31025
31269
|
canonicalTools: () => canonicalTools,
|
|
31026
31270
|
collapseLoopedAssistantText: () => collapseLoopedAssistantText,
|
|
31027
31271
|
compareReplayPrefix: () => compareReplayPrefix,
|
|
@@ -31044,6 +31288,7 @@ __export(harness_exports, {
|
|
|
31044
31288
|
recordRequest: () => recordRequest,
|
|
31045
31289
|
recordToolResult: () => recordToolResult,
|
|
31046
31290
|
recordUsage: () => recordUsage,
|
|
31291
|
+
resolveRequestSnapshotMode: () => resolveRequestSnapshotMode,
|
|
31047
31292
|
runExtensionPreToolUse: () => runExtensionPreToolUse,
|
|
31048
31293
|
sha256Hex: () => sha256Hex,
|
|
31049
31294
|
splitHookCommandLine: () => splitHookCommandLine,
|
|
@@ -37380,6 +37625,146 @@ var init_agentAdapter = __esm({
|
|
|
37380
37625
|
}
|
|
37381
37626
|
});
|
|
37382
37627
|
|
|
37628
|
+
// packages/core/dist/session/replayCache.js
|
|
37629
|
+
import { promises as fs14 } from "node:fs";
|
|
37630
|
+
function isReplayCacheEnabled(env = process.env) {
|
|
37631
|
+
const v = (env.ZELARI_SPINE_REPLAY_CACHE ?? "").trim().toLowerCase();
|
|
37632
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
37633
|
+
}
|
|
37634
|
+
function utf8IncompleteTailBytes(buf) {
|
|
37635
|
+
const max = Math.min(4, buf.length);
|
|
37636
|
+
for (let back = 1; back <= max; back++) {
|
|
37637
|
+
const b = buf[buf.length - back];
|
|
37638
|
+
if (b < 128)
|
|
37639
|
+
return 0;
|
|
37640
|
+
if (b >= 192) {
|
|
37641
|
+
const need = b >= 240 ? 4 : b >= 224 ? 3 : 2;
|
|
37642
|
+
return back >= need ? 0 : need - back;
|
|
37643
|
+
}
|
|
37644
|
+
}
|
|
37645
|
+
return 0;
|
|
37646
|
+
}
|
|
37647
|
+
async function readAt(fh, position, length) {
|
|
37648
|
+
const buf = Buffer.allocUnsafe(length);
|
|
37649
|
+
let done = 0;
|
|
37650
|
+
while (done < length) {
|
|
37651
|
+
const { bytesRead } = await fh.read(buf, done, length - done, position + done);
|
|
37652
|
+
if (bytesRead === 0)
|
|
37653
|
+
break;
|
|
37654
|
+
done += bytesRead;
|
|
37655
|
+
}
|
|
37656
|
+
return done === length ? buf : buf.subarray(0, done);
|
|
37657
|
+
}
|
|
37658
|
+
function toReport(filePath, entry) {
|
|
37659
|
+
const events = entry.events.slice();
|
|
37660
|
+
const issues = entry.issues.slice();
|
|
37661
|
+
return { path: filePath, events, issues, ok: issues.length === 0 };
|
|
37662
|
+
}
|
|
37663
|
+
async function readSessionLogCached(filePath, cache4, env = process.env) {
|
|
37664
|
+
if (!cache4 || !isReplayCacheEnabled(env))
|
|
37665
|
+
return readSessionLog(filePath);
|
|
37666
|
+
return cache4.read(filePath);
|
|
37667
|
+
}
|
|
37668
|
+
var NL, SessionLogCache;
|
|
37669
|
+
var init_replayCache = __esm({
|
|
37670
|
+
"packages/core/dist/session/replayCache.js"() {
|
|
37671
|
+
"use strict";
|
|
37672
|
+
init_replay();
|
|
37673
|
+
NL = 10;
|
|
37674
|
+
SessionLogCache = class {
|
|
37675
|
+
entries = /* @__PURE__ */ new Map();
|
|
37676
|
+
/** Files currently cached (diagnostics). */
|
|
37677
|
+
get size() {
|
|
37678
|
+
return this.entries.size;
|
|
37679
|
+
}
|
|
37680
|
+
/** The cached entry for `filePath` (copy; tests + diagnostics), if any. */
|
|
37681
|
+
peek(filePath) {
|
|
37682
|
+
const entry = this.entries.get(filePath);
|
|
37683
|
+
return entry ? { ...entry } : void 0;
|
|
37684
|
+
}
|
|
37685
|
+
/** Read the log, incrementally when a usable entry exists. */
|
|
37686
|
+
async read(filePath) {
|
|
37687
|
+
const cached2 = this.entries.get(filePath);
|
|
37688
|
+
let stat8;
|
|
37689
|
+
try {
|
|
37690
|
+
stat8 = await fs14.stat(filePath);
|
|
37691
|
+
} catch (err) {
|
|
37692
|
+
if (err.code === "ENOENT") {
|
|
37693
|
+
this.entries.delete(filePath);
|
|
37694
|
+
return { path: filePath, events: [], issues: [], ok: true };
|
|
37695
|
+
}
|
|
37696
|
+
throw err;
|
|
37697
|
+
}
|
|
37698
|
+
if (cached2 && stat8.size >= cached2.byteSize && stat8.mtimeMs >= cached2.mtimeMs) {
|
|
37699
|
+
if (stat8.size > cached2.byteSize)
|
|
37700
|
+
return this.extend(filePath, cached2, stat8);
|
|
37701
|
+
return toReport(filePath, cached2);
|
|
37702
|
+
}
|
|
37703
|
+
return this.full(filePath, stat8);
|
|
37704
|
+
}
|
|
37705
|
+
/** Append-path read: only the bytes written since the last read are parsed. */
|
|
37706
|
+
async extend(filePath, cached2, stat8) {
|
|
37707
|
+
const fh = await fs14.open(filePath, "r");
|
|
37708
|
+
let chunk;
|
|
37709
|
+
try {
|
|
37710
|
+
chunk = await readAt(fh, cached2.byteSize, stat8.size - cached2.byteSize);
|
|
37711
|
+
} finally {
|
|
37712
|
+
await fh.close();
|
|
37713
|
+
}
|
|
37714
|
+
const nl = chunk.lastIndexOf(NL);
|
|
37715
|
+
const headEnd = nl === -1 ? 0 : nl + 1;
|
|
37716
|
+
const tail2 = chunk.subarray(headEnd);
|
|
37717
|
+
const keep = tail2.subarray(0, tail2.length - utf8IncompleteTailBytes(tail2));
|
|
37718
|
+
const head = cached2.partial + chunk.subarray(0, headEnd).toString("utf8");
|
|
37719
|
+
const lines = headEnd > 0 ? head.split("\n").slice(0, -1) : [];
|
|
37720
|
+
const parsed = parseSessionLogLines(lines, {
|
|
37721
|
+
expected: cached2.expectedSeq,
|
|
37722
|
+
linesConsumed: cached2.linesConsumed
|
|
37723
|
+
});
|
|
37724
|
+
const entry = {
|
|
37725
|
+
byteSize: cached2.byteSize + headEnd + keep.length,
|
|
37726
|
+
mtimeMs: stat8.mtimeMs,
|
|
37727
|
+
events: parsed.events.length > 0 ? cached2.events.concat(parsed.events) : cached2.events,
|
|
37728
|
+
issues: parsed.issues.length > 0 ? cached2.issues.concat(parsed.issues) : cached2.issues,
|
|
37729
|
+
expectedSeq: parsed.expected,
|
|
37730
|
+
partial: (headEnd > 0 ? "" : cached2.partial) + keep.toString("utf8"),
|
|
37731
|
+
linesConsumed: parsed.linesConsumed
|
|
37732
|
+
};
|
|
37733
|
+
this.entries.set(filePath, entry);
|
|
37734
|
+
return toReport(filePath, entry);
|
|
37735
|
+
}
|
|
37736
|
+
/** Cold / rotated read: same parse as `readSessionLog`, then seed the entry. */
|
|
37737
|
+
async full(filePath, stat8) {
|
|
37738
|
+
let content;
|
|
37739
|
+
try {
|
|
37740
|
+
content = await fs14.readFile(filePath, "utf-8");
|
|
37741
|
+
} catch (err) {
|
|
37742
|
+
if (err.code === "ENOENT") {
|
|
37743
|
+
this.entries.delete(filePath);
|
|
37744
|
+
return { path: filePath, events: [], issues: [], ok: true };
|
|
37745
|
+
}
|
|
37746
|
+
throw err;
|
|
37747
|
+
}
|
|
37748
|
+
const lines = content.split("\n");
|
|
37749
|
+
const parsed = parseSessionLogLines(lines);
|
|
37750
|
+
const linesConsumed = content.length === 0 ? 0 : content.endsWith("\n") ? lines.length - 1 : lines.length;
|
|
37751
|
+
const entry = {
|
|
37752
|
+
// Bytes actually read (never the pre-read stat: the log may have grown).
|
|
37753
|
+
byteSize: Buffer.byteLength(content, "utf8"),
|
|
37754
|
+
mtimeMs: stat8.mtimeMs,
|
|
37755
|
+
events: parsed.events,
|
|
37756
|
+
issues: parsed.issues,
|
|
37757
|
+
expectedSeq: parsed.expected,
|
|
37758
|
+
partial: "",
|
|
37759
|
+
linesConsumed
|
|
37760
|
+
};
|
|
37761
|
+
this.entries.set(filePath, entry);
|
|
37762
|
+
return { path: filePath, events: entry.events.slice(), issues: entry.issues.slice(), ok: entry.issues.length === 0 };
|
|
37763
|
+
}
|
|
37764
|
+
};
|
|
37765
|
+
}
|
|
37766
|
+
});
|
|
37767
|
+
|
|
37383
37768
|
// packages/core/dist/session/lineage.js
|
|
37384
37769
|
async function forkSession(store6, parentSessionId, options = {}) {
|
|
37385
37770
|
const parent = await store6.read(parentSessionId);
|
|
@@ -37943,6 +38328,7 @@ var init_session = __esm({
|
|
|
37943
38328
|
init_agentAdapter();
|
|
37944
38329
|
init_writer();
|
|
37945
38330
|
init_replay();
|
|
38331
|
+
init_replayCache();
|
|
37946
38332
|
init_store();
|
|
37947
38333
|
init_lineage();
|
|
37948
38334
|
init_exportSession();
|
|
@@ -38436,12 +38822,12 @@ var CORE_VERSION;
|
|
|
38436
38822
|
var init_version = __esm({
|
|
38437
38823
|
"packages/core/dist/version.js"() {
|
|
38438
38824
|
"use strict";
|
|
38439
|
-
CORE_VERSION = "2.
|
|
38825
|
+
CORE_VERSION = "2.38.0";
|
|
38440
38826
|
}
|
|
38441
38827
|
});
|
|
38442
38828
|
|
|
38443
38829
|
// packages/core/dist/runtime/fingerprints.js
|
|
38444
|
-
import { createHash as
|
|
38830
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
38445
38831
|
function toolFingerprintHash(tools) {
|
|
38446
38832
|
const canonical = [...tools].map((t) => ({
|
|
38447
38833
|
name: t.name,
|
|
@@ -38450,7 +38836,7 @@ function toolFingerprintHash(tools) {
|
|
|
38450
38836
|
...t.outputContractVersion !== void 0 ? { outputContractVersion: t.outputContractVersion } : {},
|
|
38451
38837
|
...t.capabilityFlags !== void 0 ? { capabilityFlags: [...t.capabilityFlags].sort() } : {}
|
|
38452
38838
|
})).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
38453
|
-
return
|
|
38839
|
+
return createHash11("sha256").update(stableStringify(canonical)).digest("hex");
|
|
38454
38840
|
}
|
|
38455
38841
|
function skillFingerprintHash(skills) {
|
|
38456
38842
|
const canonical = [...skills].map((s) => ({
|
|
@@ -38458,7 +38844,7 @@ function skillFingerprintHash(skills) {
|
|
|
38458
38844
|
...s.version !== void 0 ? { version: s.version } : {},
|
|
38459
38845
|
...s.contentDigest !== void 0 ? { contentDigest: s.contentDigest } : {}
|
|
38460
38846
|
})).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
38461
|
-
return
|
|
38847
|
+
return createHash11("sha256").update(stableStringify(canonical)).digest("hex");
|
|
38462
38848
|
}
|
|
38463
38849
|
var init_fingerprints = __esm({
|
|
38464
38850
|
"packages/core/dist/runtime/fingerprints.js"() {
|
|
@@ -38496,6 +38882,7 @@ __export(dist_exports, {
|
|
|
38496
38882
|
CommandCheckSchema: () => CommandCheckSchema,
|
|
38497
38883
|
CriterionSchema: () => CriterionSchema,
|
|
38498
38884
|
CriterionSourceSchema: () => CriterionSourceSchema,
|
|
38885
|
+
DEFAULT_COMMAND_CONCURRENCY: () => DEFAULT_COMMAND_CONCURRENCY,
|
|
38499
38886
|
DEFAULT_CONTEXT_POLICY: () => DEFAULT_CONTEXT_POLICY,
|
|
38500
38887
|
DEFAULT_HEARTBEAT_STALE_MS: () => DEFAULT_HEARTBEAT_STALE_MS,
|
|
38501
38888
|
DEFAULT_MAX_NODES: () => DEFAULT_MAX_NODES,
|
|
@@ -38622,6 +39009,7 @@ __export(dist_exports, {
|
|
|
38622
39009
|
SessionActorSchema: () => SessionActorSchema,
|
|
38623
39010
|
SessionEventEnvelopeSchema: () => SessionEventEnvelopeSchema,
|
|
38624
39011
|
SessionJsonlWriter: () => SessionJsonlWriter,
|
|
39012
|
+
SessionLogCache: () => SessionLogCache,
|
|
38625
39013
|
SessionLogLockedError: () => SessionLogLockedError,
|
|
38626
39014
|
SessionLogWriter: () => SessionLogWriter,
|
|
38627
39015
|
SessionStore: () => SessionStore,
|
|
@@ -38660,6 +39048,7 @@ __export(dist_exports, {
|
|
|
38660
39048
|
WorkspacePathEscapeError: () => WorkspacePathEscapeError,
|
|
38661
39049
|
WorktreeWorkspace: () => WorktreeWorkspace,
|
|
38662
39050
|
ZELARI_CODING_PACK_ID: () => ZELARI_CODING_PACK_ID,
|
|
39051
|
+
__resetRequestSnapshotMemoForTests: () => __resetRequestSnapshotMemoForTests,
|
|
38663
39052
|
analyzeScope: () => analyzeScope,
|
|
38664
39053
|
applyCompletionRetry: () => applyCompletionRetry,
|
|
38665
39054
|
applyDeterministicAutofix: () => applyDeterministicAutofix,
|
|
@@ -38821,6 +39210,7 @@ __export(dist_exports, {
|
|
|
38821
39210
|
isFollowUpControlEvent: () => isFollowUpControlEvent,
|
|
38822
39211
|
isGeneratedPath: () => isGeneratedPath,
|
|
38823
39212
|
isModelSurfaceEvent: () => isModelSurfaceEvent,
|
|
39213
|
+
isReplayCacheEnabled: () => isReplayCacheEnabled,
|
|
38824
39214
|
isReviewerKind: () => isReviewerKind,
|
|
38825
39215
|
isSearchTool: () => isSearchTool,
|
|
38826
39216
|
isSeqShadowed: () => isSeqShadowed,
|
|
@@ -38829,6 +39219,7 @@ __export(dist_exports, {
|
|
|
38829
39219
|
isSteerControlEvent: () => isSteerControlEvent,
|
|
38830
39220
|
isValidTool: () => isValidTool,
|
|
38831
39221
|
isVerificationReserveProtected: () => isVerificationReserveProtected,
|
|
39222
|
+
isVerifyParallelEnabled: () => isVerifyParallelEnabled,
|
|
38832
39223
|
isVerifyToolCheckSkipped: () => isVerifyToolCheckSkipped,
|
|
38833
39224
|
jaccardSimilarity: () => jaccardSimilarity,
|
|
38834
39225
|
jsonBytes: () => jsonBytes,
|
|
@@ -38867,6 +39258,8 @@ __export(dist_exports, {
|
|
|
38867
39258
|
parseNameOnlyDiff: () => parseNameOnlyDiff,
|
|
38868
39259
|
parsePersonaVerdict: () => parsePersonaVerdict,
|
|
38869
39260
|
parseProjectRootFromWorkspaceContext: () => parseProjectRootFromWorkspaceContext,
|
|
39261
|
+
parseSessionLogLines: () => parseSessionLogLines,
|
|
39262
|
+
parseSessionLogText: () => parseSessionLogText,
|
|
38870
39263
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
38871
39264
|
parseTextToolCallsDetailed: () => parseTextToolCallsDetailed,
|
|
38872
39265
|
parseThinking: () => parseThinking,
|
|
@@ -38884,6 +39277,7 @@ __export(dist_exports, {
|
|
|
38884
39277
|
readLessonsDeduped: () => readLessonsDeduped,
|
|
38885
39278
|
readSession: () => readSession,
|
|
38886
39279
|
readSessionLog: () => readSessionLog,
|
|
39280
|
+
readSessionLogCached: () => readSessionLogCached,
|
|
38887
39281
|
recallLessons: () => recallLessons,
|
|
38888
39282
|
recencyScore: () => recencyScore,
|
|
38889
39283
|
recordRequest: () => recordRequest,
|
|
@@ -38900,6 +39294,7 @@ __export(dist_exports, {
|
|
|
38900
39294
|
renderSteers: () => renderSteers,
|
|
38901
39295
|
replayChairmanTextTools: () => replayChairmanTextTools,
|
|
38902
39296
|
resolveAgentSkills: () => resolveAgentSkills,
|
|
39297
|
+
resolveCommandConcurrency: () => resolveCommandConcurrency,
|
|
38903
39298
|
resolveCouncilRunMode: () => resolveCouncilRunMode,
|
|
38904
39299
|
resolveHeartbeatStaleMs: () => resolveHeartbeatStaleMs,
|
|
38905
39300
|
resolveInterventions: () => resolveInterventions,
|
|
@@ -38907,6 +39302,7 @@ __export(dist_exports, {
|
|
|
38907
39302
|
resolveMaxTentacles: () => resolveMaxTentacles,
|
|
38908
39303
|
resolvePlanTimeoutMs: () => resolvePlanTimeoutMs,
|
|
38909
39304
|
resolveProfile: () => resolveProfile,
|
|
39305
|
+
resolveRequestSnapshotMode: () => resolveRequestSnapshotMode,
|
|
38910
39306
|
resolveResponseLanguage: () => resolveResponseLanguage,
|
|
38911
39307
|
resolveRoleSystemPrompt: () => resolveRoleSystemPrompt,
|
|
38912
39308
|
resolveSessionsDir: () => resolveSessionsDir,
|
|
@@ -39141,7 +39537,7 @@ var init_graphStatus = __esm({
|
|
|
39141
39537
|
});
|
|
39142
39538
|
|
|
39143
39539
|
// src/cli/sessionManager.ts
|
|
39144
|
-
import { promises as
|
|
39540
|
+
import { promises as fs15, existsSync as existsSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync11, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, statSync } from "node:fs";
|
|
39145
39541
|
import path30 from "node:path";
|
|
39146
39542
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
39147
39543
|
function getSessionBaseDir() {
|
|
@@ -39151,7 +39547,7 @@ function getCurrentSessionFile() {
|
|
|
39151
39547
|
return currentSessionPath();
|
|
39152
39548
|
}
|
|
39153
39549
|
async function ensureSessionDir() {
|
|
39154
|
-
await
|
|
39550
|
+
await fs15.mkdir(getSessionBaseDir(), { recursive: true });
|
|
39155
39551
|
}
|
|
39156
39552
|
function getCurrentSessionId() {
|
|
39157
39553
|
const file2 = getCurrentSessionFile();
|
|
@@ -39201,7 +39597,7 @@ async function listSessions() {
|
|
|
39201
39597
|
const baseDir = getSessionBaseDir();
|
|
39202
39598
|
let entries;
|
|
39203
39599
|
try {
|
|
39204
|
-
entries = await
|
|
39600
|
+
entries = await fs15.readdir(baseDir);
|
|
39205
39601
|
} catch (err) {
|
|
39206
39602
|
if (err.code === "ENOENT") return [];
|
|
39207
39603
|
throw err;
|
|
@@ -39591,16 +39987,16 @@ var init_budgetRuntime = __esm({
|
|
|
39591
39987
|
|
|
39592
39988
|
// src/cli/budget/restoreRuntime.ts
|
|
39593
39989
|
import path31 from "node:path";
|
|
39594
|
-
async function restoreBudgetRuntimeFromSession(budget, sessionId2, baseDir) {
|
|
39990
|
+
async function restoreBudgetRuntimeFromSession(budget, sessionId2, baseDir, cache4) {
|
|
39595
39991
|
const eventsPath = path31.join(resolveSessionsDir({ baseDir }), sessionId2, "events.jsonl");
|
|
39596
|
-
const report = await
|
|
39992
|
+
const report = await readSessionLogCached(eventsPath, cache4).catch(() => null);
|
|
39597
39993
|
if (!report || report.events.length === 0) return false;
|
|
39598
39994
|
budget.adoptLedgerFromEvents(report.events);
|
|
39599
39995
|
return true;
|
|
39600
39996
|
}
|
|
39601
|
-
async function lastHarnessManifestHash(sessionId2, baseDir) {
|
|
39997
|
+
async function lastHarnessManifestHash(sessionId2, baseDir, cache4) {
|
|
39602
39998
|
const eventsPath = path31.join(resolveSessionsDir({ baseDir }), sessionId2, "events.jsonl");
|
|
39603
|
-
const report = await
|
|
39999
|
+
const report = await readSessionLogCached(eventsPath, cache4).catch(() => null);
|
|
39604
40000
|
if (!report) return null;
|
|
39605
40001
|
for (let i = report.events.length - 1; i >= 0; i--) {
|
|
39606
40002
|
const e = report.events[i];
|
|
@@ -40066,7 +40462,7 @@ async function wrapSessionWriter(inner, sessionId2, options = {}) {
|
|
|
40066
40462
|
enforcement: resolveResourceEnforcement()
|
|
40067
40463
|
});
|
|
40068
40464
|
if (spine.resumedFromSeq !== void 0 && spine.resumedFromSeq > 0) {
|
|
40069
|
-
await restoreBudgetRuntimeFromSession(budget, sessionId2, options.baseDir);
|
|
40465
|
+
await restoreBudgetRuntimeFromSession(budget, sessionId2, options.baseDir, spine.replayCache);
|
|
40070
40466
|
}
|
|
40071
40467
|
spine.attachBudgetRuntime(budget);
|
|
40072
40468
|
await noteHarnessLifecycle(
|
|
@@ -40097,7 +40493,7 @@ async function noteHarnessLifecycle(spine, sessionId2, profileId, budget, baseDi
|
|
|
40097
40493
|
resourcePolicy: budget.policy
|
|
40098
40494
|
});
|
|
40099
40495
|
if (spine.resumedFromSeq !== void 0 && spine.resumedFromSeq > 0) {
|
|
40100
|
-
if (await lastHarnessManifestHash(sessionId2, baseDir) === null) {
|
|
40496
|
+
if (await lastHarnessManifestHash(sessionId2, baseDir, spine.replayCache) === null) {
|
|
40101
40497
|
spine.harnessManifest(manifest, manifestHash);
|
|
40102
40498
|
}
|
|
40103
40499
|
} else {
|
|
@@ -40147,6 +40543,13 @@ var init_sessionSpine = __esm({
|
|
|
40147
40543
|
/** Seq the log continued from when adopting an existing session. */
|
|
40148
40544
|
resumedFromSeq;
|
|
40149
40545
|
sessionsDir;
|
|
40546
|
+
/**
|
|
40547
|
+
* PERF-4a: session log cache — ONE per session (this mirror). Every read of
|
|
40548
|
+
* `<sessionId>/events.jsonl` goes through it; the kill switch
|
|
40549
|
+
* ZELARI_SPINE_REPLAY_CACHE defaults OFF (see @zelari/core/session
|
|
40550
|
+
* replayCache.ts), and shared with the host helpers that take a cache.
|
|
40551
|
+
*/
|
|
40552
|
+
replayCache = new SessionLogCache();
|
|
40150
40553
|
/**
|
|
40151
40554
|
* Adopt a 1.x sessionId into the spine: continue the seq when the log
|
|
40152
40555
|
* already exists (resume), otherwise start fresh with `session.started`.
|
|
@@ -40157,7 +40560,10 @@ var init_sessionSpine = __esm({
|
|
|
40157
40560
|
if (!spineEnabled()) return mirror;
|
|
40158
40561
|
try {
|
|
40159
40562
|
const sessionDir = path33.join(mirror.sessionsDir, sessionId2);
|
|
40160
|
-
const report = await
|
|
40563
|
+
const report = await readSessionLogCached(
|
|
40564
|
+
path33.join(sessionDir, "events.jsonl"),
|
|
40565
|
+
mirror.replayCache
|
|
40566
|
+
);
|
|
40161
40567
|
const existed = report.events.length > 0 || report.issues.length > 0;
|
|
40162
40568
|
if (report.events.some((e) => e.kind === "task.contract" || e.kind === "user.message")) {
|
|
40163
40569
|
mirror.contractSeeded = true;
|
|
@@ -40332,8 +40738,9 @@ var init_sessionSpine = __esm({
|
|
|
40332
40738
|
*/
|
|
40333
40739
|
async derivedPriorTurns() {
|
|
40334
40740
|
if (this.status !== "active" && this.status !== "closed") return null;
|
|
40335
|
-
const report = await
|
|
40336
|
-
path33.join(this.sessionsDir, this.sessionId, "events.jsonl")
|
|
40741
|
+
const report = await readSessionLogCached(
|
|
40742
|
+
path33.join(this.sessionsDir, this.sessionId, "events.jsonl"),
|
|
40743
|
+
this.replayCache
|
|
40337
40744
|
).catch(() => null);
|
|
40338
40745
|
if (!report || report.events.length === 0) return null;
|
|
40339
40746
|
return deriveMessages(report.events);
|
|
@@ -40342,8 +40749,9 @@ var init_sessionSpine = __esm({
|
|
|
40342
40749
|
async compactionStateSnapshot(toSeq) {
|
|
40343
40750
|
if (this.status !== "active" && this.status !== "closed") return null;
|
|
40344
40751
|
await this.flush();
|
|
40345
|
-
const report = await
|
|
40346
|
-
path33.join(this.sessionsDir, this.sessionId, "events.jsonl")
|
|
40752
|
+
const report = await readSessionLogCached(
|
|
40753
|
+
path33.join(this.sessionsDir, this.sessionId, "events.jsonl"),
|
|
40754
|
+
this.replayCache
|
|
40347
40755
|
).catch(() => null);
|
|
40348
40756
|
if (!report || report.events.length === 0) return null;
|
|
40349
40757
|
return buildCompactionStateSnapshot(report.events, toSeq);
|
|
@@ -40355,8 +40763,9 @@ var init_sessionSpine = __esm({
|
|
|
40355
40763
|
*/
|
|
40356
40764
|
async lastVerificationRun() {
|
|
40357
40765
|
if (this.status !== "active" && this.status !== "closed") return null;
|
|
40358
|
-
const report = await
|
|
40359
|
-
path33.join(this.sessionsDir, this.sessionId, "events.jsonl")
|
|
40766
|
+
const report = await readSessionLogCached(
|
|
40767
|
+
path33.join(this.sessionsDir, this.sessionId, "events.jsonl"),
|
|
40768
|
+
this.replayCache
|
|
40360
40769
|
).catch(() => null);
|
|
40361
40770
|
if (!report) return null;
|
|
40362
40771
|
return lastVerificationRun(report.events);
|
|
@@ -40492,7 +40901,7 @@ var init_sessionSpine = __esm({
|
|
|
40492
40901
|
seq = seq.then(async (s) => {
|
|
40493
40902
|
try {
|
|
40494
40903
|
const eventsPath = path33.join(this.sessionsDir, this.sessionId, "events.jsonl");
|
|
40495
|
-
const report = await
|
|
40904
|
+
const report = await readSessionLogCached(eventsPath, this.replayCache).catch(() => null);
|
|
40496
40905
|
if (!report || typeof s !== "number") return s;
|
|
40497
40906
|
const current = latestTaskContract(report.events);
|
|
40498
40907
|
if (!current) return s;
|
|
@@ -40760,7 +41169,7 @@ async function loadObservationIndex(sessionId2, baseDir) {
|
|
|
40760
41169
|
mtimeMs = 0;
|
|
40761
41170
|
}
|
|
40762
41171
|
}
|
|
40763
|
-
const hit =
|
|
41172
|
+
const hit = cache2.get(sessionId2);
|
|
40764
41173
|
if (hit && !exists) return hit;
|
|
40765
41174
|
if (hit && hit.filePath === filePath && hit.mtimeMs === mtimeMs) return hit;
|
|
40766
41175
|
const events = existsSync15(filePath) ? await readSession(filePath) : [];
|
|
@@ -40789,12 +41198,12 @@ async function loadObservationIndex(sessionId2, baseDir) {
|
|
|
40789
41198
|
if (e.toolCallId) byToolCallId.set(e.toolCallId, seq);
|
|
40790
41199
|
}
|
|
40791
41200
|
const index = { filePath, mtimeMs, bySeq, byToolCallId, names };
|
|
40792
|
-
|
|
41201
|
+
cache2.set(sessionId2, index);
|
|
40793
41202
|
return index;
|
|
40794
41203
|
}
|
|
40795
41204
|
function invalidateObservationIndex(sessionId2) {
|
|
40796
|
-
if (sessionId2)
|
|
40797
|
-
else
|
|
41205
|
+
if (sessionId2) cache2.delete(sessionId2);
|
|
41206
|
+
else cache2.clear();
|
|
40798
41207
|
}
|
|
40799
41208
|
async function getObservationBySeq(sessionId2, seq, baseDir) {
|
|
40800
41209
|
const index = await loadObservationIndex(sessionId2, baseDir);
|
|
@@ -40802,7 +41211,7 @@ async function getObservationBySeq(sessionId2, seq, baseDir) {
|
|
|
40802
41211
|
}
|
|
40803
41212
|
function lookupSeqSync(sessionId2, toolCallId, baseDir) {
|
|
40804
41213
|
const filePath = sessionFilePath(sessionId2, baseDir);
|
|
40805
|
-
const hit =
|
|
41214
|
+
const hit = cache2.get(sessionId2);
|
|
40806
41215
|
if (hit && hit.filePath === filePath) return hit.byToolCallId.get(toolCallId);
|
|
40807
41216
|
return void 0;
|
|
40808
41217
|
}
|
|
@@ -40817,10 +41226,10 @@ function emptyIndex(sessionId2, baseDir) {
|
|
|
40817
41226
|
}
|
|
40818
41227
|
function ingestLiveEvent(sessionId2, event, baseDir) {
|
|
40819
41228
|
if (!sessionId2) return;
|
|
40820
|
-
let index =
|
|
41229
|
+
let index = cache2.get(sessionId2);
|
|
40821
41230
|
if (!index) {
|
|
40822
41231
|
index = emptyIndex(sessionId2, baseDir);
|
|
40823
|
-
|
|
41232
|
+
cache2.set(sessionId2, index);
|
|
40824
41233
|
}
|
|
40825
41234
|
if (isToolStart(event)) {
|
|
40826
41235
|
index.names.set(event.toolCallId, event.toolName);
|
|
@@ -40848,19 +41257,19 @@ function applySessionSurface(messages) {
|
|
|
40848
41257
|
const lookup = sid ? (id3) => lookupSeqSync(sid, id3) : void 0;
|
|
40849
41258
|
return projectSessionSurface(messages, void 0, lookup).messages;
|
|
40850
41259
|
}
|
|
40851
|
-
var
|
|
41260
|
+
var cache2;
|
|
40852
41261
|
var init_observationStore = __esm({
|
|
40853
41262
|
"src/cli/hooks/observationStore.ts"() {
|
|
40854
41263
|
"use strict";
|
|
40855
41264
|
init_harness();
|
|
40856
41265
|
init_sessionManager();
|
|
40857
41266
|
init_sessionSurface();
|
|
40858
|
-
|
|
41267
|
+
cache2 = /* @__PURE__ */ new Map();
|
|
40859
41268
|
}
|
|
40860
41269
|
});
|
|
40861
41270
|
|
|
40862
41271
|
// packages/core/dist/core/tools/toolOutputSpill.js
|
|
40863
|
-
import { createHash as
|
|
41272
|
+
import { createHash as createHash12, randomBytes as randomBytes3 } from "node:crypto";
|
|
40864
41273
|
import { existsSync as existsSync16, mkdirSync as mkdirSync7, writeFileSync as writeFileSync12 } from "node:fs";
|
|
40865
41274
|
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
40866
41275
|
import { join as join14 } from "node:path";
|
|
@@ -40890,7 +41299,7 @@ function spillToolOutput(fullText, meta3) {
|
|
|
40890
41299
|
if (!existsSync16(dir)) {
|
|
40891
41300
|
mkdirSync7(dir, { recursive: true });
|
|
40892
41301
|
}
|
|
40893
|
-
const hash3 =
|
|
41302
|
+
const hash3 = createHash12("sha256").update(fullText).digest("hex").slice(0, 12);
|
|
40894
41303
|
const stamp = Date.now().toString(36);
|
|
40895
41304
|
const rnd = randomBytes3(3).toString("hex");
|
|
40896
41305
|
const safeTool = (meta3?.toolName ?? "tool").replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 32);
|
|
@@ -41193,7 +41602,7 @@ var init_registry2 = __esm({
|
|
|
41193
41602
|
|
|
41194
41603
|
// src/cli/safety/sandboxPath.ts
|
|
41195
41604
|
import path35 from "node:path";
|
|
41196
|
-
import
|
|
41605
|
+
import fs16 from "node:fs";
|
|
41197
41606
|
function normalizedCase(p3) {
|
|
41198
41607
|
return IS_CASE_FOLDING ? p3.toLowerCase() : p3;
|
|
41199
41608
|
}
|
|
@@ -41227,7 +41636,7 @@ function assertRealAncestorContained(resolvedLexical, realRoot, userPath) {
|
|
|
41227
41636
|
for (; ; ) {
|
|
41228
41637
|
if (probe === path35.dirname(probe)) break;
|
|
41229
41638
|
try {
|
|
41230
|
-
realProbe =
|
|
41639
|
+
realProbe = fs16.realpathSync(probe);
|
|
41231
41640
|
break;
|
|
41232
41641
|
} catch (err) {
|
|
41233
41642
|
if (err?.code === "ENOENT") {
|
|
@@ -41255,7 +41664,7 @@ function resolveSandboxedCore(userPath, options = {}) {
|
|
|
41255
41664
|
assertLexicalContainment(resolved, root, userPath);
|
|
41256
41665
|
let realRoot = null;
|
|
41257
41666
|
try {
|
|
41258
|
-
realRoot =
|
|
41667
|
+
realRoot = fs16.realpathSync(root);
|
|
41259
41668
|
} catch {
|
|
41260
41669
|
return resolved;
|
|
41261
41670
|
}
|
|
@@ -41274,7 +41683,7 @@ function verifyContainment(resolvedAbsolute, options = {}) {
|
|
|
41274
41683
|
assertLexicalContainment(resolved, root, resolvedAbsolute);
|
|
41275
41684
|
let realRoot = null;
|
|
41276
41685
|
try {
|
|
41277
|
-
realRoot =
|
|
41686
|
+
realRoot = fs16.realpathSync(root);
|
|
41278
41687
|
} catch {
|
|
41279
41688
|
return;
|
|
41280
41689
|
}
|
|
@@ -41298,7 +41707,7 @@ var init_sandboxPath = __esm({
|
|
|
41298
41707
|
});
|
|
41299
41708
|
|
|
41300
41709
|
// src/cli/tools/krakenRadio.ts
|
|
41301
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync16, readdirSync as readdirSync3 } from "node:fs";
|
|
41710
|
+
import { appendFileSync as appendFileSync2, closeSync, existsSync as existsSync17, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync16, readdirSync as readdirSync3, writeSync } from "node:fs";
|
|
41302
41711
|
import path36 from "node:path";
|
|
41303
41712
|
function radioDir(cwd) {
|
|
41304
41713
|
return path36.join(cwd, ".zelari", "radio");
|
|
@@ -41307,6 +41716,35 @@ function radioPath(cwd, sessionId2) {
|
|
|
41307
41716
|
const safe = (sessionId2 || "default").replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
41308
41717
|
return path36.join(radioDir(cwd), `${safe}.jsonl`);
|
|
41309
41718
|
}
|
|
41719
|
+
function appendRadioLine(file2, line) {
|
|
41720
|
+
try {
|
|
41721
|
+
const cached2 = radioFds.get(file2);
|
|
41722
|
+
if (cached2 !== void 0) {
|
|
41723
|
+
writeSync(cached2, line, null, "utf8");
|
|
41724
|
+
return;
|
|
41725
|
+
}
|
|
41726
|
+
if (radioFds.size >= MAX_CACHED_RADIO_FDS) {
|
|
41727
|
+
appendFileSync2(file2, line, "utf8");
|
|
41728
|
+
return;
|
|
41729
|
+
}
|
|
41730
|
+
const fd = openSync(file2, "a");
|
|
41731
|
+
writeSync(fd, line, null, "utf8");
|
|
41732
|
+
radioFds.set(file2, fd);
|
|
41733
|
+
} catch {
|
|
41734
|
+
const stale = radioFds.get(file2);
|
|
41735
|
+
if (stale !== void 0) {
|
|
41736
|
+
radioFds.delete(file2);
|
|
41737
|
+
try {
|
|
41738
|
+
closeSync(stale);
|
|
41739
|
+
} catch {
|
|
41740
|
+
}
|
|
41741
|
+
}
|
|
41742
|
+
try {
|
|
41743
|
+
appendFileSync2(file2, line, "utf8");
|
|
41744
|
+
} catch {
|
|
41745
|
+
}
|
|
41746
|
+
}
|
|
41747
|
+
}
|
|
41310
41748
|
function appendKrakenRadio(cwd, sessionId2, event) {
|
|
41311
41749
|
try {
|
|
41312
41750
|
const dir = radioDir(cwd);
|
|
@@ -41332,8 +41770,8 @@ function appendKrakenRadio(cwd, sessionId2, event) {
|
|
|
41332
41770
|
...event.symbolsA !== void 0 ? { symbolsA: event.symbolsA } : {},
|
|
41333
41771
|
...event.symbolsB !== void 0 ? { symbolsB: event.symbolsB } : {}
|
|
41334
41772
|
};
|
|
41335
|
-
|
|
41336
|
-
|
|
41773
|
+
appendRadioLine(radioPath(cwd, sessionId2), `${JSON.stringify(row)}
|
|
41774
|
+
`);
|
|
41337
41775
|
} catch {
|
|
41338
41776
|
}
|
|
41339
41777
|
}
|
|
@@ -41370,9 +41808,12 @@ function formatKrakenRadioStatus(cwd, sessionId2, limit = 12) {
|
|
|
41370
41808
|
});
|
|
41371
41809
|
return [`Kraken radio (last ${events.length}) session=${sessionId2}:`, ...lines].join("\n");
|
|
41372
41810
|
}
|
|
41811
|
+
var MAX_CACHED_RADIO_FDS, radioFds;
|
|
41373
41812
|
var init_krakenRadio = __esm({
|
|
41374
41813
|
"src/cli/tools/krakenRadio.ts"() {
|
|
41375
41814
|
"use strict";
|
|
41815
|
+
MAX_CACHED_RADIO_FDS = 32;
|
|
41816
|
+
radioFds = /* @__PURE__ */ new Map();
|
|
41376
41817
|
}
|
|
41377
41818
|
});
|
|
41378
41819
|
|
|
@@ -41386,7 +41827,7 @@ import {
|
|
|
41386
41827
|
realpathSync
|
|
41387
41828
|
} from "node:fs";
|
|
41388
41829
|
import { join as join15, basename } from "node:path";
|
|
41389
|
-
import { createHash as
|
|
41830
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
41390
41831
|
function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
41391
41832
|
const candidates = [
|
|
41392
41833
|
join15(projectRoot, ".zelari"),
|
|
@@ -41402,7 +41843,7 @@ function resolveWorkspaceRoot(projectRoot = process.cwd()) {
|
|
|
41402
41843
|
return candidates[0];
|
|
41403
41844
|
}
|
|
41404
41845
|
function hashProject(projectPath) {
|
|
41405
|
-
return
|
|
41846
|
+
return createHash13("sha1").update(realpathSync(projectPath)).digest("hex").slice(0, 12);
|
|
41406
41847
|
}
|
|
41407
41848
|
function isWritableDir(dir) {
|
|
41408
41849
|
try {
|
|
@@ -42127,12 +42568,12 @@ var init_taskTouchGuard = __esm({
|
|
|
42127
42568
|
});
|
|
42128
42569
|
|
|
42129
42570
|
// src/cli/gitOps.ts
|
|
42130
|
-
import { execFile as
|
|
42131
|
-
import { promisify } from "node:util";
|
|
42571
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
42572
|
+
import { promisify as promisify2 } from "node:util";
|
|
42132
42573
|
import path38 from "node:path";
|
|
42133
42574
|
async function git2(cwd, args) {
|
|
42134
42575
|
try {
|
|
42135
|
-
const { stdout } = await
|
|
42576
|
+
const { stdout } = await execFileAsync2("git", ["-C", cwd, ...args], {
|
|
42136
42577
|
maxBuffer: 16 * 1024 * 1024
|
|
42137
42578
|
});
|
|
42138
42579
|
return stdout;
|
|
@@ -42184,11 +42625,11 @@ async function undoWorkingChanges(opts = {}) {
|
|
|
42184
42625
|
function defaultProjectRoot() {
|
|
42185
42626
|
return path38.resolve(__dirname, "..", "..", "..");
|
|
42186
42627
|
}
|
|
42187
|
-
var
|
|
42628
|
+
var execFileAsync2;
|
|
42188
42629
|
var init_gitOps = __esm({
|
|
42189
42630
|
"src/cli/gitOps.ts"() {
|
|
42190
42631
|
"use strict";
|
|
42191
|
-
|
|
42632
|
+
execFileAsync2 = promisify2(execFile3);
|
|
42192
42633
|
}
|
|
42193
42634
|
});
|
|
42194
42635
|
|
|
@@ -42323,7 +42764,7 @@ var auditLogger_exports = {};
|
|
|
42323
42764
|
__export(auditLogger_exports, {
|
|
42324
42765
|
AuditLogger: () => AuditLogger
|
|
42325
42766
|
});
|
|
42326
|
-
import { promises as
|
|
42767
|
+
import { promises as fs17 } from "node:fs";
|
|
42327
42768
|
import path39 from "node:path";
|
|
42328
42769
|
function defaultAuditPath() {
|
|
42329
42770
|
return auditLogPath();
|
|
@@ -42370,8 +42811,8 @@ var init_auditLogger = __esm({
|
|
|
42370
42811
|
async append(entry) {
|
|
42371
42812
|
const line = JSON.stringify(entry) + "\n";
|
|
42372
42813
|
this.writeQueue = this.writeQueue.then(async () => {
|
|
42373
|
-
await
|
|
42374
|
-
await
|
|
42814
|
+
await fs17.mkdir(path39.dirname(this.logPath), { recursive: true });
|
|
42815
|
+
await fs17.appendFile(this.logPath, line, "utf-8");
|
|
42375
42816
|
});
|
|
42376
42817
|
return this.writeQueue;
|
|
42377
42818
|
}
|
|
@@ -42590,11 +43031,54 @@ var init_engine2 = __esm({
|
|
|
42590
43031
|
}
|
|
42591
43032
|
});
|
|
42592
43033
|
|
|
43034
|
+
// src/cli/kraken/worktreeCleanupBatch.ts
|
|
43035
|
+
function resolveWorktreeCleanupMode(env = process.env) {
|
|
43036
|
+
const v = (env.ZELARI_KRAKEN_WORKTREE_CLEANUP ?? "").trim().toLowerCase();
|
|
43037
|
+
if (v === "eager") return "eager";
|
|
43038
|
+
return "batch";
|
|
43039
|
+
}
|
|
43040
|
+
function isKrakenWorktreeCleanupBatched(env = process.env) {
|
|
43041
|
+
return batchScopes > 0 && resolveWorktreeCleanupMode(env) === "batch";
|
|
43042
|
+
}
|
|
43043
|
+
function beginKrakenWorktreeCleanupBatch(env = process.env) {
|
|
43044
|
+
if (resolveWorktreeCleanupMode(env) !== "batch") return false;
|
|
43045
|
+
batchScopes += 1;
|
|
43046
|
+
return true;
|
|
43047
|
+
}
|
|
43048
|
+
function queueWorktreeCleanup(repoRoot, branch) {
|
|
43049
|
+
pendingPruneRoots.add(repoRoot);
|
|
43050
|
+
if (!branch) return;
|
|
43051
|
+
const queued = pendingBranches.get(repoRoot) ?? /* @__PURE__ */ new Set();
|
|
43052
|
+
queued.add(branch);
|
|
43053
|
+
pendingBranches.set(repoRoot, queued);
|
|
43054
|
+
}
|
|
43055
|
+
function takeQueuedWorktreeCleanup() {
|
|
43056
|
+
if (batchScopes > 0) batchScopes -= 1;
|
|
43057
|
+
const repoRoots = /* @__PURE__ */ new Set([...pendingPruneRoots, ...pendingBranches.keys()]);
|
|
43058
|
+
const branchesByRoot = /* @__PURE__ */ new Map();
|
|
43059
|
+
for (const repoRoot of repoRoots) {
|
|
43060
|
+
const queued = pendingBranches.get(repoRoot);
|
|
43061
|
+
if (queued && queued.size > 0) branchesByRoot.set(repoRoot, [...queued]);
|
|
43062
|
+
pendingPruneRoots.delete(repoRoot);
|
|
43063
|
+
pendingBranches.delete(repoRoot);
|
|
43064
|
+
}
|
|
43065
|
+
return { repoRoots: [...repoRoots], branchesByRoot };
|
|
43066
|
+
}
|
|
43067
|
+
var pendingPruneRoots, pendingBranches, batchScopes;
|
|
43068
|
+
var init_worktreeCleanupBatch = __esm({
|
|
43069
|
+
"src/cli/kraken/worktreeCleanupBatch.ts"() {
|
|
43070
|
+
"use strict";
|
|
43071
|
+
pendingPruneRoots = /* @__PURE__ */ new Set();
|
|
43072
|
+
pendingBranches = /* @__PURE__ */ new Map();
|
|
43073
|
+
batchScopes = 0;
|
|
43074
|
+
}
|
|
43075
|
+
});
|
|
43076
|
+
|
|
42593
43077
|
// src/cli/tools/krakenWorktree.ts
|
|
42594
|
-
import { execFile as
|
|
43078
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
42595
43079
|
import { existsSync as existsSync24, mkdirSync as mkdirSync12, rmSync } from "node:fs";
|
|
42596
43080
|
import path41 from "node:path";
|
|
42597
|
-
import { promisify as
|
|
43081
|
+
import { promisify as promisify3 } from "node:util";
|
|
42598
43082
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
42599
43083
|
function isKrakenWorktreeEnabled(env = process.env) {
|
|
42600
43084
|
const v = (env.ZELARI_KRAKEN_WORKTREE ?? "").trim().toLowerCase();
|
|
@@ -42610,9 +43094,29 @@ function isKrakenWorktreeAutoMergeEnabled(env = process.env) {
|
|
|
42610
43094
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
42611
43095
|
return true;
|
|
42612
43096
|
}
|
|
43097
|
+
async function flushKrakenWorktreeCleanupBatch() {
|
|
43098
|
+
const { repoRoots, branchesByRoot } = takeQueuedWorktreeCleanup();
|
|
43099
|
+
const branches = [];
|
|
43100
|
+
const deleted = [];
|
|
43101
|
+
let pruned = 0;
|
|
43102
|
+
for (const repoRoot of repoRoots) {
|
|
43103
|
+
await git3(repoRoot, ["worktree", "prune"]);
|
|
43104
|
+
pruned += 1;
|
|
43105
|
+
const list = branchesByRoot.get(repoRoot);
|
|
43106
|
+
if (list && list.length > 0) {
|
|
43107
|
+
branches.push(...list);
|
|
43108
|
+
const r = await git3(repoRoot, ["branch", "-D", ...list]);
|
|
43109
|
+
for (const line of r.stdout.split("\n")) {
|
|
43110
|
+
const m = /^Deleted branch (\S+)/.exec(line.trim());
|
|
43111
|
+
if (m?.[1]) deleted.push(m[1]);
|
|
43112
|
+
}
|
|
43113
|
+
}
|
|
43114
|
+
}
|
|
43115
|
+
return { pruned, branches, deleted, repoRoots };
|
|
43116
|
+
}
|
|
42613
43117
|
async function git3(cwd, args) {
|
|
42614
43118
|
try {
|
|
42615
|
-
const { stdout, stderr } = await
|
|
43119
|
+
const { stdout, stderr } = await execFileAsync3("git", ["-C", cwd, ...args], {
|
|
42616
43120
|
maxBuffer: 16 * 1024 * 1024,
|
|
42617
43121
|
windowsHide: true
|
|
42618
43122
|
});
|
|
@@ -42628,10 +43132,15 @@ async function git3(cwd, args) {
|
|
|
42628
43132
|
}
|
|
42629
43133
|
}
|
|
42630
43134
|
async function resolveGitRoot(cwd) {
|
|
43135
|
+
const key = path41.resolve(cwd);
|
|
43136
|
+
const memo = gitRootMemo.get(key);
|
|
43137
|
+
if (memo) return memo;
|
|
42631
43138
|
const r = await git3(cwd, ["rev-parse", "--show-toplevel"]);
|
|
42632
43139
|
if (!r.ok) return null;
|
|
42633
43140
|
const root = r.stdout.trim();
|
|
42634
|
-
|
|
43141
|
+
if (!root) return null;
|
|
43142
|
+
gitRootMemo.set(key, root);
|
|
43143
|
+
return root;
|
|
42635
43144
|
}
|
|
42636
43145
|
async function createKrakenWorktree(cwd, label) {
|
|
42637
43146
|
const repoRoot = await resolveGitRoot(cwd);
|
|
@@ -42761,9 +43270,14 @@ async function cleanupKrakenWorktree(handle, env = process.env) {
|
|
|
42761
43270
|
}
|
|
42762
43271
|
} catch {
|
|
42763
43272
|
}
|
|
43273
|
+
const branch = handle.branch.startsWith("kraken/") ? handle.branch : null;
|
|
43274
|
+
if (isKrakenWorktreeCleanupBatched(env)) {
|
|
43275
|
+
queueWorktreeCleanup(handle.repoRoot, branch);
|
|
43276
|
+
return;
|
|
43277
|
+
}
|
|
42764
43278
|
await git3(handle.repoRoot, ["worktree", "prune"]);
|
|
42765
|
-
if (
|
|
42766
|
-
await git3(handle.repoRoot, ["branch", "-D",
|
|
43279
|
+
if (branch) {
|
|
43280
|
+
await git3(handle.repoRoot, ["branch", "-D", branch]);
|
|
42767
43281
|
}
|
|
42768
43282
|
}
|
|
42769
43283
|
function formatWorktreeFooter(handle, opts = {}) {
|
|
@@ -42777,11 +43291,14 @@ function formatWorktreeFooter(handle, opts = {}) {
|
|
|
42777
43291
|
}
|
|
42778
43292
|
return `worktree used: branch=${handle.branch} path=${handle.path}`;
|
|
42779
43293
|
}
|
|
42780
|
-
var
|
|
43294
|
+
var execFileAsync3, gitRootMemo;
|
|
42781
43295
|
var init_krakenWorktree = __esm({
|
|
42782
43296
|
"src/cli/tools/krakenWorktree.ts"() {
|
|
42783
43297
|
"use strict";
|
|
42784
|
-
|
|
43298
|
+
init_worktreeCleanupBatch();
|
|
43299
|
+
init_worktreeCleanupBatch();
|
|
43300
|
+
execFileAsync3 = promisify3(execFile4);
|
|
43301
|
+
gitRootMemo = /* @__PURE__ */ new Map();
|
|
42785
43302
|
}
|
|
42786
43303
|
});
|
|
42787
43304
|
|
|
@@ -43157,15 +43674,46 @@ var init_tentacle = __esm({
|
|
|
43157
43674
|
}
|
|
43158
43675
|
});
|
|
43159
43676
|
|
|
43677
|
+
// src/cli/asyncLimit.ts
|
|
43678
|
+
async function runWithLimit2(items, limit, fn) {
|
|
43679
|
+
const slots = Math.min(
|
|
43680
|
+
items.length,
|
|
43681
|
+
Math.max(1, Number.isFinite(limit) ? Math.floor(limit) : 1)
|
|
43682
|
+
);
|
|
43683
|
+
if (slots <= 0) return;
|
|
43684
|
+
let cursor = 0;
|
|
43685
|
+
let failed = false;
|
|
43686
|
+
const worker = async () => {
|
|
43687
|
+
while (!failed && cursor < items.length) {
|
|
43688
|
+
const index = cursor;
|
|
43689
|
+
cursor += 1;
|
|
43690
|
+
try {
|
|
43691
|
+
await fn(items[index], index);
|
|
43692
|
+
} catch (err) {
|
|
43693
|
+
failed = true;
|
|
43694
|
+
throw err;
|
|
43695
|
+
}
|
|
43696
|
+
}
|
|
43697
|
+
};
|
|
43698
|
+
const workers = [];
|
|
43699
|
+
for (let i = 0; i < slots; i += 1) workers.push(worker());
|
|
43700
|
+
await Promise.all(workers);
|
|
43701
|
+
}
|
|
43702
|
+
var init_asyncLimit = __esm({
|
|
43703
|
+
"src/cli/asyncLimit.ts"() {
|
|
43704
|
+
"use strict";
|
|
43705
|
+
}
|
|
43706
|
+
});
|
|
43707
|
+
|
|
43160
43708
|
// src/cli/checkpoint/checkpointManager.ts
|
|
43161
|
-
import { execFile as
|
|
43162
|
-
import { promisify as
|
|
43709
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
43710
|
+
import { promisify as promisify4 } from "node:util";
|
|
43163
43711
|
import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
43164
43712
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
43165
43713
|
import path42 from "node:path";
|
|
43166
43714
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
43167
43715
|
async function git4(cwd, args, env) {
|
|
43168
|
-
const { stdout } = await
|
|
43716
|
+
const { stdout } = await execFileAsync4("git", ["-C", cwd, ...args], {
|
|
43169
43717
|
maxBuffer: 64 * 1024 * 1024,
|
|
43170
43718
|
env: env ? { ...process.env, ...env } : process.env
|
|
43171
43719
|
});
|
|
@@ -43287,11 +43835,11 @@ async function restoreCheckpoint(cwd, id3) {
|
|
|
43287
43835
|
async function dropCheckpoint(cwd, id3) {
|
|
43288
43836
|
return await gitSafe(cwd, ["update-ref", "-d", `${REF_PREFIX}${id3}`]) !== null;
|
|
43289
43837
|
}
|
|
43290
|
-
var
|
|
43838
|
+
var execFileAsync4, REF_PREFIX;
|
|
43291
43839
|
var init_checkpointManager = __esm({
|
|
43292
43840
|
"src/cli/checkpoint/checkpointManager.ts"() {
|
|
43293
43841
|
"use strict";
|
|
43294
|
-
|
|
43842
|
+
execFileAsync4 = promisify4(execFile5);
|
|
43295
43843
|
REF_PREFIX = "refs/zelari/checkpoints/";
|
|
43296
43844
|
}
|
|
43297
43845
|
});
|
|
@@ -43353,7 +43901,7 @@ var init_transactional = __esm({
|
|
|
43353
43901
|
});
|
|
43354
43902
|
|
|
43355
43903
|
// src/cli/workspace/worldModel.ts
|
|
43356
|
-
import { promises as
|
|
43904
|
+
import { promises as fs18 } from "node:fs";
|
|
43357
43905
|
import path43 from "node:path";
|
|
43358
43906
|
import { spawn as spawn8 } from "node:child_process";
|
|
43359
43907
|
function worldDir(cwd) {
|
|
@@ -43361,18 +43909,18 @@ function worldDir(cwd) {
|
|
|
43361
43909
|
}
|
|
43362
43910
|
async function ensureWorldDir(cwd) {
|
|
43363
43911
|
const dir = worldDir(cwd);
|
|
43364
|
-
await
|
|
43912
|
+
await fs18.mkdir(dir, { recursive: true });
|
|
43365
43913
|
return dir;
|
|
43366
43914
|
}
|
|
43367
43915
|
async function appendTimeline(cwd, entry) {
|
|
43368
43916
|
const dir = await ensureWorldDir(cwd);
|
|
43369
43917
|
const line = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n";
|
|
43370
|
-
await
|
|
43918
|
+
await fs18.appendFile(path43.join(dir, TIMELINE_FILE), line, "utf8");
|
|
43371
43919
|
}
|
|
43372
43920
|
async function readChecks(cwd) {
|
|
43373
43921
|
const p3 = path43.join(worldDir(cwd), CHECKS_FILE);
|
|
43374
43922
|
try {
|
|
43375
|
-
const raw = await
|
|
43923
|
+
const raw = await fs18.readFile(p3, "utf8");
|
|
43376
43924
|
const parsed = JSON.parse(raw);
|
|
43377
43925
|
return Array.isArray(parsed.checks) ? parsed.checks : [];
|
|
43378
43926
|
} catch {
|
|
@@ -43540,11 +44088,11 @@ var init_worldModel = __esm({
|
|
|
43540
44088
|
|
|
43541
44089
|
${args.content}
|
|
43542
44090
|
`;
|
|
43543
|
-
await
|
|
44091
|
+
await fs18.appendFile(file2, block, "utf8");
|
|
43544
44092
|
} else {
|
|
43545
|
-
await
|
|
44093
|
+
await fs18.writeFile(file2, args.content, "utf8");
|
|
43546
44094
|
}
|
|
43547
|
-
const st = await
|
|
44095
|
+
const st = await fs18.stat(file2);
|
|
43548
44096
|
await appendTimeline(ctx.cwd, { kind: "hypothesis_update", bytes: st.size, append: !!args.append });
|
|
43549
44097
|
return typedOk({ path: file2, bytes: st.size });
|
|
43550
44098
|
} catch (err) {
|
|
@@ -43573,7 +44121,7 @@ ${args.content}
|
|
|
43573
44121
|
const dir = await ensureWorldDir(ctx.cwd);
|
|
43574
44122
|
const file2 = path43.join(dir, CHECKS_FILE);
|
|
43575
44123
|
const body = { checks: args.checks };
|
|
43576
|
-
await
|
|
44124
|
+
await fs18.writeFile(file2, JSON.stringify(body, null, 2) + "\n", "utf8");
|
|
43577
44125
|
await appendTimeline(ctx.cwd, { kind: "checks_set", count: args.checks.length });
|
|
43578
44126
|
return typedOk({ path: file2, count: args.checks.length });
|
|
43579
44127
|
} catch (err) {
|
|
@@ -43658,7 +44206,7 @@ __export(graphMemory_exports, {
|
|
|
43658
44206
|
saveGraphSnapshot: () => saveGraphSnapshot,
|
|
43659
44207
|
toGraphSnapshot: () => toGraphSnapshot
|
|
43660
44208
|
});
|
|
43661
|
-
import { promises as
|
|
44209
|
+
import { promises as fs19 } from "node:fs";
|
|
43662
44210
|
import path44 from "node:path";
|
|
43663
44211
|
function snapshotPath(cwd) {
|
|
43664
44212
|
return path44.join(cwd, SNAPSHOT_DIR, SNAPSHOT_FILE);
|
|
@@ -43686,16 +44234,16 @@ function toGraphSnapshot(graph, opts) {
|
|
|
43686
44234
|
}
|
|
43687
44235
|
async function saveGraphSnapshot(cwd, snapshot) {
|
|
43688
44236
|
try {
|
|
43689
|
-
await
|
|
44237
|
+
await fs19.access(cwd);
|
|
43690
44238
|
const file2 = snapshotPath(cwd);
|
|
43691
|
-
await
|
|
43692
|
-
await
|
|
44239
|
+
await fs19.mkdir(path44.dirname(file2), { recursive: true });
|
|
44240
|
+
await fs19.writeFile(file2, JSON.stringify(snapshot, null, 2) + "\n", "utf8");
|
|
43693
44241
|
} catch {
|
|
43694
44242
|
}
|
|
43695
44243
|
}
|
|
43696
44244
|
async function loadGraphSnapshot(cwd) {
|
|
43697
44245
|
try {
|
|
43698
|
-
const raw = await
|
|
44246
|
+
const raw = await fs19.readFile(snapshotPath(cwd), "utf8");
|
|
43699
44247
|
const parsed = JSON.parse(raw);
|
|
43700
44248
|
if (!parsed || !Array.isArray(parsed.nodes)) return null;
|
|
43701
44249
|
return parsed;
|
|
@@ -43762,7 +44310,7 @@ var init_graphMemory = __esm({
|
|
|
43762
44310
|
});
|
|
43763
44311
|
|
|
43764
44312
|
// src/cli/kraken/workbench.ts
|
|
43765
|
-
import { promises as
|
|
44313
|
+
import { promises as fs20 } from "node:fs";
|
|
43766
44314
|
import path45 from "node:path";
|
|
43767
44315
|
function isWorkbenchEnabled(env = process.env) {
|
|
43768
44316
|
const v = (env.ZELARI_KRAKEN_WORKBENCH ?? "1").trim().toLowerCase();
|
|
@@ -43933,11 +44481,11 @@ var init_workbench = __esm({
|
|
|
43933
44481
|
if (!this.enabled) return null;
|
|
43934
44482
|
if (!this.dirty && this.lastWrite) return this.lastWrite;
|
|
43935
44483
|
const out = workbenchPath(this.cwd, this.graphId);
|
|
43936
|
-
await
|
|
44484
|
+
await fs20.mkdir(path45.dirname(out), { recursive: true });
|
|
43937
44485
|
const body = this.render();
|
|
43938
44486
|
const tmp = `${out}.${process.pid}.${Date.now()}.tmp`;
|
|
43939
|
-
await
|
|
43940
|
-
await
|
|
44487
|
+
await fs20.writeFile(tmp, body, "utf8");
|
|
44488
|
+
await fs20.rename(tmp, out);
|
|
43941
44489
|
this.dirty = false;
|
|
43942
44490
|
this.lastWrite = Promise.resolve(out);
|
|
43943
44491
|
return out;
|
|
@@ -44517,9 +45065,11 @@ var init_reputationStore = __esm({
|
|
|
44517
45065
|
// src/cli/tools/krakenModel.ts
|
|
44518
45066
|
var krakenModel_exports = {};
|
|
44519
45067
|
__export(krakenModel_exports, {
|
|
45068
|
+
familyCandidatesFromRegistry: () => familyCandidatesFromRegistry,
|
|
44520
45069
|
inferModelFamily: () => inferModelFamily,
|
|
44521
45070
|
isCheapModelId: () => isCheapModelId,
|
|
44522
45071
|
isKrakenAutoModelEnabled: () => isKrakenAutoModelEnabled,
|
|
45072
|
+
isKrakenCrossModelEnabled: () => isKrakenCrossModelEnabled,
|
|
44523
45073
|
isUnknownModelError: () => isUnknownModelError,
|
|
44524
45074
|
parseQualifiedModelRef: () => parseQualifiedModelRef,
|
|
44525
45075
|
pickCheapModel: () => pickCheapModel,
|
|
@@ -44560,6 +45110,10 @@ function isKrakenAutoModelEnabled(env = process.env) {
|
|
|
44560
45110
|
if (v === "0" || v === "false" || v === "no" || v === "off") return false;
|
|
44561
45111
|
return true;
|
|
44562
45112
|
}
|
|
45113
|
+
function isKrakenCrossModelEnabled(env = process.env) {
|
|
45114
|
+
const v = (env.ZELARI_KRAKEN_CROSS_MODEL ?? "").trim().toLowerCase();
|
|
45115
|
+
return !(v === "0" || v === "false" || v === "no" || v === "off");
|
|
45116
|
+
}
|
|
44563
45117
|
function parseQualifiedModelRef(ref) {
|
|
44564
45118
|
const s = ref?.trim() ?? "";
|
|
44565
45119
|
const slash = s.indexOf("/");
|
|
@@ -44596,8 +45150,7 @@ function pickDifferentFamily(builder, candidates) {
|
|
|
44596
45150
|
return null;
|
|
44597
45151
|
}
|
|
44598
45152
|
function resolveCrossModelVerifier(builder, candidates, env = process.env) {
|
|
44599
|
-
|
|
44600
|
-
if (cross === "0" || cross === "false" || cross === "off") return null;
|
|
45153
|
+
if (!isKrakenCrossModelEnabled(env)) return null;
|
|
44601
45154
|
const specific = env.ZELARI_KRAKEN_VERIFY_MODEL?.trim();
|
|
44602
45155
|
if (specific) {
|
|
44603
45156
|
const qualified = parseQualifiedModelRef(specific);
|
|
@@ -44619,7 +45172,7 @@ function resolveKrakenSubModel(agent, parentModel, env = process.env, opts = {})
|
|
|
44619
45172
|
}
|
|
44620
45173
|
return shared;
|
|
44621
45174
|
}
|
|
44622
|
-
if (agent === "verify" && opts.familyCandidates && opts.familyCandidates.length > 0) {
|
|
45175
|
+
if (agent === "verify" && opts.familyCandidates && opts.familyCandidates.length > 0 && isKrakenCrossModelEnabled(env)) {
|
|
44623
45176
|
const picked = pickDifferentFamily(
|
|
44624
45177
|
{ provider: opts.provider ?? "", model: parentModel },
|
|
44625
45178
|
opts.familyCandidates
|
|
@@ -44649,20 +45202,40 @@ function resolvePersonaModel(kind2, parentModel, env = process.env, opts = {}) {
|
|
|
44649
45202
|
if (specific) return specific;
|
|
44650
45203
|
return resolveKrakenSubModel("verify", parentModel, env, opts);
|
|
44651
45204
|
}
|
|
45205
|
+
function familyCandidatesFromRegistry(registry4) {
|
|
45206
|
+
if (!registry4 || typeof registry4 !== "object") return [];
|
|
45207
|
+
const out = [];
|
|
45208
|
+
for (const [key, entry] of Object.entries(registry4)) {
|
|
45209
|
+
const provider = key?.trim() ?? "";
|
|
45210
|
+
if (!provider) continue;
|
|
45211
|
+
const models = entry?.models;
|
|
45212
|
+
if (!Array.isArray(models)) continue;
|
|
45213
|
+
for (const raw of models) {
|
|
45214
|
+
const id3 = typeof raw === "string" ? raw : raw && typeof raw.id === "string" ? raw.id : "";
|
|
45215
|
+
const model = id3.trim();
|
|
45216
|
+
if (model) out.push({ provider, model });
|
|
45217
|
+
}
|
|
45218
|
+
}
|
|
45219
|
+
return out;
|
|
45220
|
+
}
|
|
44652
45221
|
async function resolveKrakenSubModelAsync(agent, parentModel, env = process.env, opts = {}) {
|
|
44653
45222
|
let candidates = [];
|
|
44654
|
-
|
|
44655
|
-
|
|
44656
|
-
|
|
45223
|
+
let familyCandidates = [];
|
|
45224
|
+
try {
|
|
45225
|
+
const mod = await Promise.resolve().then(() => (init_modelDiscovery(), modelDiscovery_exports));
|
|
45226
|
+
if (opts.provider) {
|
|
44657
45227
|
const ids = mod.getDiscoveredModelIds(opts.provider);
|
|
44658
45228
|
if (Array.isArray(ids)) candidates = ids;
|
|
44659
|
-
} catch {
|
|
44660
|
-
candidates = [];
|
|
44661
45229
|
}
|
|
45230
|
+
familyCandidates = familyCandidatesFromRegistry(mod.loadModelsRegistry());
|
|
45231
|
+
} catch {
|
|
45232
|
+
candidates = [];
|
|
45233
|
+
familyCandidates = [];
|
|
44662
45234
|
}
|
|
44663
45235
|
return resolveKrakenSubModel(agent, parentModel, env, {
|
|
44664
45236
|
provider: opts.provider,
|
|
44665
|
-
candidates
|
|
45237
|
+
candidates,
|
|
45238
|
+
familyCandidates
|
|
44666
45239
|
});
|
|
44667
45240
|
}
|
|
44668
45241
|
var CHEAP_RE, FLAGSHIP_RE;
|
|
@@ -45125,6 +45698,7 @@ var init_executor = __esm({
|
|
|
45125
45698
|
init_tentacle();
|
|
45126
45699
|
init_krakenWorktree();
|
|
45127
45700
|
init_krakenRadio();
|
|
45701
|
+
init_asyncLimit();
|
|
45128
45702
|
init_transactional();
|
|
45129
45703
|
init_worldModel();
|
|
45130
45704
|
init_graphStatus();
|
|
@@ -45295,11 +45869,13 @@ var init_executor = __esm({
|
|
|
45295
45869
|
}, this.graphTimeoutMs);
|
|
45296
45870
|
graphTimer.unref?.();
|
|
45297
45871
|
}
|
|
45872
|
+
const worktreeCleanupBatched = beginKrakenWorktreeCleanupBatch(process.env);
|
|
45298
45873
|
try {
|
|
45299
45874
|
return await this.schedule(graph);
|
|
45300
45875
|
} finally {
|
|
45301
45876
|
if (graphTimer) clearTimeout(graphTimer);
|
|
45302
45877
|
this.signal?.removeEventListener("abort", onAbort);
|
|
45878
|
+
if (worktreeCleanupBatched) await flushKrakenWorktreeCleanupBatch();
|
|
45303
45879
|
}
|
|
45304
45880
|
}
|
|
45305
45881
|
/** The scheduling loop proper. See {@link execute} for the cancellation wrapper. */
|
|
@@ -46086,6 +46662,7 @@ ${upstream}` : node.prompt,
|
|
|
46086
46662
|
const memory = this.deps.memoryService;
|
|
46087
46663
|
if (!memory || this.deps.memoryAutoWrite === false) return;
|
|
46088
46664
|
try {
|
|
46665
|
+
const edges = [];
|
|
46089
46666
|
for (const node of graph.nodes.values()) {
|
|
46090
46667
|
const nodeMemoryId = this.memoryIds.get(node.id);
|
|
46091
46668
|
if (!nodeMemoryId) continue;
|
|
@@ -46094,22 +46671,21 @@ ${upstream}` : node.prompt,
|
|
|
46094
46671
|
if (!dependencyMemoryId) continue;
|
|
46095
46672
|
if (node.kind === "verify") {
|
|
46096
46673
|
const verdict = parseVerifyVerdict(node.result).verdict;
|
|
46097
|
-
|
|
46674
|
+
edges.push({
|
|
46098
46675
|
from: dependencyMemoryId,
|
|
46099
46676
|
to: nodeMemoryId,
|
|
46100
|
-
relation: verdict === "pass" ? "validated_by" : verdict === "fail" ? "invalidated_by" : "related_to"
|
|
46101
|
-
createdBy: "kraken-orchestrator"
|
|
46677
|
+
relation: verdict === "pass" ? "validated_by" : verdict === "fail" ? "invalidated_by" : "related_to"
|
|
46102
46678
|
});
|
|
46103
46679
|
} else {
|
|
46104
|
-
|
|
46105
|
-
from: nodeMemoryId,
|
|
46106
|
-
to: dependencyMemoryId,
|
|
46107
|
-
relation: "derived_from",
|
|
46108
|
-
createdBy: "kraken-orchestrator"
|
|
46109
|
-
});
|
|
46680
|
+
edges.push({ from: nodeMemoryId, to: dependencyMemoryId, relation: "derived_from" });
|
|
46110
46681
|
}
|
|
46111
46682
|
}
|
|
46112
46683
|
}
|
|
46684
|
+
await runWithLimit2(
|
|
46685
|
+
edges,
|
|
46686
|
+
8,
|
|
46687
|
+
(edge) => memory.connect({ ...edge, createdBy: "kraken-orchestrator" }).catch(() => void 0)
|
|
46688
|
+
);
|
|
46113
46689
|
const counts = countByStatus(graph);
|
|
46114
46690
|
const outcome = await memory.remember({
|
|
46115
46691
|
kind: converged ? "outcome" : "failure",
|
|
@@ -46121,14 +46697,17 @@ ${upstream}` : node.prompt,
|
|
|
46121
46697
|
metadata: { graphId: graph.id, converged, counts, writeClass: "auto" },
|
|
46122
46698
|
writeClass: "auto"
|
|
46123
46699
|
});
|
|
46124
|
-
|
|
46125
|
-
|
|
46126
|
-
|
|
46127
|
-
|
|
46128
|
-
|
|
46129
|
-
|
|
46130
|
-
|
|
46131
|
-
|
|
46700
|
+
const outcomeEdges = [...this.memoryIds.values()].map((memoryId) => ({
|
|
46701
|
+
from: outcome.id,
|
|
46702
|
+
to: memoryId,
|
|
46703
|
+
relation: "derived_from",
|
|
46704
|
+
createdBy: "kraken-orchestrator"
|
|
46705
|
+
}));
|
|
46706
|
+
await runWithLimit2(
|
|
46707
|
+
outcomeEdges,
|
|
46708
|
+
8,
|
|
46709
|
+
(edge) => memory.connect(edge).catch(() => void 0)
|
|
46710
|
+
);
|
|
46132
46711
|
await memory.consolidate({
|
|
46133
46712
|
source: { agent: "kraken-orchestrator", sessionId: this.sessionId },
|
|
46134
46713
|
minOccurrences: 2
|
|
@@ -49212,7 +49791,7 @@ var init_planTaskTools = __esm({
|
|
|
49212
49791
|
});
|
|
49213
49792
|
|
|
49214
49793
|
// src/cli/tools/inspectTypecheckSafety.ts
|
|
49215
|
-
import { promises as
|
|
49794
|
+
import { promises as fs21 } from "node:fs";
|
|
49216
49795
|
import path49 from "node:path";
|
|
49217
49796
|
import { spawn as spawn9 } from "node:child_process";
|
|
49218
49797
|
async function scanTsbuildinfo(root) {
|
|
@@ -49222,7 +49801,7 @@ async function scanTsbuildinfo(root) {
|
|
|
49222
49801
|
const dir = stack.pop();
|
|
49223
49802
|
let entries;
|
|
49224
49803
|
try {
|
|
49225
|
-
entries = await
|
|
49804
|
+
entries = await fs21.readdir(dir, { withFileTypes: true });
|
|
49226
49805
|
} catch {
|
|
49227
49806
|
continue;
|
|
49228
49807
|
}
|
|
@@ -49267,7 +49846,7 @@ async function cleanupArtifacts(root, relPaths) {
|
|
|
49267
49846
|
const failed = [];
|
|
49268
49847
|
for (const rel2 of relPaths) {
|
|
49269
49848
|
try {
|
|
49270
|
-
await
|
|
49849
|
+
await fs21.unlink(path49.join(root, rel2));
|
|
49271
49850
|
cleaned.push(rel2);
|
|
49272
49851
|
} catch {
|
|
49273
49852
|
failed.push(rel2);
|
|
@@ -49291,8 +49870,8 @@ var init_inspectTypecheckSafety = __esm({
|
|
|
49291
49870
|
|
|
49292
49871
|
// src/cli/tools/inspectCommand.ts
|
|
49293
49872
|
import { spawn as spawn10 } from "node:child_process";
|
|
49294
|
-
import { createHash as
|
|
49295
|
-
import { existsSync as existsSync28, promises as
|
|
49873
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
49874
|
+
import { existsSync as existsSync28, promises as fs22 } from "node:fs";
|
|
49296
49875
|
import os2 from "node:os";
|
|
49297
49876
|
import path50 from "node:path";
|
|
49298
49877
|
function resolveNodeModuleBin(start, rel2) {
|
|
@@ -49378,7 +49957,7 @@ function buildInspectCommand(op, ctx) {
|
|
|
49378
49957
|
}
|
|
49379
49958
|
case "typecheck": {
|
|
49380
49959
|
const project = path50.resolve(ctx.cwd, op.project ?? "tsconfig.json");
|
|
49381
|
-
const hash3 =
|
|
49960
|
+
const hash3 = createHash14("sha256").update(project).digest("hex").slice(0, 16);
|
|
49382
49961
|
const tsBuildInfoFile = path50.join(os2.tmpdir(), "zelari-inspect", `${hash3}.tsbuildinfo`);
|
|
49383
49962
|
return {
|
|
49384
49963
|
ok: true,
|
|
@@ -49517,7 +50096,7 @@ function createInspectCommandTool(rootOrDeps) {
|
|
|
49517
50096
|
if (op.operation === "typecheck") {
|
|
49518
50097
|
const tsc = built.argv[0];
|
|
49519
50098
|
try {
|
|
49520
|
-
await
|
|
50099
|
+
await fs22.access(tsc);
|
|
49521
50100
|
} catch {
|
|
49522
50101
|
return typedErr(
|
|
49523
50102
|
`TYPESCRIPT_UNAVAILABLE: no TypeScript compiler at ${tsc} \u2014 inspect_command typecheck uses the project toolchain (walk-up to node_modules/typescript/bin/tsc) and refuses to guess. Install dependencies or fall back to read_file/grep_content.`
|
|
@@ -50913,11 +51492,11 @@ var init_store2 = __esm({
|
|
|
50913
51492
|
});
|
|
50914
51493
|
|
|
50915
51494
|
// src/cli/semantic/index.ts
|
|
50916
|
-
import { promises as
|
|
51495
|
+
import { promises as fs23, existsSync as existsSync29, readFileSync as readFileSync21 } from "node:fs";
|
|
50917
51496
|
import path53 from "node:path";
|
|
50918
|
-
import { createHash as
|
|
51497
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
50919
51498
|
function getIndexPath(root) {
|
|
50920
|
-
const hash3 =
|
|
51499
|
+
const hash3 = createHash15("sha1").update(path53.resolve(root)).digest("hex").slice(0, 16);
|
|
50921
51500
|
return process.env.ZELARI_SEMANTIC_FILE ?? path53.join(semanticStateDir(), `${hash3}.json`);
|
|
50922
51501
|
}
|
|
50923
51502
|
async function collectSourceFiles(root, maxFiles = 1500) {
|
|
@@ -50926,7 +51505,7 @@ async function collectSourceFiles(root, maxFiles = 1500) {
|
|
|
50926
51505
|
if (out.length >= maxFiles) return;
|
|
50927
51506
|
let entries;
|
|
50928
51507
|
try {
|
|
50929
|
-
entries = await
|
|
51508
|
+
entries = await fs23.readdir(dir, { withFileTypes: true });
|
|
50930
51509
|
} catch {
|
|
50931
51510
|
return;
|
|
50932
51511
|
}
|
|
@@ -50956,7 +51535,7 @@ async function buildIndex(files, embed, options) {
|
|
|
50956
51535
|
for (const file2 of files) {
|
|
50957
51536
|
let text;
|
|
50958
51537
|
try {
|
|
50959
|
-
text = await
|
|
51538
|
+
text = await fs23.readFile(file2, "utf8");
|
|
50960
51539
|
} catch {
|
|
50961
51540
|
continue;
|
|
50962
51541
|
}
|
|
@@ -50989,10 +51568,10 @@ async function buildIndex(files, embed, options) {
|
|
|
50989
51568
|
}
|
|
50990
51569
|
async function saveIndex(root, data) {
|
|
50991
51570
|
const file2 = getIndexPath(root);
|
|
50992
|
-
await
|
|
51571
|
+
await fs23.mkdir(path53.dirname(file2), { recursive: true });
|
|
50993
51572
|
const tmp = `${file2}.tmp-${process.pid}`;
|
|
50994
|
-
await
|
|
50995
|
-
await
|
|
51573
|
+
await fs23.writeFile(tmp, JSON.stringify(data), "utf8");
|
|
51574
|
+
await fs23.rename(tmp, file2);
|
|
50996
51575
|
}
|
|
50997
51576
|
function loadIndex(root) {
|
|
50998
51577
|
const file2 = getIndexPath(root);
|
|
@@ -52253,13 +52832,13 @@ var init_tools5 = __esm({
|
|
|
52253
52832
|
});
|
|
52254
52833
|
|
|
52255
52834
|
// src/cli/tools/screenshotTool.ts
|
|
52256
|
-
import { execFile as
|
|
52835
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
52257
52836
|
import { mkdir as mkdir3, readFile as readFile8, stat as stat7 } from "node:fs/promises";
|
|
52258
52837
|
import path57 from "node:path";
|
|
52259
|
-
import { promisify as
|
|
52838
|
+
import { promisify as promisify5 } from "node:util";
|
|
52260
52839
|
async function captureWindows(target) {
|
|
52261
52840
|
const script = `Add-Type -AssemblyName System.Windows.Forms,System.Drawing;$b=[System.Windows.Forms.SystemInformation]::VirtualScreen;$bmp=New-Object System.Drawing.Bitmap $b.Width,$b.Height;$g=[System.Drawing.Graphics]::FromImage($bmp);$g.CopyFromScreen($b.Left,$b.Top,0,0,$bmp.Size);$g.Dispose(); $bmp.Save('${target.replace(/'/g, "''")}'); $bmp.Dispose();`;
|
|
52262
|
-
await
|
|
52841
|
+
await execFileAsync5("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
|
|
52263
52842
|
timeout: 12e3,
|
|
52264
52843
|
windowsHide: true
|
|
52265
52844
|
});
|
|
@@ -52273,7 +52852,7 @@ async function captureUnixLike(target) {
|
|
|
52273
52852
|
let lastErr = null;
|
|
52274
52853
|
for (const [bin, args] of attempts) {
|
|
52275
52854
|
try {
|
|
52276
|
-
await
|
|
52855
|
+
await execFileAsync5(bin, args, { timeout: 12e3 });
|
|
52277
52856
|
return;
|
|
52278
52857
|
} catch (e) {
|
|
52279
52858
|
lastErr = e;
|
|
@@ -52327,13 +52906,13 @@ function createScreenshotTool(deps = {}) {
|
|
|
52327
52906
|
}
|
|
52328
52907
|
};
|
|
52329
52908
|
}
|
|
52330
|
-
var
|
|
52909
|
+
var execFileAsync5, SCREENSHOT_MAX_BYTES2;
|
|
52331
52910
|
var init_screenshotTool = __esm({
|
|
52332
52911
|
"src/cli/tools/screenshotTool.ts"() {
|
|
52333
52912
|
"use strict";
|
|
52334
52913
|
init_zod();
|
|
52335
52914
|
init_toolTypes();
|
|
52336
|
-
|
|
52915
|
+
execFileAsync5 = promisify5(execFile6);
|
|
52337
52916
|
SCREENSHOT_MAX_BYTES2 = 8 * 1024 * 1024;
|
|
52338
52917
|
}
|
|
52339
52918
|
});
|
|
@@ -53656,6 +54235,163 @@ var init_resolveStream = __esm({
|
|
|
53656
54235
|
}
|
|
53657
54236
|
});
|
|
53658
54237
|
|
|
54238
|
+
// src/cli/providerFailover.ts
|
|
54239
|
+
function providerFailover(options) {
|
|
54240
|
+
const isTransient = options.isTransientFailure ?? DEFAULT_IS_TRANSIENT;
|
|
54241
|
+
const primaryFailedMsg = options.fallbackLabel ? `[failover] primary failed, switching to ${options.fallbackLabel}` : "[failover] primary failed, switching to fallback";
|
|
54242
|
+
const primaryThrewMsg = options.fallbackLabel ? `[failover] primary threw, switching to ${options.fallbackLabel}: ` : "[failover] primary threw: ";
|
|
54243
|
+
const fallbackFailedMsg = options.fallbackLabel ? `[failover] fallback (${options.fallbackLabel}) also failed: ` : "[failover] fallback also failed: ";
|
|
54244
|
+
const notify = (phase2, message) => {
|
|
54245
|
+
if (!options.onFailover) return;
|
|
54246
|
+
try {
|
|
54247
|
+
options.onFailover({
|
|
54248
|
+
phase: phase2,
|
|
54249
|
+
message,
|
|
54250
|
+
...options.fallbackLabel ? { label: options.fallbackLabel } : {}
|
|
54251
|
+
});
|
|
54252
|
+
} catch {
|
|
54253
|
+
}
|
|
54254
|
+
};
|
|
54255
|
+
return async function* (params) {
|
|
54256
|
+
const triedFallback = { value: false };
|
|
54257
|
+
try {
|
|
54258
|
+
for await (const delta of options.primary(params)) {
|
|
54259
|
+
if (isTransient(delta)) {
|
|
54260
|
+
yield delta;
|
|
54261
|
+
triedFallback.value = true;
|
|
54262
|
+
yield {
|
|
54263
|
+
kind: "error",
|
|
54264
|
+
message: primaryFailedMsg
|
|
54265
|
+
};
|
|
54266
|
+
notify("swap-delta", primaryFailedMsg);
|
|
54267
|
+
break;
|
|
54268
|
+
}
|
|
54269
|
+
yield delta;
|
|
54270
|
+
}
|
|
54271
|
+
} catch (err) {
|
|
54272
|
+
triedFallback.value = true;
|
|
54273
|
+
const threwMsg = `${primaryThrewMsg}${err instanceof Error ? err.message : String(err)}`;
|
|
54274
|
+
yield {
|
|
54275
|
+
kind: "error",
|
|
54276
|
+
message: threwMsg
|
|
54277
|
+
};
|
|
54278
|
+
notify("swap-throw", threwMsg);
|
|
54279
|
+
}
|
|
54280
|
+
if (triedFallback.value) {
|
|
54281
|
+
try {
|
|
54282
|
+
for await (const delta of options.fallback(params)) {
|
|
54283
|
+
yield delta;
|
|
54284
|
+
}
|
|
54285
|
+
} catch (err) {
|
|
54286
|
+
const failedMsg = `${fallbackFailedMsg}${err instanceof Error ? err.message : String(err)}`;
|
|
54287
|
+
yield {
|
|
54288
|
+
kind: "error",
|
|
54289
|
+
message: failedMsg
|
|
54290
|
+
};
|
|
54291
|
+
notify("fallback-failed", failedMsg);
|
|
54292
|
+
return;
|
|
54293
|
+
}
|
|
54294
|
+
}
|
|
54295
|
+
};
|
|
54296
|
+
}
|
|
54297
|
+
var DEFAULT_IS_TRANSIENT;
|
|
54298
|
+
var init_providerFailover = __esm({
|
|
54299
|
+
"src/cli/providerFailover.ts"() {
|
|
54300
|
+
"use strict";
|
|
54301
|
+
DEFAULT_IS_TRANSIENT = (delta) => delta.kind === "error";
|
|
54302
|
+
}
|
|
54303
|
+
});
|
|
54304
|
+
|
|
54305
|
+
// src/cli/crossProviderFailover.ts
|
|
54306
|
+
var crossProviderFailover_exports = {};
|
|
54307
|
+
__export(crossProviderFailover_exports, {
|
|
54308
|
+
isHeadlessFailoverEnabled: () => isHeadlessFailoverEnabled,
|
|
54309
|
+
resolveFailoverStream: () => resolveFailoverStream,
|
|
54310
|
+
wrapWithHeadlessFailover: () => wrapWithHeadlessFailover
|
|
54311
|
+
});
|
|
54312
|
+
async function resolveFailoverStream(options) {
|
|
54313
|
+
if (!options.failoverEnabled) {
|
|
54314
|
+
return {
|
|
54315
|
+
fallback: options.primary,
|
|
54316
|
+
fallbackLabel: void 0,
|
|
54317
|
+
warning: "",
|
|
54318
|
+
reason: "disabled"
|
|
54319
|
+
};
|
|
54320
|
+
}
|
|
54321
|
+
const requested = options.envValue?.trim();
|
|
54322
|
+
if (!requested || requested.length === 0) {
|
|
54323
|
+
return {
|
|
54324
|
+
fallback: options.primary,
|
|
54325
|
+
fallbackLabel: void 0,
|
|
54326
|
+
warning: "",
|
|
54327
|
+
reason: "unset"
|
|
54328
|
+
};
|
|
54329
|
+
}
|
|
54330
|
+
const valid = new Set(options.validProviderIds);
|
|
54331
|
+
if (!valid.has(requested)) {
|
|
54332
|
+
return {
|
|
54333
|
+
fallback: options.primary,
|
|
54334
|
+
fallbackLabel: void 0,
|
|
54335
|
+
warning: `[failover] ANATHEMA_FAILOVER_PROVIDER="${requested}" is not a known provider. Falling back to v3-G same-provider behavior. Available: ${options.validProviderIds.join(", ")}.`,
|
|
54336
|
+
reason: "unknown"
|
|
54337
|
+
};
|
|
54338
|
+
}
|
|
54339
|
+
if (requested === options.primaryProviderId) {
|
|
54340
|
+
return {
|
|
54341
|
+
fallback: options.primary,
|
|
54342
|
+
fallbackLabel: void 0,
|
|
54343
|
+
warning: "",
|
|
54344
|
+
reason: "same-as-primary"
|
|
54345
|
+
};
|
|
54346
|
+
}
|
|
54347
|
+
const fallbackConfig = await options.lookupFallbackConfig(requested);
|
|
54348
|
+
if (!fallbackConfig) {
|
|
54349
|
+
return {
|
|
54350
|
+
fallback: options.primary,
|
|
54351
|
+
fallbackLabel: void 0,
|
|
54352
|
+
warning: `[failover] No API key configured for provider "${requested}". Falling back to v3-G same-provider behavior.`,
|
|
54353
|
+
reason: "missing-key"
|
|
54354
|
+
};
|
|
54355
|
+
}
|
|
54356
|
+
return {
|
|
54357
|
+
fallback: options.buildStream(fallbackConfig),
|
|
54358
|
+
fallbackLabel: requested,
|
|
54359
|
+
warning: "",
|
|
54360
|
+
reason: "resolved"
|
|
54361
|
+
};
|
|
54362
|
+
}
|
|
54363
|
+
function isHeadlessFailoverEnabled(env = process.env) {
|
|
54364
|
+
return env.ZELARI_HEADLESS_FAILOVER === "1" && env.ANATHEMA_FAILOVER !== "0";
|
|
54365
|
+
}
|
|
54366
|
+
async function wrapWithHeadlessFailover(options) {
|
|
54367
|
+
const env = options.env ?? process.env;
|
|
54368
|
+
if (!isHeadlessFailoverEnabled(env)) {
|
|
54369
|
+
return options.primary;
|
|
54370
|
+
}
|
|
54371
|
+
const resolved = await resolveFailoverStream({
|
|
54372
|
+
failoverEnabled: true,
|
|
54373
|
+
envValue: env.ANATHEMA_FAILOVER_PROVIDER,
|
|
54374
|
+
primaryProviderId: options.primaryProviderId,
|
|
54375
|
+
primary: options.primary,
|
|
54376
|
+
validProviderIds: options.validProviderIds,
|
|
54377
|
+
lookupFallbackConfig: options.lookupFallbackConfig,
|
|
54378
|
+
buildStream: options.buildStream
|
|
54379
|
+
});
|
|
54380
|
+
if (resolved.warning) options.onWarning?.(resolved.warning);
|
|
54381
|
+
return providerFailover({
|
|
54382
|
+
primary: options.primary,
|
|
54383
|
+
fallback: resolved.fallback,
|
|
54384
|
+
...resolved.fallbackLabel ? { fallbackLabel: resolved.fallbackLabel } : {},
|
|
54385
|
+
...options.onFailover ? { onFailover: options.onFailover } : {}
|
|
54386
|
+
});
|
|
54387
|
+
}
|
|
54388
|
+
var init_crossProviderFailover = __esm({
|
|
54389
|
+
"src/cli/crossProviderFailover.ts"() {
|
|
54390
|
+
"use strict";
|
|
54391
|
+
init_providerFailover();
|
|
54392
|
+
}
|
|
54393
|
+
});
|
|
54394
|
+
|
|
53659
54395
|
// src/cli/safety/toolPermissions.ts
|
|
53660
54396
|
var toolPermissions_exports = {};
|
|
53661
54397
|
__export(toolPermissions_exports, {
|
|
@@ -53842,7 +54578,7 @@ function recordNonUserContent(source2, text, tool) {
|
|
|
53842
54578
|
const excerpt = normalize5(raw).slice(0, MAX_EXCERPT);
|
|
53843
54579
|
if (excerpt.length < PROVENANCE_MIN_MATCH * 2) return;
|
|
53844
54580
|
ring.push({ source: source2, tool, excerpt, at: Date.now() });
|
|
53845
|
-
if (ring.length >
|
|
54581
|
+
if (ring.length > MAX_ENTRIES2) ring.splice(0, ring.length - MAX_ENTRIES2);
|
|
53846
54582
|
} catch {
|
|
53847
54583
|
}
|
|
53848
54584
|
}
|
|
@@ -53898,11 +54634,11 @@ function safeJson2(v) {
|
|
|
53898
54634
|
return "";
|
|
53899
54635
|
}
|
|
53900
54636
|
}
|
|
53901
|
-
var
|
|
54637
|
+
var MAX_ENTRIES2, MAX_EXCERPT, PROVENANCE_MIN_MATCH, SHINGLE_STEP, MAX_SHINGLES, ring;
|
|
53902
54638
|
var init_provenance = __esm({
|
|
53903
54639
|
"src/cli/safety/provenance.ts"() {
|
|
53904
54640
|
"use strict";
|
|
53905
|
-
|
|
54641
|
+
MAX_ENTRIES2 = 40;
|
|
53906
54642
|
MAX_EXCERPT = 8192;
|
|
53907
54643
|
PROVENANCE_MIN_MATCH = 48;
|
|
53908
54644
|
SHINGLE_STEP = 24;
|
|
@@ -54095,7 +54831,7 @@ var init_lifecycleHooks = __esm({
|
|
|
54095
54831
|
});
|
|
54096
54832
|
|
|
54097
54833
|
// src/cli/safety/astGate.ts
|
|
54098
|
-
import { promises as
|
|
54834
|
+
import { promises as fs24 } from "node:fs";
|
|
54099
54835
|
import path59 from "node:path";
|
|
54100
54836
|
function astGateEnabled() {
|
|
54101
54837
|
return process.env.ZELARI_AST_GATE !== "0";
|
|
@@ -54145,7 +54881,7 @@ function wrapWithAstGate(original, opts) {
|
|
|
54145
54881
|
if (astGateEnabled()) gateTarget = containedPathOf(args);
|
|
54146
54882
|
if (gateTarget !== null && isAstSupported(gateTarget)) {
|
|
54147
54883
|
try {
|
|
54148
|
-
preContent = await
|
|
54884
|
+
preContent = await fs24.readFile(gateTarget, "utf8");
|
|
54149
54885
|
} catch (err) {
|
|
54150
54886
|
if (err?.code === "ENOENT") preContent = null;
|
|
54151
54887
|
}
|
|
@@ -54174,16 +54910,16 @@ function wrapWithAstGate(original, opts) {
|
|
|
54174
54910
|
);
|
|
54175
54911
|
return result;
|
|
54176
54912
|
}
|
|
54177
|
-
const post = await
|
|
54913
|
+
const post = await fs24.readFile(absPath, "utf8");
|
|
54178
54914
|
const syntaxError = firstSyntaxError(ts, path59.basename(absPath), post);
|
|
54179
54915
|
if (!syntaxError) return result;
|
|
54180
54916
|
const parseError = `${syntaxError.message} (line ${syntaxError.line}, col ${syntaxError.character})`;
|
|
54181
54917
|
let revertedTo;
|
|
54182
54918
|
if (preContent === null) {
|
|
54183
|
-
await
|
|
54919
|
+
await fs24.unlink(absPath).catch(() => void 0);
|
|
54184
54920
|
revertedTo = "absent";
|
|
54185
54921
|
} else {
|
|
54186
|
-
await
|
|
54922
|
+
await fs24.writeFile(absPath, preContent, "utf8");
|
|
54187
54923
|
revertedTo = snapshotIdOf(preContent);
|
|
54188
54924
|
}
|
|
54189
54925
|
const relLabel = path59.relative(opts.root, absPath) || path59.basename(absPath);
|
|
@@ -54609,8 +55345,8 @@ var init_resourceClaims = __esm({
|
|
|
54609
55345
|
});
|
|
54610
55346
|
|
|
54611
55347
|
// src/cli/toolResultCache.ts
|
|
54612
|
-
import { createHash as
|
|
54613
|
-
import { promises as
|
|
55348
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
55349
|
+
import { promises as fs25 } from "node:fs";
|
|
54614
55350
|
import path60 from "node:path";
|
|
54615
55351
|
function isToolCacheEnabled() {
|
|
54616
55352
|
const raw = process.env.ZELARI_TOOL_CACHE;
|
|
@@ -54622,7 +55358,7 @@ function resolveToolCacheTtlMs() {
|
|
|
54622
55358
|
return Number.isFinite(n) && n >= 0 ? n : TOOL_CACHE_DEFAULT_TTL_MS;
|
|
54623
55359
|
}
|
|
54624
55360
|
function hashKey(parts) {
|
|
54625
|
-
return
|
|
55361
|
+
return createHash16("sha256").update(JSON.stringify(parts), "utf8").digest("hex");
|
|
54626
55362
|
}
|
|
54627
55363
|
function resultBytes(result) {
|
|
54628
55364
|
try {
|
|
@@ -54698,7 +55434,7 @@ async function statKey(toolName, input, ctx) {
|
|
|
54698
55434
|
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
54699
55435
|
const abs = path60.isAbsolute(rawPath) ? rawPath : path60.join(ctx.cwd, rawPath);
|
|
54700
55436
|
try {
|
|
54701
|
-
const st = await
|
|
55437
|
+
const st = await fs25.stat(abs);
|
|
54702
55438
|
return hashKey({
|
|
54703
55439
|
tool: toolName,
|
|
54704
55440
|
args: input,
|
|
@@ -55123,9 +55859,11 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
55123
55859
|
return async ({ agent, cwd: subCwd }) => {
|
|
55124
55860
|
const cfg = providerOverride ? await providerConfigFor(providerOverride) : await providerFromEnv();
|
|
55125
55861
|
if (!cfg) return null;
|
|
55126
|
-
const {
|
|
55862
|
+
const { resolveKrakenSubModelAsync: resolveKrakenSubModelAsync2, parseQualifiedModelRef: parseQualifiedModelRef2 } = await Promise.resolve().then(() => (init_krakenModel(), krakenModel_exports));
|
|
55127
55863
|
const parentModel = modelOverride || cfg.model;
|
|
55128
|
-
const resolvedModel =
|
|
55864
|
+
const resolvedModel = await resolveKrakenSubModelAsync2(agent, parentModel, process.env, {
|
|
55865
|
+
provider: cfg.providerId
|
|
55866
|
+
});
|
|
55129
55867
|
let effCfg = cfg;
|
|
55130
55868
|
let model = resolvedModel;
|
|
55131
55869
|
const ref = parseQualifiedModelRef2(resolvedModel);
|
|
@@ -55158,15 +55896,31 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
55158
55896
|
// P0.5: the tentacle's agent identity drives per-agent policy rules.
|
|
55159
55897
|
policyAgent: agent
|
|
55160
55898
|
});
|
|
55899
|
+
const wrapTentacleStream = (primary, primaryProviderId) => wrapWithHeadlessFailover({
|
|
55900
|
+
primary,
|
|
55901
|
+
primaryProviderId,
|
|
55902
|
+
validProviderIds: PROVIDERS.map((p3) => p3.id),
|
|
55903
|
+
lookupFallbackConfig: (id3) => providerConfigFor(id3),
|
|
55904
|
+
buildStream: (config2) => buildProviderStream(config2)
|
|
55905
|
+
});
|
|
55906
|
+
const providerStream = await wrapTentacleStream(
|
|
55907
|
+
buildProviderStream(subCfg),
|
|
55908
|
+
subCfg.providerId
|
|
55909
|
+
);
|
|
55161
55910
|
return {
|
|
55162
|
-
providerStream
|
|
55911
|
+
providerStream,
|
|
55163
55912
|
model,
|
|
55164
55913
|
provider: subCfg.providerId,
|
|
55165
55914
|
...model !== parentModel ? {
|
|
55166
55915
|
fallback: {
|
|
55167
55916
|
model: parentModel,
|
|
55168
55917
|
provider: cfg.providerId,
|
|
55169
|
-
|
|
55918
|
+
// Wrap the 404-parent fallback too so a later model retry still
|
|
55919
|
+
// has transport failover. Orthogonal to isUnknownModelError.
|
|
55920
|
+
providerStream: await wrapTentacleStream(
|
|
55921
|
+
buildProviderStream({ ...cfg, model: parentModel }),
|
|
55922
|
+
cfg.providerId
|
|
55923
|
+
)
|
|
55170
55924
|
}
|
|
55171
55925
|
} : {},
|
|
55172
55926
|
registry: subRegistry,
|
|
@@ -55653,6 +56407,8 @@ var init_toolRegistry = __esm({
|
|
|
55653
56407
|
init_openai_compatible();
|
|
55654
56408
|
init_resolveStream();
|
|
55655
56409
|
init_providerConfig();
|
|
56410
|
+
init_crossProviderFailover();
|
|
56411
|
+
init_keyStore();
|
|
55656
56412
|
init_toolPermissions();
|
|
55657
56413
|
init_destructiveCommands();
|
|
55658
56414
|
init_provenance();
|
|
@@ -55693,12 +56449,12 @@ var init_toolRegistry = __esm({
|
|
|
55693
56449
|
});
|
|
55694
56450
|
|
|
55695
56451
|
// src/cli/metrics.ts
|
|
55696
|
-
import { promises as
|
|
56452
|
+
import { promises as fs26, existsSync as existsSync33, statSync as statSync4, renameSync as renameSync4, appendFileSync as appendFileSync3, mkdirSync as mkdirSync15 } from "node:fs";
|
|
55697
56453
|
import path62 from "node:path";
|
|
55698
56454
|
async function readMetrics(file2) {
|
|
55699
56455
|
let raw = "";
|
|
55700
56456
|
try {
|
|
55701
|
-
raw = await
|
|
56457
|
+
raw = await fs26.readFile(file2, "utf-8");
|
|
55702
56458
|
} catch {
|
|
55703
56459
|
return [];
|
|
55704
56460
|
}
|
|
@@ -56076,8 +56832,8 @@ __export(completionProofProbe_exports, {
|
|
|
56076
56832
|
gatherGitAttestation: () => gatherGitAttestation,
|
|
56077
56833
|
harnessManifest: () => harnessManifest
|
|
56078
56834
|
});
|
|
56079
|
-
import { execFile as
|
|
56080
|
-
import { promisify as
|
|
56835
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
56836
|
+
import { promisify as promisify6 } from "node:util";
|
|
56081
56837
|
async function readHarnessVersion() {
|
|
56082
56838
|
if (cachedHarnessVersion !== null) return cachedHarnessVersion;
|
|
56083
56839
|
try {
|
|
@@ -56108,7 +56864,7 @@ async function harnessManifest(env = process.env) {
|
|
|
56108
56864
|
}
|
|
56109
56865
|
async function git5(cwd, args) {
|
|
56110
56866
|
try {
|
|
56111
|
-
const { stdout } = await
|
|
56867
|
+
const { stdout } = await execFileAsync6("git", ["-C", cwd, ...args], {
|
|
56112
56868
|
maxBuffer: 32 * 1024 * 1024,
|
|
56113
56869
|
windowsHide: true
|
|
56114
56870
|
});
|
|
@@ -56150,7 +56906,7 @@ function activeTaskContractSnapshot() {
|
|
|
56150
56906
|
return void 0;
|
|
56151
56907
|
}
|
|
56152
56908
|
}
|
|
56153
|
-
var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion,
|
|
56909
|
+
var HARNESS_VERSION_FALLBACK, ADAPTER_IDS, cachedHarnessVersion, execFileAsync6;
|
|
56154
56910
|
var init_completionProofProbe = __esm({
|
|
56155
56911
|
"src/cli/kraken/completionProofProbe.ts"() {
|
|
56156
56912
|
"use strict";
|
|
@@ -56158,14 +56914,14 @@ var init_completionProofProbe = __esm({
|
|
|
56158
56914
|
HARNESS_VERSION_FALLBACK = "2.13.0";
|
|
56159
56915
|
ADAPTER_IDS = ["node", "python", "rust", "go", "java", "dotnet"];
|
|
56160
56916
|
cachedHarnessVersion = null;
|
|
56161
|
-
|
|
56917
|
+
execFileAsync6 = promisify6(execFile7);
|
|
56162
56918
|
}
|
|
56163
56919
|
});
|
|
56164
56920
|
|
|
56165
56921
|
// src/cli/kraken/completionProofAttestation.ts
|
|
56166
|
-
import { createHash as
|
|
56922
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
56167
56923
|
function sha256Hex3(data) {
|
|
56168
|
-
return
|
|
56924
|
+
return createHash17("sha256").update(data, "utf8").digest("hex");
|
|
56169
56925
|
}
|
|
56170
56926
|
function canonicalJson(value) {
|
|
56171
56927
|
return JSON.stringify(canonicalValue(value));
|
|
@@ -56625,21 +57381,21 @@ var init_askUserTimeout = __esm({
|
|
|
56625
57381
|
});
|
|
56626
57382
|
|
|
56627
57383
|
// src/cli/state/fileStateStore.ts
|
|
56628
|
-
import { createHash as
|
|
56629
|
-
import { promises as
|
|
57384
|
+
import { createHash as createHash18, randomUUID as randomUUID5 } from "node:crypto";
|
|
57385
|
+
import { promises as fs27 } from "node:fs";
|
|
56630
57386
|
import * as path65 from "node:path";
|
|
56631
57387
|
function shortId() {
|
|
56632
57388
|
return randomUUID5().replace(/-/g, "").slice(0, 12);
|
|
56633
57389
|
}
|
|
56634
57390
|
async function writeJsonAtomic(filePath, data) {
|
|
56635
|
-
await
|
|
57391
|
+
await fs27.mkdir(path65.dirname(filePath), { recursive: true });
|
|
56636
57392
|
const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
56637
|
-
await
|
|
56638
|
-
await
|
|
57393
|
+
await fs27.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
57394
|
+
await fs27.rename(tmp, filePath);
|
|
56639
57395
|
}
|
|
56640
57396
|
async function readJsonFile(filePath) {
|
|
56641
57397
|
try {
|
|
56642
|
-
const raw = await
|
|
57398
|
+
const raw = await fs27.readFile(filePath, "utf8");
|
|
56643
57399
|
return JSON.parse(raw);
|
|
56644
57400
|
} catch {
|
|
56645
57401
|
return null;
|
|
@@ -56677,7 +57433,7 @@ async function getStateStore(projectRoot, env = process.env) {
|
|
|
56677
57433
|
}
|
|
56678
57434
|
}
|
|
56679
57435
|
function hashStablePrompt(stable) {
|
|
56680
|
-
return
|
|
57436
|
+
return createHash18("sha256").update(stable, "utf8").digest("hex").slice(0, 16);
|
|
56681
57437
|
}
|
|
56682
57438
|
var DEFAULT_MATERIALIZE_CHARS, FileDurableStateStore, NoopDurableStateStore;
|
|
56683
57439
|
var init_fileStateStore = __esm({
|
|
@@ -56698,8 +57454,8 @@ var init_fileStateStore = __esm({
|
|
|
56698
57454
|
this.artifactsDir = path65.join(this.stateDir, "artifacts");
|
|
56699
57455
|
this.headPath = path65.join(this.stateDir, "HEAD.json");
|
|
56700
57456
|
this.indexPath = path65.join(this.stateDir, "index.jsonl");
|
|
56701
|
-
await
|
|
56702
|
-
await
|
|
57457
|
+
await fs27.mkdir(this.commitsDir, { recursive: true });
|
|
57458
|
+
await fs27.mkdir(this.artifactsDir, { recursive: true });
|
|
56703
57459
|
}
|
|
56704
57460
|
async commit(input) {
|
|
56705
57461
|
if (!input.force && input.verification.ran && !input.verification.ok) {
|
|
@@ -56712,9 +57468,9 @@ var init_fileStateStore = __esm({
|
|
|
56712
57468
|
const id3 = shortId();
|
|
56713
57469
|
const artifactRel = path65.join("artifacts", id3);
|
|
56714
57470
|
const artifactAbs = path65.join(this.artifactsDir, id3);
|
|
56715
|
-
await
|
|
57471
|
+
await fs27.mkdir(artifactAbs, { recursive: true });
|
|
56716
57472
|
const summary = defaultSummary(input, discoveries);
|
|
56717
|
-
await
|
|
57473
|
+
await fs27.writeFile(path65.join(artifactAbs, "summary.md"), summary + "\n", "utf8");
|
|
56718
57474
|
await writeJsonAtomic(path65.join(artifactAbs, "discoveries.json"), discoveries);
|
|
56719
57475
|
await writeJsonAtomic(path65.join(artifactAbs, "verification.json"), input.verification);
|
|
56720
57476
|
const meta3 = {
|
|
@@ -56737,7 +57493,7 @@ var init_fileStateStore = __esm({
|
|
|
56737
57493
|
};
|
|
56738
57494
|
await writeJsonAtomic(path65.join(this.commitsDir, `${id3}.json`), meta3);
|
|
56739
57495
|
await writeJsonAtomic(this.headPath, { id: id3, updatedAt: meta3.createdAt });
|
|
56740
|
-
await
|
|
57496
|
+
await fs27.appendFile(this.indexPath, JSON.stringify({ id: id3, createdAt: meta3.createdAt, label: meta3.label }) + "\n", "utf8");
|
|
56741
57497
|
return stripStored(meta3);
|
|
56742
57498
|
}
|
|
56743
57499
|
async head() {
|
|
@@ -56752,7 +57508,7 @@ var init_fileStateStore = __esm({
|
|
|
56752
57508
|
async list(limit = 20) {
|
|
56753
57509
|
let raw;
|
|
56754
57510
|
try {
|
|
56755
|
-
raw = await
|
|
57511
|
+
raw = await fs27.readFile(this.indexPath, "utf8");
|
|
56756
57512
|
} catch {
|
|
56757
57513
|
return [];
|
|
56758
57514
|
}
|
|
@@ -57725,7 +58481,10 @@ async function countVerificationEvidenceInLog(mirror, sessionId2) {
|
|
|
57725
58481
|
if (mirror.status !== "active" && mirror.status !== "closed") return -1;
|
|
57726
58482
|
try {
|
|
57727
58483
|
await mirror.flush().catch(() => void 0);
|
|
57728
|
-
const report = await
|
|
58484
|
+
const report = await readSessionLogCached(
|
|
58485
|
+
path67.join(mirror.sessionsDir, sessionId2, "events.jsonl"),
|
|
58486
|
+
mirror.replayCache
|
|
58487
|
+
);
|
|
57729
58488
|
return report.events.filter((e) => e.kind === "verification.evidence").length;
|
|
57730
58489
|
} catch (err) {
|
|
57731
58490
|
process.stderr.write(
|
|
@@ -57758,7 +58517,7 @@ async function openHeadlessSpine(opts) {
|
|
|
57758
58517
|
if (spine.status === "active") {
|
|
57759
58518
|
const budget = new BudgetRuntime(profileId, { enforcement: resolveResourceEnforcement() });
|
|
57760
58519
|
if (spine.resumedFromSeq !== void 0 && spine.resumedFromSeq > 0) {
|
|
57761
|
-
await restoreBudgetRuntimeFromSession(budget, opts.sessionId, opts.baseDir);
|
|
58520
|
+
await restoreBudgetRuntimeFromSession(budget, opts.sessionId, opts.baseDir, spine.replayCache);
|
|
57762
58521
|
}
|
|
57763
58522
|
spine.attachBudgetRuntime(budget);
|
|
57764
58523
|
const manifestSpecs = opts.toolSpecs?.filter((spec) => profileTools.includes(spec.name));
|
|
@@ -58518,11 +59277,11 @@ var init_planDetect = __esm({
|
|
|
58518
59277
|
});
|
|
58519
59278
|
|
|
58520
59279
|
// src/cli/memory/legacyImport.ts
|
|
58521
|
-
import { createHash as
|
|
58522
|
-
import { promises as
|
|
59280
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
59281
|
+
import { promises as fs28 } from "node:fs";
|
|
58523
59282
|
import * as path68 from "node:path";
|
|
58524
59283
|
function sourceId(fact, line) {
|
|
58525
|
-
return `jsonl:${fact.id ??
|
|
59284
|
+
return `jsonl:${fact.id ?? createHash19("sha256").update(line).digest("hex")}`;
|
|
58526
59285
|
}
|
|
58527
59286
|
function kind(metadata2) {
|
|
58528
59287
|
const raw = metadata2.memoryKind;
|
|
@@ -58536,15 +59295,38 @@ function timestamp(value) {
|
|
|
58536
59295
|
const parsed = Date.parse(value);
|
|
58537
59296
|
return Number.isFinite(parsed) ? new Date(parsed).toISOString() : void 0;
|
|
58538
59297
|
}
|
|
59298
|
+
function isPermanentSkip(error51) {
|
|
59299
|
+
return error51 instanceof MemoryPolicyError || error51?.name === "ZodError";
|
|
59300
|
+
}
|
|
59301
|
+
async function isImportComplete(markerPath) {
|
|
59302
|
+
try {
|
|
59303
|
+
const marker = JSON.parse(await fs28.readFile(markerPath, "utf8"));
|
|
59304
|
+
return typeof marker?.found === "number" && typeof marker?.at === "string";
|
|
59305
|
+
} catch {
|
|
59306
|
+
return false;
|
|
59307
|
+
}
|
|
59308
|
+
}
|
|
59309
|
+
async function markImportComplete(markerPath, found) {
|
|
59310
|
+
const temporary = `${markerPath}.tmp`;
|
|
59311
|
+
try {
|
|
59312
|
+
await fs28.writeFile(temporary, `${JSON.stringify({ found, at: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
59313
|
+
`, "utf8");
|
|
59314
|
+
await fs28.rename(temporary, markerPath);
|
|
59315
|
+
} catch {
|
|
59316
|
+
}
|
|
59317
|
+
}
|
|
58539
59318
|
async function importLegacyMemoryLog(backend, service) {
|
|
58540
59319
|
const result = { found: 0, imported: 0, skipped: 0, corrupt: 0 };
|
|
58541
|
-
const
|
|
59320
|
+
const memoryDir = path68.dirname(backend.databasePath);
|
|
59321
|
+
const markerPath = path68.join(memoryDir, LEGACY_IMPORT_MARKER);
|
|
59322
|
+
if (await isImportComplete(markerPath)) return result;
|
|
58542
59323
|
let raw;
|
|
58543
59324
|
try {
|
|
58544
|
-
raw = await
|
|
59325
|
+
raw = await fs28.readFile(path68.join(memoryDir, "log.jsonl"), "utf8");
|
|
58545
59326
|
} catch {
|
|
58546
59327
|
return result;
|
|
58547
59328
|
}
|
|
59329
|
+
const rows = [];
|
|
58548
59330
|
for (const line of raw.split(/\r?\n/)) {
|
|
58549
59331
|
const trimmed = line.trim();
|
|
58550
59332
|
if (!trimmed) continue;
|
|
@@ -58561,17 +59343,22 @@ async function importLegacyMemoryLog(backend, service) {
|
|
|
58561
59343
|
result.corrupt += 1;
|
|
58562
59344
|
continue;
|
|
58563
59345
|
}
|
|
58564
|
-
|
|
58565
|
-
|
|
59346
|
+
rows.push({ fact, content, importId: sourceId(fact, trimmed) });
|
|
59347
|
+
}
|
|
59348
|
+
const known = rows.length > 0 ? await backend.hasImports([...new Set(rows.map((row) => row.importId))]) : /* @__PURE__ */ new Set();
|
|
59349
|
+
const importedHere = /* @__PURE__ */ new Set();
|
|
59350
|
+
let unresolved = 0;
|
|
59351
|
+
for (const row of rows) {
|
|
59352
|
+
if (known.has(row.importId) || importedHere.has(row.importId)) {
|
|
58566
59353
|
result.skipped += 1;
|
|
58567
59354
|
continue;
|
|
58568
59355
|
}
|
|
58569
|
-
const metadata2 = fact.metadata && typeof fact.metadata === "object" ? fact.metadata : {};
|
|
58570
|
-
const createdAt = timestamp(fact.createdAt);
|
|
59356
|
+
const metadata2 = row.fact.metadata && typeof row.fact.metadata === "object" ? row.fact.metadata : {};
|
|
59357
|
+
const createdAt = timestamp(row.fact.createdAt);
|
|
58571
59358
|
try {
|
|
58572
59359
|
const node = await service.remember({
|
|
58573
59360
|
kind: kind(metadata2),
|
|
58574
|
-
content,
|
|
59361
|
+
content: row.content,
|
|
58575
59362
|
importance: typeof metadata2.importance === "number" ? metadata2.importance : 0.55,
|
|
58576
59363
|
confidence: typeof metadata2.confidence === "number" ? metadata2.confidence : 0.65,
|
|
58577
59364
|
source: {
|
|
@@ -58583,24 +59370,30 @@ async function importLegacyMemoryLog(backend, service) {
|
|
|
58583
59370
|
...createdAt ? { createdAt, recordedAt: createdAt } : {},
|
|
58584
59371
|
metadata: {
|
|
58585
59372
|
...metadata2,
|
|
58586
|
-
legacyId: fact.id,
|
|
58587
|
-
legacyCreatedAt: fact.createdAt,
|
|
58588
|
-
...fact.graph ? { legacyGraph: fact.graph } : {}
|
|
59373
|
+
legacyId: row.fact.id,
|
|
59374
|
+
legacyCreatedAt: row.fact.createdAt,
|
|
59375
|
+
...row.fact.graph ? { legacyGraph: row.fact.graph } : {}
|
|
58589
59376
|
},
|
|
58590
59377
|
writeClass: "auto"
|
|
58591
59378
|
});
|
|
58592
|
-
await backend.recordImport(importId, node.id);
|
|
59379
|
+
await backend.recordImport(row.importId, node.id);
|
|
59380
|
+
importedHere.add(row.importId);
|
|
58593
59381
|
result.imported += 1;
|
|
58594
|
-
} catch {
|
|
59382
|
+
} catch (error51) {
|
|
58595
59383
|
result.skipped += 1;
|
|
59384
|
+
if (!isPermanentSkip(error51)) unresolved += 1;
|
|
58596
59385
|
}
|
|
58597
59386
|
}
|
|
59387
|
+
const everyRowResolved = result.imported + result.skipped + result.corrupt === result.found;
|
|
59388
|
+
if (everyRowResolved && unresolved === 0) await markImportComplete(markerPath, result.found);
|
|
58598
59389
|
return result;
|
|
58599
59390
|
}
|
|
59391
|
+
var LEGACY_IMPORT_MARKER;
|
|
58600
59392
|
var init_legacyImport = __esm({
|
|
58601
59393
|
"src/cli/memory/legacyImport.ts"() {
|
|
58602
59394
|
"use strict";
|
|
58603
59395
|
init_memory();
|
|
59396
|
+
LEGACY_IMPORT_MARKER = "legacy-import-done.json";
|
|
58604
59397
|
}
|
|
58605
59398
|
});
|
|
58606
59399
|
|
|
@@ -59020,8 +59813,8 @@ WHERE NOT EXISTS (SELECT 1 FROM memory_fts f WHERE f.node_id = n.id);
|
|
|
59020
59813
|
});
|
|
59021
59814
|
|
|
59022
59815
|
// src/cli/memory/sqliteBackend.ts
|
|
59023
|
-
import { createHash as
|
|
59024
|
-
import { promises as
|
|
59816
|
+
import { createHash as createHash20, randomUUID as randomUUID6 } from "node:crypto";
|
|
59817
|
+
import { promises as fs29 } from "node:fs";
|
|
59025
59818
|
import * as path70 from "node:path";
|
|
59026
59819
|
function boundedLimit(value, fallback = 50) {
|
|
59027
59820
|
return Math.max(1, Math.min(Math.floor(value ?? fallback), 1e5));
|
|
@@ -59035,9 +59828,9 @@ function withOptional(target, key, value) {
|
|
|
59035
59828
|
return { ...target, [key]: value };
|
|
59036
59829
|
}
|
|
59037
59830
|
function contentHash(content) {
|
|
59038
|
-
return
|
|
59831
|
+
return createHash20("sha256").update(content).digest("hex");
|
|
59039
59832
|
}
|
|
59040
|
-
var NODE_COLUMNS, INSERT_NODE_SQL, SOURCE_COLUMNS, SQLiteMemoryBackend;
|
|
59833
|
+
var NODE_COLUMNS, INSERT_NODE_SQL, IMPORT_ID_CHUNK, SOURCE_COLUMNS, SQLiteMemoryBackend;
|
|
59041
59834
|
var init_sqliteBackend = __esm({
|
|
59042
59835
|
"src/cli/memory/sqliteBackend.ts"() {
|
|
59043
59836
|
"use strict";
|
|
@@ -59051,6 +59844,7 @@ var init_sqliteBackend = __esm({
|
|
|
59051
59844
|
valid_until, recorded_at, retracted_at, embedding_ref, metadata_json`;
|
|
59052
59845
|
INSERT_NODE_SQL = `INSERT INTO memory_nodes (${NODE_COLUMNS})
|
|
59053
59846
|
VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
59847
|
+
IMPORT_ID_CHUNK = 500;
|
|
59054
59848
|
SOURCE_COLUMNS = {
|
|
59055
59849
|
agent: "agent",
|
|
59056
59850
|
sessionId: "sessionId",
|
|
@@ -59082,7 +59876,7 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
59082
59876
|
async init(projectRoot) {
|
|
59083
59877
|
let resolved;
|
|
59084
59878
|
try {
|
|
59085
|
-
resolved = await
|
|
59879
|
+
resolved = await fs29.realpath(projectRoot);
|
|
59086
59880
|
} catch {
|
|
59087
59881
|
resolved = path70.resolve(projectRoot);
|
|
59088
59882
|
}
|
|
@@ -59097,21 +59891,21 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
59097
59891
|
for (const candidate of [zelariDirectory, directory]) {
|
|
59098
59892
|
let stat8;
|
|
59099
59893
|
try {
|
|
59100
|
-
stat8 = await
|
|
59894
|
+
stat8 = await fs29.lstat(candidate);
|
|
59101
59895
|
} catch (error51) {
|
|
59102
59896
|
if (error51.code !== "ENOENT") throw error51;
|
|
59103
59897
|
try {
|
|
59104
|
-
await
|
|
59898
|
+
await fs29.mkdir(candidate);
|
|
59105
59899
|
} catch (mkdirError) {
|
|
59106
59900
|
if (mkdirError.code !== "EEXIST") throw mkdirError;
|
|
59107
59901
|
}
|
|
59108
|
-
stat8 = await
|
|
59902
|
+
stat8 = await fs29.lstat(candidate);
|
|
59109
59903
|
}
|
|
59110
59904
|
if (stat8.isSymbolicLink() || !stat8.isDirectory()) {
|
|
59111
59905
|
throw new Error(`Memory directory is not a real directory: ${candidate}`);
|
|
59112
59906
|
}
|
|
59113
59907
|
}
|
|
59114
|
-
const canonicalDirectory = await
|
|
59908
|
+
const canonicalDirectory = await fs29.realpath(directory);
|
|
59115
59909
|
const relativeDirectory = path70.relative(resolved, canonicalDirectory);
|
|
59116
59910
|
if (relativeDirectory.startsWith("..") || path70.isAbsolute(relativeDirectory)) {
|
|
59117
59911
|
throw new Error("SQLite memory directory resolves outside the active project.");
|
|
@@ -59614,14 +60408,24 @@ VALUES (${Array.from({ length: 19 }, () => "?").join(",")})`;
|
|
|
59614
60408
|
versions: versionRows.map(decodeVersion).filter((version2) => Boolean(version2))
|
|
59615
60409
|
};
|
|
59616
60410
|
}
|
|
59617
|
-
|
|
60411
|
+
/** Batched `hasImport`: one `IN` query per 500 ids instead of one RPC per row. */
|
|
60412
|
+
async hasImports(ids) {
|
|
59618
60413
|
this.assertReady();
|
|
59619
|
-
const
|
|
59620
|
-
|
|
59621
|
-
|
|
59622
|
-
|
|
59623
|
-
|
|
59624
|
-
|
|
60414
|
+
const found = /* @__PURE__ */ new Set();
|
|
60415
|
+
const unique = [...new Set(ids)];
|
|
60416
|
+
for (let index = 0; index < unique.length; index += IMPORT_ID_CHUNK) {
|
|
60417
|
+
const chunk = unique.slice(index, index + IMPORT_ID_CHUNK);
|
|
60418
|
+
const rows = await this.rpc.statement({
|
|
60419
|
+
sql: `SELECT source_id FROM memory_imports WHERE source_id IN (${chunk.map(() => "?").join(",")})`,
|
|
60420
|
+
params: chunk,
|
|
60421
|
+
mode: "all"
|
|
60422
|
+
});
|
|
60423
|
+
for (const row of rows) found.add(String(row.source_id));
|
|
60424
|
+
}
|
|
60425
|
+
return found;
|
|
60426
|
+
}
|
|
60427
|
+
async hasImport(sourceId2) {
|
|
60428
|
+
return (await this.hasImports([sourceId2])).has(sourceId2);
|
|
59625
60429
|
}
|
|
59626
60430
|
async recordImport(sourceId2, memoryId) {
|
|
59627
60431
|
this.assertReady();
|
|
@@ -59648,8 +60452,8 @@ __export(serviceFactory_exports, {
|
|
|
59648
60452
|
isMemorySemanticEnabled: () => isMemorySemanticEnabled,
|
|
59649
60453
|
isMemoryV2Enabled: () => isMemoryV2Enabled
|
|
59650
60454
|
});
|
|
59651
|
-
import { createHash as
|
|
59652
|
-
import { promises as
|
|
60455
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
60456
|
+
import { promises as fs30 } from "node:fs";
|
|
59653
60457
|
import * as path71 from "node:path";
|
|
59654
60458
|
function isMemoryV2Enabled(env = process.env) {
|
|
59655
60459
|
if (env.ZELARI_MEMORY === "0") return false;
|
|
@@ -59669,13 +60473,13 @@ function semanticMinScore(env) {
|
|
|
59669
60473
|
async function canonicalProjectId(projectRoot) {
|
|
59670
60474
|
let canonical;
|
|
59671
60475
|
try {
|
|
59672
|
-
canonical = await
|
|
60476
|
+
canonical = await fs30.realpath(projectRoot);
|
|
59673
60477
|
} catch {
|
|
59674
60478
|
canonical = path71.resolve(projectRoot);
|
|
59675
60479
|
}
|
|
59676
60480
|
canonical = canonical.replace(/\\/g, "/").replace(/\/$/, "");
|
|
59677
60481
|
if (process.platform === "win32") canonical = canonical.toLocaleLowerCase("en-US");
|
|
59678
|
-
return `project_${
|
|
60482
|
+
return `project_${createHash21("sha256").update(canonical).digest("hex").slice(0, 24)}`;
|
|
59679
60483
|
}
|
|
59680
60484
|
async function getMemoryService(projectRoot, env = process.env, options = {}) {
|
|
59681
60485
|
const projectId2 = await canonicalProjectId(projectRoot);
|
|
@@ -60298,32 +61102,32 @@ __export(loadDurableContext_exports, {
|
|
|
60298
61102
|
loadDurableContext: () => loadDurableContext
|
|
60299
61103
|
});
|
|
60300
61104
|
function clearDurableContextCache() {
|
|
60301
|
-
|
|
61105
|
+
cache3 = null;
|
|
60302
61106
|
}
|
|
60303
61107
|
async function loadDurableContext(projectRoot, opts) {
|
|
60304
61108
|
const env = opts?.env ?? process.env;
|
|
60305
61109
|
if (!isStateEnabled(env)) return "";
|
|
60306
61110
|
const cacheMs = opts?.cacheMs ?? DEFAULT_CACHE_MS;
|
|
60307
61111
|
const now = Date.now();
|
|
60308
|
-
if (
|
|
60309
|
-
return
|
|
61112
|
+
if (cache3 && cache3.projectRoot === projectRoot && now - cache3.at < cacheMs) {
|
|
61113
|
+
return cache3.text;
|
|
60310
61114
|
}
|
|
60311
61115
|
try {
|
|
60312
61116
|
const store6 = await getStateStore(projectRoot, env);
|
|
60313
61117
|
const text = await store6.materializeContext(void 0, opts?.maxChars);
|
|
60314
|
-
|
|
60315
|
-
return
|
|
61118
|
+
cache3 = { text: text || "", at: now, projectRoot };
|
|
61119
|
+
return cache3.text;
|
|
60316
61120
|
} catch {
|
|
60317
61121
|
return "";
|
|
60318
61122
|
}
|
|
60319
61123
|
}
|
|
60320
|
-
var DEFAULT_CACHE_MS,
|
|
61124
|
+
var DEFAULT_CACHE_MS, cache3;
|
|
60321
61125
|
var init_loadDurableContext = __esm({
|
|
60322
61126
|
"src/cli/state/loadDurableContext.ts"() {
|
|
60323
61127
|
"use strict";
|
|
60324
61128
|
init_fileStateStore();
|
|
60325
61129
|
DEFAULT_CACHE_MS = 2e3;
|
|
60326
|
-
|
|
61130
|
+
cache3 = null;
|
|
60327
61131
|
}
|
|
60328
61132
|
});
|
|
60329
61133
|
|
|
@@ -62087,7 +62891,7 @@ __export(agentsMd_exports, {
|
|
|
62087
62891
|
updateAgentsMd: () => updateAgentsMd
|
|
62088
62892
|
});
|
|
62089
62893
|
import { existsSync as existsSync44, readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
|
|
62090
|
-
import { createHash as
|
|
62894
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
62091
62895
|
import { join as join34 } from "node:path";
|
|
62092
62896
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
62093
62897
|
async function readPackageJson3(projectRoot) {
|
|
@@ -62302,7 +63106,7 @@ async function updateAgentsMd(ctx, projectRoot) {
|
|
|
62302
63106
|
return { changed: true, sections: changedSections };
|
|
62303
63107
|
}
|
|
62304
63108
|
function hash2(s) {
|
|
62305
|
-
return
|
|
63109
|
+
return createHash22("sha256").update(s).digest("hex").slice(0, 16);
|
|
62306
63110
|
}
|
|
62307
63111
|
var AUTO_SECTIONS, MARKER_OPEN, MARKER_CLOSE, GENERATORS;
|
|
62308
63112
|
var init_agentsMd = __esm({
|
|
@@ -63030,7 +63834,7 @@ __export(councilFeedback_exports, {
|
|
|
63030
63834
|
FeedbackStore: () => FeedbackStore
|
|
63031
63835
|
});
|
|
63032
63836
|
import {
|
|
63033
|
-
promises as
|
|
63837
|
+
promises as fs31,
|
|
63034
63838
|
existsSync as existsSync49,
|
|
63035
63839
|
readFileSync as readFileSync37,
|
|
63036
63840
|
writeFileSync as writeFileSync22,
|
|
@@ -63163,7 +63967,7 @@ var init_councilFeedback = __esm({
|
|
|
63163
63967
|
/** Async variant of load for callers that prefer async IO. */
|
|
63164
63968
|
async loadAsync() {
|
|
63165
63969
|
try {
|
|
63166
|
-
const raw = await
|
|
63970
|
+
const raw = await fs31.readFile(this.file, "utf-8");
|
|
63167
63971
|
const parsed = JSON.parse(raw);
|
|
63168
63972
|
if (parsed && Array.isArray(parsed.entries)) {
|
|
63169
63973
|
this.entries = parsed.entries.filter(
|
|
@@ -63483,7 +64287,7 @@ __export(fileBackend_exports, {
|
|
|
63483
64287
|
isMemoryEnabled: () => isMemoryEnabled
|
|
63484
64288
|
});
|
|
63485
64289
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
63486
|
-
import { promises as
|
|
64290
|
+
import { promises as fs32 } from "node:fs";
|
|
63487
64291
|
import * as path75 from "node:path";
|
|
63488
64292
|
function tokenize2(text) {
|
|
63489
64293
|
return text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 3);
|
|
@@ -63539,7 +64343,7 @@ var init_fileBackend = __esm({
|
|
|
63539
64343
|
async init(projectRoot) {
|
|
63540
64344
|
this.memoryDir = path75.join(projectRoot, ".zelari", "memory");
|
|
63541
64345
|
this.logPath = path75.join(this.memoryDir, "log.jsonl");
|
|
63542
|
-
await
|
|
64346
|
+
await fs32.mkdir(this.memoryDir, { recursive: true });
|
|
63543
64347
|
}
|
|
63544
64348
|
async add(content, metadata2 = {}, graph) {
|
|
63545
64349
|
const fact = {
|
|
@@ -63549,7 +64353,7 @@ var init_fileBackend = __esm({
|
|
|
63549
64353
|
...graph ? { graph } : {},
|
|
63550
64354
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
63551
64355
|
};
|
|
63552
|
-
await
|
|
64356
|
+
await fs32.appendFile(this.logPath, JSON.stringify(fact) + "\n", "utf8");
|
|
63553
64357
|
return fact.id;
|
|
63554
64358
|
}
|
|
63555
64359
|
async search(query, options = {}) {
|
|
@@ -63577,7 +64381,7 @@ var init_fileBackend = __esm({
|
|
|
63577
64381
|
async readAll() {
|
|
63578
64382
|
let raw;
|
|
63579
64383
|
try {
|
|
63580
|
-
raw = await
|
|
64384
|
+
raw = await fs32.readFile(this.logPath, "utf8");
|
|
63581
64385
|
} catch {
|
|
63582
64386
|
return [];
|
|
63583
64387
|
}
|
|
@@ -63610,7 +64414,7 @@ var init_fileBackend = __esm({
|
|
|
63610
64414
|
});
|
|
63611
64415
|
|
|
63612
64416
|
// src/cli/traceStore.ts
|
|
63613
|
-
import { promises as
|
|
64417
|
+
import { promises as fs33 } from "node:fs";
|
|
63614
64418
|
import * as path76 from "node:path";
|
|
63615
64419
|
function traceDir(projectRoot) {
|
|
63616
64420
|
return path76.join(projectRoot, ".zelari", "trace");
|
|
@@ -63620,13 +64424,13 @@ function tracePath(projectRoot, missionId) {
|
|
|
63620
64424
|
}
|
|
63621
64425
|
async function saveTrace(projectRoot, missionId, entries) {
|
|
63622
64426
|
const dir = traceDir(projectRoot);
|
|
63623
|
-
await
|
|
64427
|
+
await fs33.mkdir(dir, { recursive: true });
|
|
63624
64428
|
const payload = {
|
|
63625
64429
|
missionId,
|
|
63626
64430
|
ts: Date.now(),
|
|
63627
64431
|
entries
|
|
63628
64432
|
};
|
|
63629
|
-
await
|
|
64433
|
+
await fs33.writeFile(
|
|
63630
64434
|
tracePath(projectRoot, missionId),
|
|
63631
64435
|
JSON.stringify(payload, null, 2) + "\n",
|
|
63632
64436
|
"utf8"
|
|
@@ -63657,7 +64461,7 @@ __export(zelariMission_exports, {
|
|
|
63657
64461
|
runZelariMission: () => runZelariMission
|
|
63658
64462
|
});
|
|
63659
64463
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
63660
|
-
import { promises as
|
|
64464
|
+
import { promises as fs34 } from "node:fs";
|
|
63661
64465
|
import * as path77 from "node:path";
|
|
63662
64466
|
function resolveMaxIterations(env = process.env) {
|
|
63663
64467
|
const raw = env.ZELARI_MISSION_MAX_ITER;
|
|
@@ -63702,8 +64506,8 @@ function isMissionAutoStart(env = process.env) {
|
|
|
63702
64506
|
}
|
|
63703
64507
|
async function writeMissionState(projectRoot, state3) {
|
|
63704
64508
|
const dir = path77.join(projectRoot, ".zelari");
|
|
63705
|
-
await
|
|
63706
|
-
await
|
|
64509
|
+
await fs34.mkdir(dir, { recursive: true });
|
|
64510
|
+
await fs34.writeFile(
|
|
63707
64511
|
path77.join(dir, "mission-state.json"),
|
|
63708
64512
|
JSON.stringify(state3, null, 2) + "\n",
|
|
63709
64513
|
"utf8"
|
|
@@ -63717,7 +64521,7 @@ async function writeMissionState(projectRoot, state3) {
|
|
|
63717
64521
|
}
|
|
63718
64522
|
async function loadMissionState(projectRoot) {
|
|
63719
64523
|
try {
|
|
63720
|
-
const raw = await
|
|
64524
|
+
const raw = await fs34.readFile(
|
|
63721
64525
|
path77.join(projectRoot, ".zelari", "mission-state.json"),
|
|
63722
64526
|
"utf8"
|
|
63723
64527
|
);
|
|
@@ -66995,11 +67799,11 @@ var init_policy = __esm({
|
|
|
66995
67799
|
});
|
|
66996
67800
|
|
|
66997
67801
|
// src/cli/orchestration/facts.ts
|
|
66998
|
-
import { promises as
|
|
67802
|
+
import { promises as fs44 } from "node:fs";
|
|
66999
67803
|
import path88 from "node:path";
|
|
67000
67804
|
async function collectRepoFileCount(root = process.cwd()) {
|
|
67001
67805
|
try {
|
|
67002
|
-
await
|
|
67806
|
+
await fs44.readdir(root);
|
|
67003
67807
|
} catch {
|
|
67004
67808
|
return void 0;
|
|
67005
67809
|
}
|
|
@@ -67010,7 +67814,7 @@ async function collectRepoFileCount(root = process.cwd()) {
|
|
|
67010
67814
|
const dir = queue.pop();
|
|
67011
67815
|
let entries;
|
|
67012
67816
|
try {
|
|
67013
|
-
entries = await
|
|
67817
|
+
entries = await fs44.readdir(dir, { withFileTypes: true });
|
|
67014
67818
|
} catch {
|
|
67015
67819
|
continue;
|
|
67016
67820
|
}
|
|
@@ -67288,8 +68092,8 @@ function contractFor(t) {
|
|
|
67288
68092
|
blockers
|
|
67289
68093
|
};
|
|
67290
68094
|
}
|
|
67291
|
-
async function readHarnessState(sessionDir) {
|
|
67292
|
-
const report = await
|
|
68095
|
+
async function readHarnessState(sessionDir, cache4) {
|
|
68096
|
+
const report = await readSessionLogCached(path89.join(sessionDir, "events.jsonl"), cache4);
|
|
67293
68097
|
return deriveHarnessState(report.events);
|
|
67294
68098
|
}
|
|
67295
68099
|
var init_harnessState = __esm({
|
|
@@ -67913,7 +68717,7 @@ var init_sandboxedFs = __esm({
|
|
|
67913
68717
|
// src/cli/extensions/loader.ts
|
|
67914
68718
|
import { join as join44 } from "node:path";
|
|
67915
68719
|
import { readdirSync as readdirSync11, readFileSync as readFileSync43 } from "node:fs";
|
|
67916
|
-
import { createHash as
|
|
68720
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
67917
68721
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
67918
68722
|
function globalExtensionsDir() {
|
|
67919
68723
|
return join44(zelariHome(), "extensions");
|
|
@@ -67922,7 +68726,7 @@ function projectExtensionsDir(projectRoot) {
|
|
|
67922
68726
|
return join44(projectRoot, ".zelari", "extensions");
|
|
67923
68727
|
}
|
|
67924
68728
|
function sha256File(file2) {
|
|
67925
|
-
return
|
|
68729
|
+
return createHash23("sha256").update(readFileSync43(file2)).digest("hex");
|
|
67926
68730
|
}
|
|
67927
68731
|
function candidateFiles(dir) {
|
|
67928
68732
|
let names;
|
|
@@ -67953,7 +68757,7 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
67953
68757
|
skipped
|
|
67954
68758
|
};
|
|
67955
68759
|
const fsRoot = options.fsRoot ?? process.cwd();
|
|
67956
|
-
let
|
|
68760
|
+
let fs49 = null;
|
|
67957
68761
|
const pending = [];
|
|
67958
68762
|
for (const dir of dirs) {
|
|
67959
68763
|
const files = candidateFiles(dir.path);
|
|
@@ -68008,9 +68812,9 @@ async function loadExtensionsFromDirs(dirs, options = {}) {
|
|
|
68008
68812
|
skipped.push(`${file2}: missing ZelariExtension export`);
|
|
68009
68813
|
continue;
|
|
68010
68814
|
}
|
|
68011
|
-
if (!
|
|
68815
|
+
if (!fs49) fs49 = bindSandboxedFs(fsRoot);
|
|
68012
68816
|
try {
|
|
68013
|
-
await runtime.registry.registerExtension(ext, { fs:
|
|
68817
|
+
await runtime.registry.registerExtension(ext, { fs: fs49 });
|
|
68014
68818
|
runtime.loaded.push({ id: ext.id, file: file2, scope });
|
|
68015
68819
|
} catch (err) {
|
|
68016
68820
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -68068,7 +68872,7 @@ var init_loader = __esm({
|
|
|
68068
68872
|
});
|
|
68069
68873
|
|
|
68070
68874
|
// src/cli/headless/runOneTurn.ts
|
|
68071
|
-
import { promises as
|
|
68875
|
+
import { promises as fs45 } from "node:fs";
|
|
68072
68876
|
import path92 from "node:path";
|
|
68073
68877
|
function planModeFromOpts(opts) {
|
|
68074
68878
|
return (opts.phase ?? "build") === "plan";
|
|
@@ -68639,8 +69443,8 @@ async function runOneTurn(opts, provider, model, providerStream, extras) {
|
|
|
68639
69443
|
if (json3) {
|
|
68640
69444
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
68641
69445
|
else {
|
|
68642
|
-
await
|
|
68643
|
-
await
|
|
69446
|
+
await fs45.mkdir(path92.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
69447
|
+
await fs45.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
68644
69448
|
}
|
|
68645
69449
|
}
|
|
68646
69450
|
} catch {
|
|
@@ -69687,7 +70491,7 @@ __export(triggerLock_exports, {
|
|
|
69687
70491
|
lockPath: () => lockPath,
|
|
69688
70492
|
releaseLock: () => releaseLock
|
|
69689
70493
|
});
|
|
69690
|
-
import { promises as
|
|
70494
|
+
import { promises as fs46 } from "node:fs";
|
|
69691
70495
|
import * as path93 from "node:path";
|
|
69692
70496
|
function lockPath(projectRoot) {
|
|
69693
70497
|
return path93.join(projectRoot, ".zelari", "trigger.lock");
|
|
@@ -69704,9 +70508,9 @@ function isPidAlive(pid) {
|
|
|
69704
70508
|
async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date()) {
|
|
69705
70509
|
const lp = lockPath(projectRoot);
|
|
69706
70510
|
const dir = path93.dirname(lp);
|
|
69707
|
-
await
|
|
70511
|
+
await fs46.mkdir(dir, { recursive: true });
|
|
69708
70512
|
try {
|
|
69709
|
-
const raw = await
|
|
70513
|
+
const raw = await fs46.readFile(lp, "utf8");
|
|
69710
70514
|
const existing = JSON.parse(raw);
|
|
69711
70515
|
if (existing.pid && isPidAlive(existing.pid)) {
|
|
69712
70516
|
return { acquired: false, heldBy: existing.pid, lockPath: lp };
|
|
@@ -69717,13 +70521,13 @@ async function acquireLock(projectRoot, now = () => /* @__PURE__ */ new Date())
|
|
|
69717
70521
|
pid: process.pid,
|
|
69718
70522
|
acquiredAt: now().toISOString()
|
|
69719
70523
|
};
|
|
69720
|
-
await
|
|
70524
|
+
await fs46.writeFile(lp, JSON.stringify(payload, null, 2) + "\n", "utf8");
|
|
69721
70525
|
return { acquired: true, lockPath: lp };
|
|
69722
70526
|
}
|
|
69723
70527
|
async function releaseLock(projectRoot) {
|
|
69724
70528
|
const lp = lockPath(projectRoot);
|
|
69725
70529
|
try {
|
|
69726
|
-
await
|
|
70530
|
+
await fs46.unlink(lp);
|
|
69727
70531
|
} catch {
|
|
69728
70532
|
}
|
|
69729
70533
|
}
|
|
@@ -69734,7 +70538,7 @@ var init_triggerLock = __esm({
|
|
|
69734
70538
|
});
|
|
69735
70539
|
|
|
69736
70540
|
// src/cli/runHeadless.ts
|
|
69737
|
-
import { promises as
|
|
70541
|
+
import { promises as fs47 } from "node:fs";
|
|
69738
70542
|
import path94 from "node:path";
|
|
69739
70543
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
69740
70544
|
async function runHeadless(opts) {
|
|
@@ -69806,12 +70610,42 @@ ${err.stack}` : "";
|
|
|
69806
70610
|
return 1;
|
|
69807
70611
|
}
|
|
69808
70612
|
const { buildProviderStream: buildProviderStream2 } = await Promise.resolve().then(() => (init_resolveStream(), resolveStream_exports));
|
|
69809
|
-
|
|
70613
|
+
const primaryStream = buildProviderStream2({
|
|
69810
70614
|
providerId: provider,
|
|
69811
70615
|
apiKey: key.apiKey,
|
|
69812
70616
|
baseUrl: key.baseUrl,
|
|
69813
70617
|
model
|
|
69814
70618
|
});
|
|
70619
|
+
const { isHeadlessFailoverEnabled: isHeadlessFailoverEnabled2, wrapWithHeadlessFailover: wrapWithHeadlessFailover2 } = await Promise.resolve().then(() => (init_crossProviderFailover(), crossProviderFailover_exports));
|
|
70620
|
+
if (isHeadlessFailoverEnabled2()) {
|
|
70621
|
+
const { PROVIDERS: PROVIDERS2 } = await Promise.resolve().then(() => (init_keyStore(), keyStore_exports));
|
|
70622
|
+
const { providerConfigFor: providerConfigFor2 } = await Promise.resolve().then(() => (init_openai_compatible(), openai_compatible_exports));
|
|
70623
|
+
providerStream = await wrapWithHeadlessFailover2({
|
|
70624
|
+
primary: primaryStream,
|
|
70625
|
+
primaryProviderId: provider,
|
|
70626
|
+
validProviderIds: PROVIDERS2.map((p3) => p3.id),
|
|
70627
|
+
lookupFallbackConfig: async (id3) => providerConfigFor2(id3),
|
|
70628
|
+
buildStream: (config2) => buildProviderStream2(config2),
|
|
70629
|
+
onWarning: (warning) => {
|
|
70630
|
+
try {
|
|
70631
|
+
process.stderr.write(`[zelari-code --headless] ${warning}
|
|
70632
|
+
`);
|
|
70633
|
+
} catch {
|
|
70634
|
+
}
|
|
70635
|
+
},
|
|
70636
|
+
onFailover: (info) => {
|
|
70637
|
+
try {
|
|
70638
|
+
process.stderr.write(
|
|
70639
|
+
`[zelari-code --headless] [failover] ${info.phase}${info.label ? ` \u2192 ${info.label}` : ""}: ${info.message}
|
|
70640
|
+
`
|
|
70641
|
+
);
|
|
70642
|
+
} catch {
|
|
70643
|
+
}
|
|
70644
|
+
}
|
|
70645
|
+
});
|
|
70646
|
+
} else {
|
|
70647
|
+
providerStream = primaryStream;
|
|
70648
|
+
}
|
|
69815
70649
|
}
|
|
69816
70650
|
return dispatchHeadlessTurn(opts, provider, model, providerStream, {
|
|
69817
70651
|
// H10-fix3: the gate already ran above on the SAME input (no chdir in
|
|
@@ -69983,7 +70817,7 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
69983
70817
|
log(`loading pre-flight plan: ${planPath}`);
|
|
69984
70818
|
let raw;
|
|
69985
70819
|
try {
|
|
69986
|
-
raw = await
|
|
70820
|
+
raw = await fs47.readFile(planPath, "utf8");
|
|
69987
70821
|
} catch (e) {
|
|
69988
70822
|
log(`plan file not found: ${planPath} (${e.message})`);
|
|
69989
70823
|
exitCode = 1;
|
|
@@ -70024,8 +70858,8 @@ async function runHeadlessKrakenGraph(opts, provider, model) {
|
|
|
70024
70858
|
const planId = randomUUID10();
|
|
70025
70859
|
const planDir = path94.join(cwd, ".zelari", "radio");
|
|
70026
70860
|
const planPath = path94.join(planDir, `plan-${planId}.json`);
|
|
70027
|
-
await
|
|
70028
|
-
await
|
|
70861
|
+
await fs47.mkdir(planDir, { recursive: true });
|
|
70862
|
+
await fs47.writeFile(
|
|
70029
70863
|
planPath,
|
|
70030
70864
|
JSON.stringify(
|
|
70031
70865
|
{ id: graph.id, nodes: [...graph.nodes.values()] },
|
|
@@ -70414,8 +71248,8 @@ async function runHeadlessCouncilBody(opts, provider, model, providerStream, ext
|
|
|
70414
71248
|
if (json3) {
|
|
70415
71249
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70416
71250
|
else {
|
|
70417
|
-
await
|
|
70418
|
-
await
|
|
71251
|
+
await fs47.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
71252
|
+
await fs47.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70419
71253
|
}
|
|
70420
71254
|
}
|
|
70421
71255
|
} catch {
|
|
@@ -70886,8 +71720,8 @@ ${ragContext}` : slicePrompt;
|
|
|
70886
71720
|
if (json3) {
|
|
70887
71721
|
if (opts.exportSessionPath === "-") process.stdout.write(json3 + "\n");
|
|
70888
71722
|
else {
|
|
70889
|
-
await
|
|
70890
|
-
await
|
|
71723
|
+
await fs47.mkdir(path94.dirname(opts.exportSessionPath), { recursive: true }).catch(() => void 0);
|
|
71724
|
+
await fs47.writeFile(opts.exportSessionPath, json3, "utf8");
|
|
70891
71725
|
}
|
|
70892
71726
|
}
|
|
70893
71727
|
} catch {
|
|
@@ -72358,7 +73192,7 @@ import {
|
|
|
72358
73192
|
writeFileSync as writeFileSync26
|
|
72359
73193
|
} from "node:fs";
|
|
72360
73194
|
import { join as join47 } from "node:path";
|
|
72361
|
-
import { createHash as
|
|
73195
|
+
import { createHash as createHash24, randomBytes as randomBytes7, timingSafeEqual } from "node:crypto";
|
|
72362
73196
|
function getZelariHome() {
|
|
72363
73197
|
return zelariHome();
|
|
72364
73198
|
}
|
|
@@ -72426,16 +73260,16 @@ function loadOrCreateToken(explicit) {
|
|
|
72426
73260
|
const token = randomBytes7(24).toString("base64url");
|
|
72427
73261
|
writeFileSync26(path101, token + "\n", "utf8");
|
|
72428
73262
|
try {
|
|
72429
|
-
const
|
|
72430
|
-
|
|
73263
|
+
const fs49 = __require("node:fs");
|
|
73264
|
+
fs49.chmodSync?.(path101, 384);
|
|
72431
73265
|
} catch {
|
|
72432
73266
|
}
|
|
72433
73267
|
return { token, created: true };
|
|
72434
73268
|
}
|
|
72435
73269
|
function tokenMatches(expected, provided) {
|
|
72436
73270
|
if (!provided) return false;
|
|
72437
|
-
const a =
|
|
72438
|
-
const b =
|
|
73271
|
+
const a = createHash24("sha256").update(expected).digest();
|
|
73272
|
+
const b = createHash24("sha256").update(provided).digest();
|
|
72439
73273
|
try {
|
|
72440
73274
|
return timingSafeEqual(a, b);
|
|
72441
73275
|
} catch {
|
|
@@ -72704,7 +73538,7 @@ var init_askUserBridge = __esm({
|
|
|
72704
73538
|
});
|
|
72705
73539
|
|
|
72706
73540
|
// src/cli/serve/spineLockSweep.ts
|
|
72707
|
-
import { promises as
|
|
73541
|
+
import { promises as fs48 } from "node:fs";
|
|
72708
73542
|
import path96 from "node:path";
|
|
72709
73543
|
async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
72710
73544
|
const dir = sessionsDir2 ?? resolveSessionsDir();
|
|
@@ -72718,14 +73552,14 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
72718
73552
|
const result = { swept: 0, kept: 0, errors: 0 };
|
|
72719
73553
|
let entries;
|
|
72720
73554
|
try {
|
|
72721
|
-
entries = await
|
|
73555
|
+
entries = await fs48.readdir(dir);
|
|
72722
73556
|
} catch {
|
|
72723
73557
|
return result;
|
|
72724
73558
|
}
|
|
72725
73559
|
for (const sessionId2 of entries) {
|
|
72726
73560
|
const lockPath2 = path96.join(dir, sessionId2, "writer.lock");
|
|
72727
73561
|
try {
|
|
72728
|
-
const raw = await
|
|
73562
|
+
const raw = await fs48.readFile(lockPath2, "utf-8");
|
|
72729
73563
|
let lockInfo = {};
|
|
72730
73564
|
try {
|
|
72731
73565
|
lockInfo = JSON.parse(raw);
|
|
@@ -72742,7 +73576,7 @@ async function sweepOrphanSpineLocks(sessionsDir2, options = {}) {
|
|
|
72742
73576
|
result.kept += 1;
|
|
72743
73577
|
continue;
|
|
72744
73578
|
}
|
|
72745
|
-
await
|
|
73579
|
+
await fs48.rm(lockPath2, { force: true });
|
|
72746
73580
|
result.swept += 1;
|
|
72747
73581
|
onSwept(sessionId2, verdict.reason);
|
|
72748
73582
|
} catch (err) {
|
|
@@ -78050,107 +78884,8 @@ init_metrics3();
|
|
|
78050
78884
|
init_modelPricing();
|
|
78051
78885
|
init_openai_compatible();
|
|
78052
78886
|
init_resolveStream();
|
|
78053
|
-
|
|
78054
|
-
|
|
78055
|
-
// src/cli/providerFailover.ts
|
|
78056
|
-
var DEFAULT_IS_TRANSIENT = (delta) => delta.kind === "error";
|
|
78057
|
-
function providerFailover(options) {
|
|
78058
|
-
const isTransient = options.isTransientFailure ?? DEFAULT_IS_TRANSIENT;
|
|
78059
|
-
const primaryFailedMsg = options.fallbackLabel ? `[failover] primary failed, switching to ${options.fallbackLabel}` : "[failover] primary failed, switching to fallback";
|
|
78060
|
-
const primaryThrewMsg = options.fallbackLabel ? `[failover] primary threw, switching to ${options.fallbackLabel}: ` : "[failover] primary threw: ";
|
|
78061
|
-
const fallbackFailedMsg = options.fallbackLabel ? `[failover] fallback (${options.fallbackLabel}) also failed: ` : "[failover] fallback also failed: ";
|
|
78062
|
-
return async function* (params) {
|
|
78063
|
-
const triedFallback = { value: false };
|
|
78064
|
-
try {
|
|
78065
|
-
for await (const delta of options.primary(params)) {
|
|
78066
|
-
if (isTransient(delta)) {
|
|
78067
|
-
yield delta;
|
|
78068
|
-
triedFallback.value = true;
|
|
78069
|
-
yield {
|
|
78070
|
-
kind: "error",
|
|
78071
|
-
message: primaryFailedMsg
|
|
78072
|
-
};
|
|
78073
|
-
break;
|
|
78074
|
-
}
|
|
78075
|
-
yield delta;
|
|
78076
|
-
}
|
|
78077
|
-
} catch (err) {
|
|
78078
|
-
triedFallback.value = true;
|
|
78079
|
-
yield {
|
|
78080
|
-
kind: "error",
|
|
78081
|
-
message: `${primaryThrewMsg}${err instanceof Error ? err.message : String(err)}`
|
|
78082
|
-
};
|
|
78083
|
-
}
|
|
78084
|
-
if (triedFallback.value) {
|
|
78085
|
-
try {
|
|
78086
|
-
for await (const delta of options.fallback(params)) {
|
|
78087
|
-
yield delta;
|
|
78088
|
-
}
|
|
78089
|
-
} catch (err) {
|
|
78090
|
-
yield {
|
|
78091
|
-
kind: "error",
|
|
78092
|
-
message: `${fallbackFailedMsg}${err instanceof Error ? err.message : String(err)}`
|
|
78093
|
-
};
|
|
78094
|
-
return;
|
|
78095
|
-
}
|
|
78096
|
-
}
|
|
78097
|
-
};
|
|
78098
|
-
}
|
|
78099
|
-
|
|
78100
|
-
// src/cli/crossProviderFailover.ts
|
|
78101
|
-
async function resolveFailoverStream(options) {
|
|
78102
|
-
if (!options.failoverEnabled) {
|
|
78103
|
-
return {
|
|
78104
|
-
fallback: options.primary,
|
|
78105
|
-
fallbackLabel: void 0,
|
|
78106
|
-
warning: "",
|
|
78107
|
-
reason: "disabled"
|
|
78108
|
-
};
|
|
78109
|
-
}
|
|
78110
|
-
const requested = options.envValue?.trim();
|
|
78111
|
-
if (!requested || requested.length === 0) {
|
|
78112
|
-
return {
|
|
78113
|
-
fallback: options.primary,
|
|
78114
|
-
fallbackLabel: void 0,
|
|
78115
|
-
warning: "",
|
|
78116
|
-
reason: "unset"
|
|
78117
|
-
};
|
|
78118
|
-
}
|
|
78119
|
-
const valid = new Set(options.validProviderIds);
|
|
78120
|
-
if (!valid.has(requested)) {
|
|
78121
|
-
return {
|
|
78122
|
-
fallback: options.primary,
|
|
78123
|
-
fallbackLabel: void 0,
|
|
78124
|
-
warning: `[failover] ANATHEMA_FAILOVER_PROVIDER="${requested}" is not a known provider. Falling back to v3-G same-provider behavior. Available: ${options.validProviderIds.join(", ")}.`,
|
|
78125
|
-
reason: "unknown"
|
|
78126
|
-
};
|
|
78127
|
-
}
|
|
78128
|
-
if (requested === options.primaryProviderId) {
|
|
78129
|
-
return {
|
|
78130
|
-
fallback: options.primary,
|
|
78131
|
-
fallbackLabel: void 0,
|
|
78132
|
-
warning: "",
|
|
78133
|
-
reason: "same-as-primary"
|
|
78134
|
-
};
|
|
78135
|
-
}
|
|
78136
|
-
const fallbackConfig = await options.lookupFallbackConfig(requested);
|
|
78137
|
-
if (!fallbackConfig) {
|
|
78138
|
-
return {
|
|
78139
|
-
fallback: options.primary,
|
|
78140
|
-
fallbackLabel: void 0,
|
|
78141
|
-
warning: `[failover] No API key configured for provider "${requested}". Falling back to v3-G same-provider behavior.`,
|
|
78142
|
-
reason: "missing-key"
|
|
78143
|
-
};
|
|
78144
|
-
}
|
|
78145
|
-
return {
|
|
78146
|
-
fallback: options.buildStream(fallbackConfig),
|
|
78147
|
-
fallbackLabel: requested,
|
|
78148
|
-
warning: "",
|
|
78149
|
-
reason: "resolved"
|
|
78150
|
-
};
|
|
78151
|
-
}
|
|
78152
|
-
|
|
78153
|
-
// src/cli/hooks/useChatTurn.ts
|
|
78887
|
+
init_providerFailover();
|
|
78888
|
+
init_crossProviderFailover();
|
|
78154
78889
|
init_shellResolver();
|
|
78155
78890
|
init_keyStore();
|
|
78156
78891
|
init_providerConfig();
|
|
@@ -78167,6 +78902,7 @@ init_completionProof();
|
|
|
78167
78902
|
init_verifyStatus();
|
|
78168
78903
|
init_nativeVerification();
|
|
78169
78904
|
init_spineTelemetry();
|
|
78905
|
+
import { useState as useState6, useRef as useRef4, useCallback as useCallback2 } from "react";
|
|
78170
78906
|
|
|
78171
78907
|
// src/cli/hooks/permissionPicker.ts
|
|
78172
78908
|
init_toolPermissions();
|
|
@@ -81412,11 +82148,11 @@ function handleCacheStats(ctx) {
|
|
|
81412
82148
|
// src/cli/slashHandlers/memory.ts
|
|
81413
82149
|
init_messageHelpers();
|
|
81414
82150
|
init_serviceFactory();
|
|
81415
|
-
import { promises as
|
|
82151
|
+
import { promises as fs36 } from "node:fs";
|
|
81416
82152
|
import * as path80 from "node:path";
|
|
81417
82153
|
|
|
81418
82154
|
// src/cli/memory/promotion.ts
|
|
81419
|
-
import { promises as
|
|
82155
|
+
import { promises as fs35 } from "node:fs";
|
|
81420
82156
|
import * as path79 from "node:path";
|
|
81421
82157
|
var START = "<!-- zelari:memory-promotions:start -->";
|
|
81422
82158
|
var END = "<!-- zelari:memory-promotions:end -->";
|
|
@@ -81433,17 +82169,17 @@ async function promoteMemoryToAgentsMd(projectRoot, node) {
|
|
|
81433
82169
|
if (!DURABLE_KINDS.has(node.kind)) {
|
|
81434
82170
|
return { added: false, path: path79.join(projectRoot, "AGENTS.md"), reason: `${node.kind} is not a durable instruction kind` };
|
|
81435
82171
|
}
|
|
81436
|
-
const root = await
|
|
82172
|
+
const root = await fs35.realpath(projectRoot).catch(() => path79.resolve(projectRoot));
|
|
81437
82173
|
const target = path79.join(root, "AGENTS.md");
|
|
81438
82174
|
try {
|
|
81439
|
-
const stat8 = await
|
|
82175
|
+
const stat8 = await fs35.lstat(target);
|
|
81440
82176
|
if (stat8.isSymbolicLink() || !stat8.isFile()) throw new Error("AGENTS.md must be a regular project file.");
|
|
81441
82177
|
} catch (error51) {
|
|
81442
82178
|
if (error51.code !== "ENOENT") throw error51;
|
|
81443
82179
|
}
|
|
81444
82180
|
let current = "";
|
|
81445
82181
|
try {
|
|
81446
|
-
current = await
|
|
82182
|
+
current = await fs35.readFile(target, "utf8");
|
|
81447
82183
|
} catch (error51) {
|
|
81448
82184
|
if (error51.code !== "ENOENT") throw error51;
|
|
81449
82185
|
}
|
|
@@ -81466,11 +82202,11 @@ ${END}
|
|
|
81466
82202
|
`;
|
|
81467
82203
|
}
|
|
81468
82204
|
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
81469
|
-
await
|
|
82205
|
+
await fs35.writeFile(temporary, updated, { encoding: "utf8", flag: "wx" });
|
|
81470
82206
|
try {
|
|
81471
|
-
await
|
|
82207
|
+
await fs35.rename(temporary, target);
|
|
81472
82208
|
} catch (error51) {
|
|
81473
|
-
await
|
|
82209
|
+
await fs35.unlink(temporary).catch(() => void 0);
|
|
81474
82210
|
throw error51;
|
|
81475
82211
|
}
|
|
81476
82212
|
return { added: true, path: target };
|
|
@@ -81504,7 +82240,7 @@ function isInside(root, target) {
|
|
|
81504
82240
|
}
|
|
81505
82241
|
async function safeExportPath(cwd, requested) {
|
|
81506
82242
|
const lexicalRoot = path80.resolve(cwd);
|
|
81507
|
-
const root = await
|
|
82243
|
+
const root = await fs36.realpath(lexicalRoot).catch(() => lexicalRoot);
|
|
81508
82244
|
const fallback = path80.join(root, ".zelari", "memory", `export-${Date.now()}.json`);
|
|
81509
82245
|
const target = requested?.trim() ? path80.resolve(root, requested.trim()) : fallback;
|
|
81510
82246
|
if (!isInside(root, target)) {
|
|
@@ -81516,7 +82252,7 @@ async function safeExportPath(cwd, requested) {
|
|
|
81516
82252
|
for (const segment of relativeParent.split(path80.sep).filter(Boolean)) {
|
|
81517
82253
|
cursor = path80.join(cursor, segment);
|
|
81518
82254
|
try {
|
|
81519
|
-
const stat8 = await
|
|
82255
|
+
const stat8 = await fs36.lstat(cursor);
|
|
81520
82256
|
if (stat8.isSymbolicLink()) {
|
|
81521
82257
|
throw new Error("Export path must not traverse a symbolic link.");
|
|
81522
82258
|
}
|
|
@@ -81526,7 +82262,7 @@ async function safeExportPath(cwd, requested) {
|
|
|
81526
82262
|
}
|
|
81527
82263
|
}
|
|
81528
82264
|
try {
|
|
81529
|
-
if ((await
|
|
82265
|
+
if ((await fs36.lstat(target)).isSymbolicLink()) {
|
|
81530
82266
|
throw new Error("Export target must not be a symbolic link.");
|
|
81531
82267
|
}
|
|
81532
82268
|
} catch (error51) {
|
|
@@ -81686,13 +82422,13 @@ ${message}` : message
|
|
|
81686
82422
|
}
|
|
81687
82423
|
case "export": {
|
|
81688
82424
|
const target = await safeExportPath(ctx.cwd, args.join(" ").trim() || void 0);
|
|
81689
|
-
await
|
|
81690
|
-
const root = await
|
|
81691
|
-
const realParent = await
|
|
82425
|
+
await fs36.mkdir(path80.dirname(target), { recursive: true });
|
|
82426
|
+
const root = await fs36.realpath(ctx.cwd).catch(() => path80.resolve(ctx.cwd));
|
|
82427
|
+
const realParent = await fs36.realpath(path80.dirname(target));
|
|
81692
82428
|
if (!isInside(root, realParent)) {
|
|
81693
82429
|
throw new Error("Export path resolves outside the active project.");
|
|
81694
82430
|
}
|
|
81695
|
-
await
|
|
82431
|
+
await fs36.writeFile(target, JSON.stringify(await memory.export(), null, 2) + "\n", "utf8");
|
|
81696
82432
|
emit(`[memory] export written to ${target}`);
|
|
81697
82433
|
return;
|
|
81698
82434
|
}
|
|
@@ -81897,12 +82633,12 @@ ${digest}
|
|
|
81897
82633
|
init_auditLogger();
|
|
81898
82634
|
init_toolRegistry();
|
|
81899
82635
|
init_messageHelpers();
|
|
81900
|
-
import { promises as
|
|
82636
|
+
import { promises as fs38 } from "node:fs";
|
|
81901
82637
|
|
|
81902
82638
|
// src/cli/tools/krakenCsvFanout.ts
|
|
81903
82639
|
init_zod();
|
|
81904
82640
|
init_taskTool();
|
|
81905
|
-
import { promises as
|
|
82641
|
+
import { promises as fs37 } from "node:fs";
|
|
81906
82642
|
import path81 from "node:path";
|
|
81907
82643
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
81908
82644
|
var CsvFanoutArgsSchema = external_exports.object({
|
|
@@ -81924,7 +82660,7 @@ var CsvFanoutArgsSchema = external_exports.object({
|
|
|
81924
82660
|
max_runtime_seconds: external_exports.number().int().positive().optional()
|
|
81925
82661
|
});
|
|
81926
82662
|
async function readCsv(filePath) {
|
|
81927
|
-
const text = await
|
|
82663
|
+
const text = await fs37.readFile(filePath, "utf8");
|
|
81928
82664
|
return parseCsv(text);
|
|
81929
82665
|
}
|
|
81930
82666
|
function parseCsv(text) {
|
|
@@ -82054,7 +82790,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
82054
82790
|
errored += 1;
|
|
82055
82791
|
errors.push(`${row[args.id_column] ?? i}: ${res.error}`);
|
|
82056
82792
|
}
|
|
82057
|
-
await
|
|
82793
|
+
await fs37.mkdir(path81.dirname(absOut), { recursive: true });
|
|
82058
82794
|
await queueWrite(serializeCsv(outHeaders, outputRecords));
|
|
82059
82795
|
}
|
|
82060
82796
|
}
|
|
@@ -82076,8 +82812,8 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
82076
82812
|
}
|
|
82077
82813
|
async function atomicWrite(file2, contents) {
|
|
82078
82814
|
const tmp = `${file2}.${process.pid}.${Date.now()}.${randomBytes6(6).toString("hex")}.tmp`;
|
|
82079
|
-
await
|
|
82080
|
-
await
|
|
82815
|
+
await fs37.writeFile(tmp, contents, "utf8");
|
|
82816
|
+
await fs37.rename(tmp, file2);
|
|
82081
82817
|
}
|
|
82082
82818
|
|
|
82083
82819
|
// src/cli/slashHandlers/krakenFanout.ts
|
|
@@ -82175,7 +82911,7 @@ async function handleKrakenFanout(ctx, raw) {
|
|
|
82175
82911
|
}
|
|
82176
82912
|
const absCsv = isAbsolute3(parsed.args.csv_path) ? parsed.args.csv_path : joinPath(ctx.cwd, parsed.args.csv_path);
|
|
82177
82913
|
try {
|
|
82178
|
-
await
|
|
82914
|
+
await fs38.access(absCsv);
|
|
82179
82915
|
} catch {
|
|
82180
82916
|
appendSystem(ctx.setMessages, `[kraken fanout] source CSV not found: ${absCsv}`);
|
|
82181
82917
|
return;
|
|
@@ -82248,7 +82984,7 @@ function splitArgs(s) {
|
|
|
82248
82984
|
|
|
82249
82985
|
// src/cli/slashHandlers/krakenWorkbench.ts
|
|
82250
82986
|
init_messageHelpers();
|
|
82251
|
-
import { promises as
|
|
82987
|
+
import { promises as fs39 } from "node:fs";
|
|
82252
82988
|
import path82 from "node:path";
|
|
82253
82989
|
|
|
82254
82990
|
// src/cli/kraken/workbenchView.ts
|
|
@@ -82370,11 +83106,11 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
82370
83106
|
let latest = null;
|
|
82371
83107
|
let latestMtime = 0;
|
|
82372
83108
|
try {
|
|
82373
|
-
const files = await
|
|
83109
|
+
const files = await fs39.readdir(dir);
|
|
82374
83110
|
for (const f of files) {
|
|
82375
83111
|
if (!f.startsWith("workbench-") || !f.endsWith(".md")) continue;
|
|
82376
83112
|
const full = path82.join(dir, f);
|
|
82377
|
-
const stat8 = await
|
|
83113
|
+
const stat8 = await fs39.stat(full);
|
|
82378
83114
|
if (stat8.mtimeMs > latestMtime) {
|
|
82379
83115
|
latestMtime = stat8.mtimeMs;
|
|
82380
83116
|
latest = full;
|
|
@@ -82386,7 +83122,7 @@ async function handleKrakenWorkbench(ctx) {
|
|
|
82386
83122
|
appendSystem(ctx.setMessages, "[kraken workbench] no workbench file found (.zelari/radio/workbench-*.md)");
|
|
82387
83123
|
return;
|
|
82388
83124
|
}
|
|
82389
|
-
const content = await
|
|
83125
|
+
const content = await fs39.readFile(latest, "utf8");
|
|
82390
83126
|
const parsed = parseWorkbench(content);
|
|
82391
83127
|
const rendered = formatWorkbenchForTerminal(parsed);
|
|
82392
83128
|
if (!rendered.trim()) {
|
|
@@ -82700,20 +83436,20 @@ ${result.output.split("\n").slice(-8).join("\n")}` : "";
|
|
|
82700
83436
|
// src/cli/slashHandlers/promoteMember.ts
|
|
82701
83437
|
init_messageHelpers();
|
|
82702
83438
|
init_paths();
|
|
82703
|
-
import { promises as
|
|
83439
|
+
import { promises as fs40 } from "node:fs";
|
|
82704
83440
|
import path85 from "node:path";
|
|
82705
83441
|
async function handlePromoteMember(ctx, memberId) {
|
|
82706
83442
|
try {
|
|
82707
83443
|
const { promoteMember: promoteMember2 } = await Promise.resolve().then(() => (init_council(), council_exports));
|
|
82708
83444
|
const { skill, markdown } = promoteMember2(memberId);
|
|
82709
83445
|
const skillDir = skillsDir();
|
|
82710
|
-
await
|
|
83446
|
+
await fs40.mkdir(skillDir, { recursive: true });
|
|
82711
83447
|
const filePath = path85.join(skillDir, `${skill.id}.md`);
|
|
82712
|
-
const previous = await
|
|
82713
|
-
const { createHash:
|
|
82714
|
-
const sha = (s) =>
|
|
83448
|
+
const previous = await fs40.readFile(filePath, "utf8").catch(() => null);
|
|
83449
|
+
const { createHash: createHash25 } = await import("node:crypto");
|
|
83450
|
+
const sha = (s) => createHash25("sha256").update(s, "utf8").digest("hex");
|
|
82715
83451
|
const lineage = `<!-- lineage: genome=sha256:${sha(markdown)} parent=${previous ? `sha256:${sha(previous)}` : "none"} promotedBy=user promotedAt=${(/* @__PURE__ */ new Date()).toISOString()} -->`;
|
|
82716
|
-
await
|
|
83452
|
+
await fs40.writeFile(filePath, `${markdown}
|
|
82717
83453
|
${lineage}
|
|
82718
83454
|
`, "utf8");
|
|
82719
83455
|
appendSystem(
|
|
@@ -82733,7 +83469,7 @@ ${lineage}
|
|
|
82733
83469
|
|
|
82734
83470
|
// src/cli/branchManager.ts
|
|
82735
83471
|
init_paths();
|
|
82736
|
-
import { promises as
|
|
83472
|
+
import { promises as fs41, existsSync as existsSync55, readFileSync as readFileSync41, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
|
|
82737
83473
|
import path86 from "node:path";
|
|
82738
83474
|
var META_FILENAME = "meta.json";
|
|
82739
83475
|
var SESSIONS_SUBDIR = "sessions";
|
|
@@ -82781,7 +83517,7 @@ function writeBranchMeta(name, baseDir, meta3) {
|
|
|
82781
83517
|
async function countSessions(name, baseDir) {
|
|
82782
83518
|
const sessionsPath = sessionsPathFor(name, baseDir);
|
|
82783
83519
|
try {
|
|
82784
|
-
const entries = await
|
|
83520
|
+
const entries = await fs41.readdir(sessionsPath);
|
|
82785
83521
|
return entries.filter((e) => e.endsWith(".jsonl")).length;
|
|
82786
83522
|
} catch (err) {
|
|
82787
83523
|
if (err.code === "ENOENT") return 0;
|
|
@@ -82834,7 +83570,7 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
82834
83570
|
const branchSessionsPath = sessionsPathFor(name, baseDir);
|
|
82835
83571
|
mkdirSync21(branchSessionsPath, { recursive: true });
|
|
82836
83572
|
const destPath = path86.join(branchSessionsPath, `${fromSessionId}.jsonl`);
|
|
82837
|
-
await
|
|
83573
|
+
await fs41.copyFile(sourcePath, destPath);
|
|
82838
83574
|
const meta3 = {
|
|
82839
83575
|
name,
|
|
82840
83576
|
createdAt: Date.now(),
|
|
@@ -82852,7 +83588,7 @@ async function createBranch(name, fromSessionId, baseDir = getBranchesBaseDir(),
|
|
|
82852
83588
|
async function listBranches(baseDir = getBranchesBaseDir()) {
|
|
82853
83589
|
let entries;
|
|
82854
83590
|
try {
|
|
82855
|
-
entries = await
|
|
83591
|
+
entries = await fs41.readdir(baseDir);
|
|
82856
83592
|
} catch (err) {
|
|
82857
83593
|
if (err.code === "ENOENT") return [];
|
|
82858
83594
|
throw err;
|
|
@@ -82936,7 +83672,7 @@ async function handleBranchCheckout(ctx, branchName) {
|
|
|
82936
83672
|
|
|
82937
83673
|
// src/cli/slashHandlers/workspace.ts
|
|
82938
83674
|
init_messageHelpers();
|
|
82939
|
-
import { promises as
|
|
83675
|
+
import { promises as fs42 } from "node:fs";
|
|
82940
83676
|
import path87 from "node:path";
|
|
82941
83677
|
async function handleWorkspaceShow(ctx, what) {
|
|
82942
83678
|
try {
|
|
@@ -82946,7 +83682,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82946
83682
|
case "plan": {
|
|
82947
83683
|
const planPath = path87.join(zelari, "plan.md");
|
|
82948
83684
|
try {
|
|
82949
|
-
content = await
|
|
83685
|
+
content = await fs42.readFile(planPath, "utf-8");
|
|
82950
83686
|
} catch {
|
|
82951
83687
|
content = "(no plan.md yet \u2014 run a council session first)";
|
|
82952
83688
|
}
|
|
@@ -82955,7 +83691,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82955
83691
|
case "decisions": {
|
|
82956
83692
|
const decisionsDir = path87.join(zelari, "decisions");
|
|
82957
83693
|
try {
|
|
82958
|
-
const files = (await
|
|
83694
|
+
const files = (await fs42.readdir(decisionsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
82959
83695
|
if (files.length === 0) {
|
|
82960
83696
|
content = "(no ADRs yet \u2014 invoke /council to generate some)";
|
|
82961
83697
|
} else {
|
|
@@ -82963,7 +83699,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82963
83699
|
`];
|
|
82964
83700
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
82965
83701
|
for (const f of files) {
|
|
82966
|
-
const raw = await
|
|
83702
|
+
const raw = await fs42.readFile(path87.join(decisionsDir, f), "utf-8");
|
|
82967
83703
|
const { meta: meta3, body } = parseFrontmatter2(raw);
|
|
82968
83704
|
const title = meta3.title ?? body.split("\n")[0]?.replace(/^#\s*/, "").trim() ?? f;
|
|
82969
83705
|
lines.push(`- **${f.replace(/\.md$/, "")}** [${meta3.status ?? "unknown"}] ${title}`);
|
|
@@ -82978,7 +83714,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82978
83714
|
case "risks": {
|
|
82979
83715
|
const risksPath = path87.join(zelari, "risks.md");
|
|
82980
83716
|
try {
|
|
82981
|
-
content = await
|
|
83717
|
+
content = await fs42.readFile(risksPath, "utf-8");
|
|
82982
83718
|
} catch {
|
|
82983
83719
|
content = "(no risks.md yet)";
|
|
82984
83720
|
}
|
|
@@ -82987,7 +83723,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82987
83723
|
case "agents": {
|
|
82988
83724
|
const agentsPath = path87.join(process.cwd(), "AGENTS.MD");
|
|
82989
83725
|
try {
|
|
82990
|
-
content = await
|
|
83726
|
+
content = await fs42.readFile(agentsPath, "utf-8");
|
|
82991
83727
|
} catch {
|
|
82992
83728
|
content = "(no AGENTS.MD yet at project root \u2014 run `/workspace sync` after a council session)";
|
|
82993
83729
|
}
|
|
@@ -82996,7 +83732,7 @@ async function handleWorkspaceShow(ctx, what) {
|
|
|
82996
83732
|
case "docs": {
|
|
82997
83733
|
const docsDir = path87.join(zelari, "docs");
|
|
82998
83734
|
try {
|
|
82999
|
-
const files = (await
|
|
83735
|
+
const files = (await fs42.readdir(docsDir)).filter((f) => f.endsWith(".md")).sort();
|
|
83000
83736
|
content = files.length ? `# Docs (${files.length})
|
|
83001
83737
|
|
|
83002
83738
|
` + files.map((f) => `- ${f}`).join("\n") : "(no docs drafts yet)";
|
|
@@ -83037,7 +83773,7 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
83037
83773
|
}
|
|
83038
83774
|
try {
|
|
83039
83775
|
const target = path87.join(process.cwd(), ".zelari");
|
|
83040
|
-
await
|
|
83776
|
+
await fs42.rm(target, { recursive: true, force: true });
|
|
83041
83777
|
appendSystem(ctx.setMessages, "[workspace] .zelari/ removed");
|
|
83042
83778
|
} catch (err) {
|
|
83043
83779
|
appendSystem(ctx.setMessages, `[workspace reset error] ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -83048,13 +83784,13 @@ async function handleWorkspaceReset(ctx, force) {
|
|
|
83048
83784
|
init_provider2();
|
|
83049
83785
|
|
|
83050
83786
|
// src/cli/skillHistory.ts
|
|
83051
|
-
import { promises as
|
|
83787
|
+
import { promises as fs43, existsSync as existsSync56, statSync as statSync8, renameSync as renameSync6, appendFileSync as appendFileSync5, mkdirSync as mkdirSync22 } from "node:fs";
|
|
83052
83788
|
init_paths();
|
|
83053
83789
|
var SKILL_HISTORY_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
83054
83790
|
async function readSkillHistory(file2) {
|
|
83055
83791
|
let raw = "";
|
|
83056
83792
|
try {
|
|
83057
|
-
raw = await
|
|
83793
|
+
raw = await fs43.readFile(file2, "utf-8");
|
|
83058
83794
|
} catch {
|
|
83059
83795
|
return [];
|
|
83060
83796
|
}
|