@wrongstack/core 0.257.0 → 0.260.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/{agent-bridge-BrxWHEOm.d.ts → agent-bridge-BbskZ7HH.d.ts} +1 -1
- package/dist/{agent-subagent-runner-US741uBH.d.ts → agent-subagent-runner-BNIGZx18.d.ts} +28 -8
- package/dist/{brain-TjEEwSpw.d.ts → brain-C2yDd7Lw.d.ts} +58 -1
- package/dist/{compactor-C5sT4U7I.d.ts → compactor-t0R_AIt_.d.ts} +1 -1
- package/dist/{config-DuAu23zm.d.ts → config-FG6As4H5.d.ts} +1 -1
- package/dist/{context-CGdgA0q6.d.ts → context-JFOVvu6z.d.ts} +22 -0
- package/dist/coordination/index.d.ts +14 -14
- package/dist/coordination/index.js +195 -33
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +25 -25
- package/dist/defaults/index.js +908 -92
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +15 -15
- package/dist/execution/index.js +134 -35
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{goal-preamble-UiEkbNmW.d.ts → goal-preamble-B1IXJtLX.d.ts} +11 -9
- package/dist/{goal-store-CV9Yz2X_.d.ts → goal-store-CPXz6Mml.d.ts} +4 -2
- package/dist/{index-CitPrI3a.d.ts → index-BPcg4N3M.d.ts} +5 -5
- package/dist/{index-CC0Mcm05.d.ts → index-CebbJB94.d.ts} +8 -8
- package/dist/index.d.ts +47 -43
- package/dist/index.js +1571 -284
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{llm-selector-CJ4SyAFE.d.ts → llm-selector-DXxI2tlu.d.ts} +2 -2
- package/dist/{mcp-servers-D8YnLaEp.d.ts → mcp-servers-OwNHo43-.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/{models-registry-ByZCdFuQ.d.ts → models-registry-Djlmq4uB.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-DqTUEAeC.d.ts → multi-agent-coordinator-CEmrSCMJ.d.ts} +1 -1
- package/dist/{null-fleet-bus-B5mfTJXT.d.ts → null-fleet-bus-DT92xqgJ.d.ts} +13 -8
- package/dist/observability/index.d.ts +2 -2
- package/dist/{package-outdated-watcher-BSgR_kK-.d.ts → package-outdated-watcher-C70ag2G9.d.ts} +3 -3
- package/dist/{parallel-eternal-engine-C0juOszP.d.ts → parallel-eternal-engine-0SItuq5r.d.ts} +13 -9
- package/dist/{path-resolver-CbkT-RMU.d.ts → path-resolver-DKBh6Jlo.d.ts} +3 -3
- package/dist/{permission-CwBBpCoF.d.ts → permission-BJ7eO9Vl.d.ts} +1 -1
- package/dist/{permission-policy-B8rSu908.d.ts → permission-policy-DEXOfnpm.d.ts} +3 -2
- package/dist/{pipeline-JG8XoudC.d.ts → pipeline-zflkI2dp.d.ts} +2 -2
- package/dist/{plan-templates-DPiQMkBz.d.ts → plan-templates-BFXyRkEK.d.ts} +32 -11
- package/dist/{provider-runner-hM7EXlLI.d.ts → provider-runner-BC-uywtT.d.ts} +3 -3
- package/dist/{retry-policy-Tg7LXkoK.d.ts → retry-policy-Cavrzmtk.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +20 -2
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-gxtFZYBt.d.ts → secret-vault-CDvDYXWX.d.ts} +1 -1
- package/dist/security/index.d.ts +4 -4
- package/dist/security/index.js +30 -1
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-DWsqVjGf.d.ts → selector-B7AivHsu.d.ts} +1 -1
- package/dist/{session-event-bridge-BAFWdgQ3.d.ts → session-event-bridge-BmIDxdJd.d.ts} +1 -1
- package/dist/{session-reader-CqRvaL5v.d.ts → session-reader-DtofsB-2.d.ts} +1 -1
- package/dist/storage/index.d.ts +30 -21
- package/dist/storage/index.js +1264 -216
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +101 -3
- package/dist/utils/index.js +92 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/output-standards/SKILL.md +14 -9
- package/skills/output-standards/SKILL.save.md +3 -2
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@ import { join, extname, relative, isAbsolute, resolve, sep } from 'path';
|
|
|
7
7
|
import * as fs2 from 'fs';
|
|
8
8
|
import * as os6 from 'os';
|
|
9
9
|
import { hostname } from 'os';
|
|
10
|
+
import * as dns from 'dns/promises';
|
|
11
|
+
import * as net from 'net';
|
|
10
12
|
import { execFile, spawn } from 'child_process';
|
|
11
13
|
import { promisify } from 'util';
|
|
12
14
|
import { EventEmitter } from 'events';
|
|
@@ -4277,6 +4279,13 @@ function hasDangerousCapabilityForSubagents(toolOrCaps) {
|
|
|
4277
4279
|
const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
|
|
4278
4280
|
return caps.some((c) => DANGEROUS_FOR_SUBAGENTS.includes(c));
|
|
4279
4281
|
}
|
|
4282
|
+
function hasCapability(toolOrCaps, capability) {
|
|
4283
|
+
if (!toolOrCaps) return false;
|
|
4284
|
+
const input = toolOrCaps;
|
|
4285
|
+
const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
|
|
4286
|
+
const toCheck = Array.isArray(capability) ? capability : [capability];
|
|
4287
|
+
return toCheck.some((c) => caps.includes(c));
|
|
4288
|
+
}
|
|
4280
4289
|
function getDangerousCapabilities(toolOrCaps) {
|
|
4281
4290
|
if (!toolOrCaps) return [];
|
|
4282
4291
|
const input = toolOrCaps;
|
|
@@ -5050,6 +5059,12 @@ var Context = class {
|
|
|
5050
5059
|
agentId;
|
|
5051
5060
|
/** Human-readable agent name. */
|
|
5052
5061
|
agentName;
|
|
5062
|
+
/**
|
|
5063
|
+
* Session-level trace ID for correlating storage events with agent
|
|
5064
|
+
* iterations. Stored here and also propagated to `session.traceId`
|
|
5065
|
+
* so storage operations can include it in `storage.*` events.
|
|
5066
|
+
*/
|
|
5067
|
+
traceId;
|
|
5053
5068
|
/** Callbacks fired when `setWorkingDir()` changes the working directory. */
|
|
5054
5069
|
_onWorkingDirChanged = [];
|
|
5055
5070
|
/**
|
|
@@ -5085,6 +5100,8 @@ var Context = class {
|
|
|
5085
5100
|
this.tools = init.tools ?? [];
|
|
5086
5101
|
this.agentId = init.agentId ?? "unknown";
|
|
5087
5102
|
this.agentName = init.agentName ?? "Unknown Agent";
|
|
5103
|
+
this.traceId = init.traceId;
|
|
5104
|
+
this.session.traceId = init.traceId;
|
|
5088
5105
|
}
|
|
5089
5106
|
/**
|
|
5090
5107
|
* Observable wrapper over the mutable conversation state. Lazy so
|
|
@@ -6374,6 +6391,95 @@ function mergeCustomModelDefs(providerCustomModels, configModels) {
|
|
|
6374
6391
|
if (Object.keys(out).length === 0) return void 0;
|
|
6375
6392
|
return out;
|
|
6376
6393
|
}
|
|
6394
|
+
function isPrivateIPv4(addr) {
|
|
6395
|
+
const parts = addr.split(".").map((p) => Number.parseInt(p, 10));
|
|
6396
|
+
if (parts.length !== 4 || parts.some((n) => Number.isNaN(n) || n < 0 || n > 255)) {
|
|
6397
|
+
return true;
|
|
6398
|
+
}
|
|
6399
|
+
const [a, b, c] = parts;
|
|
6400
|
+
if (a === 0) return true;
|
|
6401
|
+
if (a === 10) return true;
|
|
6402
|
+
if (a === 127) return true;
|
|
6403
|
+
if (a === 169 && b === 254) return true;
|
|
6404
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
6405
|
+
if (a === 192 && b === 168) return true;
|
|
6406
|
+
if (a === 192 && b === 0 && c === 0) return true;
|
|
6407
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
6408
|
+
if (a >= 224) return true;
|
|
6409
|
+
return false;
|
|
6410
|
+
}
|
|
6411
|
+
function isPrivateIPv6(raw) {
|
|
6412
|
+
const lower = raw.toLowerCase();
|
|
6413
|
+
if (lower === "::" || lower === "::1") return true;
|
|
6414
|
+
const groups = expandIPv6(lower);
|
|
6415
|
+
if (!groups) return true;
|
|
6416
|
+
if (groups[0] === 0 && groups[1] === 0 && groups[2] === 0 && groups[3] === 0 && groups[4] === 0 && groups[5] === 65535) {
|
|
6417
|
+
const a = (groups[6] ?? 0) >> 8;
|
|
6418
|
+
const b = (groups[6] ?? 0) & 255;
|
|
6419
|
+
const c = (groups[7] ?? 0) >> 8;
|
|
6420
|
+
const d = (groups[7] ?? 0) & 255;
|
|
6421
|
+
return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
|
|
6422
|
+
}
|
|
6423
|
+
const high = groups[0] ?? 0;
|
|
6424
|
+
if ((high & 65024) === 64512) return true;
|
|
6425
|
+
if ((high & 65472) === 65152) return true;
|
|
6426
|
+
if ((high & 65280) === 65280) return true;
|
|
6427
|
+
return false;
|
|
6428
|
+
}
|
|
6429
|
+
function expandIPv6(addr) {
|
|
6430
|
+
const parts = addr.split("::");
|
|
6431
|
+
if (parts.length > 2) return null;
|
|
6432
|
+
const parseGroups = (s) => {
|
|
6433
|
+
if (s === "") return [];
|
|
6434
|
+
const out = [];
|
|
6435
|
+
for (const g of s.split(":")) {
|
|
6436
|
+
if (g.length === 0 || g.length > 4) return null;
|
|
6437
|
+
const n = Number.parseInt(g, 16);
|
|
6438
|
+
if (Number.isNaN(n) || n < 0 || n > 65535) return null;
|
|
6439
|
+
out.push(n);
|
|
6440
|
+
}
|
|
6441
|
+
return out;
|
|
6442
|
+
};
|
|
6443
|
+
if (parts.length === 1) {
|
|
6444
|
+
const groups = parseGroups(parts[0] ?? "");
|
|
6445
|
+
if (!groups || groups.length !== 8) return null;
|
|
6446
|
+
return groups;
|
|
6447
|
+
}
|
|
6448
|
+
const head = parseGroups(parts[0] ?? "");
|
|
6449
|
+
const tail = parseGroups(parts[1] ?? "");
|
|
6450
|
+
if (!head || !tail) return null;
|
|
6451
|
+
const fill = 8 - head.length - tail.length;
|
|
6452
|
+
if (fill < 0) return null;
|
|
6453
|
+
return [...head, ...new Array(fill).fill(0), ...tail];
|
|
6454
|
+
}
|
|
6455
|
+
async function assertNotPrivateHost(hostname3) {
|
|
6456
|
+
const host = hostname3.startsWith("[") && hostname3.endsWith("]") ? hostname3.slice(1, -1) : hostname3;
|
|
6457
|
+
if (host === "localhost" || host.endsWith(".localhost")) {
|
|
6458
|
+
throw new Error("fetch: blocked localhost target");
|
|
6459
|
+
}
|
|
6460
|
+
const ipVersion = net.isIP(host);
|
|
6461
|
+
if (ipVersion === 4) {
|
|
6462
|
+
if (isPrivateIPv4(host)) {
|
|
6463
|
+
throw new Error(`fetch: blocked private/loopback address "${host}"`);
|
|
6464
|
+
}
|
|
6465
|
+
} else if (ipVersion === 6) {
|
|
6466
|
+
if (isPrivateIPv6(host)) {
|
|
6467
|
+
throw new Error(`fetch: blocked private/loopback address "${host}"`);
|
|
6468
|
+
}
|
|
6469
|
+
} else {
|
|
6470
|
+
try {
|
|
6471
|
+
const records = await dns.lookup(host, { all: true });
|
|
6472
|
+
for (const r of records) {
|
|
6473
|
+
const bad = r.family === 4 ? isPrivateIPv4(r.address) : isPrivateIPv6(r.address);
|
|
6474
|
+
if (bad) {
|
|
6475
|
+
throw new Error(`fetch: resolved to private address ${r.address}`);
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6478
|
+
} catch (err) {
|
|
6479
|
+
if (err instanceof Error && err.message.startsWith("fetch:")) throw err;
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6377
6483
|
|
|
6378
6484
|
// src/storage/session-store.ts
|
|
6379
6485
|
init_atomic_write();
|
|
@@ -6396,6 +6502,40 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6396
6502
|
this.events = opts.events;
|
|
6397
6503
|
this.secretScrubber = opts.secretScrubber;
|
|
6398
6504
|
}
|
|
6505
|
+
// ── Storage event helpers ───────────────────────────────────────────────────
|
|
6506
|
+
emitRead(sessionId, filePath, operation, outcome, durationMs, error) {
|
|
6507
|
+
this.events?.emit("storage.read", {
|
|
6508
|
+
sessionId,
|
|
6509
|
+
store: "session",
|
|
6510
|
+
filePath,
|
|
6511
|
+
operation,
|
|
6512
|
+
outcome,
|
|
6513
|
+
durationMs,
|
|
6514
|
+
...error !== void 0 ? { error } : {}
|
|
6515
|
+
});
|
|
6516
|
+
}
|
|
6517
|
+
emitWrite(sessionId, filePath, operation, outcome, durationMs, eventCount, error) {
|
|
6518
|
+
this.events?.emit("storage.write", {
|
|
6519
|
+
sessionId,
|
|
6520
|
+
store: "session",
|
|
6521
|
+
filePath,
|
|
6522
|
+
operation,
|
|
6523
|
+
outcome,
|
|
6524
|
+
durationMs,
|
|
6525
|
+
...eventCount !== void 0 ? { eventCount } : {},
|
|
6526
|
+
...error !== void 0 ? { error } : {}
|
|
6527
|
+
});
|
|
6528
|
+
}
|
|
6529
|
+
emitError(sessionId, filePath, operation, error, recoverable) {
|
|
6530
|
+
this.events?.emit("storage.error", {
|
|
6531
|
+
sessionId,
|
|
6532
|
+
store: "session",
|
|
6533
|
+
filePath,
|
|
6534
|
+
operation,
|
|
6535
|
+
error,
|
|
6536
|
+
recoverable
|
|
6537
|
+
});
|
|
6538
|
+
}
|
|
6399
6539
|
/** Absolute path to the session index file. */
|
|
6400
6540
|
get indexFile() {
|
|
6401
6541
|
return path7.join(this.dir, "_index.jsonl");
|
|
@@ -6419,22 +6559,26 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6419
6559
|
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
6420
6560
|
const shardDir = await this.ensureShardDir(id);
|
|
6421
6561
|
const file = path7.join(shardDir, `${path7.basename(id)}.jsonl`);
|
|
6562
|
+
const t0 = Date.now();
|
|
6422
6563
|
let handle;
|
|
6423
6564
|
try {
|
|
6424
6565
|
handle = await fsp3.open(file, "a", 384);
|
|
6425
6566
|
} catch (err) {
|
|
6567
|
+
this.emitError(id, file, "create", err instanceof Error ? err.message : String(err), false);
|
|
6426
6568
|
throw new Error(
|
|
6427
6569
|
`Failed to open session file: ${err instanceof Error ? err.message : String(err)}`,
|
|
6428
6570
|
{ cause: err }
|
|
6429
6571
|
);
|
|
6430
6572
|
}
|
|
6431
6573
|
try {
|
|
6432
|
-
|
|
6574
|
+
const writer = new FileSessionWriter(id, handle, startedAt, meta, this.events, {
|
|
6433
6575
|
dir: shardDir,
|
|
6434
6576
|
filePath: file,
|
|
6435
6577
|
secretScrubber: this.secretScrubber,
|
|
6436
6578
|
onClose: (s) => this.appendToIndex(s)
|
|
6437
6579
|
});
|
|
6580
|
+
this.emitWrite(id, file, "create", "success", Date.now() - t0);
|
|
6581
|
+
return writer;
|
|
6438
6582
|
} catch (err) {
|
|
6439
6583
|
await handle.close().catch((e) => console.warn(JSON.stringify({
|
|
6440
6584
|
level: "warn",
|
|
@@ -6442,16 +6586,19 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6442
6586
|
message: e instanceof Error ? e.message : String(e),
|
|
6443
6587
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6444
6588
|
})));
|
|
6589
|
+
this.emitError(id, file, "create", err instanceof Error ? err.message : String(err), true);
|
|
6445
6590
|
throw err;
|
|
6446
6591
|
}
|
|
6447
6592
|
}
|
|
6448
6593
|
async resume(id) {
|
|
6449
6594
|
const file = this.sessionPath(id, ".jsonl");
|
|
6595
|
+
const t0 = Date.now();
|
|
6450
6596
|
const data = await this.load(id);
|
|
6451
6597
|
let handle;
|
|
6452
6598
|
try {
|
|
6453
6599
|
handle = await fsp3.open(file, "a", 384);
|
|
6454
6600
|
} catch (err) {
|
|
6601
|
+
this.emitError(id, file, "resume", err instanceof Error ? err.message : String(err), false);
|
|
6455
6602
|
throw new Error(
|
|
6456
6603
|
`Failed to open session "${id}" for append: ${err instanceof Error ? err.message : String(err)}`,
|
|
6457
6604
|
{ cause: err }
|
|
@@ -6479,6 +6626,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6479
6626
|
onClose: (s) => this.appendToIndex(s)
|
|
6480
6627
|
}
|
|
6481
6628
|
);
|
|
6629
|
+
this.emitWrite(id, file, "resume", "success", Date.now() - t0);
|
|
6482
6630
|
return { writer, data };
|
|
6483
6631
|
} catch (err) {
|
|
6484
6632
|
await handle.close().catch((e) => console.warn(JSON.stringify({
|
|
@@ -6487,27 +6635,39 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6487
6635
|
message: e instanceof Error ? e.message : String(e),
|
|
6488
6636
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6489
6637
|
})));
|
|
6638
|
+
this.emitError(id, file, "resume", err instanceof Error ? err.message : String(err), true);
|
|
6490
6639
|
throw err;
|
|
6491
6640
|
}
|
|
6492
6641
|
}
|
|
6493
6642
|
async load(id) {
|
|
6494
6643
|
const file = this.sessionPath(id, ".jsonl");
|
|
6495
|
-
const
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6644
|
+
const t0 = Date.now();
|
|
6645
|
+
let outcome = "success";
|
|
6646
|
+
let errorMsg;
|
|
6647
|
+
try {
|
|
6648
|
+
const raw = await fsp3.readFile(file, "utf8");
|
|
6649
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
6650
|
+
const events = [];
|
|
6651
|
+
for (const line of lines) {
|
|
6652
|
+
try {
|
|
6653
|
+
const parsed = JSON.parse(line);
|
|
6654
|
+
if (parsed !== null && typeof parsed === "object" && typeof parsed.type === "string" && typeof parsed.ts === "string") {
|
|
6655
|
+
events.push(parsed);
|
|
6656
|
+
}
|
|
6657
|
+
} catch {
|
|
6503
6658
|
}
|
|
6504
|
-
} catch {
|
|
6505
6659
|
}
|
|
6660
|
+
const meta = this.metaFromEvents(id, events);
|
|
6661
|
+
const { messages, usage } = this.replay(events, id);
|
|
6662
|
+
const toolCallEnds = extractToolCallEnds(events);
|
|
6663
|
+
return { metadata: meta, events, messages, usage, toolCallEnds };
|
|
6664
|
+
} catch (err) {
|
|
6665
|
+
outcome = "failure";
|
|
6666
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
6667
|
+
throw err;
|
|
6668
|
+
} finally {
|
|
6669
|
+
this.emitRead(id, file, "load", outcome, Date.now() - t0, errorMsg);
|
|
6506
6670
|
}
|
|
6507
|
-
const meta = this.metaFromEvents(id, events);
|
|
6508
|
-
const { messages, usage } = this.replay(events, id);
|
|
6509
|
-
const toolCallEnds = extractToolCallEnds(events);
|
|
6510
|
-
return { metadata: meta, events, messages, usage, toolCallEnds };
|
|
6511
6671
|
}
|
|
6512
6672
|
async list(limit = 20) {
|
|
6513
6673
|
try {
|
|
@@ -6574,12 +6734,22 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6574
6734
|
* (keep latest per session), and rewrite. Atomic via temp+rename.
|
|
6575
6735
|
*/
|
|
6576
6736
|
async compactIndex() {
|
|
6577
|
-
const
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6737
|
+
const t0 = Date.now();
|
|
6738
|
+
let outcome = "success";
|
|
6739
|
+
let errorMsg;
|
|
6740
|
+
try {
|
|
6741
|
+
const entries = await this.readIndex();
|
|
6742
|
+
if (entries.length === 0) return;
|
|
6743
|
+
const tmp = `${this.indexFile}.compact.tmp`;
|
|
6744
|
+
const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
6745
|
+
await fsp3.writeFile(tmp, lines, "utf8");
|
|
6746
|
+
await fsp3.rename(tmp, this.indexFile);
|
|
6747
|
+
} catch (err) {
|
|
6748
|
+
outcome = "failure";
|
|
6749
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
6750
|
+
} finally {
|
|
6751
|
+
this.emitWrite("~compact~", this.indexFile, "compact", outcome, Date.now() - t0, void 0, errorMsg);
|
|
6752
|
+
}
|
|
6583
6753
|
}
|
|
6584
6754
|
/**
|
|
6585
6755
|
* Read the index file and return deduplicated session summaries.
|
|
@@ -6655,22 +6825,31 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
6655
6825
|
}
|
|
6656
6826
|
async summaryFor(id) {
|
|
6657
6827
|
const manifest = this.sessionPath(id, ".summary.json");
|
|
6828
|
+
const t0 = Date.now();
|
|
6829
|
+
let outcome = "success";
|
|
6830
|
+
let errorMsg;
|
|
6658
6831
|
try {
|
|
6659
6832
|
const raw = await fsp3.readFile(manifest, "utf8");
|
|
6833
|
+
this.emitRead(id, manifest, "summary", "success", Date.now() - t0);
|
|
6660
6834
|
return JSON.parse(raw);
|
|
6661
6835
|
} catch {
|
|
6662
6836
|
const full = this.sessionPath(id, ".jsonl");
|
|
6663
6837
|
const stat11 = await fsp3.stat(full);
|
|
6664
6838
|
const summary = await this.summarize(id, stat11.mtime.toISOString());
|
|
6665
6839
|
await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
|
|
6840
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6841
|
+
this.emitError(id, manifest, "summary_fallback", msg, true);
|
|
6666
6842
|
console.warn(JSON.stringify({
|
|
6667
6843
|
level: "warn",
|
|
6668
6844
|
event: "session_store.manifest_write_failed",
|
|
6669
6845
|
sessionId: id,
|
|
6670
|
-
message:
|
|
6846
|
+
message: msg,
|
|
6671
6847
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6672
6848
|
}));
|
|
6673
6849
|
});
|
|
6850
|
+
outcome = "failure";
|
|
6851
|
+
errorMsg = "summary fallback \u2014 manifest rebuilt";
|
|
6852
|
+
this.emitRead(id, manifest, "summary", outcome, Date.now() - t0, errorMsg);
|
|
6674
6853
|
return summary;
|
|
6675
6854
|
}
|
|
6676
6855
|
}
|
|
@@ -6936,7 +7115,7 @@ function extractToolCallEnds(events) {
|
|
|
6936
7115
|
return result;
|
|
6937
7116
|
}
|
|
6938
7117
|
var FileSessionWriter = class _FileSessionWriter {
|
|
6939
|
-
constructor(id, handle, startedAt, meta, events, opts = {}) {
|
|
7118
|
+
constructor(id, handle, startedAt, meta, events, opts = {}, traceId) {
|
|
6940
7119
|
this.id = id;
|
|
6941
7120
|
this.handle = handle;
|
|
6942
7121
|
this.startedAt = startedAt;
|
|
@@ -6955,6 +7134,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
6955
7134
|
provider: meta.provider ?? "unknown",
|
|
6956
7135
|
tokenTotal: 0
|
|
6957
7136
|
};
|
|
7137
|
+
this.traceId = traceId;
|
|
6958
7138
|
}
|
|
6959
7139
|
id;
|
|
6960
7140
|
handle;
|
|
@@ -6987,6 +7167,8 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
6987
7167
|
lastAppendWarnAt = 0;
|
|
6988
7168
|
secretScrubber;
|
|
6989
7169
|
onCloseCb;
|
|
7170
|
+
/** Implements SessionWriter.traceId — propagated from ContextInit.traceId. */
|
|
7171
|
+
traceId;
|
|
6990
7172
|
// ── Write buffer — batches events to reduce per-event disk I/O ─────────
|
|
6991
7173
|
//
|
|
6992
7174
|
// Every append() pushes the scrubbed event into an in-memory buffer instead
|
|
@@ -7140,9 +7322,14 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
7140
7322
|
const eventCount = this.writeBuffer.length;
|
|
7141
7323
|
const batch = this.writeBuffer.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
7142
7324
|
this.writeBuffer = [];
|
|
7325
|
+
const t0 = Date.now();
|
|
7326
|
+
let outcome = "success";
|
|
7327
|
+
let errorMsg;
|
|
7143
7328
|
try {
|
|
7144
7329
|
await this.enqueueWrite(batch);
|
|
7145
7330
|
} catch (err) {
|
|
7331
|
+
outcome = "failure";
|
|
7332
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
7146
7333
|
this.appendFailCount += eventCount;
|
|
7147
7334
|
const now = Date.now();
|
|
7148
7335
|
if (now - this.lastAppendWarnAt > 5e3) {
|
|
@@ -7156,6 +7343,18 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
7156
7343
|
this.lastAppendWarnAt = now;
|
|
7157
7344
|
this.appendFailCount = 0;
|
|
7158
7345
|
}
|
|
7346
|
+
} finally {
|
|
7347
|
+
this.events?.emit("storage.write", {
|
|
7348
|
+
sessionId: this.id,
|
|
7349
|
+
store: "session",
|
|
7350
|
+
filePath: this.filePath,
|
|
7351
|
+
operation: "flush",
|
|
7352
|
+
outcome,
|
|
7353
|
+
durationMs: Date.now() - t0,
|
|
7354
|
+
...errorMsg !== void 0 ? { error: errorMsg } : {},
|
|
7355
|
+
...eventCount !== void 0 ? { eventCount } : {},
|
|
7356
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
7357
|
+
});
|
|
7159
7358
|
}
|
|
7160
7359
|
}
|
|
7161
7360
|
observeForSummary(event) {
|
|
@@ -7221,14 +7420,46 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
7221
7420
|
outcome: this.outcome ?? "completed"
|
|
7222
7421
|
};
|
|
7223
7422
|
if (this.manifestFile) {
|
|
7423
|
+
const t0 = Date.now();
|
|
7424
|
+
let outcome = "success";
|
|
7425
|
+
let errorMsg;
|
|
7224
7426
|
try {
|
|
7225
7427
|
await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 384 });
|
|
7226
|
-
} catch {
|
|
7428
|
+
} catch (err) {
|
|
7429
|
+
outcome = "failure";
|
|
7430
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
7431
|
+
} finally {
|
|
7432
|
+
this.events?.emit("storage.write", {
|
|
7433
|
+
sessionId: this.id,
|
|
7434
|
+
store: "session",
|
|
7435
|
+
filePath: this.manifestFile,
|
|
7436
|
+
operation: "close",
|
|
7437
|
+
outcome,
|
|
7438
|
+
durationMs: Date.now() - t0,
|
|
7439
|
+
...errorMsg !== void 0 ? { error: errorMsg } : {},
|
|
7440
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
7441
|
+
});
|
|
7227
7442
|
}
|
|
7228
7443
|
}
|
|
7444
|
+
const idxT0 = Date.now();
|
|
7445
|
+
let idxOutcome = "success";
|
|
7446
|
+
let idxError;
|
|
7229
7447
|
try {
|
|
7230
7448
|
await this.onCloseCb?.(this.summary);
|
|
7231
|
-
} catch {
|
|
7449
|
+
} catch (err) {
|
|
7450
|
+
idxOutcome = "failure";
|
|
7451
|
+
idxError = err instanceof Error ? err.message : String(err);
|
|
7452
|
+
} finally {
|
|
7453
|
+
this.events?.emit("storage.write", {
|
|
7454
|
+
sessionId: this.summary.id,
|
|
7455
|
+
store: "session",
|
|
7456
|
+
filePath: this.filePath,
|
|
7457
|
+
operation: "index_append",
|
|
7458
|
+
outcome: idxOutcome,
|
|
7459
|
+
durationMs: Date.now() - idxT0,
|
|
7460
|
+
...idxError !== void 0 ? { error: idxError } : {},
|
|
7461
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
7462
|
+
});
|
|
7232
7463
|
}
|
|
7233
7464
|
try {
|
|
7234
7465
|
await this.handle.close();
|
|
@@ -7390,23 +7621,81 @@ function userInputTitle(content) {
|
|
|
7390
7621
|
init_atomic_write();
|
|
7391
7622
|
var QueueStore = class {
|
|
7392
7623
|
file;
|
|
7624
|
+
// Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't
|
|
7625
|
+
// reject assigning an optional constructor parameter to these fields.
|
|
7626
|
+
events;
|
|
7627
|
+
traceId;
|
|
7393
7628
|
constructor(opts) {
|
|
7394
7629
|
this.file = path7.join(opts.dir, "queue.json");
|
|
7630
|
+
this.events = opts.events;
|
|
7631
|
+
this.traceId = opts.traceId;
|
|
7395
7632
|
}
|
|
7396
7633
|
async write(items) {
|
|
7634
|
+
const t0 = Date.now();
|
|
7397
7635
|
if (items.length === 0) {
|
|
7398
7636
|
await this.clear();
|
|
7399
7637
|
return;
|
|
7400
7638
|
}
|
|
7401
|
-
|
|
7639
|
+
try {
|
|
7640
|
+
await atomicWrite(this.file, JSON.stringify(items), { mode: 384 });
|
|
7641
|
+
this.events?.emit("storage.write", {
|
|
7642
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7643
|
+
store: "queue",
|
|
7644
|
+
filePath: this.file,
|
|
7645
|
+
operation: "write",
|
|
7646
|
+
outcome: "success",
|
|
7647
|
+
durationMs: Date.now() - t0,
|
|
7648
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7649
|
+
});
|
|
7650
|
+
} catch (err) {
|
|
7651
|
+
this.events?.emit("storage.error", {
|
|
7652
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7653
|
+
store: "queue",
|
|
7654
|
+
filePath: this.file,
|
|
7655
|
+
operation: "write",
|
|
7656
|
+
outcome: "failure",
|
|
7657
|
+
error: err instanceof Error ? err.message : String(err),
|
|
7658
|
+
recoverable: false,
|
|
7659
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7660
|
+
});
|
|
7661
|
+
console.warn(JSON.stringify({
|
|
7662
|
+
level: "warn",
|
|
7663
|
+
event: "queue_store.write_failed",
|
|
7664
|
+
path: this.file,
|
|
7665
|
+
message: err instanceof Error ? err.message : String(err),
|
|
7666
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
7667
|
+
}));
|
|
7668
|
+
}
|
|
7402
7669
|
}
|
|
7403
7670
|
async read() {
|
|
7671
|
+
const t0 = Date.now();
|
|
7404
7672
|
let raw;
|
|
7405
7673
|
try {
|
|
7406
7674
|
raw = await fsp3.readFile(this.file, "utf8");
|
|
7407
7675
|
} catch (err) {
|
|
7408
7676
|
const code = err.code;
|
|
7409
|
-
if (code === "ENOENT")
|
|
7677
|
+
if (code === "ENOENT") {
|
|
7678
|
+
this.events?.emit("storage.read", {
|
|
7679
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7680
|
+
store: "queue",
|
|
7681
|
+
filePath: this.file,
|
|
7682
|
+
operation: "read",
|
|
7683
|
+
outcome: "success",
|
|
7684
|
+
durationMs: Date.now() - t0,
|
|
7685
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7686
|
+
});
|
|
7687
|
+
return [];
|
|
7688
|
+
}
|
|
7689
|
+
this.events?.emit("storage.error", {
|
|
7690
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7691
|
+
store: "queue",
|
|
7692
|
+
filePath: this.file,
|
|
7693
|
+
operation: "read",
|
|
7694
|
+
outcome: "failure",
|
|
7695
|
+
error: err instanceof Error ? err.message : String(err),
|
|
7696
|
+
recoverable: true,
|
|
7697
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7698
|
+
});
|
|
7410
7699
|
console.warn(JSON.stringify({
|
|
7411
7700
|
level: "warn",
|
|
7412
7701
|
event: "queue_store.read_failed",
|
|
@@ -7420,9 +7709,40 @@ var QueueStore = class {
|
|
|
7420
7709
|
try {
|
|
7421
7710
|
parsed = JSON.parse(raw);
|
|
7422
7711
|
} catch {
|
|
7712
|
+
this.events?.emit("storage.read", {
|
|
7713
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7714
|
+
store: "queue",
|
|
7715
|
+
filePath: this.file,
|
|
7716
|
+
operation: "read",
|
|
7717
|
+
outcome: "failure",
|
|
7718
|
+
durationMs: Date.now() - t0,
|
|
7719
|
+
error: "parse_failed",
|
|
7720
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7721
|
+
});
|
|
7722
|
+
return [];
|
|
7723
|
+
}
|
|
7724
|
+
if (!Array.isArray(parsed)) {
|
|
7725
|
+
this.events?.emit("storage.read", {
|
|
7726
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7727
|
+
store: "queue",
|
|
7728
|
+
filePath: this.file,
|
|
7729
|
+
operation: "read",
|
|
7730
|
+
outcome: "failure",
|
|
7731
|
+
durationMs: Date.now() - t0,
|
|
7732
|
+
error: "invalid_schema",
|
|
7733
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7734
|
+
});
|
|
7423
7735
|
return [];
|
|
7424
7736
|
}
|
|
7425
|
-
|
|
7737
|
+
this.events?.emit("storage.read", {
|
|
7738
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7739
|
+
store: "queue",
|
|
7740
|
+
filePath: this.file,
|
|
7741
|
+
operation: "read",
|
|
7742
|
+
outcome: "success",
|
|
7743
|
+
durationMs: Date.now() - t0,
|
|
7744
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7745
|
+
});
|
|
7426
7746
|
const out = [];
|
|
7427
7747
|
for (const v of parsed) {
|
|
7428
7748
|
if (isPersistedQueueItem(v)) out.push(v);
|
|
@@ -7430,11 +7750,31 @@ var QueueStore = class {
|
|
|
7430
7750
|
return out;
|
|
7431
7751
|
}
|
|
7432
7752
|
async clear() {
|
|
7753
|
+
const t0 = Date.now();
|
|
7433
7754
|
try {
|
|
7434
7755
|
await fsp3.unlink(this.file);
|
|
7756
|
+
this.events?.emit("storage.write", {
|
|
7757
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7758
|
+
store: "queue",
|
|
7759
|
+
filePath: this.file,
|
|
7760
|
+
operation: "clear",
|
|
7761
|
+
outcome: "success",
|
|
7762
|
+
durationMs: Date.now() - t0,
|
|
7763
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7764
|
+
});
|
|
7435
7765
|
} catch (err) {
|
|
7436
7766
|
const code = err.code;
|
|
7437
7767
|
if (code === "ENOENT") return;
|
|
7768
|
+
this.events?.emit("storage.error", {
|
|
7769
|
+
sessionId: this.traceId ?? "~boot~",
|
|
7770
|
+
store: "queue",
|
|
7771
|
+
filePath: this.file,
|
|
7772
|
+
operation: "clear",
|
|
7773
|
+
outcome: "failure",
|
|
7774
|
+
error: err instanceof Error ? err.message : String(err),
|
|
7775
|
+
recoverable: true,
|
|
7776
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
7777
|
+
});
|
|
7438
7778
|
console.warn(JSON.stringify({
|
|
7439
7779
|
level: "warn",
|
|
7440
7780
|
event: "queue_store.clear_failed",
|
|
@@ -7809,6 +8149,7 @@ var MAX_BYTES_TOTAL = 32e3;
|
|
|
7809
8149
|
var DefaultMemoryStore = class {
|
|
7810
8150
|
files;
|
|
7811
8151
|
events;
|
|
8152
|
+
traceId;
|
|
7812
8153
|
backend;
|
|
7813
8154
|
/**
|
|
7814
8155
|
* Per-scope serialization queue. `remember` / `forget` / `consolidate` /
|
|
@@ -7874,15 +8215,70 @@ var DefaultMemoryStore = class {
|
|
|
7874
8215
|
if (writeErr2) {
|
|
7875
8216
|
parts.push(`> \u26A0\uFE0F Memory write error (${labelOf(scope)}): ${writeErr2.message}`);
|
|
7876
8217
|
}
|
|
7877
|
-
const
|
|
7878
|
-
|
|
8218
|
+
const t0 = Date.now();
|
|
8219
|
+
const filePath = this.files[scope];
|
|
8220
|
+
try {
|
|
8221
|
+
const body = await this.backend.readAll(scope, filePath);
|
|
8222
|
+
const dur = Date.now() - t0;
|
|
8223
|
+
this.events?.emit("storage.read", {
|
|
8224
|
+
sessionId: "~memory~",
|
|
8225
|
+
store: "memory",
|
|
8226
|
+
filePath,
|
|
8227
|
+
operation: "readAll",
|
|
8228
|
+
outcome: "success",
|
|
8229
|
+
durationMs: dur,
|
|
8230
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8231
|
+
});
|
|
8232
|
+
if (body.trim()) parts.push(`## ${labelOf(scope)}
|
|
7879
8233
|
|
|
7880
8234
|
${body.trim()}`);
|
|
8235
|
+
} catch (err) {
|
|
8236
|
+
const dur = Date.now() - t0;
|
|
8237
|
+
this.events?.emit("storage.read", {
|
|
8238
|
+
sessionId: "~memory~",
|
|
8239
|
+
store: "memory",
|
|
8240
|
+
filePath,
|
|
8241
|
+
operation: "readAll",
|
|
8242
|
+
outcome: "failure",
|
|
8243
|
+
durationMs: dur,
|
|
8244
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8245
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8246
|
+
});
|
|
8247
|
+
throw err;
|
|
8248
|
+
}
|
|
7881
8249
|
}
|
|
7882
8250
|
return parts.join("\n\n");
|
|
7883
8251
|
}
|
|
7884
8252
|
async read(scope) {
|
|
7885
|
-
|
|
8253
|
+
const t0 = Date.now();
|
|
8254
|
+
const filePath = this.files[scope];
|
|
8255
|
+
try {
|
|
8256
|
+
const body = await this.backend.readAll(scope, filePath);
|
|
8257
|
+
const dur = Date.now() - t0;
|
|
8258
|
+
this.events?.emit("storage.read", {
|
|
8259
|
+
sessionId: "~memory~",
|
|
8260
|
+
store: "memory",
|
|
8261
|
+
filePath,
|
|
8262
|
+
operation: "read",
|
|
8263
|
+
outcome: "success",
|
|
8264
|
+
durationMs: dur,
|
|
8265
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8266
|
+
});
|
|
8267
|
+
return body;
|
|
8268
|
+
} catch (err) {
|
|
8269
|
+
const dur = Date.now() - t0;
|
|
8270
|
+
this.events?.emit("storage.read", {
|
|
8271
|
+
sessionId: "~memory~",
|
|
8272
|
+
store: "memory",
|
|
8273
|
+
filePath,
|
|
8274
|
+
operation: "read",
|
|
8275
|
+
outcome: "failure",
|
|
8276
|
+
durationMs: dur,
|
|
8277
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8278
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8279
|
+
});
|
|
8280
|
+
throw err;
|
|
8281
|
+
}
|
|
7886
8282
|
}
|
|
7887
8283
|
/**
|
|
7888
8284
|
* List entries from a scope, newest first. Delegates to the backend
|
|
@@ -7908,7 +8304,34 @@ ${body.trim()}`);
|
|
|
7908
8304
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
7909
8305
|
return this.runSerialized(scope, async () => {
|
|
7910
8306
|
const entry = { scope, text, ts, ...metadata };
|
|
7911
|
-
|
|
8307
|
+
const filePath = this.files[scope];
|
|
8308
|
+
const t0 = Date.now();
|
|
8309
|
+
try {
|
|
8310
|
+
await this.backend.remember(scope, entry, filePath);
|
|
8311
|
+
const dur = Date.now() - t0;
|
|
8312
|
+
this.events?.emit("storage.write", {
|
|
8313
|
+
sessionId: "~memory~",
|
|
8314
|
+
store: "memory",
|
|
8315
|
+
filePath,
|
|
8316
|
+
operation: "remember",
|
|
8317
|
+
outcome: "success",
|
|
8318
|
+
durationMs: dur,
|
|
8319
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8320
|
+
});
|
|
8321
|
+
} catch (err) {
|
|
8322
|
+
const dur = Date.now() - t0;
|
|
8323
|
+
this.events?.emit("storage.write", {
|
|
8324
|
+
sessionId: "~memory~",
|
|
8325
|
+
store: "memory",
|
|
8326
|
+
filePath,
|
|
8327
|
+
operation: "remember",
|
|
8328
|
+
outcome: "failure",
|
|
8329
|
+
durationMs: dur,
|
|
8330
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8331
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8332
|
+
});
|
|
8333
|
+
throw err;
|
|
8334
|
+
}
|
|
7912
8335
|
const raw = await this.backend.readAll(scope, this.files[scope]);
|
|
7913
8336
|
if (Buffer.byteLength(raw, "utf8") > MAX_BYTES_TOTAL) {
|
|
7914
8337
|
const removed = await this.backend.consolidate(scope, this.files[scope]);
|
|
@@ -8036,7 +8459,35 @@ ${body.trim()}`);
|
|
|
8036
8459
|
}
|
|
8037
8460
|
async forget(query, scope = "project-memory") {
|
|
8038
8461
|
return this.runSerialized(scope, async () => {
|
|
8039
|
-
const
|
|
8462
|
+
const filePath = this.files[scope];
|
|
8463
|
+
const t0 = Date.now();
|
|
8464
|
+
let removed = 0;
|
|
8465
|
+
try {
|
|
8466
|
+
removed = await this.backend.forget(scope, query, filePath);
|
|
8467
|
+
const dur = Date.now() - t0;
|
|
8468
|
+
this.events?.emit("storage.write", {
|
|
8469
|
+
sessionId: "~memory~",
|
|
8470
|
+
store: "memory",
|
|
8471
|
+
filePath,
|
|
8472
|
+
operation: "forget",
|
|
8473
|
+
outcome: "success",
|
|
8474
|
+
durationMs: dur,
|
|
8475
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8476
|
+
});
|
|
8477
|
+
} catch (err) {
|
|
8478
|
+
const dur = Date.now() - t0;
|
|
8479
|
+
this.events?.emit("storage.write", {
|
|
8480
|
+
sessionId: "~memory~",
|
|
8481
|
+
store: "memory",
|
|
8482
|
+
filePath,
|
|
8483
|
+
operation: "forget",
|
|
8484
|
+
outcome: "failure",
|
|
8485
|
+
durationMs: dur,
|
|
8486
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8487
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8488
|
+
});
|
|
8489
|
+
throw err;
|
|
8490
|
+
}
|
|
8040
8491
|
if (removed > 0) {
|
|
8041
8492
|
this.events?.emit("memory.forgotten", {
|
|
8042
8493
|
scope,
|
|
@@ -8050,7 +8501,35 @@ ${body.trim()}`);
|
|
|
8050
8501
|
}
|
|
8051
8502
|
async consolidate(scope) {
|
|
8052
8503
|
return this.runSerialized(scope, async () => {
|
|
8053
|
-
const
|
|
8504
|
+
const filePath = this.files[scope];
|
|
8505
|
+
const t0 = Date.now();
|
|
8506
|
+
let removed = 0;
|
|
8507
|
+
try {
|
|
8508
|
+
removed = await this.backend.consolidate(scope, filePath);
|
|
8509
|
+
const dur = Date.now() - t0;
|
|
8510
|
+
this.events?.emit("storage.write", {
|
|
8511
|
+
sessionId: "~memory~",
|
|
8512
|
+
store: "memory",
|
|
8513
|
+
filePath,
|
|
8514
|
+
operation: "consolidate",
|
|
8515
|
+
outcome: "success",
|
|
8516
|
+
durationMs: dur,
|
|
8517
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8518
|
+
});
|
|
8519
|
+
} catch (err) {
|
|
8520
|
+
const dur = Date.now() - t0;
|
|
8521
|
+
this.events?.emit("storage.write", {
|
|
8522
|
+
sessionId: "~memory~",
|
|
8523
|
+
store: "memory",
|
|
8524
|
+
filePath,
|
|
8525
|
+
operation: "consolidate",
|
|
8526
|
+
outcome: "failure",
|
|
8527
|
+
durationMs: dur,
|
|
8528
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8529
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8530
|
+
});
|
|
8531
|
+
throw err;
|
|
8532
|
+
}
|
|
8054
8533
|
if (removed > 0) {
|
|
8055
8534
|
this.events?.emit("memory.consolidated", {
|
|
8056
8535
|
scope,
|
|
@@ -8063,7 +8542,34 @@ ${body.trim()}`);
|
|
|
8063
8542
|
async clear(scope) {
|
|
8064
8543
|
if (scope) {
|
|
8065
8544
|
await this.runSerialized(scope, async () => {
|
|
8066
|
-
|
|
8545
|
+
const filePath = this.files[scope];
|
|
8546
|
+
const t0 = Date.now();
|
|
8547
|
+
try {
|
|
8548
|
+
await this.backend.clear(scope, filePath);
|
|
8549
|
+
const dur = Date.now() - t0;
|
|
8550
|
+
this.events?.emit("storage.write", {
|
|
8551
|
+
sessionId: "~memory~",
|
|
8552
|
+
store: "memory",
|
|
8553
|
+
filePath,
|
|
8554
|
+
operation: "clear",
|
|
8555
|
+
outcome: "success",
|
|
8556
|
+
durationMs: dur,
|
|
8557
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8558
|
+
});
|
|
8559
|
+
} catch (err) {
|
|
8560
|
+
const dur = Date.now() - t0;
|
|
8561
|
+
this.events?.emit("storage.write", {
|
|
8562
|
+
sessionId: "~memory~",
|
|
8563
|
+
store: "memory",
|
|
8564
|
+
filePath,
|
|
8565
|
+
operation: "clear",
|
|
8566
|
+
outcome: "failure",
|
|
8567
|
+
durationMs: dur,
|
|
8568
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8569
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8570
|
+
});
|
|
8571
|
+
throw err;
|
|
8572
|
+
}
|
|
8067
8573
|
this.events?.emit("memory.cleared", { scope });
|
|
8068
8574
|
await this.mirrorBackup(scope);
|
|
8069
8575
|
});
|
|
@@ -8071,15 +8577,54 @@ ${body.trim()}`);
|
|
|
8071
8577
|
}
|
|
8072
8578
|
await Promise.all(
|
|
8073
8579
|
["project-agents", "project-memory", "user-memory"].map(
|
|
8074
|
-
(s) => this.runSerialized(s, async () => {
|
|
8075
|
-
|
|
8580
|
+
async (s) => this.runSerialized(s, async () => {
|
|
8581
|
+
const filePath = this.files[s];
|
|
8582
|
+
const t0 = Date.now();
|
|
8583
|
+
try {
|
|
8584
|
+
await this.backend.clear(s, filePath);
|
|
8585
|
+
const dur = Date.now() - t0;
|
|
8586
|
+
this.events?.emit("storage.write", {
|
|
8587
|
+
sessionId: "~memory~",
|
|
8588
|
+
store: "memory",
|
|
8589
|
+
filePath,
|
|
8590
|
+
operation: "clear",
|
|
8591
|
+
outcome: "success",
|
|
8592
|
+
durationMs: dur,
|
|
8593
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8594
|
+
});
|
|
8595
|
+
} catch (err) {
|
|
8596
|
+
const dur = Date.now() - t0;
|
|
8597
|
+
this.events?.emit("storage.write", {
|
|
8598
|
+
sessionId: "~memory~",
|
|
8599
|
+
store: "memory",
|
|
8600
|
+
filePath,
|
|
8601
|
+
operation: "clear",
|
|
8602
|
+
outcome: "failure",
|
|
8603
|
+
durationMs: dur,
|
|
8604
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8605
|
+
...this.traceId !== void 0 && { traceId: this.traceId }
|
|
8606
|
+
});
|
|
8607
|
+
throw err;
|
|
8608
|
+
}
|
|
8076
8609
|
this.events?.emit("memory.cleared", { scope: s });
|
|
8077
8610
|
await this.mirrorBackup(s);
|
|
8078
8611
|
})
|
|
8079
8612
|
)
|
|
8080
8613
|
);
|
|
8081
8614
|
}
|
|
8082
|
-
/**
|
|
8615
|
+
/**
|
|
8616
|
+
* Return a new MemoryStore proxy that carries `traceId` on every storage
|
|
8617
|
+
* event. The original store is left unchanged — callers that need a
|
|
8618
|
+
* trace-decorated view (e.g. session-run tools) receive the proxy while
|
|
8619
|
+
* the singleton remains trace-free for boot-time use.
|
|
8620
|
+
*
|
|
8621
|
+
* The proxy implements the full `MemoryStore` interface; all other
|
|
8622
|
+
* properties (backend, etc.) are delegated to the original store.
|
|
8623
|
+
*/
|
|
8624
|
+
withTraceId(traceId) {
|
|
8625
|
+
this.traceId = traceId;
|
|
8626
|
+
return this;
|
|
8627
|
+
}
|
|
8083
8628
|
async mirrorBackup(scope) {
|
|
8084
8629
|
if (!this.persistBackup || scope === "project-agents") return;
|
|
8085
8630
|
try {
|
|
@@ -8173,6 +8718,13 @@ function deepFreeze(obj) {
|
|
|
8173
8718
|
return Object.freeze(obj);
|
|
8174
8719
|
}
|
|
8175
8720
|
init_atomic_write();
|
|
8721
|
+
function storageErrorString(err) {
|
|
8722
|
+
if (err instanceof Error) {
|
|
8723
|
+
const code = err.code;
|
|
8724
|
+
return code ? `${code}: ${err.message}` : err.message;
|
|
8725
|
+
}
|
|
8726
|
+
return String(err);
|
|
8727
|
+
}
|
|
8176
8728
|
var BEHAVIOR_DEFAULTS = {
|
|
8177
8729
|
version: 1,
|
|
8178
8730
|
context: {
|
|
@@ -8275,11 +8827,15 @@ var DefaultConfigLoader = class {
|
|
|
8275
8827
|
strict;
|
|
8276
8828
|
vault;
|
|
8277
8829
|
extraSources;
|
|
8830
|
+
events;
|
|
8831
|
+
traceId;
|
|
8278
8832
|
constructor(opts) {
|
|
8279
8833
|
this.paths = opts.paths;
|
|
8280
8834
|
this.strict = opts.strict ?? false;
|
|
8281
8835
|
this.vault = opts.vault;
|
|
8282
8836
|
this.extraSources = opts.sources ?? [];
|
|
8837
|
+
this.events = opts.events;
|
|
8838
|
+
this.traceId = opts.traceId;
|
|
8283
8839
|
}
|
|
8284
8840
|
async load(opts = {}) {
|
|
8285
8841
|
let cfg = { ...BEHAVIOR_DEFAULTS };
|
|
@@ -8356,7 +8912,33 @@ var DefaultConfigLoader = class {
|
|
|
8356
8912
|
if (this.vault && toWrite.githubToken && !toWrite.githubToken.startsWith("enc:")) {
|
|
8357
8913
|
toWrite = { ...toWrite, githubToken: this.vault.encrypt(toWrite.githubToken) };
|
|
8358
8914
|
}
|
|
8359
|
-
|
|
8915
|
+
const fp = this.paths.syncConfig;
|
|
8916
|
+
const t0 = Date.now();
|
|
8917
|
+
try {
|
|
8918
|
+
await atomicWrite(fp, JSON.stringify(toWrite, null, 2), { mode: 384 });
|
|
8919
|
+
this.events?.emit("storage.write", {
|
|
8920
|
+
sessionId: "~config~",
|
|
8921
|
+
store: "config",
|
|
8922
|
+
filePath: fp,
|
|
8923
|
+
operation: "persist_sync",
|
|
8924
|
+
outcome: "success",
|
|
8925
|
+
durationMs: Date.now() - t0,
|
|
8926
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
8927
|
+
});
|
|
8928
|
+
} catch (err) {
|
|
8929
|
+
this.events?.emit("storage.error", {
|
|
8930
|
+
sessionId: "~config~",
|
|
8931
|
+
store: "config",
|
|
8932
|
+
filePath: fp,
|
|
8933
|
+
operation: "persist_sync",
|
|
8934
|
+
outcome: "failure",
|
|
8935
|
+
error: storageErrorString(err),
|
|
8936
|
+
recoverable: false,
|
|
8937
|
+
durationMs: Date.now() - t0,
|
|
8938
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
8939
|
+
});
|
|
8940
|
+
throw err;
|
|
8941
|
+
}
|
|
8360
8942
|
}
|
|
8361
8943
|
/**
|
|
8362
8944
|
* Read ~/.wrongstack/sync.json (encrypted GitHub token storage) and decrypt
|
|
@@ -8365,17 +8947,60 @@ var DefaultConfigLoader = class {
|
|
|
8365
8947
|
* isolated — it should never be part of project-local or env-driven config.
|
|
8366
8948
|
*/
|
|
8367
8949
|
async loadSyncConfig() {
|
|
8950
|
+
const fp = this.paths.syncConfig;
|
|
8951
|
+
const t0 = Date.now();
|
|
8368
8952
|
try {
|
|
8369
|
-
const raw = await fsp3.readFile(
|
|
8953
|
+
const raw = await fsp3.readFile(fp, "utf8");
|
|
8370
8954
|
const parsed = safeParse(raw);
|
|
8371
|
-
if (!parsed.ok || !parsed.value)
|
|
8955
|
+
if (!parsed.ok || !parsed.value) {
|
|
8956
|
+
this.events?.emit("storage.read", {
|
|
8957
|
+
sessionId: "~config~",
|
|
8958
|
+
store: "config",
|
|
8959
|
+
filePath: fp,
|
|
8960
|
+
operation: "load_sync",
|
|
8961
|
+
outcome: "failure",
|
|
8962
|
+
durationMs: Date.now() - t0,
|
|
8963
|
+
error: "parse error or empty file",
|
|
8964
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
8965
|
+
});
|
|
8966
|
+
return null;
|
|
8967
|
+
}
|
|
8372
8968
|
if (this.vault) {
|
|
8373
8969
|
const decrypted = decryptConfigSecrets({ sync: parsed.value }, this.vault);
|
|
8374
|
-
|
|
8970
|
+
const result = decrypted.sync ?? null;
|
|
8971
|
+
this.events?.emit("storage.read", {
|
|
8972
|
+
sessionId: "~config~",
|
|
8973
|
+
store: "config",
|
|
8974
|
+
filePath: fp,
|
|
8975
|
+
operation: "load_sync",
|
|
8976
|
+
outcome: "success",
|
|
8977
|
+
durationMs: Date.now() - t0,
|
|
8978
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
8979
|
+
});
|
|
8980
|
+
return result;
|
|
8375
8981
|
}
|
|
8982
|
+
this.events?.emit("storage.read", {
|
|
8983
|
+
sessionId: "~config~",
|
|
8984
|
+
store: "config",
|
|
8985
|
+
filePath: fp,
|
|
8986
|
+
operation: "load_sync",
|
|
8987
|
+
outcome: "success",
|
|
8988
|
+
durationMs: Date.now() - t0,
|
|
8989
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
8990
|
+
});
|
|
8376
8991
|
return parsed.value;
|
|
8377
8992
|
} catch (err) {
|
|
8378
8993
|
if (err.code === "ENOENT") return null;
|
|
8994
|
+
this.events?.emit("storage.read", {
|
|
8995
|
+
sessionId: "~config~",
|
|
8996
|
+
store: "config",
|
|
8997
|
+
filePath: fp,
|
|
8998
|
+
operation: "load_sync",
|
|
8999
|
+
outcome: "failure",
|
|
9000
|
+
durationMs: Date.now() - t0,
|
|
9001
|
+
error: storageErrorString(err),
|
|
9002
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
9003
|
+
});
|
|
8379
9004
|
console.warn(JSON.stringify({
|
|
8380
9005
|
level: "warn",
|
|
8381
9006
|
event: "config.sync_load_failed",
|
|
@@ -8387,10 +9012,21 @@ var DefaultConfigLoader = class {
|
|
|
8387
9012
|
}
|
|
8388
9013
|
async readJson(file) {
|
|
8389
9014
|
let raw;
|
|
9015
|
+
const t0 = Date.now();
|
|
8390
9016
|
try {
|
|
8391
9017
|
raw = await fsp3.readFile(file, "utf8");
|
|
8392
9018
|
} catch (err) {
|
|
8393
9019
|
if (err.code !== "ENOENT") {
|
|
9020
|
+
this.events?.emit("storage.read", {
|
|
9021
|
+
sessionId: "~config~",
|
|
9022
|
+
store: "config",
|
|
9023
|
+
filePath: file,
|
|
9024
|
+
operation: "read_json",
|
|
9025
|
+
outcome: "failure",
|
|
9026
|
+
durationMs: Date.now() - t0,
|
|
9027
|
+
error: storageErrorString(err),
|
|
9028
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
9029
|
+
});
|
|
8394
9030
|
console.warn(JSON.stringify({
|
|
8395
9031
|
level: "warn",
|
|
8396
9032
|
event: "config.read_failed",
|
|
@@ -8403,6 +9039,16 @@ var DefaultConfigLoader = class {
|
|
|
8403
9039
|
}
|
|
8404
9040
|
const parsed = safeParse(raw);
|
|
8405
9041
|
if (!parsed.ok || !parsed.value) {
|
|
9042
|
+
this.events?.emit("storage.read", {
|
|
9043
|
+
sessionId: "~config~",
|
|
9044
|
+
store: "config",
|
|
9045
|
+
filePath: file,
|
|
9046
|
+
operation: "read_json",
|
|
9047
|
+
outcome: "failure",
|
|
9048
|
+
durationMs: Date.now() - t0,
|
|
9049
|
+
error: "parse error or empty file",
|
|
9050
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
9051
|
+
});
|
|
8406
9052
|
console.warn(JSON.stringify({
|
|
8407
9053
|
level: "warn",
|
|
8408
9054
|
event: "config.parse_failed",
|
|
@@ -8878,24 +9524,66 @@ function resolveSessionLoggingConfig(cfg) {
|
|
|
8878
9524
|
|
|
8879
9525
|
// src/storage/todos-checkpoint.ts
|
|
8880
9526
|
init_atomic_write();
|
|
8881
|
-
async function loadTodosCheckpoint(filePath) {
|
|
9527
|
+
async function loadTodosCheckpoint(filePath, events, traceId) {
|
|
9528
|
+
const t0 = Date.now();
|
|
8882
9529
|
let raw;
|
|
8883
9530
|
try {
|
|
8884
9531
|
raw = await fsp3.readFile(filePath, "utf8");
|
|
8885
|
-
} catch {
|
|
9532
|
+
} catch (err) {
|
|
9533
|
+
events?.emit("storage.error", {
|
|
9534
|
+
sessionId: traceId ?? "~boot~",
|
|
9535
|
+
store: "todos",
|
|
9536
|
+
filePath,
|
|
9537
|
+
operation: "load",
|
|
9538
|
+
outcome: "failure",
|
|
9539
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9540
|
+
recoverable: true
|
|
9541
|
+
});
|
|
8886
9542
|
return null;
|
|
8887
9543
|
}
|
|
8888
9544
|
try {
|
|
8889
9545
|
const parsed = JSON.parse(raw);
|
|
8890
|
-
if (parsed?.version !== 1 || !Array.isArray(parsed.todos))
|
|
9546
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) {
|
|
9547
|
+
events?.emit("storage.read", {
|
|
9548
|
+
sessionId: traceId ?? "~boot~",
|
|
9549
|
+
store: "todos",
|
|
9550
|
+
filePath,
|
|
9551
|
+
operation: "load",
|
|
9552
|
+
outcome: "failure",
|
|
9553
|
+
durationMs: Date.now() - t0,
|
|
9554
|
+
error: "invalid_schema",
|
|
9555
|
+
...traceId !== void 0 && { traceId }
|
|
9556
|
+
});
|
|
9557
|
+
return null;
|
|
9558
|
+
}
|
|
9559
|
+
events?.emit("storage.read", {
|
|
9560
|
+
sessionId: traceId ?? "~boot~",
|
|
9561
|
+
store: "todos",
|
|
9562
|
+
filePath,
|
|
9563
|
+
operation: "load",
|
|
9564
|
+
outcome: "success",
|
|
9565
|
+
durationMs: Date.now() - t0,
|
|
9566
|
+
...traceId !== void 0 && { traceId }
|
|
9567
|
+
});
|
|
8891
9568
|
return parsed.todos.filter(
|
|
8892
9569
|
(t2) => !!t2 && typeof t2.id === "string" && typeof t2.content === "string" && typeof t2.status === "string" && (t2.activeForm === void 0 || typeof t2.activeForm === "string")
|
|
8893
9570
|
);
|
|
8894
9571
|
} catch {
|
|
9572
|
+
events?.emit("storage.read", {
|
|
9573
|
+
sessionId: traceId ?? "~boot~",
|
|
9574
|
+
store: "todos",
|
|
9575
|
+
filePath,
|
|
9576
|
+
operation: "load",
|
|
9577
|
+
outcome: "failure",
|
|
9578
|
+
durationMs: Date.now() - t0,
|
|
9579
|
+
error: "parse_failed",
|
|
9580
|
+
...traceId !== void 0 && { traceId }
|
|
9581
|
+
});
|
|
8895
9582
|
return null;
|
|
8896
9583
|
}
|
|
8897
9584
|
}
|
|
8898
|
-
async function saveTodosCheckpoint(filePath, sessionId, todos) {
|
|
9585
|
+
async function saveTodosCheckpoint(filePath, sessionId, todos, events, traceId) {
|
|
9586
|
+
const t0 = Date.now();
|
|
8899
9587
|
const payload = {
|
|
8900
9588
|
version: 1,
|
|
8901
9589
|
sessionId,
|
|
@@ -8904,7 +9592,25 @@ async function saveTodosCheckpoint(filePath, sessionId, todos) {
|
|
|
8904
9592
|
};
|
|
8905
9593
|
try {
|
|
8906
9594
|
await atomicWrite(filePath, JSON.stringify(payload, null, 2), { mode: 384 });
|
|
9595
|
+
events?.emit("storage.write", {
|
|
9596
|
+
sessionId: traceId ?? sessionId,
|
|
9597
|
+
store: "todos",
|
|
9598
|
+
filePath,
|
|
9599
|
+
operation: "save",
|
|
9600
|
+
outcome: "success",
|
|
9601
|
+
durationMs: Date.now() - t0,
|
|
9602
|
+
...traceId !== void 0 && { traceId }
|
|
9603
|
+
});
|
|
8907
9604
|
} catch (err) {
|
|
9605
|
+
events?.emit("storage.error", {
|
|
9606
|
+
sessionId: traceId ?? sessionId,
|
|
9607
|
+
store: "todos",
|
|
9608
|
+
filePath,
|
|
9609
|
+
operation: "save",
|
|
9610
|
+
outcome: "failure",
|
|
9611
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9612
|
+
recoverable: false
|
|
9613
|
+
});
|
|
8908
9614
|
console.warn(JSON.stringify({
|
|
8909
9615
|
level: "warn",
|
|
8910
9616
|
event: "todos_checkpoint.save_failed",
|
|
@@ -8913,12 +9619,12 @@ async function saveTodosCheckpoint(filePath, sessionId, todos) {
|
|
|
8913
9619
|
}));
|
|
8914
9620
|
}
|
|
8915
9621
|
}
|
|
8916
|
-
function attachTodosCheckpoint(state, filePath, sessionId) {
|
|
9622
|
+
function attachTodosCheckpoint(state, filePath, sessionId, events, traceId) {
|
|
8917
9623
|
let timer = null;
|
|
8918
9624
|
let pending = null;
|
|
8919
9625
|
let writeChain = Promise.resolve();
|
|
8920
9626
|
const enqueueWrite = (todos) => {
|
|
8921
|
-
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos)).catch((err) => {
|
|
9627
|
+
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos, events, traceId)).catch((err) => {
|
|
8922
9628
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8923
9629
|
console.error(JSON.stringify({
|
|
8924
9630
|
level: "error",
|
|
@@ -8960,25 +9666,79 @@ function attachTodosCheckpoint(state, filePath, sessionId) {
|
|
|
8960
9666
|
|
|
8961
9667
|
// src/storage/plan-store.ts
|
|
8962
9668
|
init_atomic_write();
|
|
8963
|
-
async function loadPlan(filePath) {
|
|
9669
|
+
async function loadPlan(filePath, events) {
|
|
9670
|
+
const t0 = Date.now();
|
|
8964
9671
|
let raw;
|
|
8965
9672
|
try {
|
|
8966
9673
|
raw = await fsp3.readFile(filePath, "utf8");
|
|
8967
|
-
} catch {
|
|
9674
|
+
} catch (err) {
|
|
9675
|
+
events?.emit("storage.error", {
|
|
9676
|
+
sessionId: "~boot~",
|
|
9677
|
+
store: "plan",
|
|
9678
|
+
filePath,
|
|
9679
|
+
operation: "load",
|
|
9680
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9681
|
+
recoverable: true
|
|
9682
|
+
});
|
|
8968
9683
|
return null;
|
|
8969
9684
|
}
|
|
8970
9685
|
try {
|
|
8971
9686
|
const parsed = JSON.parse(raw);
|
|
8972
|
-
if (parsed?.version !== 1 || !Array.isArray(parsed.items))
|
|
9687
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.items)) {
|
|
9688
|
+
events?.emit("storage.read", {
|
|
9689
|
+
sessionId: "~boot~",
|
|
9690
|
+
store: "plan",
|
|
9691
|
+
filePath,
|
|
9692
|
+
operation: "load",
|
|
9693
|
+
outcome: "failure",
|
|
9694
|
+
durationMs: Date.now() - t0,
|
|
9695
|
+
error: "invalid_schema"
|
|
9696
|
+
});
|
|
9697
|
+
return null;
|
|
9698
|
+
}
|
|
9699
|
+
events?.emit("storage.read", {
|
|
9700
|
+
sessionId: "~boot~",
|
|
9701
|
+
store: "plan",
|
|
9702
|
+
filePath,
|
|
9703
|
+
operation: "load",
|
|
9704
|
+
outcome: "success",
|
|
9705
|
+
durationMs: Date.now() - t0
|
|
9706
|
+
});
|
|
8973
9707
|
return parsed;
|
|
8974
9708
|
} catch {
|
|
9709
|
+
events?.emit("storage.read", {
|
|
9710
|
+
sessionId: "~boot~",
|
|
9711
|
+
store: "plan",
|
|
9712
|
+
filePath,
|
|
9713
|
+
operation: "load",
|
|
9714
|
+
outcome: "failure",
|
|
9715
|
+
durationMs: Date.now() - t0,
|
|
9716
|
+
error: "parse_failed"
|
|
9717
|
+
});
|
|
8975
9718
|
return null;
|
|
8976
9719
|
}
|
|
8977
9720
|
}
|
|
8978
|
-
async function savePlan(filePath, plan) {
|
|
9721
|
+
async function savePlan(filePath, plan, events) {
|
|
9722
|
+
const t0 = Date.now();
|
|
8979
9723
|
try {
|
|
8980
9724
|
await atomicWrite(filePath, JSON.stringify(plan, null, 2), { mode: 384 });
|
|
9725
|
+
events?.emit("storage.write", {
|
|
9726
|
+
sessionId: "~boot~",
|
|
9727
|
+
store: "plan",
|
|
9728
|
+
filePath,
|
|
9729
|
+
operation: "save",
|
|
9730
|
+
outcome: "success",
|
|
9731
|
+
durationMs: Date.now() - t0
|
|
9732
|
+
});
|
|
8981
9733
|
} catch (err) {
|
|
9734
|
+
events?.emit("storage.error", {
|
|
9735
|
+
sessionId: "~boot~",
|
|
9736
|
+
store: "plan",
|
|
9737
|
+
filePath,
|
|
9738
|
+
operation: "save",
|
|
9739
|
+
error: err instanceof Error ? err.message : String(err),
|
|
9740
|
+
recoverable: false
|
|
9741
|
+
});
|
|
8982
9742
|
console.warn(
|
|
8983
9743
|
"[plan-store] save failed:",
|
|
8984
9744
|
err instanceof Error ? err.message : String(err)
|
|
@@ -9662,7 +10422,16 @@ var DefaultPermissionPolicy = class {
|
|
|
9662
10422
|
};
|
|
9663
10423
|
}
|
|
9664
10424
|
}
|
|
9665
|
-
|
|
10425
|
+
const hasWriteCap = hasCapability(tool, ToolCapabilities.FS_WRITE);
|
|
10426
|
+
const hasShellCap = hasCapability(tool, [
|
|
10427
|
+
ToolCapabilities.SHELL_ARBITRARY,
|
|
10428
|
+
ToolCapabilities.SHELL_RESTRICTED
|
|
10429
|
+
]);
|
|
10430
|
+
const hasInstallCap = hasCapability(tool, ToolCapabilities.PACKAGE_INSTALL);
|
|
10431
|
+
const hasConfigCap = hasCapability(tool, ToolCapabilities.CONFIG_MUTATE);
|
|
10432
|
+
const hasSubagentCap = hasCapability(tool, ToolCapabilities.SUBAGENT_SPAWN);
|
|
10433
|
+
const isMutating = tool.mutating || hasWriteCap || hasShellCap || hasInstallCap || hasConfigCap || hasSubagentCap;
|
|
10434
|
+
if (tool.permission === "auto" && !isMutating) {
|
|
9666
10435
|
const decision = { permission: "auto", source: "default" };
|
|
9667
10436
|
this._evalCache.set(cacheKey, decision);
|
|
9668
10437
|
return decision;
|
|
@@ -9681,7 +10450,27 @@ var DefaultPermissionPolicy = class {
|
|
|
9681
10450
|
}
|
|
9682
10451
|
return { permission: "confirm", source: "default" };
|
|
9683
10452
|
}
|
|
10453
|
+
// Capability-based destructive check (preferred over name-based)
|
|
10454
|
+
isDestructiveByCapability(tool) {
|
|
10455
|
+
const caps = tool.capabilities ?? [];
|
|
10456
|
+
if (caps.includes("shell.arbitrary")) return true;
|
|
10457
|
+
if (caps.includes("fs.write")) return true;
|
|
10458
|
+
if (caps.includes("fs.write.outside-project")) return true;
|
|
10459
|
+
return false;
|
|
10460
|
+
}
|
|
9684
10461
|
isDestructiveYoloCall(tool, input, ctx) {
|
|
10462
|
+
if (this.isDestructiveByCapability(tool)) {
|
|
10463
|
+
if (tool.name === "bash") {
|
|
10464
|
+
const command = getInputString(input, "command");
|
|
10465
|
+
return command ? isClearlyDestructiveBashCommand(command, ctx.projectRoot) : true;
|
|
10466
|
+
}
|
|
10467
|
+
if (tool.name === "write" || tool.name === "edit" || tool.name === "replace" || tool.name === "patch") {
|
|
10468
|
+
const targetPath = getInputString(input, "path") ?? getInputString(input, "file");
|
|
10469
|
+
if (!targetPath || !ctx.projectRoot) return false;
|
|
10470
|
+
return !pathLooksInsideProject(targetPath, ctx.projectRoot);
|
|
10471
|
+
}
|
|
10472
|
+
return true;
|
|
10473
|
+
}
|
|
9685
10474
|
if (tool.name === "bash") {
|
|
9686
10475
|
const command = getInputString(input, "command");
|
|
9687
10476
|
return command ? isClearlyDestructiveBashCommand(command, ctx.projectRoot) : true;
|
|
@@ -9840,6 +10629,8 @@ function compactSkillBody(body) {
|
|
|
9840
10629
|
var DefaultSkillLoader = class {
|
|
9841
10630
|
dirs;
|
|
9842
10631
|
cache;
|
|
10632
|
+
entriesCache;
|
|
10633
|
+
bodyCache = /* @__PURE__ */ new Map();
|
|
9843
10634
|
constructor(opts) {
|
|
9844
10635
|
this.dirs = [
|
|
9845
10636
|
{ dir: opts.paths.inProjectSkills, source: "project" },
|
|
@@ -9898,6 +10689,7 @@ var DefaultSkillLoader = class {
|
|
|
9898
10689
|
return lines.join("\n");
|
|
9899
10690
|
}
|
|
9900
10691
|
async listEntries() {
|
|
10692
|
+
if (this.entriesCache) return this.entriesCache;
|
|
9901
10693
|
const skills = await this.list();
|
|
9902
10694
|
const entries = [];
|
|
9903
10695
|
for (const s of skills) {
|
|
@@ -9908,33 +10700,47 @@ var DefaultSkillLoader = class {
|
|
|
9908
10700
|
} catch {
|
|
9909
10701
|
}
|
|
9910
10702
|
}
|
|
10703
|
+
this.entriesCache = entries;
|
|
9911
10704
|
return entries;
|
|
9912
10705
|
}
|
|
9913
10706
|
invalidateCache() {
|
|
9914
10707
|
this.cache = void 0;
|
|
10708
|
+
this.entriesCache = void 0;
|
|
10709
|
+
this.bodyCache.clear();
|
|
9915
10710
|
}
|
|
9916
10711
|
async readBody(name) {
|
|
10712
|
+
const cached = this.bodyCache.get(name);
|
|
10713
|
+
if (cached !== void 0) return cached;
|
|
9917
10714
|
const m = await this.find(name);
|
|
9918
10715
|
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
9919
|
-
|
|
10716
|
+
const body = await fsp3.readFile(m.path, "utf8");
|
|
10717
|
+
this.bodyCache.set(name, body);
|
|
10718
|
+
return body;
|
|
9920
10719
|
}
|
|
9921
10720
|
async readSaveBody(name) {
|
|
10721
|
+
const key = `save:${name}`;
|
|
10722
|
+
const cached = this.bodyCache.get(key);
|
|
10723
|
+
if (cached !== void 0) return cached;
|
|
9922
10724
|
const m = await this.find(name);
|
|
9923
10725
|
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
9924
10726
|
const savePath = path7.join(path7.dirname(m.path), "SKILL.save.md");
|
|
10727
|
+
let result;
|
|
9925
10728
|
try {
|
|
9926
|
-
|
|
10729
|
+
result = await fsp3.readFile(savePath, "utf8");
|
|
9927
10730
|
} catch {
|
|
9928
10731
|
const full = await fsp3.readFile(m.path, "utf8");
|
|
9929
10732
|
const body = stripFrontmatter(full);
|
|
9930
10733
|
const compact = compactSkillBody(body);
|
|
9931
10734
|
if (compact) {
|
|
9932
|
-
|
|
10735
|
+
result = `## Overview
|
|
9933
10736
|
|
|
9934
10737
|
${compact}`;
|
|
10738
|
+
} else {
|
|
10739
|
+
result = body.trim().slice(0, 300);
|
|
9935
10740
|
}
|
|
9936
|
-
return body.trim().slice(0, 300);
|
|
9937
10741
|
}
|
|
10742
|
+
this.bodyCache.set(key, result);
|
|
10743
|
+
return result;
|
|
9938
10744
|
}
|
|
9939
10745
|
};
|
|
9940
10746
|
function parseFrontmatter(raw) {
|
|
@@ -11333,13 +12139,32 @@ var MAX_JOURNAL_ENTRIES = 500;
|
|
|
11333
12139
|
function goalFilePath(projectRoot) {
|
|
11334
12140
|
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
11335
12141
|
}
|
|
11336
|
-
async function loadGoal(filePath) {
|
|
12142
|
+
async function loadGoal(filePath, events) {
|
|
12143
|
+
const t0 = Date.now();
|
|
11337
12144
|
let raw;
|
|
11338
12145
|
try {
|
|
11339
12146
|
raw = await fsp3.readFile(filePath, "utf8");
|
|
11340
12147
|
} catch (err) {
|
|
11341
12148
|
const code = err.code;
|
|
11342
|
-
if (code === "ENOENT")
|
|
12149
|
+
if (code === "ENOENT") {
|
|
12150
|
+
events?.emit("storage.read", {
|
|
12151
|
+
sessionId: "~boot~",
|
|
12152
|
+
store: "goal",
|
|
12153
|
+
filePath,
|
|
12154
|
+
operation: "load",
|
|
12155
|
+
outcome: "success",
|
|
12156
|
+
durationMs: Date.now() - t0
|
|
12157
|
+
});
|
|
12158
|
+
return null;
|
|
12159
|
+
}
|
|
12160
|
+
events?.emit("storage.error", {
|
|
12161
|
+
sessionId: "~boot~",
|
|
12162
|
+
store: "goal",
|
|
12163
|
+
filePath,
|
|
12164
|
+
operation: "load",
|
|
12165
|
+
error: err instanceof Error ? err.message : String(err),
|
|
12166
|
+
recoverable: false
|
|
12167
|
+
});
|
|
11343
12168
|
throw err;
|
|
11344
12169
|
}
|
|
11345
12170
|
try {
|
|
@@ -11352,8 +12177,25 @@ async function loadGoal(filePath) {
|
|
|
11352
12177
|
message: "invalid schema \u2014 consider deleting and re-creating",
|
|
11353
12178
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
11354
12179
|
}));
|
|
12180
|
+
events?.emit("storage.read", {
|
|
12181
|
+
sessionId: "~boot~",
|
|
12182
|
+
store: "goal",
|
|
12183
|
+
filePath,
|
|
12184
|
+
operation: "load",
|
|
12185
|
+
outcome: "failure",
|
|
12186
|
+
durationMs: Date.now() - t0,
|
|
12187
|
+
error: "invalid_schema"
|
|
12188
|
+
});
|
|
11355
12189
|
return null;
|
|
11356
12190
|
}
|
|
12191
|
+
events?.emit("storage.read", {
|
|
12192
|
+
sessionId: "~boot~",
|
|
12193
|
+
store: "goal",
|
|
12194
|
+
filePath,
|
|
12195
|
+
operation: "load",
|
|
12196
|
+
outcome: "success",
|
|
12197
|
+
durationMs: Date.now() - t0
|
|
12198
|
+
});
|
|
11357
12199
|
return parsed;
|
|
11358
12200
|
} catch {
|
|
11359
12201
|
console.warn(JSON.stringify({
|
|
@@ -11363,13 +12205,39 @@ async function loadGoal(filePath) {
|
|
|
11363
12205
|
message: "JSON parse failed \u2014 consider deleting and re-creating",
|
|
11364
12206
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
11365
12207
|
}));
|
|
12208
|
+
events?.emit("storage.read", {
|
|
12209
|
+
sessionId: "~boot~",
|
|
12210
|
+
store: "goal",
|
|
12211
|
+
filePath,
|
|
12212
|
+
operation: "load",
|
|
12213
|
+
outcome: "failure",
|
|
12214
|
+
durationMs: Date.now() - t0,
|
|
12215
|
+
error: "parse_failed"
|
|
12216
|
+
});
|
|
11366
12217
|
return null;
|
|
11367
12218
|
}
|
|
11368
12219
|
}
|
|
11369
|
-
async function saveGoal(filePath, goal) {
|
|
12220
|
+
async function saveGoal(filePath, goal, events) {
|
|
12221
|
+
const t0 = Date.now();
|
|
11370
12222
|
try {
|
|
11371
12223
|
await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 384 });
|
|
12224
|
+
events?.emit("storage.write", {
|
|
12225
|
+
sessionId: "~boot~",
|
|
12226
|
+
store: "goal",
|
|
12227
|
+
filePath,
|
|
12228
|
+
operation: "save",
|
|
12229
|
+
outcome: "success",
|
|
12230
|
+
durationMs: Date.now() - t0
|
|
12231
|
+
});
|
|
11372
12232
|
} catch (err) {
|
|
12233
|
+
events?.emit("storage.error", {
|
|
12234
|
+
sessionId: "~boot~",
|
|
12235
|
+
store: "goal",
|
|
12236
|
+
filePath,
|
|
12237
|
+
operation: "save",
|
|
12238
|
+
error: err instanceof Error ? err.message : String(err),
|
|
12239
|
+
recoverable: false
|
|
12240
|
+
});
|
|
11373
12241
|
throw new FsError({
|
|
11374
12242
|
message: err instanceof Error ? err.message : String(err),
|
|
11375
12243
|
code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,
|
|
@@ -11815,7 +12683,7 @@ var EternalAutonomyEngine = class {
|
|
|
11815
12683
|
const emit = (stage) => {
|
|
11816
12684
|
this.opts.onStage?.(stage);
|
|
11817
12685
|
};
|
|
11818
|
-
const goal = await loadGoal(this.goalPath);
|
|
12686
|
+
const goal = await loadGoal(this.goalPath, this.opts.events);
|
|
11819
12687
|
if (!goal) {
|
|
11820
12688
|
emit({ phase: "stopped" });
|
|
11821
12689
|
this.stopRequested = true;
|
|
@@ -11919,7 +12787,7 @@ var EternalAutonomyEngine = class {
|
|
|
11919
12787
|
emit({ phase: "reflect", status, note });
|
|
11920
12788
|
let iterationIndex = 0;
|
|
11921
12789
|
try {
|
|
11922
|
-
const reloaded = await loadGoal(this.goalPath);
|
|
12790
|
+
const reloaded = await loadGoal(this.goalPath, this.opts.events);
|
|
11923
12791
|
iterationIndex = reloaded?.iterations ?? 0;
|
|
11924
12792
|
} catch {
|
|
11925
12793
|
}
|
|
@@ -12239,12 +13107,12 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
12239
13107
|
}
|
|
12240
13108
|
}
|
|
12241
13109
|
async appendIterationEntry(entry) {
|
|
12242
|
-
const current = await loadGoal(this.goalPath);
|
|
13110
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12243
13111
|
if (!current) {
|
|
12244
13112
|
return;
|
|
12245
13113
|
}
|
|
12246
13114
|
const updated = appendJournal(current, entry);
|
|
12247
|
-
await saveGoal(this.goalPath, updated);
|
|
13115
|
+
await saveGoal(this.goalPath, updated, this.opts.events);
|
|
12248
13116
|
}
|
|
12249
13117
|
/**
|
|
12250
13118
|
* Persistent per-todo failure counter. Skipped silently when the goal
|
|
@@ -12253,11 +13121,11 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
12253
13121
|
* the counter to rotate past stuck todos once they cross `todoMaxAttempts`.
|
|
12254
13122
|
*/
|
|
12255
13123
|
async bumpTodoAttempt(todoId) {
|
|
12256
|
-
const current = await loadGoal(this.goalPath);
|
|
13124
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12257
13125
|
if (!current) return;
|
|
12258
13126
|
const attempts = { ...current.todoAttempts ?? {} };
|
|
12259
13127
|
attempts[todoId] = (attempts[todoId] ?? 0) + 1;
|
|
12260
|
-
await saveGoal(this.goalPath, { ...current, todoAttempts: attempts });
|
|
13128
|
+
await saveGoal(this.goalPath, { ...current, todoAttempts: attempts }, this.opts.events);
|
|
12261
13129
|
}
|
|
12262
13130
|
/**
|
|
12263
13131
|
* Flip the mission to `completed` and journal it. Called from two
|
|
@@ -12267,7 +13135,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
12267
13135
|
* goal is already `completed`.
|
|
12268
13136
|
*/
|
|
12269
13137
|
async markGoalCompleted(action, note) {
|
|
12270
|
-
const current = await loadGoal(this.goalPath);
|
|
13138
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12271
13139
|
if (!current) return;
|
|
12272
13140
|
if (current.goalState === "completed") return;
|
|
12273
13141
|
const withFlag = { ...current, goalState: "completed" };
|
|
@@ -12277,7 +13145,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
12277
13145
|
status: "success",
|
|
12278
13146
|
note: note.slice(0, 240)
|
|
12279
13147
|
});
|
|
12280
|
-
await saveGoal(this.goalPath, withEntry);
|
|
13148
|
+
await saveGoal(this.goalPath, withEntry, this.opts.events);
|
|
12281
13149
|
this.opts.onEternalStop?.();
|
|
12282
13150
|
}
|
|
12283
13151
|
/**
|
|
@@ -12286,10 +13154,10 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
12286
13154
|
* `onEternalStop` so the REPL returns to normal mode.
|
|
12287
13155
|
*/
|
|
12288
13156
|
async clearGoalManually(note) {
|
|
12289
|
-
const current = await loadGoal(this.goalPath);
|
|
13157
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12290
13158
|
if (current) {
|
|
12291
13159
|
const abandoned = { ...current, goalState: "abandoned" };
|
|
12292
|
-
await saveGoal(this.goalPath, abandoned);
|
|
13160
|
+
await saveGoal(this.goalPath, abandoned, this.opts.events);
|
|
12293
13161
|
}
|
|
12294
13162
|
try {
|
|
12295
13163
|
const { unlink: unlink16 } = await import('fs/promises');
|
|
@@ -12365,16 +13233,16 @@ ${recentJournal}` : ""
|
|
|
12365
13233
|
* Persist a progress update from the agent's [PROGRESS: N%] output.
|
|
12366
13234
|
*/
|
|
12367
13235
|
async updateProgress(progress, note) {
|
|
12368
|
-
const current = await loadGoal(this.goalPath);
|
|
13236
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12369
13237
|
if (!current) return;
|
|
12370
13238
|
const updated = recordProgress(current, progress, note);
|
|
12371
|
-
await saveGoal(this.goalPath, updated);
|
|
13239
|
+
await saveGoal(this.goalPath, updated, this.opts.events);
|
|
12372
13240
|
}
|
|
12373
13241
|
async persistEngineState(state) {
|
|
12374
|
-
const current = await loadGoal(this.goalPath);
|
|
13242
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
12375
13243
|
if (!current) return;
|
|
12376
13244
|
if (current.engineState === state) return;
|
|
12377
|
-
await saveGoal(this.goalPath, { ...current, engineState: state });
|
|
13245
|
+
await saveGoal(this.goalPath, { ...current, engineState: state }, this.opts.events);
|
|
12378
13246
|
}
|
|
12379
13247
|
};
|
|
12380
13248
|
|
|
@@ -12723,6 +13591,20 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
12723
13591
|
};
|
|
12724
13592
|
|
|
12725
13593
|
// src/coordination/agent-subagent-runner.ts
|
|
13594
|
+
function withDisabledToolFiltering(factory) {
|
|
13595
|
+
return async (config) => {
|
|
13596
|
+
const result = await factory(config);
|
|
13597
|
+
const disabled = config.disabledTools ?? [];
|
|
13598
|
+
if (disabled.length === 0) return result;
|
|
13599
|
+
const registry = result.agent.tools;
|
|
13600
|
+
if (registry && typeof registry.unregister === "function") {
|
|
13601
|
+
for (const toolName of disabled) {
|
|
13602
|
+
registry.unregister(toolName);
|
|
13603
|
+
}
|
|
13604
|
+
}
|
|
13605
|
+
return result;
|
|
13606
|
+
};
|
|
13607
|
+
}
|
|
12726
13608
|
function makeAgentSubagentRunner(opts) {
|
|
12727
13609
|
const format = opts.formatTaskInput ?? defaultFormatTaskInput;
|
|
12728
13610
|
return async (task, ctx) => {
|
|
@@ -15546,17 +16428,17 @@ function normalize2(text) {
|
|
|
15546
16428
|
return ` ${text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim()} `;
|
|
15547
16429
|
}
|
|
15548
16430
|
function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
15549
|
-
const
|
|
16431
|
+
const haySet = new Set(normalize2(task).split(/\s+/).filter(Boolean));
|
|
15550
16432
|
const out = [];
|
|
15551
16433
|
for (const def of Object.values(catalog)) {
|
|
15552
16434
|
if (!def?.config?.role) continue;
|
|
15553
16435
|
let score = 0;
|
|
15554
16436
|
const matched = [];
|
|
15555
16437
|
for (const kw of def.capability.keywords) {
|
|
15556
|
-
const
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
score +=
|
|
16438
|
+
const needleWords = normalize2(kw).split(/\s+/).filter(Boolean);
|
|
16439
|
+
const allPresent = needleWords.every((w) => haySet.has(w));
|
|
16440
|
+
if (allPresent) {
|
|
16441
|
+
score += needleWords.length;
|
|
15560
16442
|
matched.push(kw);
|
|
15561
16443
|
}
|
|
15562
16444
|
}
|
|
@@ -16889,7 +17771,8 @@ var ParallelEternalEngine = class {
|
|
|
16889
17771
|
doneCondition: { type: "all_tasks_done" }
|
|
16890
17772
|
};
|
|
16891
17773
|
this.coordinator = new DefaultMultiAgentCoordinator(config);
|
|
16892
|
-
const
|
|
17774
|
+
const filteredFactory = withDisabledToolFiltering(this.agentFactory);
|
|
17775
|
+
const runner = makeAgentSubagentRunner({ factory: filteredFactory });
|
|
16893
17776
|
this.coordinator.setRunner?.(runner);
|
|
16894
17777
|
try {
|
|
16895
17778
|
while (!this.stopRequested) {
|
|
@@ -16924,7 +17807,7 @@ var ParallelEternalEngine = class {
|
|
|
16924
17807
|
this.opts.onStage?.(stage);
|
|
16925
17808
|
};
|
|
16926
17809
|
this.iterations++;
|
|
16927
|
-
const goal = await loadGoal(this.goalPath);
|
|
17810
|
+
const goal = await loadGoal(this.goalPath, this.opts.events);
|
|
16928
17811
|
if (!goal) {
|
|
16929
17812
|
this.stopRequested = true;
|
|
16930
17813
|
emit({ phase: "stopped" });
|
|
@@ -16942,7 +17825,8 @@ var ParallelEternalEngine = class {
|
|
|
16942
17825
|
doneCondition: { type: "all_tasks_done" }
|
|
16943
17826
|
};
|
|
16944
17827
|
this.coordinator = new DefaultMultiAgentCoordinator(config);
|
|
16945
|
-
const
|
|
17828
|
+
const filteredFactory = withDisabledToolFiltering(this.agentFactory);
|
|
17829
|
+
const runner = makeAgentSubagentRunner({ factory: filteredFactory });
|
|
16946
17830
|
this.coordinator.setRunner?.(runner);
|
|
16947
17831
|
}
|
|
16948
17832
|
emit({ phase: "decompose" });
|
|
@@ -17051,13 +17935,17 @@ ${personaLine}Task: ${task}
|
|
|
17051
17935
|
role: route.role,
|
|
17052
17936
|
tools: route.definition.config.tools,
|
|
17053
17937
|
systemPromptOverride: route.definition.config.prompt,
|
|
17054
|
-
timeoutMs: this.timeoutMs
|
|
17938
|
+
timeoutMs: this.timeoutMs,
|
|
17939
|
+
// Disable delegation — subagents are leaf workers, not orchestrators
|
|
17940
|
+
disabledTools: ["delegate"]
|
|
17055
17941
|
} : {
|
|
17056
17942
|
id: subagentId,
|
|
17057
17943
|
name: `slot-${subagentId.slice(-6)}`,
|
|
17058
17944
|
// Let the coordinator apply its default budget (roster or generic).
|
|
17059
17945
|
// Hardcoding low limits here defeats the x10 budget improvement.
|
|
17060
|
-
timeoutMs: this.timeoutMs
|
|
17946
|
+
timeoutMs: this.timeoutMs,
|
|
17947
|
+
// Disable delegation — subagents are leaf workers, not orchestrators
|
|
17948
|
+
disabledTools: ["delegate"]
|
|
17061
17949
|
}
|
|
17062
17950
|
);
|
|
17063
17951
|
subagentIds.push(subagentId);
|
|
@@ -17203,10 +18091,10 @@ ${lastFew}` : "No prior iterations.",
|
|
|
17203
18091
|
// Helpers
|
|
17204
18092
|
// -------------------------------------------------------------------------
|
|
17205
18093
|
async appendIterationEntry(entry) {
|
|
17206
|
-
const current = await loadGoal(this.goalPath);
|
|
18094
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
17207
18095
|
if (!current) return;
|
|
17208
18096
|
const updated = appendJournal(current, entry);
|
|
17209
|
-
await saveGoal(this.goalPath, updated);
|
|
18097
|
+
await saveGoal(this.goalPath, updated, this.opts.events);
|
|
17210
18098
|
const entryWithMeta = {
|
|
17211
18099
|
at: (this.opts.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
17212
18100
|
iteration: updated.iterations,
|
|
@@ -17218,10 +18106,10 @@ ${lastFew}` : "No prior iterations.",
|
|
|
17218
18106
|
await this.appendIterationEntry({ source: "manual", task, status: "failure", note });
|
|
17219
18107
|
}
|
|
17220
18108
|
async persistState(state) {
|
|
17221
|
-
const current = await loadGoal(this.goalPath);
|
|
18109
|
+
const current = await loadGoal(this.goalPath, this.opts.events);
|
|
17222
18110
|
if (!current) return;
|
|
17223
18111
|
if (current.engineState === state) return;
|
|
17224
|
-
await saveGoal(this.goalPath, { ...current, engineState: state });
|
|
18112
|
+
await saveGoal(this.goalPath, { ...current, engineState: state }, this.opts.events);
|
|
17225
18113
|
}
|
|
17226
18114
|
};
|
|
17227
18115
|
|
|
@@ -17967,6 +18855,7 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
|
|
|
17967
18855
|
}
|
|
17968
18856
|
for (const dispose of this.disposers) dispose();
|
|
17969
18857
|
this.disposers.length = 0;
|
|
18858
|
+
this.snapshot.files.length = 0;
|
|
17970
18859
|
}
|
|
17971
18860
|
};
|
|
17972
18861
|
|
|
@@ -18000,7 +18889,12 @@ Working rules:
|
|
|
18000
18889
|
6. Never claim a subagent's work as your own without verifying it. If a
|
|
18001
18890
|
result looks wrong, ask_subagent for clarification before passing it
|
|
18002
18891
|
to the user.
|
|
18003
|
-
7.
|
|
18892
|
+
7. **Act on subagent mail immediately**. Subagent messages (result, ask,
|
|
18893
|
+
assign, note) are injected inline before every step \u2014 even mid-task.
|
|
18894
|
+
When you see one, address it before continuing: reply to asks, factor
|
|
18895
|
+
in results, act on assignments. Use \`mailbox action=ack\` to mark
|
|
18896
|
+
completed messages.
|
|
18897
|
+
8. Wind down when satisfied. When the results are good enough, call
|
|
18004
18898
|
work_complete \u2014 no new subagents will spawn and queued tasks complete
|
|
18005
18899
|
as aborted. Running subagents finish naturally. Call terminate_subagent
|
|
18006
18900
|
only for ones you need to stop immediately.`;
|
|
@@ -18017,6 +18911,13 @@ Bridge contract:
|
|
|
18017
18911
|
structured, and self-contained \u2014 assume the Director will paste your
|
|
18018
18912
|
output into its own context.
|
|
18019
18913
|
|
|
18914
|
+
CRITICAL CONSTRAINT \u2014 NO FURTHER DELEGATION:
|
|
18915
|
+
- You MUST NOT call the \`delegate\` tool or attempt to spawn subagents.
|
|
18916
|
+
- You MUST NOT use \`spawn_subagent\`, \`assign_task\`, or any equivalent.
|
|
18917
|
+
- Your role is to execute the assigned task yourself, not to orchestrate.
|
|
18918
|
+
- If a subtask is too complex, report back to the Director with what you
|
|
18919
|
+
found and let the Director decide how to decompose.
|
|
18920
|
+
|
|
18020
18921
|
Inter-agent mailbox (if you have the \`mail_send\`/\`mail_inbox\`/\`mailbox\` tools):
|
|
18021
18922
|
- You are part of a project-wide fleet that may span other terminals and
|
|
18022
18923
|
WebUIs. Your mailbox identity is \`<your-name>@<session-tag>\` (unique
|
|
@@ -18031,7 +18932,12 @@ Inter-agent mailbox (if you have the \`mail_send\`/\`mail_inbox\`/\`mailbox\` to
|
|
|
18031
18932
|
their exact id instead of doing everything yourself. Discover ids with
|
|
18032
18933
|
\`mailbox action=online\`.
|
|
18033
18934
|
- Answer your mail: reply to the sender's exact \`from\` id. When done with
|
|
18034
|
-
an assigned task, post a \`result\` back to whoever assigned it
|
|
18935
|
+
an assigned task, post a \`result\` back to whoever assigned it.
|
|
18936
|
+
- **Mail to the leader is always seen**: when you send \`ask\`, \`result\`,
|
|
18937
|
+
or \`assign\` to the director/leader, the message is injected inline into
|
|
18938
|
+
the leader's conversation before their next step \u2014 even if the leader is
|
|
18939
|
+
mid-task. Use \`mail_send\` to reliably reach the leader instead of
|
|
18940
|
+
waiting for them to check in.`;
|
|
18035
18941
|
function composeDirectorPrompt(parts = {}) {
|
|
18036
18942
|
const sections = [];
|
|
18037
18943
|
const preamble = parts.directorPreamble ?? DEFAULT_DIRECTOR_PREAMBLE;
|
|
@@ -20440,6 +21346,7 @@ async function readSubagentPartial(opts, subagentId) {
|
|
|
20440
21346
|
}
|
|
20441
21347
|
function makeDirectorSessionFactory(opts) {
|
|
20442
21348
|
const runId = opts.directorRunId ?? `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-director`;
|
|
21349
|
+
const { traceId } = opts;
|
|
20443
21350
|
let store;
|
|
20444
21351
|
let dir;
|
|
20445
21352
|
if (opts.store) {
|
|
@@ -20455,12 +21362,16 @@ function makeDirectorSessionFactory(opts) {
|
|
|
20455
21362
|
dir,
|
|
20456
21363
|
directorRunId: runId,
|
|
20457
21364
|
async createSubagentSession({ subagentId, provider, model, title }) {
|
|
20458
|
-
|
|
21365
|
+
const writer = await store.create({
|
|
20459
21366
|
id: subagentId,
|
|
20460
21367
|
title: title ?? subagentId,
|
|
20461
21368
|
provider: provider ?? "unknown",
|
|
20462
21369
|
model: model ?? "unknown"
|
|
20463
21370
|
});
|
|
21371
|
+
if (traceId !== void 0) {
|
|
21372
|
+
writer.traceId = traceId;
|
|
21373
|
+
}
|
|
21374
|
+
return writer;
|
|
20464
21375
|
}
|
|
20465
21376
|
};
|
|
20466
21377
|
}
|
|
@@ -23179,7 +24090,9 @@ var SddParallelRun = class {
|
|
|
23179
24090
|
doneCondition: { type: "all_tasks_done" }
|
|
23180
24091
|
};
|
|
23181
24092
|
this.coordinator = new DefaultMultiAgentCoordinator(config);
|
|
23182
|
-
const
|
|
24093
|
+
const baseFactory = this.opts.subagentFactory ?? this.defaultFactory();
|
|
24094
|
+
const filteredFactory = withDisabledToolFiltering(baseFactory);
|
|
24095
|
+
const runner = makeAgentSubagentRunner({ factory: filteredFactory });
|
|
23183
24096
|
this.coordinator.setRunner?.(runner);
|
|
23184
24097
|
}
|
|
23185
24098
|
defaultFactory() {
|
|
@@ -23221,7 +24134,9 @@ var SddParallelRun = class {
|
|
|
23221
24134
|
id: subagentId,
|
|
23222
24135
|
name: subagentId,
|
|
23223
24136
|
role: "executor",
|
|
23224
|
-
timeoutMs: this.timeoutMs
|
|
24137
|
+
timeoutMs: this.timeoutMs,
|
|
24138
|
+
// Disable delegation — subagents are leaf workers, not orchestrators
|
|
24139
|
+
disabledTools: ["delegate"]
|
|
23225
24140
|
})
|
|
23226
24141
|
);
|
|
23227
24142
|
const spawnResults = await Promise.all(spawns);
|
|
@@ -25308,20 +26223,53 @@ var MAX_TEXT_LENGTH = 2e3;
|
|
|
25308
26223
|
var MAX_ANNOTATIONS = 1e3;
|
|
25309
26224
|
var AnnotationsStore = class {
|
|
25310
26225
|
dir;
|
|
26226
|
+
events;
|
|
26227
|
+
traceId;
|
|
25311
26228
|
/** Per-session write queue. Created lazily on first add. */
|
|
25312
26229
|
writeChains = /* @__PURE__ */ new Map();
|
|
25313
26230
|
constructor(opts) {
|
|
25314
26231
|
this.dir = opts.dir;
|
|
26232
|
+
this.events = opts.events;
|
|
26233
|
+
this.traceId = opts.traceId;
|
|
25315
26234
|
}
|
|
25316
26235
|
// ── Reads ──────────────────────────────────────────────────────────────
|
|
25317
26236
|
/**
|
|
25318
26237
|
* Return all annotations for `sessionId` in insertion order
|
|
25319
26238
|
* (oldest first). Returns an empty array when no file exists
|
|
25320
|
-
* yet (the normal case for a fresh session)
|
|
26239
|
+
* yet (the normal case for a fresh session) and also degrades
|
|
26240
|
+
* gracefully to `[]` on a read error (permissions, corruption) —
|
|
26241
|
+
* the failure is still surfaced via a `storage.read` event so it
|
|
26242
|
+
* never silently hides I/O problems from observers.
|
|
25321
26243
|
*/
|
|
25322
26244
|
async list(sessionId) {
|
|
25323
|
-
const
|
|
25324
|
-
|
|
26245
|
+
const t0 = Date.now();
|
|
26246
|
+
const fp = this.filePath(sessionId);
|
|
26247
|
+
try {
|
|
26248
|
+
const file = await this.readFile(sessionId);
|
|
26249
|
+
const durationMs = Date.now() - t0;
|
|
26250
|
+
this.events?.emit("storage.read", {
|
|
26251
|
+
sessionId,
|
|
26252
|
+
store: "annotations",
|
|
26253
|
+
filePath: fp,
|
|
26254
|
+
operation: "list",
|
|
26255
|
+
outcome: "success",
|
|
26256
|
+
durationMs,
|
|
26257
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26258
|
+
});
|
|
26259
|
+
return file ? file.annotations : [];
|
|
26260
|
+
} catch (err) {
|
|
26261
|
+
this.events?.emit("storage.read", {
|
|
26262
|
+
sessionId,
|
|
26263
|
+
store: "annotations",
|
|
26264
|
+
filePath: fp,
|
|
26265
|
+
operation: "list",
|
|
26266
|
+
outcome: "failure",
|
|
26267
|
+
durationMs: Date.now() - t0,
|
|
26268
|
+
error: err instanceof Error ? err.message : String(err),
|
|
26269
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26270
|
+
});
|
|
26271
|
+
return [];
|
|
26272
|
+
}
|
|
25325
26273
|
}
|
|
25326
26274
|
/**
|
|
25327
26275
|
* Convenience: only unresolved annotations, newest first — the
|
|
@@ -25373,25 +26321,62 @@ var AnnotationsStore = class {
|
|
|
25373
26321
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25374
26322
|
resolved: false
|
|
25375
26323
|
};
|
|
25376
|
-
|
|
25377
|
-
|
|
25378
|
-
|
|
25379
|
-
|
|
25380
|
-
|
|
25381
|
-
const
|
|
25382
|
-
|
|
25383
|
-
|
|
25384
|
-
|
|
25385
|
-
|
|
25386
|
-
|
|
25387
|
-
|
|
25388
|
-
|
|
25389
|
-
|
|
25390
|
-
|
|
25391
|
-
|
|
26324
|
+
const fp = this.filePath(input.sessionId);
|
|
26325
|
+
const t0 = Date.now();
|
|
26326
|
+
try {
|
|
26327
|
+
await this.enqueue(input.sessionId, async () => {
|
|
26328
|
+
await withFileLock(fp, async () => {
|
|
26329
|
+
const all = await this.list(input.sessionId);
|
|
26330
|
+
all.push(annotation);
|
|
26331
|
+
if (all.length > MAX_ANNOTATIONS) {
|
|
26332
|
+
const sorted = all.map((a, i) => ({ a, i })).sort((x, y) => {
|
|
26333
|
+
if (x.a.resolved !== y.a.resolved) return x.a.resolved ? 1 : -1;
|
|
26334
|
+
return x.a.createdAt.localeCompare(y.a.createdAt);
|
|
26335
|
+
});
|
|
26336
|
+
const evictCount = all.length - MAX_ANNOTATIONS;
|
|
26337
|
+
const toEvict = new Set(sorted.slice(0, evictCount).map((s) => s.a.id));
|
|
26338
|
+
const kept = all.filter((a) => !toEvict.has(a.id));
|
|
26339
|
+
await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: kept });
|
|
26340
|
+
const durationMs = Date.now() - t0;
|
|
26341
|
+
this.events?.emit("storage.write", {
|
|
26342
|
+
sessionId: input.sessionId,
|
|
26343
|
+
store: "annotations",
|
|
26344
|
+
filePath: fp,
|
|
26345
|
+
operation: "evict",
|
|
26346
|
+
outcome: "success",
|
|
26347
|
+
durationMs,
|
|
26348
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26349
|
+
});
|
|
26350
|
+
} else {
|
|
26351
|
+
await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });
|
|
26352
|
+
const durationMs = Date.now() - t0;
|
|
26353
|
+
this.events?.emit("storage.write", {
|
|
26354
|
+
sessionId: input.sessionId,
|
|
26355
|
+
store: "annotations",
|
|
26356
|
+
filePath: fp,
|
|
26357
|
+
operation: "add",
|
|
26358
|
+
outcome: "success",
|
|
26359
|
+
durationMs,
|
|
26360
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26361
|
+
});
|
|
26362
|
+
}
|
|
26363
|
+
});
|
|
25392
26364
|
});
|
|
25393
|
-
|
|
25394
|
-
|
|
26365
|
+
return annotation;
|
|
26366
|
+
} catch (err) {
|
|
26367
|
+
this.events?.emit("storage.error", {
|
|
26368
|
+
sessionId: input.sessionId,
|
|
26369
|
+
store: "annotations",
|
|
26370
|
+
filePath: fp,
|
|
26371
|
+
operation: "add",
|
|
26372
|
+
outcome: "failure",
|
|
26373
|
+
error: err instanceof Error ? err.message : String(err),
|
|
26374
|
+
recoverable: false,
|
|
26375
|
+
durationMs: Date.now() - t0,
|
|
26376
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26377
|
+
});
|
|
26378
|
+
throw err;
|
|
26379
|
+
}
|
|
25395
26380
|
}
|
|
25396
26381
|
/**
|
|
25397
26382
|
* Mark an annotation as resolved. Returns the updated record, or
|
|
@@ -25401,26 +26386,53 @@ var AnnotationsStore = class {
|
|
|
25401
26386
|
*/
|
|
25402
26387
|
async resolve(input) {
|
|
25403
26388
|
let updated = null;
|
|
25404
|
-
|
|
25405
|
-
|
|
25406
|
-
|
|
25407
|
-
|
|
25408
|
-
|
|
25409
|
-
|
|
25410
|
-
|
|
25411
|
-
|
|
25412
|
-
|
|
25413
|
-
|
|
25414
|
-
|
|
25415
|
-
|
|
25416
|
-
|
|
25417
|
-
|
|
25418
|
-
|
|
25419
|
-
|
|
25420
|
-
|
|
26389
|
+
const fp = this.filePath(input.sessionId);
|
|
26390
|
+
const t0 = Date.now();
|
|
26391
|
+
try {
|
|
26392
|
+
await this.enqueue(input.sessionId, async () => {
|
|
26393
|
+
await withFileLock(fp, async () => {
|
|
26394
|
+
const all = await this.list(input.sessionId);
|
|
26395
|
+
const idx = all.findIndex((a) => a.id === input.annotationId);
|
|
26396
|
+
if (idx === -1) {
|
|
26397
|
+
updated = null;
|
|
26398
|
+
return;
|
|
26399
|
+
}
|
|
26400
|
+
const next = {
|
|
26401
|
+
...expectDefined(all[idx]),
|
|
26402
|
+
resolved: true,
|
|
26403
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26404
|
+
resolvedBy: input.resolvedBy
|
|
26405
|
+
};
|
|
26406
|
+
all[idx] = next;
|
|
26407
|
+
await this.writeFile(input.sessionId, { version: FILE_VERSION, annotations: all });
|
|
26408
|
+
updated = next;
|
|
26409
|
+
const durationMs = Date.now() - t0;
|
|
26410
|
+
this.events?.emit("storage.write", {
|
|
26411
|
+
sessionId: input.sessionId,
|
|
26412
|
+
store: "annotations",
|
|
26413
|
+
filePath: fp,
|
|
26414
|
+
operation: "resolve",
|
|
26415
|
+
outcome: "success",
|
|
26416
|
+
durationMs,
|
|
26417
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26418
|
+
});
|
|
26419
|
+
});
|
|
25421
26420
|
});
|
|
25422
|
-
|
|
25423
|
-
|
|
26421
|
+
return updated;
|
|
26422
|
+
} catch (err) {
|
|
26423
|
+
this.events?.emit("storage.error", {
|
|
26424
|
+
sessionId: input.sessionId,
|
|
26425
|
+
store: "annotations",
|
|
26426
|
+
filePath: fp,
|
|
26427
|
+
operation: "resolve",
|
|
26428
|
+
outcome: "failure",
|
|
26429
|
+
error: err instanceof Error ? err.message : String(err),
|
|
26430
|
+
recoverable: false,
|
|
26431
|
+
durationMs: Date.now() - t0,
|
|
26432
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26433
|
+
});
|
|
26434
|
+
throw err;
|
|
26435
|
+
}
|
|
25424
26436
|
}
|
|
25425
26437
|
// ── Internals ──────────────────────────────────────────────────────────
|
|
25426
26438
|
filePath(sessionId) {
|
|
@@ -25428,16 +26440,21 @@ var AnnotationsStore = class {
|
|
|
25428
26440
|
}
|
|
25429
26441
|
async readFile(sessionId) {
|
|
25430
26442
|
const fp = this.filePath(sessionId);
|
|
26443
|
+
let raw;
|
|
26444
|
+
try {
|
|
26445
|
+
raw = await fsp3.readFile(fp, "utf8");
|
|
26446
|
+
} catch (err) {
|
|
26447
|
+
if (err.code === "ENOENT") return null;
|
|
26448
|
+
throw err;
|
|
26449
|
+
}
|
|
25431
26450
|
try {
|
|
25432
|
-
const raw = await fsp3.readFile(fp, "utf8");
|
|
25433
26451
|
const parsed = JSON.parse(raw);
|
|
25434
26452
|
if (parsed.version !== FILE_VERSION) {
|
|
25435
26453
|
return { version: FILE_VERSION, annotations: [] };
|
|
25436
26454
|
}
|
|
25437
26455
|
return parsed;
|
|
25438
|
-
} catch
|
|
25439
|
-
|
|
25440
|
-
return { version: FILE_VERSION, annotations: [] };
|
|
26456
|
+
} catch {
|
|
26457
|
+
return null;
|
|
25441
26458
|
}
|
|
25442
26459
|
}
|
|
25443
26460
|
async writeFile(sessionId, file) {
|
|
@@ -25494,9 +26511,20 @@ function hashRequest(request) {
|
|
|
25494
26511
|
const digest = createHash("sha256").update(json, "utf8").digest("hex");
|
|
25495
26512
|
return `sha256:${digest}`;
|
|
25496
26513
|
}
|
|
26514
|
+
|
|
26515
|
+
// src/storage/replay-log-store.ts
|
|
26516
|
+
function storageErrorString2(err) {
|
|
26517
|
+
if (err instanceof Error) {
|
|
26518
|
+
const code = err.code;
|
|
26519
|
+
return code ? `${code}: ${err.message}` : err.message;
|
|
26520
|
+
}
|
|
26521
|
+
return String(err);
|
|
26522
|
+
}
|
|
25497
26523
|
var DEFAULT_MAX_ENTRIES = 1e3;
|
|
25498
26524
|
var ReplayLogStore = class {
|
|
25499
26525
|
dir;
|
|
26526
|
+
events;
|
|
26527
|
+
traceId;
|
|
25500
26528
|
writeChains = /* @__PURE__ */ new Map();
|
|
25501
26529
|
/** Per-session hash → entry index, kept in memory after the first load. */
|
|
25502
26530
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -25505,6 +26533,8 @@ var ReplayLogStore = class {
|
|
|
25505
26533
|
maxEntries;
|
|
25506
26534
|
constructor(opts) {
|
|
25507
26535
|
this.dir = opts.dir;
|
|
26536
|
+
this.events = opts.events;
|
|
26537
|
+
this.traceId = opts.traceId;
|
|
25508
26538
|
this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
25509
26539
|
}
|
|
25510
26540
|
// ── Writes ──────────────────────────────────────────────────────────────
|
|
@@ -25515,38 +26545,43 @@ var ReplayLogStore = class {
|
|
|
25515
26545
|
*/
|
|
25516
26546
|
async record(input) {
|
|
25517
26547
|
const hash = hashRequest(input.request);
|
|
25518
|
-
|
|
25519
|
-
|
|
25520
|
-
|
|
25521
|
-
|
|
25522
|
-
|
|
25523
|
-
|
|
25524
|
-
|
|
25525
|
-
|
|
25526
|
-
|
|
25527
|
-
|
|
25528
|
-
|
|
25529
|
-
|
|
25530
|
-
|
|
25531
|
-
|
|
25532
|
-
|
|
25533
|
-
|
|
26548
|
+
const fp = this.filePath(input.sessionId);
|
|
26549
|
+
const t0 = Date.now();
|
|
26550
|
+
try {
|
|
26551
|
+
await this.enqueue(input.sessionId, async () => {
|
|
26552
|
+
await withFileLock(this.filePath(input.sessionId), async () => {
|
|
26553
|
+
const entries = await this.readAll(input.sessionId);
|
|
26554
|
+
if (entries.some((entry2) => entry2.hash === hash)) return;
|
|
26555
|
+
const entry = {
|
|
26556
|
+
hash,
|
|
26557
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26558
|
+
request: input.request,
|
|
26559
|
+
response: input.response
|
|
26560
|
+
};
|
|
26561
|
+
entries.push(entry);
|
|
26562
|
+
const keep = entries.slice(-this.maxEntries);
|
|
26563
|
+
const didEvict = keep.length < entries.length;
|
|
26564
|
+
const cache = /* @__PURE__ */ new Map();
|
|
26565
|
+
for (const e of keep) cache.set(e.hash, e);
|
|
26566
|
+
this.cache.set(input.sessionId, cache);
|
|
26567
|
+
await this.writeAll(input.sessionId, keep, didEvict ? "compact" : "record");
|
|
26568
|
+
});
|
|
25534
26569
|
});
|
|
25535
|
-
|
|
25536
|
-
|
|
25537
|
-
|
|
25538
|
-
|
|
25539
|
-
|
|
25540
|
-
|
|
25541
|
-
|
|
25542
|
-
|
|
25543
|
-
|
|
25544
|
-
|
|
25545
|
-
|
|
25546
|
-
|
|
25547
|
-
|
|
25548
|
-
|
|
25549
|
-
|
|
26570
|
+
return hash;
|
|
26571
|
+
} catch (err) {
|
|
26572
|
+
this.events?.emit("storage.error", {
|
|
26573
|
+
sessionId: input.sessionId,
|
|
26574
|
+
store: "replay",
|
|
26575
|
+
filePath: fp,
|
|
26576
|
+
operation: "record",
|
|
26577
|
+
outcome: "failure",
|
|
26578
|
+
error: storageErrorString2(err),
|
|
26579
|
+
recoverable: false,
|
|
26580
|
+
durationMs: Date.now() - t0,
|
|
26581
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26582
|
+
});
|
|
26583
|
+
throw err;
|
|
26584
|
+
}
|
|
25550
26585
|
}
|
|
25551
26586
|
// ── Reads ───────────────────────────────────────────────────────────────
|
|
25552
26587
|
/**
|
|
@@ -25555,13 +26590,65 @@ var ReplayLogStore = class {
|
|
|
25555
26590
|
* per session (in-memory cache).
|
|
25556
26591
|
*/
|
|
25557
26592
|
async lookup(sessionId, hash) {
|
|
25558
|
-
const
|
|
25559
|
-
|
|
26593
|
+
const fp = this.filePath(sessionId);
|
|
26594
|
+
const t0 = Date.now();
|
|
26595
|
+
try {
|
|
26596
|
+
const cache = await this.ensureCache(sessionId);
|
|
26597
|
+
this.events?.emit("storage.read", {
|
|
26598
|
+
sessionId,
|
|
26599
|
+
store: "replay",
|
|
26600
|
+
filePath: fp,
|
|
26601
|
+
operation: "lookup",
|
|
26602
|
+
outcome: "success",
|
|
26603
|
+
durationMs: Date.now() - t0,
|
|
26604
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26605
|
+
});
|
|
26606
|
+
return cache.get(hash) ?? null;
|
|
26607
|
+
} catch (err) {
|
|
26608
|
+
this.events?.emit("storage.read", {
|
|
26609
|
+
sessionId,
|
|
26610
|
+
store: "replay",
|
|
26611
|
+
filePath: fp,
|
|
26612
|
+
operation: "lookup",
|
|
26613
|
+
outcome: "failure",
|
|
26614
|
+
durationMs: Date.now() - t0,
|
|
26615
|
+
error: storageErrorString2(err),
|
|
26616
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26617
|
+
});
|
|
26618
|
+
throw err;
|
|
26619
|
+
}
|
|
25560
26620
|
}
|
|
25561
26621
|
/** All recorded entries for a session, in insertion order. */
|
|
25562
26622
|
async load(sessionId) {
|
|
25563
|
-
const
|
|
25564
|
-
|
|
26623
|
+
const fp = this.filePath(sessionId);
|
|
26624
|
+
const t0 = Date.now();
|
|
26625
|
+
try {
|
|
26626
|
+
const cache = await this.ensureCache(sessionId);
|
|
26627
|
+
const durationMs = Date.now() - t0;
|
|
26628
|
+
this.events?.emit("storage.read", {
|
|
26629
|
+
sessionId,
|
|
26630
|
+
store: "replay",
|
|
26631
|
+
filePath: fp,
|
|
26632
|
+
operation: "load",
|
|
26633
|
+
outcome: "success",
|
|
26634
|
+
durationMs,
|
|
26635
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26636
|
+
});
|
|
26637
|
+
return [...cache.values()];
|
|
26638
|
+
} catch (err) {
|
|
26639
|
+
const durationMs = Date.now() - t0;
|
|
26640
|
+
this.events?.emit("storage.read", {
|
|
26641
|
+
sessionId,
|
|
26642
|
+
store: "replay",
|
|
26643
|
+
filePath: fp,
|
|
26644
|
+
operation: "load",
|
|
26645
|
+
outcome: "failure",
|
|
26646
|
+
durationMs,
|
|
26647
|
+
error: storageErrorString2(err),
|
|
26648
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26649
|
+
});
|
|
26650
|
+
throw err;
|
|
26651
|
+
}
|
|
25565
26652
|
}
|
|
25566
26653
|
/**
|
|
25567
26654
|
* List every session id that has a replay log in the store dir.
|
|
@@ -25631,13 +26718,24 @@ var ReplayLogStore = class {
|
|
|
25631
26718
|
return out;
|
|
25632
26719
|
} catch (err) {
|
|
25633
26720
|
if (err.code === "ENOENT") return [];
|
|
25634
|
-
|
|
26721
|
+
throw err;
|
|
25635
26722
|
}
|
|
25636
26723
|
}
|
|
25637
|
-
async writeAll(sessionId, entries) {
|
|
26724
|
+
async writeAll(sessionId, entries, operation = "record") {
|
|
25638
26725
|
const fp = this.filePath(sessionId);
|
|
26726
|
+
const t0 = Date.now();
|
|
25639
26727
|
const body = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length ? "\n" : "");
|
|
25640
26728
|
await atomicWrite(fp, body);
|
|
26729
|
+
const durationMs = Date.now() - t0;
|
|
26730
|
+
this.events?.emit("storage.write", {
|
|
26731
|
+
sessionId,
|
|
26732
|
+
store: "replay",
|
|
26733
|
+
filePath: fp,
|
|
26734
|
+
operation,
|
|
26735
|
+
outcome: "success",
|
|
26736
|
+
durationMs,
|
|
26737
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26738
|
+
});
|
|
25641
26739
|
}
|
|
25642
26740
|
async ensureCache(sessionId) {
|
|
25643
26741
|
let cache = this.cache.get(sessionId);
|
|
@@ -25818,6 +26916,8 @@ var GENESIS_PREV = "0".repeat(64);
|
|
|
25818
26916
|
var DEFAULT_FSYNC_EVERY = 100;
|
|
25819
26917
|
var ToolAuditLog = class {
|
|
25820
26918
|
dir;
|
|
26919
|
+
events;
|
|
26920
|
+
traceId;
|
|
25821
26921
|
/** In-memory cache of the last entry's hash (per session), to compute chains efficiently. */
|
|
25822
26922
|
tailHash = /* @__PURE__ */ new Map();
|
|
25823
26923
|
/** In-memory counter for entry indices — avoids re-reading the file on every write. */
|
|
@@ -25828,6 +26928,8 @@ var ToolAuditLog = class {
|
|
|
25828
26928
|
fsyncEvery;
|
|
25829
26929
|
constructor(opts) {
|
|
25830
26930
|
this.dir = opts.dir;
|
|
26931
|
+
this.events = opts.events;
|
|
26932
|
+
this.traceId = opts.traceId;
|
|
25831
26933
|
this.fsyncEvery = opts.fsyncEvery ?? DEFAULT_FSYNC_EVERY;
|
|
25832
26934
|
}
|
|
25833
26935
|
/**
|
|
@@ -25838,96 +26940,180 @@ var ToolAuditLog = class {
|
|
|
25838
26940
|
*/
|
|
25839
26941
|
async record(input) {
|
|
25840
26942
|
let entry;
|
|
25841
|
-
|
|
25842
|
-
|
|
25843
|
-
|
|
25844
|
-
|
|
25845
|
-
|
|
25846
|
-
|
|
25847
|
-
|
|
25848
|
-
|
|
25849
|
-
|
|
25850
|
-
id
|
|
25851
|
-
ts
|
|
25852
|
-
|
|
25853
|
-
|
|
25854
|
-
|
|
25855
|
-
|
|
25856
|
-
|
|
25857
|
-
|
|
25858
|
-
|
|
25859
|
-
|
|
25860
|
-
|
|
25861
|
-
|
|
25862
|
-
|
|
25863
|
-
|
|
25864
|
-
|
|
25865
|
-
|
|
25866
|
-
|
|
25867
|
-
|
|
25868
|
-
|
|
25869
|
-
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
|
|
26943
|
+
const fp = this.filePath(input.sessionId);
|
|
26944
|
+
const t0 = Date.now();
|
|
26945
|
+
try {
|
|
26946
|
+
await this.enqueue(input.sessionId, async () => {
|
|
26947
|
+
await withFileLock(fp, async () => {
|
|
26948
|
+
const entries = await this.readAll(input.sessionId);
|
|
26949
|
+
const prev = entries.at(-1);
|
|
26950
|
+
const prevHash = prev?.hash ?? GENESIS_PREV;
|
|
26951
|
+
const index = prev ? prev.index + 1 : 0;
|
|
26952
|
+
const id = randomUUID();
|
|
26953
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
26954
|
+
const content = {
|
|
26955
|
+
id,
|
|
26956
|
+
ts,
|
|
26957
|
+
prevHash,
|
|
26958
|
+
toolName: input.toolName,
|
|
26959
|
+
toolUseId: input.toolUseId,
|
|
26960
|
+
input: input.input,
|
|
26961
|
+
output: input.output,
|
|
26962
|
+
isError: input.isError,
|
|
26963
|
+
index
|
|
26964
|
+
};
|
|
26965
|
+
const hash = createHash("sha256").update(stableStringify2(content), "utf8").digest("hex");
|
|
26966
|
+
entry = {
|
|
26967
|
+
id,
|
|
26968
|
+
ts,
|
|
26969
|
+
prevHash,
|
|
26970
|
+
hash,
|
|
26971
|
+
toolName: input.toolName,
|
|
26972
|
+
toolUseId: input.toolUseId,
|
|
26973
|
+
input: input.input,
|
|
26974
|
+
output: input.output,
|
|
26975
|
+
isError: input.isError,
|
|
26976
|
+
index
|
|
26977
|
+
};
|
|
26978
|
+
entries.push(entry);
|
|
26979
|
+
await this.writeAll(input.sessionId, entries);
|
|
26980
|
+
this.tailHash.set(input.sessionId, hash);
|
|
26981
|
+
this.tailIndex.set(input.sessionId, index + 1);
|
|
26982
|
+
const durationMs = Date.now() - t0;
|
|
26983
|
+
this.events?.emit("storage.write", {
|
|
26984
|
+
sessionId: input.sessionId,
|
|
26985
|
+
store: "audit",
|
|
26986
|
+
filePath: fp,
|
|
26987
|
+
operation: "record",
|
|
26988
|
+
outcome: "success",
|
|
26989
|
+
durationMs,
|
|
26990
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
26991
|
+
});
|
|
26992
|
+
});
|
|
25877
26993
|
});
|
|
25878
|
-
|
|
25879
|
-
|
|
26994
|
+
return entry;
|
|
26995
|
+
} catch (err) {
|
|
26996
|
+
this.events?.emit("storage.error", {
|
|
26997
|
+
sessionId: input.sessionId,
|
|
26998
|
+
store: "audit",
|
|
26999
|
+
filePath: fp,
|
|
27000
|
+
operation: "record",
|
|
27001
|
+
outcome: "failure",
|
|
27002
|
+
error: err instanceof Error ? err.message : String(err),
|
|
27003
|
+
recoverable: false,
|
|
27004
|
+
durationMs: Date.now() - t0,
|
|
27005
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
27006
|
+
});
|
|
27007
|
+
throw err;
|
|
27008
|
+
}
|
|
25880
27009
|
}
|
|
25881
27010
|
/**
|
|
25882
27011
|
* Walk the chain and verify every entry's hash and prevHash.
|
|
25883
27012
|
* Returns a structured verdict — never throws.
|
|
25884
27013
|
*/
|
|
25885
27014
|
async verify(sessionId) {
|
|
25886
|
-
const
|
|
25887
|
-
|
|
25888
|
-
|
|
25889
|
-
|
|
25890
|
-
|
|
25891
|
-
|
|
25892
|
-
|
|
25893
|
-
|
|
27015
|
+
const fp = this.filePath(sessionId);
|
|
27016
|
+
const t0 = Date.now();
|
|
27017
|
+
let entries;
|
|
27018
|
+
try {
|
|
27019
|
+
entries = await this.readAll(sessionId);
|
|
27020
|
+
} catch (err) {
|
|
27021
|
+
this.events?.emit("storage.read", {
|
|
27022
|
+
sessionId,
|
|
27023
|
+
store: "audit",
|
|
27024
|
+
filePath: fp,
|
|
27025
|
+
operation: "verify",
|
|
27026
|
+
outcome: "failure",
|
|
27027
|
+
durationMs: Date.now() - t0,
|
|
27028
|
+
error: err instanceof Error ? err.message : String(err),
|
|
27029
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
27030
|
+
});
|
|
27031
|
+
return { ok: true, entries: 0 };
|
|
25894
27032
|
}
|
|
25895
|
-
|
|
25896
|
-
|
|
25897
|
-
|
|
25898
|
-
if (e.prevHash !== prevHash) {
|
|
27033
|
+
const verdict = (() => {
|
|
27034
|
+
if (entries.length === 0) return { ok: true, entries: 0 };
|
|
27035
|
+
if (entries[0]?.prevHash !== GENESIS_PREV) {
|
|
25899
27036
|
return {
|
|
25900
27037
|
ok: false,
|
|
25901
|
-
brokenAt:
|
|
25902
|
-
reason:
|
|
27038
|
+
brokenAt: 0,
|
|
27039
|
+
reason: "first entry is not the genesis (prevHash != 0\u20260)"
|
|
25903
27040
|
};
|
|
25904
27041
|
}
|
|
25905
|
-
|
|
25906
|
-
|
|
25907
|
-
|
|
25908
|
-
|
|
25909
|
-
|
|
25910
|
-
|
|
25911
|
-
|
|
25912
|
-
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
25919
|
-
|
|
25920
|
-
|
|
25921
|
-
|
|
27042
|
+
let prevHash = GENESIS_PREV;
|
|
27043
|
+
for (let i = 0; i < entries.length; i++) {
|
|
27044
|
+
const e = expectDefined(entries[i]);
|
|
27045
|
+
if (e.prevHash !== prevHash) {
|
|
27046
|
+
return {
|
|
27047
|
+
ok: false,
|
|
27048
|
+
brokenAt: i,
|
|
27049
|
+
reason: `prevHash mismatch at entry ${i} (expected ${prevHash.slice(0, 8)}\u2026, got ${e.prevHash.slice(0, 8)}\u2026)`
|
|
27050
|
+
};
|
|
27051
|
+
}
|
|
27052
|
+
const content = {
|
|
27053
|
+
id: e.id,
|
|
27054
|
+
ts: e.ts,
|
|
27055
|
+
prevHash: e.prevHash,
|
|
27056
|
+
toolName: e.toolName,
|
|
27057
|
+
toolUseId: e.toolUseId,
|
|
27058
|
+
input: e.input,
|
|
27059
|
+
output: e.output,
|
|
27060
|
+
isError: e.isError,
|
|
27061
|
+
index: e.index
|
|
25922
27062
|
};
|
|
27063
|
+
const expectedHash = createHash("sha256").update(stableStringify2(content), "utf8").digest("hex");
|
|
27064
|
+
if (expectedHash !== e.hash) {
|
|
27065
|
+
return {
|
|
27066
|
+
ok: false,
|
|
27067
|
+
brokenAt: i,
|
|
27068
|
+
reason: `hash mismatch at entry ${i} (entry content was modified)`
|
|
27069
|
+
};
|
|
27070
|
+
}
|
|
27071
|
+
prevHash = e.hash;
|
|
25923
27072
|
}
|
|
25924
|
-
|
|
25925
|
-
}
|
|
25926
|
-
|
|
27073
|
+
return { ok: true, entries: entries.length };
|
|
27074
|
+
})();
|
|
27075
|
+
this.events?.emit("storage.read", {
|
|
27076
|
+
sessionId,
|
|
27077
|
+
store: "audit",
|
|
27078
|
+
filePath: fp,
|
|
27079
|
+
operation: "verify",
|
|
27080
|
+
outcome: verdict.ok ? "success" : "failure",
|
|
27081
|
+
durationMs: Date.now() - t0,
|
|
27082
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
27083
|
+
});
|
|
27084
|
+
return verdict;
|
|
25927
27085
|
}
|
|
25928
27086
|
/** All entries for a session, in insertion order. */
|
|
25929
27087
|
async load(sessionId) {
|
|
25930
|
-
|
|
27088
|
+
const fp = this.filePath(sessionId);
|
|
27089
|
+
const t0 = Date.now();
|
|
27090
|
+
try {
|
|
27091
|
+
const entries = await this.readAll(sessionId);
|
|
27092
|
+
const durationMs = Date.now() - t0;
|
|
27093
|
+
this.events?.emit("storage.read", {
|
|
27094
|
+
sessionId,
|
|
27095
|
+
store: "audit",
|
|
27096
|
+
filePath: fp,
|
|
27097
|
+
operation: "load",
|
|
27098
|
+
outcome: "success",
|
|
27099
|
+
durationMs,
|
|
27100
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
27101
|
+
});
|
|
27102
|
+
return entries;
|
|
27103
|
+
} catch (err) {
|
|
27104
|
+
const durationMs = Date.now() - t0;
|
|
27105
|
+
this.events?.emit("storage.read", {
|
|
27106
|
+
sessionId,
|
|
27107
|
+
store: "audit",
|
|
27108
|
+
filePath: fp,
|
|
27109
|
+
operation: "load",
|
|
27110
|
+
outcome: "failure",
|
|
27111
|
+
durationMs,
|
|
27112
|
+
error: err instanceof Error ? err.message : String(err),
|
|
27113
|
+
...this.traceId !== void 0 ? { traceId: this.traceId } : {}
|
|
27114
|
+
});
|
|
27115
|
+
throw err;
|
|
27116
|
+
}
|
|
25931
27117
|
}
|
|
25932
27118
|
// ── Internals ────────────────────────────────────────────────────────────
|
|
25933
27119
|
filePath(sessionId) {
|
|
@@ -25949,7 +27135,7 @@ var ToolAuditLog = class {
|
|
|
25949
27135
|
return out;
|
|
25950
27136
|
} catch (err) {
|
|
25951
27137
|
if (err.code === "ENOENT") return [];
|
|
25952
|
-
|
|
27138
|
+
throw err;
|
|
25953
27139
|
}
|
|
25954
27140
|
}
|
|
25955
27141
|
async writeAll(sessionId, entries) {
|
|
@@ -26349,37 +27535,98 @@ function emptyTaskFile(sessionId) {
|
|
|
26349
27535
|
tasks: []
|
|
26350
27536
|
};
|
|
26351
27537
|
}
|
|
26352
|
-
async function loadTasks(filePath) {
|
|
27538
|
+
async function loadTasks(filePath, events, traceId) {
|
|
27539
|
+
const t0 = Date.now();
|
|
26353
27540
|
let raw;
|
|
26354
27541
|
try {
|
|
26355
27542
|
raw = await fsp3.readFile(filePath, "utf8");
|
|
26356
|
-
} catch {
|
|
27543
|
+
} catch (err) {
|
|
27544
|
+
events?.emit("storage.error", {
|
|
27545
|
+
sessionId: traceId ?? "~boot~",
|
|
27546
|
+
store: "tasks",
|
|
27547
|
+
filePath,
|
|
27548
|
+
operation: "load",
|
|
27549
|
+
outcome: "failure",
|
|
27550
|
+
error: err instanceof Error ? err.message : String(err),
|
|
27551
|
+
recoverable: true
|
|
27552
|
+
});
|
|
26357
27553
|
return null;
|
|
26358
27554
|
}
|
|
26359
27555
|
try {
|
|
26360
27556
|
const parsed = JSON.parse(raw);
|
|
26361
|
-
if (parsed?.version !== 1 || !Array.isArray(parsed.tasks))
|
|
27557
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.tasks)) {
|
|
27558
|
+
events?.emit("storage.read", {
|
|
27559
|
+
sessionId: traceId ?? "~boot~",
|
|
27560
|
+
store: "tasks",
|
|
27561
|
+
filePath,
|
|
27562
|
+
operation: "load",
|
|
27563
|
+
outcome: "failure",
|
|
27564
|
+
durationMs: Date.now() - t0,
|
|
27565
|
+
error: "invalid_schema",
|
|
27566
|
+
...traceId !== void 0 && { traceId }
|
|
27567
|
+
});
|
|
27568
|
+
return null;
|
|
27569
|
+
}
|
|
27570
|
+
events?.emit("storage.read", {
|
|
27571
|
+
sessionId: traceId ?? "~boot~",
|
|
27572
|
+
store: "tasks",
|
|
27573
|
+
filePath,
|
|
27574
|
+
operation: "load",
|
|
27575
|
+
outcome: "success",
|
|
27576
|
+
durationMs: Date.now() - t0,
|
|
27577
|
+
...traceId !== void 0 && { traceId }
|
|
27578
|
+
});
|
|
26362
27579
|
return parsed;
|
|
26363
27580
|
} catch {
|
|
27581
|
+
events?.emit("storage.read", {
|
|
27582
|
+
sessionId: traceId ?? "~boot~",
|
|
27583
|
+
store: "tasks",
|
|
27584
|
+
filePath,
|
|
27585
|
+
operation: "load",
|
|
27586
|
+
outcome: "failure",
|
|
27587
|
+
durationMs: Date.now() - t0,
|
|
27588
|
+
error: "parse_failed",
|
|
27589
|
+
...traceId !== void 0 && { traceId }
|
|
27590
|
+
});
|
|
26364
27591
|
return null;
|
|
26365
27592
|
}
|
|
26366
27593
|
}
|
|
26367
|
-
async function saveTasks(filePath, tasks) {
|
|
27594
|
+
async function saveTasks(filePath, tasks, events, traceId) {
|
|
27595
|
+
const t0 = Date.now();
|
|
26368
27596
|
try {
|
|
26369
27597
|
tasks.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26370
27598
|
await atomicWrite(filePath, JSON.stringify(tasks, null, 2), { mode: 384 });
|
|
27599
|
+
events?.emit("storage.write", {
|
|
27600
|
+
sessionId: traceId ?? "~boot~",
|
|
27601
|
+
store: "tasks",
|
|
27602
|
+
filePath,
|
|
27603
|
+
operation: "save",
|
|
27604
|
+
outcome: "success",
|
|
27605
|
+
durationMs: Date.now() - t0,
|
|
27606
|
+
...traceId !== void 0 && { traceId }
|
|
27607
|
+
});
|
|
26371
27608
|
} catch (err) {
|
|
27609
|
+
events?.emit("storage.error", {
|
|
27610
|
+
sessionId: traceId ?? "~boot~",
|
|
27611
|
+
store: "tasks",
|
|
27612
|
+
filePath,
|
|
27613
|
+
operation: "save",
|
|
27614
|
+
outcome: "failure",
|
|
27615
|
+
error: err instanceof Error ? err.message : String(err),
|
|
27616
|
+
recoverable: false,
|
|
27617
|
+
...traceId !== void 0 && { traceId }
|
|
27618
|
+
});
|
|
26372
27619
|
console.warn(
|
|
26373
27620
|
"[task-store] save failed:",
|
|
26374
27621
|
err instanceof Error ? err.message : String(err)
|
|
26375
27622
|
);
|
|
26376
27623
|
}
|
|
26377
27624
|
}
|
|
26378
|
-
async function mutateTasks(filePath, sessionId, fn) {
|
|
27625
|
+
async function mutateTasks(filePath, sessionId, fn, events, traceId) {
|
|
26379
27626
|
return withFileLock(filePath, async () => {
|
|
26380
|
-
const file = await loadTasks(filePath) ?? emptyTaskFile(sessionId);
|
|
27627
|
+
const file = await loadTasks(filePath, events, traceId) ?? emptyTaskFile(sessionId);
|
|
26381
27628
|
const updated = await fn(file);
|
|
26382
|
-
await saveTasks(filePath, updated);
|
|
27629
|
+
await saveTasks(filePath, updated, events, traceId);
|
|
26383
27630
|
return updated;
|
|
26384
27631
|
});
|
|
26385
27632
|
}
|
|
@@ -30686,8 +31933,9 @@ function buildMailboxBlock(messages) {
|
|
|
30686
31933
|
const parts = [];
|
|
30687
31934
|
parts.push("[MAILBOX] New message(s) from other agents:");
|
|
30688
31935
|
parts.push("");
|
|
31936
|
+
const hasActionable = messages.some((m) => m.type === "ask" || m.type === "assign" || m.type === "result");
|
|
30689
31937
|
for (const m of messages) {
|
|
30690
|
-
const typeLabel = m.type === "steer" ? "\u{1F504} STEER" : m.type === "btw" ? "\u{1F4AC} BTW" : `\u{1F4E8} ${m.type.toUpperCase()}`;
|
|
31938
|
+
const typeLabel = m.type === "steer" ? "\u{1F504} STEER" : m.type === "btw" ? "\u{1F4AC} BTW" : m.type === "ask" ? "\u2753 ASK" : m.type === "assign" ? "\u{1F4CB} ASSIGN" : m.type === "result" ? "\u2705 RESULT" : `\u{1F4E8} ${m.type.toUpperCase()}`;
|
|
30691
31939
|
parts.push(`--- ${typeLabel} from ${m.from} ---`);
|
|
30692
31940
|
parts.push(`Subject: ${m.subject}`);
|
|
30693
31941
|
parts.push("");
|
|
@@ -30697,6 +31945,22 @@ function buildMailboxBlock(messages) {
|
|
|
30697
31945
|
parts.push("After your current operation reaches a stopping point, adjust your approach per the instruction above.");
|
|
30698
31946
|
parts.push("");
|
|
30699
31947
|
}
|
|
31948
|
+
if (m.type === "ask") {
|
|
31949
|
+
parts.push("\u21B3 This agent is waiting for your answer. Reply directly or use mailbox action=send to respond.");
|
|
31950
|
+
parts.push("");
|
|
31951
|
+
}
|
|
31952
|
+
if (m.type === "assign") {
|
|
31953
|
+
parts.push("\u21B3 This is a task assignment. Act on it when your current operation allows.");
|
|
31954
|
+
parts.push("");
|
|
31955
|
+
}
|
|
31956
|
+
if (m.type === "result") {
|
|
31957
|
+
parts.push("\u21B3 A subagent has completed its work. Factor this result into your next decision.");
|
|
31958
|
+
parts.push("");
|
|
31959
|
+
}
|
|
31960
|
+
}
|
|
31961
|
+
if (hasActionable) {
|
|
31962
|
+
parts.push("Action required: address the items above. When done, use `mailbox action=ack messageId=<id> completed=true` to mark them complete.");
|
|
31963
|
+
parts.push("");
|
|
30700
31964
|
}
|
|
30701
31965
|
parts.push("[END MAILBOX]");
|
|
30702
31966
|
return { type: "text", text: parts.join("\n") };
|
|
@@ -30717,26 +31981,12 @@ async function injectPendingMailboxMessages(checkMailbox, foldFn, a) {
|
|
|
30717
31981
|
});
|
|
30718
31982
|
}
|
|
30719
31983
|
if (messages.length === 0) return;
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
|
|
30723
|
-
|
|
30724
|
-
|
|
30725
|
-
|
|
30726
|
-
(a.logger.debug ?? console.debug)?.(
|
|
30727
|
-
`mailbox: failed to fold messages: ${err instanceof Error ? err.message : String(err)}`
|
|
30728
|
-
);
|
|
30729
|
-
}
|
|
30730
|
-
}
|
|
30731
|
-
if (others.length > 0) {
|
|
30732
|
-
const otherSubjects = others.map((m) => ` - [${m.type}] ${m.from}: ${m.subject}`).join("\n");
|
|
30733
|
-
const note = `[MAILBOX] You have ${others.length} other unread message(s). Use \`mailbox action=check\` to read them:
|
|
30734
|
-
${otherSubjects}
|
|
30735
|
-
[END MAILBOX]`;
|
|
30736
|
-
try {
|
|
30737
|
-
foldFn({ type: "text", text: note });
|
|
30738
|
-
} catch {
|
|
30739
|
-
}
|
|
31984
|
+
try {
|
|
31985
|
+
foldFn(buildMailboxBlock(messages));
|
|
31986
|
+
} catch (err) {
|
|
31987
|
+
(a.logger.debug ?? console.debug)?.(
|
|
31988
|
+
`mailbox: failed to fold messages: ${err instanceof Error ? err.message : String(err)}`
|
|
31989
|
+
);
|
|
30740
31990
|
}
|
|
30741
31991
|
}
|
|
30742
31992
|
|
|
@@ -31751,9 +33001,26 @@ async function writeProjectMeta(paths, projectRoot) {
|
|
|
31751
33001
|
} catch {
|
|
31752
33002
|
}
|
|
31753
33003
|
}
|
|
31754
|
-
async function registerProjectInManifest(paths, projectRoot) {
|
|
33004
|
+
async function registerProjectInManifest(paths, projectRoot, events) {
|
|
33005
|
+
const manifestPath = path7.join(paths.globalRoot, "projects.json");
|
|
33006
|
+
try {
|
|
33007
|
+
const t0 = Date.now();
|
|
33008
|
+
const raw = await fsp3.readFile(manifestPath, "utf8");
|
|
33009
|
+
events?.emit("storage.read", {
|
|
33010
|
+
sessionId: "~boot~",
|
|
33011
|
+
store: "project",
|
|
33012
|
+
filePath: manifestPath,
|
|
33013
|
+
operation: "manifest_read",
|
|
33014
|
+
outcome: "success",
|
|
33015
|
+
durationMs: Date.now() - t0
|
|
33016
|
+
});
|
|
33017
|
+
try {
|
|
33018
|
+
JSON.parse(raw);
|
|
33019
|
+
} catch {
|
|
33020
|
+
}
|
|
33021
|
+
} catch (err) {
|
|
33022
|
+
}
|
|
31755
33023
|
try {
|
|
31756
|
-
const manifestPath = path7.join(paths.globalRoot, "projects.json");
|
|
31757
33024
|
let manifest;
|
|
31758
33025
|
try {
|
|
31759
33026
|
const raw = await fsp3.readFile(manifestPath, "utf8");
|
|
@@ -31770,8 +33037,17 @@ async function registerProjectInManifest(paths, projectRoot) {
|
|
|
31770
33037
|
const name = path7.basename(projectRoot);
|
|
31771
33038
|
manifest.projects.push({ name, root: projectRoot, slug, lastSeen: now, createdAt: now });
|
|
31772
33039
|
}
|
|
33040
|
+
const writeT0 = Date.now();
|
|
31773
33041
|
await fsp3.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
31774
|
-
|
|
33042
|
+
events?.emit("storage.write", {
|
|
33043
|
+
sessionId: "~boot~",
|
|
33044
|
+
store: "project",
|
|
33045
|
+
filePath: manifestPath,
|
|
33046
|
+
operation: "manifest_write",
|
|
33047
|
+
outcome: "success",
|
|
33048
|
+
durationMs: Date.now() - writeT0
|
|
33049
|
+
});
|
|
33050
|
+
} catch (err) {
|
|
31775
33051
|
}
|
|
31776
33052
|
}
|
|
31777
33053
|
var GITIGNORE_ENTRY = ".wrongstack/\n";
|
|
@@ -32036,9 +33312,10 @@ Never silently skip a failure \u2014 always report it, even when you choose not
|
|
|
32036
33312
|
|
|
32037
33313
|
## After-task suggestions
|
|
32038
33314
|
|
|
32039
|
-
After completing a significant task, end your
|
|
32040
|
-
actions in a \`<next_steps>\` block. Use this
|
|
32041
|
-
select them with \`/next 1\`, \`/next 2\`, or
|
|
33315
|
+
**You are the leader agent.** After completing a significant task, end your
|
|
33316
|
+
response with 2\u20134 suggested next actions in a \`<next_steps>\` block. Use this
|
|
33317
|
+
exact format so the user can select them with \`/next 1\`, \`/next 2\`, or
|
|
33318
|
+
\`/next 1 2 3\`:
|
|
32042
33319
|
|
|
32043
33320
|
\`\`\`
|
|
32044
33321
|
<next_steps>
|
|
@@ -32051,6 +33328,7 @@ select them with \`/next 1\`, \`/next 2\`, or \`/next 1 2 3\`:
|
|
|
32051
33328
|
Rules:
|
|
32052
33329
|
- Each line is a single imperative sentence the user can act on immediately.
|
|
32053
33330
|
- Be specific: mention file names, tool names, or commands.
|
|
33331
|
+
- **Concrete actions only** \u2014 never write declarations of intent ("we should fix X", "consider refactoring Y") or manual suggestions ("manually check Z"). Write exactly what should be done: "Fix null deref in auth/session.ts:42", "Run pnpm typecheck".
|
|
32054
33332
|
- Order by priority. Keep each suggestion to one line.
|
|
32055
33333
|
- Skip during multi-step operations \u2014 only show after completion.
|
|
32056
33334
|
- If nothing is pending, say "No pending actions."
|
|
@@ -32380,8 +33658,17 @@ sender's exact \`from\` id.
|
|
|
32380
33658
|
### Receiving
|
|
32381
33659
|
|
|
32382
33660
|
Unread mail (direct, base-name, and \`*\` broadcasts) is injected into
|
|
32383
|
-
your conversation automatically before each step \u2014
|
|
32384
|
-
|
|
33661
|
+
your conversation automatically before each step \u2014 ALL message types
|
|
33662
|
+
(steer, btw, ask, assign, result, note) appear inline with a call to
|
|
33663
|
+
action. You do NOT need to manually check the mailbox; subagent results
|
|
33664
|
+
and questions reach you even while you are mid-task.
|
|
33665
|
+
|
|
33666
|
+
When a message includes a call to action:
|
|
33667
|
+
- **ask**: reply to the agent directly or use \`mail_send\` to respond
|
|
33668
|
+
- **assign**: act on the task when your current operation allows
|
|
33669
|
+
- **result**: factor the outcome into your next decision
|
|
33670
|
+
|
|
33671
|
+
To catch up explicitly:
|
|
32385
33672
|
|
|
32386
33673
|
- \`mail_inbox\` \u2014 read your unread mail and mark it read
|
|
32387
33674
|
- \`mailbox action=query from=<agent> type=result\` \u2014 find specific results
|
|
@@ -38351,6 +39638,6 @@ function createChimeraPlugin() {
|
|
|
38351
39638
|
};
|
|
38352
39639
|
}
|
|
38353
39640
|
|
|
38354
|
-
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BrainMonitor, BudgetExceededError, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEPENDENCY_FILE_PATTERNS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertNever, assertSafePath, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMailboxChecker, createMcpControlTool, createMcpUseTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isPrimitiveArray, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizeRecipient, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveChimeraConfig, resolveContextWindowPolicy, resolveMailboxIdentity, resolveModelMatrix, resolveProjectDir, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startTechStackConsumer, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updatePackageOutdatedStatus, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
39641
|
+
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BrainMonitor, BudgetExceededError, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEPENDENCY_FILE_PATTERNS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertNever, assertNotPrivateHost, assertSafePath, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMailboxChecker, createMcpControlTool, createMcpUseTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expandIPv6, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isPrimitiveArray, isPrivateIPv4, isPrivateIPv6, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizeRecipient, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveChimeraConfig, resolveContextWindowPolicy, resolveMailboxIdentity, resolveModelMatrix, resolveProjectDir, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startTechStackConsumer, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updatePackageOutdatedStatus, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
38355
39642
|
//# sourceMappingURL=index.js.map
|
|
38356
39643
|
//# sourceMappingURL=index.js.map
|