@wrongstack/core 0.77.0 → 0.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-bridge-EWdqs8v6.d.ts → agent-bridge-C9P_HPez.d.ts} +2 -2
- package/dist/{agent-subagent-runner-D8qW8OSC.d.ts → agent-subagent-runner-2Aq0jOSj.d.ts} +107 -102
- package/dist/{compactor-D_ExJajC.d.ts → compactor-CJq7LQev.d.ts} +3 -3
- package/dist/{config-Dy0CK_o6.d.ts → config-_DZ7dN-T.d.ts} +77 -75
- package/dist/{context-y87Jc5ei.d.ts → context-ToHAp4-U.d.ts} +119 -90
- package/dist/coordination/index.d.ts +16 -16
- package/dist/coordination/index.js +318 -37
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +32 -32
- package/dist/defaults/index.js +433 -81
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-BmYi3DGA.d.ts → director-state-CgIc30qi.d.ts} +19 -19
- package/dist/{events-CYaoLN5_.d.ts → events-DnRqXaZ3.d.ts} +43 -42
- package/dist/execution/index.d.ts +53 -53
- package/dist/execution/index.js +72 -29
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +9 -9
- package/dist/extension/index.js +8 -1
- package/dist/extension/index.js.map +1 -1
- package/dist/{goal-store-C7jcumEh.d.ts → goal-store-DvWLNu52.d.ts} +4 -4
- package/dist/{index-DIxjTOga.d.ts → index-BNOLadHw.d.ts} +28 -28
- package/dist/{index-Dsda0uCn.d.ts → index-N0_c4bHQ.d.ts} +45 -45
- package/dist/index.d.ts +167 -167
- package/dist/index.js +617 -155
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -9
- package/dist/infrastructure/index.js +13 -5
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +14 -14
- package/dist/kernel/index.js +7 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/logger-B72yyPc6.d.ts +12 -0
- package/dist/{logger-BppKxDqZ.d.ts → logger-C_27pj9i.d.ts} +6 -7
- package/dist/{mcp-servers-T0O6UN_w.d.ts → mcp-servers-Dck3T85_.d.ts} +20 -20
- package/dist/{mode-BO4SEUIv.d.ts → mode-CHo2XtHs.d.ts} +4 -4
- package/dist/models/index.d.ts +10 -10
- package/dist/models/index.js +8 -2
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-BcYJDKLm.d.ts → models-registry-Be3osGt5.d.ts} +28 -28
- package/dist/{models-registry-Cuq1C8V9.d.ts → models-registry-Boz639EI.d.ts} +12 -12
- package/dist/{multi-agent-coordinator-DpbG3wiy.d.ts → multi-agent-coordinator-DllpCVkF.d.ts} +12 -12
- package/dist/{null-fleet-bus-u5ys3lW_.d.ts → null-fleet-bus-BY0AN-sr.d.ts} +121 -121
- package/dist/observability/index.d.ts +41 -41
- package/dist/observability/index.js.map +1 -1
- package/dist/{observability-BhnVLBLS.d.ts → observability-CoSNZdhX.d.ts} +4 -4
- package/dist/{parallel-eternal-engine-Dn0P8Pbj.d.ts → parallel-eternal-engine-D402RASp.d.ts} +49 -49
- package/dist/{path-resolver-B32v2JIq.d.ts → path-resolver-UPFTsDyD.d.ts} +6 -6
- package/dist/{permission-V5BLOrY6.d.ts → permission-14CChMmO.d.ts} +10 -8
- package/dist/{permission-policy-CBVx-d-8.d.ts → permission-policy-gW5htOo1.d.ts} +7 -7
- package/dist/{plan-templates-BcUwLlMQ.d.ts → plan-templates-DRvPgkfZ.d.ts} +65 -32
- package/dist/{provider-runner-CSi_7l0h.d.ts → provider-runner-COAJM8tC.d.ts} +6 -6
- package/dist/{retry-policy-CG3qvH_e.d.ts → retry-policy-DSu6O6rD.d.ts} +4 -4
- package/dist/sdd/index.d.ts +47 -47
- package/dist/sdd/index.js +47 -22
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-7rSC_emZ.d.ts → secret-scrubber-yGBFQYju.d.ts} +10 -2
- package/dist/security/index.d.ts +7 -7
- package/dist/security/index.js +15 -8
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-RvBR_YRW.d.ts → selector-11-fm95U.d.ts} +2 -2
- package/dist/{session-event-bridge-CDHxcmQU.d.ts → session-event-bridge-D0u-x576.d.ts} +7 -7
- package/dist/{session-reader-BIpwM60D.d.ts → session-reader-BQU-toaN.d.ts} +23 -23
- package/dist/{skill-CxuWrsKK.d.ts → skill-BJeF2DwY.d.ts} +1 -1
- package/dist/skills/index.d.ts +9 -9
- package/dist/skills/index.js +15 -3
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +15 -15
- package/dist/storage/index.js +378 -76
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-CA11g6Jo.d.ts → system-prompt-C0rLCeyn.d.ts} +16 -11
- package/dist/{task-graph-D1YQbpxF.d.ts → task-graph-CikNdRTG.d.ts} +22 -22
- package/dist/types/index.d.ts +26 -26
- package/dist/types/index.js +53 -17
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +57 -45
- package/dist/utils/index.js +66 -12
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-D7evAFWM.d.ts → wstack-paths-BQMvEllz.d.ts} +2 -2
- package/package.json +1 -1
- package/dist/logger-DDd5C--Z.d.ts +0 -12
package/dist/defaults/index.js
CHANGED
|
@@ -108,8 +108,10 @@ function isStdoutTTY() {
|
|
|
108
108
|
}
|
|
109
109
|
function writeTo(s, stream) {
|
|
110
110
|
if (!stream || typeof stream.write !== "function") return false;
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
{
|
|
112
|
+
stream.write(s);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
113
115
|
}
|
|
114
116
|
function writeErr(s, stream = process.stderr) {
|
|
115
117
|
return writeTo(s, stream);
|
|
@@ -243,6 +245,12 @@ function formatCtx(ctx) {
|
|
|
243
245
|
init_atomic_write();
|
|
244
246
|
|
|
245
247
|
// src/utils/message-invariants.ts
|
|
248
|
+
function expectDefined(value) {
|
|
249
|
+
if (value === null || value === void 0) {
|
|
250
|
+
throw new Error("Expected value to be defined");
|
|
251
|
+
}
|
|
252
|
+
return value;
|
|
253
|
+
}
|
|
246
254
|
function repairToolUseAdjacency(messages) {
|
|
247
255
|
const removedToolUses = [];
|
|
248
256
|
const removedToolResults = [];
|
|
@@ -250,7 +258,7 @@ function repairToolUseAdjacency(messages) {
|
|
|
250
258
|
let changed = false;
|
|
251
259
|
const out = [];
|
|
252
260
|
for (let i = 0; i < messages.length; i++) {
|
|
253
|
-
const original = messages[i];
|
|
261
|
+
const original = expectDefined(messages[i]);
|
|
254
262
|
let msg = original;
|
|
255
263
|
if (hasToolUse(msg)) {
|
|
256
264
|
const nextIds = toolResultIds(messages[i + 1]);
|
|
@@ -335,6 +343,12 @@ function isEmptyMessage(msg) {
|
|
|
335
343
|
}
|
|
336
344
|
|
|
337
345
|
// src/storage/session-store.ts
|
|
346
|
+
function expectDefined2(value) {
|
|
347
|
+
if (value === null || value === void 0) {
|
|
348
|
+
throw new Error("Expected value to be defined");
|
|
349
|
+
}
|
|
350
|
+
return value;
|
|
351
|
+
}
|
|
338
352
|
function sanitizeModel(model) {
|
|
339
353
|
return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
340
354
|
}
|
|
@@ -345,7 +359,7 @@ function generateSessionId(startedAt, model) {
|
|
|
345
359
|
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
346
360
|
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
347
361
|
}
|
|
348
|
-
var DefaultSessionStore = class {
|
|
362
|
+
var DefaultSessionStore = class _DefaultSessionStore {
|
|
349
363
|
dir;
|
|
350
364
|
events;
|
|
351
365
|
secretScrubber;
|
|
@@ -354,6 +368,10 @@ var DefaultSessionStore = class {
|
|
|
354
368
|
this.events = opts.events;
|
|
355
369
|
this.secretScrubber = opts.secretScrubber;
|
|
356
370
|
}
|
|
371
|
+
/** Absolute path to the session index file. */
|
|
372
|
+
get indexFile() {
|
|
373
|
+
return path3.join(this.dir, "_index.jsonl");
|
|
374
|
+
}
|
|
357
375
|
/** Join session ID to its absolute path within the store directory. */
|
|
358
376
|
sessionPath(id, ext) {
|
|
359
377
|
return path3.join(this.dir, `${id}${ext}`);
|
|
@@ -386,7 +404,8 @@ var DefaultSessionStore = class {
|
|
|
386
404
|
return new FileSessionWriter(id, handle, startedAt, meta, this.events, {
|
|
387
405
|
dir: shardDir,
|
|
388
406
|
filePath: file,
|
|
389
|
-
secretScrubber: this.secretScrubber
|
|
407
|
+
secretScrubber: this.secretScrubber,
|
|
408
|
+
onClose: (s) => this.appendToIndex(s)
|
|
390
409
|
});
|
|
391
410
|
} catch (err) {
|
|
392
411
|
await handle.close().catch(() => {
|
|
@@ -417,7 +436,7 @@ var DefaultSessionStore = class {
|
|
|
417
436
|
provider: data.metadata.provider
|
|
418
437
|
},
|
|
419
438
|
this.events,
|
|
420
|
-
{ resumed: true, dir: this.dir, filePath: file, secretScrubber: this.secretScrubber }
|
|
439
|
+
{ resumed: true, dir: this.dir, filePath: file, secretScrubber: this.secretScrubber, onClose: (s) => this.appendToIndex(s) }
|
|
421
440
|
);
|
|
422
441
|
return { writer, data };
|
|
423
442
|
} catch (err) {
|
|
@@ -447,6 +466,15 @@ var DefaultSessionStore = class {
|
|
|
447
466
|
async list(limit = 20) {
|
|
448
467
|
try {
|
|
449
468
|
await ensureDir(this.dir);
|
|
469
|
+
const indexed = await this.readIndex();
|
|
470
|
+
if (indexed.length > 0) {
|
|
471
|
+
indexed.sort((a, b) => {
|
|
472
|
+
if (a.startedAt < b.startedAt) return 1;
|
|
473
|
+
if (a.startedAt > b.startedAt) return -1;
|
|
474
|
+
return a.id.localeCompare(b.id);
|
|
475
|
+
});
|
|
476
|
+
return indexed.slice(0, limit);
|
|
477
|
+
}
|
|
450
478
|
const ids = await this.collectSessionIds(this.dir);
|
|
451
479
|
const sessions = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
452
480
|
const out = sessions.filter((s) => s !== null);
|
|
@@ -460,16 +488,121 @@ var DefaultSessionStore = class {
|
|
|
460
488
|
return [];
|
|
461
489
|
}
|
|
462
490
|
}
|
|
463
|
-
|
|
464
|
-
|
|
491
|
+
// ── Session index (_index.jsonl) ─────────────────────────────────────────
|
|
492
|
+
//
|
|
493
|
+
// One JSON line per closed session, appended atomically on close().
|
|
494
|
+
// When a session is deleted, a tombstone {action:"delete",id:"..."} is
|
|
495
|
+
// appended. On read, tombstones filter out matching session entries.
|
|
496
|
+
// This keeps listing O(lines-in-index) instead of O(files-on-disk).
|
|
497
|
+
//
|
|
498
|
+
// The index auto-compacts every N appends to prevent unbounded growth
|
|
499
|
+
// from tombstones and duplicate entries (resume cycles).
|
|
500
|
+
indexAppendCount = 0;
|
|
501
|
+
static COMPACT_EVERY = 30;
|
|
502
|
+
/** Append a session summary to the index. */
|
|
503
|
+
async appendToIndex(summary) {
|
|
504
|
+
try {
|
|
505
|
+
await ensureDir(this.dir);
|
|
506
|
+
const line = JSON.stringify(summary) + "\n";
|
|
507
|
+
await fsp.appendFile(this.indexFile, line, "utf8");
|
|
508
|
+
this.indexAppendCount++;
|
|
509
|
+
if (this.indexAppendCount >= _DefaultSessionStore.COMPACT_EVERY) {
|
|
510
|
+
await this.compactIndex();
|
|
511
|
+
this.indexAppendCount = 0;
|
|
512
|
+
}
|
|
513
|
+
} catch {
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/** Append a tombstone entry for a deleted session. */
|
|
517
|
+
async writeTombstone(id) {
|
|
518
|
+
try {
|
|
519
|
+
await ensureDir(this.dir);
|
|
520
|
+
const line = JSON.stringify({ action: "delete", id }) + "\n";
|
|
521
|
+
await fsp.appendFile(this.indexFile, line, "utf8");
|
|
522
|
+
this.indexAppendCount++;
|
|
523
|
+
} catch {
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Compact the index: read all entries, drop tombstones, deduplicate
|
|
528
|
+
* (keep latest per session), and rewrite. Atomic via temp+rename.
|
|
529
|
+
*/
|
|
530
|
+
async compactIndex() {
|
|
531
|
+
const entries = await this.readIndex();
|
|
532
|
+
if (entries.length === 0) return;
|
|
533
|
+
const tmp = `${this.indexFile}.compact.tmp`;
|
|
534
|
+
const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
535
|
+
await fsp.writeFile(tmp, lines, "utf8");
|
|
536
|
+
await fsp.rename(tmp, this.indexFile);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Read the index file and return deduplicated session summaries.
|
|
540
|
+
* Entries with a matching tombstone are filtered out.
|
|
541
|
+
* Returns empty array when the index doesn't exist or is corrupt.
|
|
542
|
+
*/
|
|
543
|
+
async readIndex() {
|
|
544
|
+
let raw;
|
|
545
|
+
try {
|
|
546
|
+
raw = await fsp.readFile(this.indexFile, "utf8");
|
|
547
|
+
} catch {
|
|
548
|
+
return [];
|
|
549
|
+
}
|
|
550
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
551
|
+
const seen = /* @__PURE__ */ new Map();
|
|
552
|
+
for (const line of raw.split("\n")) {
|
|
553
|
+
if (!line.trim()) continue;
|
|
554
|
+
try {
|
|
555
|
+
const entry = JSON.parse(line);
|
|
556
|
+
if (entry.action === "delete" && entry.id) {
|
|
557
|
+
deleted.add(entry.id);
|
|
558
|
+
seen.delete(entry.id);
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if (entry.id && !deleted.has(entry.id)) {
|
|
562
|
+
seen.set(entry.id, entry);
|
|
563
|
+
}
|
|
564
|
+
} catch {
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return Array.from(seen.values());
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Rebuild the index from disk by scanning all sessions and writing a
|
|
571
|
+
* fresh _index.jsonl. Useful after manual cleanup or index corruption.
|
|
572
|
+
*/
|
|
573
|
+
async rebuildIndex() {
|
|
574
|
+
const ids = await this.collectSessionIds(this.dir);
|
|
575
|
+
const summaries = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
576
|
+
const valid = summaries.filter((s) => s !== null);
|
|
577
|
+
const tmp = `${this.indexFile}.tmp`;
|
|
578
|
+
const lines = valid.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
579
|
+
await fsp.writeFile(tmp, lines, "utf8");
|
|
580
|
+
await fsp.rename(tmp, this.indexFile);
|
|
581
|
+
return valid.length;
|
|
582
|
+
}
|
|
583
|
+
/** Recursively collect session IDs from date-shard subdirectories.
|
|
584
|
+
* IDs include the date-prefix path (e.g. "2026-06-06/17-46-57Z_…").
|
|
585
|
+
* Skips `.jsonl`/`.summary.json` root files, dot-files, and
|
|
586
|
+
* sub-directories that belong to fleet/subagent sessions. */
|
|
587
|
+
async collectSessionIds(dir, prefix = "", depth = 0) {
|
|
465
588
|
const ids = [];
|
|
466
|
-
|
|
589
|
+
let entries;
|
|
590
|
+
try {
|
|
591
|
+
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
592
|
+
} catch {
|
|
593
|
+
return ids;
|
|
594
|
+
}
|
|
467
595
|
for (const entry of entries) {
|
|
468
|
-
|
|
596
|
+
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
597
|
+
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
598
|
+
continue;
|
|
469
599
|
if (entry.isDirectory()) {
|
|
470
|
-
|
|
600
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
601
|
+
ids.push(...await this.collectSessionIds(path3.join(dir, entry.name), childPrefix, depth + 1));
|
|
471
602
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
472
|
-
|
|
603
|
+
if (entry.name === "_index.jsonl") continue;
|
|
604
|
+
const base = entry.name.replace(/\.jsonl$/, "");
|
|
605
|
+
ids.push(prefix ? `${prefix}/${base}` : base);
|
|
473
606
|
}
|
|
474
607
|
}
|
|
475
608
|
return ids;
|
|
@@ -492,9 +625,70 @@ var DefaultSessionStore = class {
|
|
|
492
625
|
return summary;
|
|
493
626
|
}
|
|
494
627
|
}
|
|
495
|
-
|
|
496
|
-
|
|
628
|
+
/**
|
|
629
|
+
* Delete a session and all associated files: JSONL, summary, plan/todos
|
|
630
|
+
* sidecars, and the session directory (fleet.json, shared/, subagents/).
|
|
631
|
+
*/
|
|
632
|
+
async deleteSession(id) {
|
|
633
|
+
await fsp.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
|
|
497
634
|
await fsp.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
|
|
635
|
+
const shardDir = path3.dirname(path3.join(this.dir, id));
|
|
636
|
+
const base = path3.basename(id);
|
|
637
|
+
for (const ext of [".plan.json", ".todos.json"]) {
|
|
638
|
+
await fsp.unlink(path3.join(shardDir, `${base}${ext}`)).catch(() => void 0);
|
|
639
|
+
}
|
|
640
|
+
const sessDir = path3.join(shardDir, base);
|
|
641
|
+
await fsp.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
|
|
642
|
+
await this.writeTombstone(id);
|
|
643
|
+
}
|
|
644
|
+
async delete(id) {
|
|
645
|
+
await this.deleteSession(id);
|
|
646
|
+
}
|
|
647
|
+
async prune(maxAgeDays = 30) {
|
|
648
|
+
const cutoff = Date.now() - maxAgeDays * 864e5;
|
|
649
|
+
let deleted = 0;
|
|
650
|
+
let activeSessionId = null;
|
|
651
|
+
try {
|
|
652
|
+
const raw = await fsp.readFile(path3.join(this.dir, "active.json"), "utf8");
|
|
653
|
+
const active = JSON.parse(raw);
|
|
654
|
+
activeSessionId = active.sessionId ?? null;
|
|
655
|
+
} catch {
|
|
656
|
+
}
|
|
657
|
+
const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);
|
|
658
|
+
for (const entry of entries) {
|
|
659
|
+
if (!entry.isDirectory()) continue;
|
|
660
|
+
const dateDir = path3.join(this.dir, entry.name);
|
|
661
|
+
const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
662
|
+
for (const file of files) {
|
|
663
|
+
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
664
|
+
const jsonlPath = path3.join(dateDir, file.name);
|
|
665
|
+
try {
|
|
666
|
+
const stat5 = await fsp.stat(jsonlPath);
|
|
667
|
+
if (stat5.mtimeMs >= cutoff) continue;
|
|
668
|
+
} catch {
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const id = `${entry.name}/${file.name.replace(/\.jsonl$/, "")}`;
|
|
672
|
+
if (activeSessionId && id === activeSessionId) continue;
|
|
673
|
+
await this.deleteSession(id);
|
|
674
|
+
deleted++;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (deleted > 0) {
|
|
678
|
+
await this.compactIndex().catch(() => void 0);
|
|
679
|
+
}
|
|
680
|
+
for (const entry of entries) {
|
|
681
|
+
if (!entry.isDirectory()) continue;
|
|
682
|
+
const dateDir = path3.join(this.dir, entry.name);
|
|
683
|
+
try {
|
|
684
|
+
const remaining = await fsp.readdir(dateDir);
|
|
685
|
+
if (remaining.length === 0) {
|
|
686
|
+
await fsp.rmdir(dateDir).catch(() => void 0);
|
|
687
|
+
}
|
|
688
|
+
} catch {
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return deleted;
|
|
498
692
|
}
|
|
499
693
|
async clearHistory(id) {
|
|
500
694
|
await this.ensureShardDir(id);
|
|
@@ -516,13 +710,42 @@ var DefaultSessionStore = class {
|
|
|
516
710
|
const data = await this.load(id);
|
|
517
711
|
const firstUser = data.events.find((e) => e.type === "user_input");
|
|
518
712
|
const title = firstUser && firstUser.type === "user_input" ? userInputTitle(firstUser.content) : "(empty session)";
|
|
713
|
+
let iterationCount = 0;
|
|
714
|
+
let toolCallCount = 0;
|
|
715
|
+
let toolErrorCount = 0;
|
|
716
|
+
let fileChangeCount = 0;
|
|
717
|
+
const toolBreakdown = {};
|
|
718
|
+
let outcome = void 0;
|
|
719
|
+
const lastEvent = data.events[data.events.length - 1];
|
|
720
|
+
for (const e of data.events) {
|
|
721
|
+
if (e.type === "in_flight_start") iterationCount++;
|
|
722
|
+
else if (e.type === "tool_call_start") {
|
|
723
|
+
toolCallCount++;
|
|
724
|
+
toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;
|
|
725
|
+
} else if (e.type === "tool_result" && e.isError) toolErrorCount++;
|
|
726
|
+
else if (e.type === "file_snapshot") fileChangeCount += e.files.length;
|
|
727
|
+
}
|
|
728
|
+
if (lastEvent?.type === "session_end") {
|
|
729
|
+
outcome = "completed";
|
|
730
|
+
} else if (lastEvent?.type === "in_flight_start") {
|
|
731
|
+
outcome = "aborted";
|
|
732
|
+
} else if (data.events.some((e) => e.type === "error")) {
|
|
733
|
+
outcome = "error";
|
|
734
|
+
}
|
|
519
735
|
return {
|
|
520
736
|
id,
|
|
521
737
|
title,
|
|
522
738
|
startedAt: data.metadata.startedAt,
|
|
739
|
+
endedAt: data.metadata.endedAt,
|
|
523
740
|
model: data.metadata.model ?? "unknown",
|
|
524
741
|
provider: data.metadata.provider ?? "unknown",
|
|
525
|
-
tokenTotal: data.usage.input + data.usage.output
|
|
742
|
+
tokenTotal: data.usage.input + data.usage.output,
|
|
743
|
+
iterationCount: iterationCount > 0 ? iterationCount : void 0,
|
|
744
|
+
toolCallCount: toolCallCount > 0 ? toolCallCount : void 0,
|
|
745
|
+
toolErrorCount: toolErrorCount > 0 ? toolErrorCount : void 0,
|
|
746
|
+
fileChangeCount: fileChangeCount > 0 ? fileChangeCount : void 0,
|
|
747
|
+
toolBreakdown: Object.keys(toolBreakdown).length > 0 ? toolBreakdown : {},
|
|
748
|
+
outcome
|
|
526
749
|
};
|
|
527
750
|
} catch {
|
|
528
751
|
return {
|
|
@@ -621,9 +844,10 @@ var FileSessionWriter = class {
|
|
|
621
844
|
this.meta = meta;
|
|
622
845
|
this.events = events;
|
|
623
846
|
this.resumed = opts.resumed ?? false;
|
|
624
|
-
this.manifestFile = opts.dir ? path3.join(opts.dir, `${id}.summary.json`) : "";
|
|
847
|
+
this.manifestFile = opts.dir ? path3.join(opts.dir, `${path3.basename(id)}.summary.json`) : "";
|
|
625
848
|
this.filePath = opts.filePath ?? "";
|
|
626
849
|
this.secretScrubber = opts.secretScrubber;
|
|
850
|
+
this.onCloseCb = opts.onClose;
|
|
627
851
|
this.summary = {
|
|
628
852
|
id,
|
|
629
853
|
title: "(empty session)",
|
|
@@ -653,6 +877,15 @@ var FileSessionWriter = class {
|
|
|
653
877
|
appendFailCount = 0;
|
|
654
878
|
lastAppendWarnAt = 0;
|
|
655
879
|
secretScrubber;
|
|
880
|
+
onCloseCb;
|
|
881
|
+
// ── Enriched summary tracking ──────────────────────────────────────────
|
|
882
|
+
iterationCount = 0;
|
|
883
|
+
toolCallCount = 0;
|
|
884
|
+
toolErrorCount = 0;
|
|
885
|
+
toolBreakdown = {};
|
|
886
|
+
fileChangeCount = 0;
|
|
887
|
+
compactionCount = 0;
|
|
888
|
+
outcome = void 0;
|
|
656
889
|
/**
|
|
657
890
|
* Scrub secrets out of conversation-turn events before they are observed
|
|
658
891
|
* for the summary, written to the JSONL log, or surfaced on resume. Only
|
|
@@ -730,8 +963,22 @@ var FileSessionWriter = class {
|
|
|
730
963
|
observeForSummary(event) {
|
|
731
964
|
if (event.type === "tool_use") {
|
|
732
965
|
this.openToolUses.add(event.id);
|
|
966
|
+
} else if (event.type === "tool_call_start") {
|
|
967
|
+
this.toolCallCount++;
|
|
968
|
+
this.toolBreakdown[event.name] = (this.toolBreakdown[event.name] ?? 0) + 1;
|
|
733
969
|
} else if (event.type === "tool_result") {
|
|
734
970
|
this.openToolUses.delete(event.id);
|
|
971
|
+
if (event.isError) {
|
|
972
|
+
this.toolErrorCount++;
|
|
973
|
+
this.outcome = "error";
|
|
974
|
+
}
|
|
975
|
+
} else if (event.type === "file_snapshot") {
|
|
976
|
+
this.fileChangeCount += event.files.length;
|
|
977
|
+
} else if (event.type === "compaction") {
|
|
978
|
+
this.compactionCount++;
|
|
979
|
+
}
|
|
980
|
+
if (event.type === "error" || event.type === "provider_error") {
|
|
981
|
+
this.outcome = "error";
|
|
735
982
|
}
|
|
736
983
|
if (event.type === "user_input" && this.summary.title === "(empty session)") {
|
|
737
984
|
this.summary = { ...this.summary, title: userInputTitle(event.content) };
|
|
@@ -742,18 +989,35 @@ var FileSessionWriter = class {
|
|
|
742
989
|
} else if (event.type === "session_end") {
|
|
743
990
|
const total = event.usage.input + event.usage.output;
|
|
744
991
|
if (total > 0) this.summary = { ...this.summary, tokenTotal: total };
|
|
992
|
+
} else if (event.type === "in_flight_start") {
|
|
993
|
+
this.iterationCount++;
|
|
745
994
|
}
|
|
746
995
|
}
|
|
747
996
|
async close() {
|
|
748
997
|
if (this.closing) return;
|
|
749
998
|
this.closing = true;
|
|
750
999
|
this.closed = true;
|
|
1000
|
+
this.summary = {
|
|
1001
|
+
...this.summary,
|
|
1002
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1003
|
+
iterationCount: this.iterationCount,
|
|
1004
|
+
toolCallCount: this.toolCallCount,
|
|
1005
|
+
toolErrorCount: this.toolErrorCount,
|
|
1006
|
+
fileChangeCount: this.fileChangeCount,
|
|
1007
|
+
compactionCount: this.compactionCount > 0 ? this.compactionCount : void 0,
|
|
1008
|
+
toolBreakdown: { ...this.toolBreakdown },
|
|
1009
|
+
outcome: this.outcome ?? "completed"
|
|
1010
|
+
};
|
|
751
1011
|
if (this.manifestFile) {
|
|
752
1012
|
try {
|
|
753
1013
|
await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 384 });
|
|
754
1014
|
} catch {
|
|
755
1015
|
}
|
|
756
1016
|
}
|
|
1017
|
+
try {
|
|
1018
|
+
await this.onCloseCb?.(this.summary);
|
|
1019
|
+
} catch {
|
|
1020
|
+
}
|
|
757
1021
|
try {
|
|
758
1022
|
await this.handle.close();
|
|
759
1023
|
} catch {
|
|
@@ -795,7 +1059,7 @@ var FileSessionWriter = class {
|
|
|
795
1059
|
let targetCheckpointLine = -1;
|
|
796
1060
|
let afterTarget = false;
|
|
797
1061
|
for (let i = 0; i < lines.length; i++) {
|
|
798
|
-
const line = lines[i];
|
|
1062
|
+
const line = expectDefined2(lines[i]);
|
|
799
1063
|
if (!line.trim()) continue;
|
|
800
1064
|
let event;
|
|
801
1065
|
try {
|
|
@@ -1971,6 +2235,12 @@ function compileUserRegex(pattern, flags) {
|
|
|
1971
2235
|
}
|
|
1972
2236
|
|
|
1973
2237
|
// src/storage/session-reader.ts
|
|
2238
|
+
function expectDefined3(value) {
|
|
2239
|
+
if (value === null || value === void 0) {
|
|
2240
|
+
throw new Error("Expected value to be defined");
|
|
2241
|
+
}
|
|
2242
|
+
return value;
|
|
2243
|
+
}
|
|
1974
2244
|
var DefaultSessionReader = class {
|
|
1975
2245
|
store;
|
|
1976
2246
|
constructor(opts) {
|
|
@@ -2032,7 +2302,7 @@ var DefaultSessionReader = class {
|
|
|
2032
2302
|
continue;
|
|
2033
2303
|
}
|
|
2034
2304
|
for (let i = 0; i < data.events.length; i++) {
|
|
2035
|
-
const ev = data.events[i];
|
|
2305
|
+
const ev = expectDefined3(data.events[i]);
|
|
2036
2306
|
if (allowedTypes && !allowedTypes.has(ev.type)) continue;
|
|
2037
2307
|
const text = eventText(ev);
|
|
2038
2308
|
if (text === null) continue;
|
|
@@ -2337,8 +2607,11 @@ var SessionAnalyzer = class {
|
|
|
2337
2607
|
}
|
|
2338
2608
|
calcDuration(events) {
|
|
2339
2609
|
if (events.length < 2) return 0;
|
|
2340
|
-
const
|
|
2341
|
-
const
|
|
2610
|
+
const firstEvent = events[0];
|
|
2611
|
+
const lastEvent = events[events.length - 1];
|
|
2612
|
+
if (!firstEvent || !lastEvent) return 0;
|
|
2613
|
+
const first = new Date(firstEvent.ts).getTime();
|
|
2614
|
+
const last = new Date(lastEvent.ts).getTime();
|
|
2342
2615
|
return last - first;
|
|
2343
2616
|
}
|
|
2344
2617
|
};
|
|
@@ -3113,20 +3386,20 @@ var DefaultSecretVault = class {
|
|
|
3113
3386
|
return key;
|
|
3114
3387
|
}
|
|
3115
3388
|
};
|
|
3116
|
-
function decryptConfigSecrets2(cfg, vault) {
|
|
3389
|
+
function decryptConfigSecrets2(cfg, vault, opts) {
|
|
3390
|
+
const warn = opts?.warn ?? ((msg) => console.warn(msg));
|
|
3117
3391
|
return walk2(cfg, vault, (v, key) => {
|
|
3118
3392
|
try {
|
|
3119
3393
|
return vault.decrypt(v);
|
|
3120
3394
|
} catch (err) {
|
|
3121
|
-
|
|
3122
|
-
`[secret-vault] Failed to decrypt "${key}"
|
|
3123
|
-
err instanceof Error ? err.message : err
|
|
3395
|
+
warn(
|
|
3396
|
+
`[secret-vault] Failed to decrypt "${key}": ${err instanceof Error ? err.message : err}`
|
|
3124
3397
|
);
|
|
3125
3398
|
return "";
|
|
3126
3399
|
}
|
|
3127
3400
|
});
|
|
3128
3401
|
}
|
|
3129
|
-
function encryptConfigSecrets(cfg, vault) {
|
|
3402
|
+
function encryptConfigSecrets(cfg, vault, _opts) {
|
|
3130
3403
|
return walk2(cfg, vault, (v) => vault.encrypt(v));
|
|
3131
3404
|
}
|
|
3132
3405
|
function walk2(node, vault, transform) {
|
|
@@ -3187,7 +3460,8 @@ async function migratePlaintextSecrets(configPath, vault) {
|
|
|
3187
3460
|
await restrictFilePermissions(configPath);
|
|
3188
3461
|
return { migrated: counter.n, file: configPath };
|
|
3189
3462
|
}
|
|
3190
|
-
async function restrictFilePermissions(filePath) {
|
|
3463
|
+
async function restrictFilePermissions(filePath, opts) {
|
|
3464
|
+
const warn = ((msg) => console.warn(msg));
|
|
3191
3465
|
if (process.platform === "win32") {
|
|
3192
3466
|
try {
|
|
3193
3467
|
const { execFile: execFile2 } = await import('child_process');
|
|
@@ -3195,7 +3469,7 @@ async function restrictFilePermissions(filePath) {
|
|
|
3195
3469
|
const execFileAsync = promisify2(execFile2);
|
|
3196
3470
|
await execFileAsync("icacls", [filePath, "/inheritance:r", "/grant:r", `${process.env.USERNAME}:(F)`]);
|
|
3197
3471
|
} catch {
|
|
3198
|
-
|
|
3472
|
+
warn(`[secret-vault] Could not restrict permissions on ${filePath} \u2014 config file may be readable by other users on this system.`);
|
|
3199
3473
|
}
|
|
3200
3474
|
} else {
|
|
3201
3475
|
try {
|
|
@@ -3291,6 +3565,12 @@ function getDangerousCapabilities(toolOrCaps) {
|
|
|
3291
3565
|
init_atomic_write();
|
|
3292
3566
|
|
|
3293
3567
|
// src/utils/glob-match.ts
|
|
3568
|
+
function expectDefined4(value) {
|
|
3569
|
+
if (value === null || value === void 0) {
|
|
3570
|
+
throw new Error("Expected value to be defined");
|
|
3571
|
+
}
|
|
3572
|
+
return value;
|
|
3573
|
+
}
|
|
3294
3574
|
function escapeRegex(s) {
|
|
3295
3575
|
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
3296
3576
|
}
|
|
@@ -3302,7 +3582,7 @@ function getCachedGlob(pattern) {
|
|
|
3302
3582
|
if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {
|
|
3303
3583
|
const keys = [...COMPILED_GLOB_CACHE.keys()];
|
|
3304
3584
|
for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {
|
|
3305
|
-
COMPILED_GLOB_CACHE.delete(keys[i]);
|
|
3585
|
+
COMPILED_GLOB_CACHE.delete(expectDefined4(keys[i]));
|
|
3306
3586
|
}
|
|
3307
3587
|
}
|
|
3308
3588
|
const re = compileGlob(pattern);
|
|
@@ -4160,13 +4440,19 @@ function parseDescription(raw) {
|
|
|
4160
4440
|
const scope = [];
|
|
4161
4441
|
const coversMatch = /(?:covers|for|including)\s+([^.]+)/i.exec(desc);
|
|
4162
4442
|
if (coversMatch) {
|
|
4163
|
-
const items = coversMatch[1].replace(/[·•]/g, ",").split(",").map((s) => s.trim()).filter(Boolean);
|
|
4443
|
+
const items = coversMatch[1] ?? "".replace(/[·•]/g, ",").split(",").map((s) => s.trim()).filter(Boolean);
|
|
4164
4444
|
scope.push(...items);
|
|
4165
4445
|
}
|
|
4166
4446
|
return { trigger, scope };
|
|
4167
4447
|
}
|
|
4168
4448
|
|
|
4169
4449
|
// src/utils/json-repair.ts
|
|
4450
|
+
function expectDefined5(value) {
|
|
4451
|
+
if (value === null || value === void 0) {
|
|
4452
|
+
throw new Error("Expected value to be defined");
|
|
4453
|
+
}
|
|
4454
|
+
return value;
|
|
4455
|
+
}
|
|
4170
4456
|
function completePartialObject(s) {
|
|
4171
4457
|
if (!s.trim().startsWith("{")) return s;
|
|
4172
4458
|
if (tryParse(s).ok) return s;
|
|
@@ -4178,7 +4464,7 @@ function completePartialObject(s) {
|
|
|
4178
4464
|
let contentEnd = 0;
|
|
4179
4465
|
let stringBraceDepth = 0;
|
|
4180
4466
|
for (let i = 0; i < s.length; i++) {
|
|
4181
|
-
const ch = s[i];
|
|
4467
|
+
const ch = expectDefined5(s[i]);
|
|
4182
4468
|
if (inString) {
|
|
4183
4469
|
contentEnd = i + 1;
|
|
4184
4470
|
if (escaped) {
|
|
@@ -4314,7 +4600,7 @@ function handleContentBlockStart(state, ev) {
|
|
|
4314
4600
|
state.textBuffers.push("");
|
|
4315
4601
|
state.blockOrder.push({ kind: "text", idx: state.currentTextIndex });
|
|
4316
4602
|
} else if (kind === "tool_use") {
|
|
4317
|
-
const id = ev.id ??
|
|
4603
|
+
const id = ev.id ?? randomUUID();
|
|
4318
4604
|
state.tools.set(id, { name: ev.name ?? "unknown", partial: "" });
|
|
4319
4605
|
state.blockOrder.push({ kind: "tool", id });
|
|
4320
4606
|
state.currentTextIndex = -1;
|
|
@@ -4563,6 +4849,12 @@ var DefaultProviderRunner = class {
|
|
|
4563
4849
|
};
|
|
4564
4850
|
|
|
4565
4851
|
// src/utils/token-estimate.ts
|
|
4852
|
+
function expectDefined6(value) {
|
|
4853
|
+
if (value === null || value === void 0) {
|
|
4854
|
+
throw new Error("Expected value to be defined");
|
|
4855
|
+
}
|
|
4856
|
+
return value;
|
|
4857
|
+
}
|
|
4566
4858
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
4567
4859
|
var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
4568
4860
|
var ESTIMATE_CACHE_MAX_SIZE = 1e4;
|
|
@@ -4572,7 +4864,7 @@ function getCachedEstimate(key, compute) {
|
|
|
4572
4864
|
if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
|
|
4573
4865
|
const keys = [...ESTIMATE_CACHE.keys()];
|
|
4574
4866
|
for (let i = 0; i < Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4); i++) {
|
|
4575
|
-
ESTIMATE_CACHE.delete(keys[i]);
|
|
4867
|
+
ESTIMATE_CACHE.delete(expectDefined6(keys[i]));
|
|
4576
4868
|
}
|
|
4577
4869
|
}
|
|
4578
4870
|
const estimate = compute();
|
|
@@ -4962,7 +5254,7 @@ var IntelligentCompactor = class {
|
|
|
4962
5254
|
maxTokens: 1024
|
|
4963
5255
|
};
|
|
4964
5256
|
const ac = ctx.signal ? void 0 : new AbortController();
|
|
4965
|
-
const signal = ctx.signal ?? ac
|
|
5257
|
+
const signal = ctx.signal ?? ac?.signal;
|
|
4966
5258
|
const res = await this.provider.complete(req, { signal });
|
|
4967
5259
|
const textBlocks = res.content.filter(isTextBlock);
|
|
4968
5260
|
return textBlocks.map((b) => b.text).join("\n").trim() || "(empty summary)";
|
|
@@ -5065,6 +5357,12 @@ var IntelligentCompactor = class {
|
|
|
5065
5357
|
};
|
|
5066
5358
|
|
|
5067
5359
|
// src/models/llm-selector.ts
|
|
5360
|
+
function expectDefined7(value) {
|
|
5361
|
+
if (value === null || value === void 0) {
|
|
5362
|
+
throw new Error("Expected value to be defined");
|
|
5363
|
+
}
|
|
5364
|
+
return value;
|
|
5365
|
+
}
|
|
5068
5366
|
var DEFAULT_SYSTEM_PROMPT = `You are a context pruning assistant. Given a conversation history and a token budget, decide which message ranges are worth keeping verbatim and which should be collapsed into summaries.
|
|
5069
5367
|
|
|
5070
5368
|
Output a JSON object with this structure:
|
|
@@ -5105,7 +5403,7 @@ function formatMessages(messages, maxChars = 8e3) {
|
|
|
5105
5403
|
const lines = [];
|
|
5106
5404
|
let used = 0;
|
|
5107
5405
|
for (let i = 0; i < messages.length; i++) {
|
|
5108
|
-
const m = messages[i];
|
|
5406
|
+
const m = expectDefined7(messages[i]);
|
|
5109
5407
|
const role = m.role.padEnd(10, " ");
|
|
5110
5408
|
let text;
|
|
5111
5409
|
if (typeof m.content === "string") {
|
|
@@ -5170,7 +5468,7 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
5170
5468
|
let tokenCount = 0;
|
|
5171
5469
|
let startIdx = 0;
|
|
5172
5470
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5173
|
-
const m = messages[i];
|
|
5471
|
+
const m = expectDefined7(messages[i]);
|
|
5174
5472
|
const cost = typeof m.content === "string" ? Math.ceil(m.content.length / 4) : m.content.reduce(
|
|
5175
5473
|
(acc, b) => acc + (b.type === "text" ? Math.ceil(b.text.length / 4) : Math.ceil(JSON.stringify(b).length / 4)),
|
|
5176
5474
|
0
|
|
@@ -5381,6 +5679,7 @@ Summarize the following message range:`;
|
|
|
5381
5679
|
let boundary = preserveIdx;
|
|
5382
5680
|
for (let i = preserveIdx; i < messages.length && i < preserveIdx + 6; i++) {
|
|
5383
5681
|
const m = messages[i];
|
|
5682
|
+
if (!m) continue;
|
|
5384
5683
|
if (m.role === "user" && this.hasTextContent(m)) {
|
|
5385
5684
|
boundary = i;
|
|
5386
5685
|
break;
|
|
@@ -5776,6 +6075,12 @@ function createToolOutputSerializer(opts = {}) {
|
|
|
5776
6075
|
}
|
|
5777
6076
|
|
|
5778
6077
|
// src/execution/tool-executor.ts
|
|
6078
|
+
function expectDefined8(value) {
|
|
6079
|
+
if (value === null || value === void 0) {
|
|
6080
|
+
throw new Error("Expected value to be defined");
|
|
6081
|
+
}
|
|
6082
|
+
return value;
|
|
6083
|
+
}
|
|
5779
6084
|
var ToolExecutor = class {
|
|
5780
6085
|
constructor(registry, opts) {
|
|
5781
6086
|
this.registry = registry;
|
|
@@ -6064,6 +6369,9 @@ ${post.additionalContext}` };
|
|
|
6064
6369
|
async runStreamedTool(tool, input, ctx, signal, toolUseId) {
|
|
6065
6370
|
let finalOutput;
|
|
6066
6371
|
let sawFinal = false;
|
|
6372
|
+
if (!tool.executeStream) {
|
|
6373
|
+
throw new Error(`Tool "${tool.name}" does not support streaming execution`);
|
|
6374
|
+
}
|
|
6067
6375
|
const stream = tool.executeStream(input, ctx, { signal });
|
|
6068
6376
|
for await (const ev of stream) {
|
|
6069
6377
|
if (ev.type === "final") {
|
|
@@ -6168,7 +6476,7 @@ function hasMalformedArguments(input) {
|
|
|
6168
6476
|
function extractMalformedRaw(input) {
|
|
6169
6477
|
if (!hasMalformedArguments(input)) return void 0;
|
|
6170
6478
|
const obj = input;
|
|
6171
|
-
const value = obj[Object.keys(obj)[0]];
|
|
6479
|
+
const value = obj[expectDefined8(Object.keys(obj)[0])];
|
|
6172
6480
|
if (value === void 0 || value === null) return void 0;
|
|
6173
6481
|
if (typeof value === "string") return value;
|
|
6174
6482
|
try {
|
|
@@ -6393,6 +6701,11 @@ function appendJournal(goal, entry) {
|
|
|
6393
6701
|
};
|
|
6394
6702
|
}
|
|
6395
6703
|
|
|
6704
|
+
// src/utils/sleep.ts
|
|
6705
|
+
function sleep(ms) {
|
|
6706
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6707
|
+
}
|
|
6708
|
+
|
|
6396
6709
|
// src/execution/eternal-autonomy.ts
|
|
6397
6710
|
var execFileP = promisify(execFile);
|
|
6398
6711
|
var BRAINSTORM_DONE = /* @__PURE__ */ Symbol("brainstorm-done");
|
|
@@ -6963,9 +7276,6 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
6963
7276
|
await saveGoal(this.goalPath, { ...current, engineState: state });
|
|
6964
7277
|
}
|
|
6965
7278
|
};
|
|
6966
|
-
function sleep(ms) {
|
|
6967
|
-
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6968
|
-
}
|
|
6969
7279
|
|
|
6970
7280
|
// src/coordination/subagent-budget.ts
|
|
6971
7281
|
var BudgetExceededError = class extends Error {
|
|
@@ -7129,16 +7439,16 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
7129
7439
|
}
|
|
7130
7440
|
if (exceeded.length === 0) return [];
|
|
7131
7441
|
if (!this._onThreshold) {
|
|
7132
|
-
const first2 = exceeded[0];
|
|
7442
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
7133
7443
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
7134
7444
|
}
|
|
7135
7445
|
if (this._mode === "sync") {
|
|
7136
|
-
const first2 = exceeded[0];
|
|
7446
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
7137
7447
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
7138
7448
|
}
|
|
7139
7449
|
const bus = this._events;
|
|
7140
7450
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
7141
|
-
const first2 = exceeded[0];
|
|
7451
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
7142
7452
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
7143
7453
|
}
|
|
7144
7454
|
for (const entry of exceeded) {
|
|
@@ -7146,8 +7456,9 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
7146
7456
|
const decision2 = this._negotiateExtension(entry.kind, exceeded);
|
|
7147
7457
|
this._pendingNegotiations.set(entry.kind, decision2);
|
|
7148
7458
|
}
|
|
7149
|
-
const first = exceeded[0];
|
|
7459
|
+
const first = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
7150
7460
|
const decision = this._pendingNegotiations.get(first.kind);
|
|
7461
|
+
if (!decision) throw new Error(`No pending negotiation for ${first.kind}`);
|
|
7151
7462
|
throw new BudgetThresholdSignal(first.kind, first.limit, first.used, decision);
|
|
7152
7463
|
}
|
|
7153
7464
|
/**
|
|
@@ -7169,8 +7480,11 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
7169
7480
|
* a fresh signal.
|
|
7170
7481
|
*/
|
|
7171
7482
|
async _negotiateExtension(kind, exceeded) {
|
|
7483
|
+
if (!this._onThreshold) {
|
|
7484
|
+
return "stop";
|
|
7485
|
+
}
|
|
7172
7486
|
try {
|
|
7173
|
-
const first = exceeded[0];
|
|
7487
|
+
const first = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
7174
7488
|
const result = this._onThreshold({
|
|
7175
7489
|
kind: first.kind,
|
|
7176
7490
|
used: first.used,
|
|
@@ -9653,6 +9967,11 @@ function getAgentDefinition(role) {
|
|
|
9653
9967
|
|
|
9654
9968
|
// src/coordination/dispatcher.ts
|
|
9655
9969
|
var DEFAULT_DISPATCH_ROLE = "executor";
|
|
9970
|
+
var FALLBACK_DEFINITION = {
|
|
9971
|
+
config: { role: "unknown", name: "Unknown Agent" },
|
|
9972
|
+
budget: {},
|
|
9973
|
+
capability: { phase: "meta", summary: "", keywords: [] }
|
|
9974
|
+
};
|
|
9656
9975
|
function normalize(text) {
|
|
9657
9976
|
return ` ${text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim()} `;
|
|
9658
9977
|
}
|
|
@@ -9680,7 +9999,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
9680
9999
|
}
|
|
9681
10000
|
function heuristicConfidence(candidates) {
|
|
9682
10001
|
if (candidates.length === 0) return 0;
|
|
9683
|
-
const top = candidates[0]
|
|
10002
|
+
const top = candidates[0]?.score ?? 0;
|
|
9684
10003
|
const second = candidates[1]?.score ?? 0;
|
|
9685
10004
|
const strength = Math.min(1, top / 3);
|
|
9686
10005
|
const margin = (top - second + 1) / (top + 1);
|
|
@@ -9696,7 +10015,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
9696
10015
|
if (top && confidence >= threshold) {
|
|
9697
10016
|
return {
|
|
9698
10017
|
role: top.role,
|
|
9699
|
-
definition: catalog[top.role],
|
|
10018
|
+
definition: catalog[top.role] ?? FALLBACK_DEFINITION,
|
|
9700
10019
|
confidence,
|
|
9701
10020
|
method: "heuristic",
|
|
9702
10021
|
reason: `Matched keywords: ${top.matched.slice(0, 4).join(", ")}`,
|
|
@@ -9704,7 +10023,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
9704
10023
|
};
|
|
9705
10024
|
}
|
|
9706
10025
|
if (opts.classifier) {
|
|
9707
|
-
const pool = (candidates.length > 0 ? candidates.slice(0, maxCandidates).map((c) => catalog[c.role]) : ALL_AGENT_DEFINITIONS).map((d) => ({
|
|
10026
|
+
const pool = (candidates.length > 0 ? candidates.slice(0, maxCandidates).map((c) => catalog[c.role] ?? FALLBACK_DEFINITION) : ALL_AGENT_DEFINITIONS).map((d) => ({
|
|
9708
10027
|
role: d.config.role,
|
|
9709
10028
|
name: d.config.name,
|
|
9710
10029
|
summary: d.capability.summary
|
|
@@ -9714,7 +10033,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
9714
10033
|
if (choice && catalog[choice.role]) {
|
|
9715
10034
|
return {
|
|
9716
10035
|
role: choice.role,
|
|
9717
|
-
definition: catalog[choice.role],
|
|
10036
|
+
definition: catalog[choice.role] ?? FALLBACK_DEFINITION,
|
|
9718
10037
|
confidence: 1,
|
|
9719
10038
|
method: "llm",
|
|
9720
10039
|
reason: choice.reason ?? "Selected by LLM classifier",
|
|
@@ -9727,17 +10046,17 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
9727
10046
|
if (top) {
|
|
9728
10047
|
return {
|
|
9729
10048
|
role: top.role,
|
|
9730
|
-
definition: catalog[top.role],
|
|
10049
|
+
definition: catalog[top.role] ?? FALLBACK_DEFINITION,
|
|
9731
10050
|
confidence,
|
|
9732
10051
|
method: "heuristic",
|
|
9733
10052
|
reason: `Weak match (${top.matched.slice(0, 3).join(", ") || "low signal"})`,
|
|
9734
10053
|
alternatives: candidates.slice(1, maxCandidates)
|
|
9735
10054
|
};
|
|
9736
10055
|
}
|
|
9737
|
-
const fallbackRole = catalog[DEFAULT_DISPATCH_ROLE] ? DEFAULT_DISPATCH_ROLE : Object.keys(catalog)[0];
|
|
10056
|
+
const fallbackRole = catalog[DEFAULT_DISPATCH_ROLE] ? DEFAULT_DISPATCH_ROLE : Object.keys(catalog)[0] ?? DEFAULT_DISPATCH_ROLE;
|
|
9738
10057
|
return {
|
|
9739
10058
|
role: fallbackRole,
|
|
9740
|
-
definition: catalog[fallbackRole],
|
|
10059
|
+
definition: catalog[fallbackRole] ?? FALLBACK_DEFINITION,
|
|
9741
10060
|
confidence: 0,
|
|
9742
10061
|
method: "fallback",
|
|
9743
10062
|
reason: "No keyword signal; defaulting to the generalist Executor",
|
|
@@ -10550,6 +10869,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10550
10869
|
takeNextDispatchableTask() {
|
|
10551
10870
|
for (let i = 0; i < this.pendingTasks.length; i++) {
|
|
10552
10871
|
const task = this.pendingTasks[i];
|
|
10872
|
+
if (!task) continue;
|
|
10553
10873
|
const subagentId = task.subagentId ? this.isIdleSubagent(task.subagentId) ? task.subagentId : null : this.findIdleSubagent();
|
|
10554
10874
|
if (!subagentId) continue;
|
|
10555
10875
|
this.pendingTasks.splice(i, 1);
|
|
@@ -10741,14 +11061,14 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10741
11061
|
const idleExceeded = idleLimit !== void 0 && budget.idleMs() >= idleLimit;
|
|
10742
11062
|
if (idleExceeded && !wallExceeded) {
|
|
10743
11063
|
this.subagents.get(ctx.subagentId)?.abortController.abort();
|
|
10744
|
-
reject(new BudgetExceededError("timeout", idleLimit, budget.idleMs()));
|
|
11064
|
+
reject(new BudgetExceededError("timeout", idleLimit ?? 0, budget.idleMs()));
|
|
10745
11065
|
return;
|
|
10746
11066
|
}
|
|
10747
11067
|
if (!wallExceeded) {
|
|
10748
11068
|
scheduleNext();
|
|
10749
11069
|
return;
|
|
10750
11070
|
}
|
|
10751
|
-
const limit = wallLimit;
|
|
11071
|
+
const limit = wallLimit ?? 0;
|
|
10752
11072
|
if (!budget.onThreshold) {
|
|
10753
11073
|
this.subagents.get(ctx.subagentId)?.abortController.abort();
|
|
10754
11074
|
reject(new BudgetExceededError("timeout", limit, elapsed));
|
|
@@ -10907,8 +11227,11 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10907
11227
|
};
|
|
10908
11228
|
|
|
10909
11229
|
// src/execution/parallel-eternal-engine.ts
|
|
10910
|
-
function
|
|
10911
|
-
|
|
11230
|
+
function expectDefined9(value) {
|
|
11231
|
+
if (value === null || value === void 0) {
|
|
11232
|
+
throw new Error("Expected value to be defined");
|
|
11233
|
+
}
|
|
11234
|
+
return value;
|
|
10912
11235
|
}
|
|
10913
11236
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
10914
11237
|
var ParallelEternalEngine = class {
|
|
@@ -10984,7 +11307,7 @@ var ParallelEternalEngine = class {
|
|
|
10984
11307
|
);
|
|
10985
11308
|
}
|
|
10986
11309
|
if (this.stopRequested) break;
|
|
10987
|
-
await
|
|
11310
|
+
await sleep(2e3);
|
|
10988
11311
|
}
|
|
10989
11312
|
} finally {
|
|
10990
11313
|
this.state = "stopped";
|
|
@@ -11065,7 +11388,7 @@ var ParallelEternalEngine = class {
|
|
|
11065
11388
|
// Fan-out
|
|
11066
11389
|
// -------------------------------------------------------------------------
|
|
11067
11390
|
async fanOut(goal, tasks) {
|
|
11068
|
-
const coordinator = this.coordinator;
|
|
11391
|
+
const coordinator = expectDefined9(this.coordinator);
|
|
11069
11392
|
const slotCount = Math.min(this.slots, tasks.length);
|
|
11070
11393
|
const routes = this.dispatchEnabled ? await Promise.all(
|
|
11071
11394
|
tasks.slice(0, slotCount).map(
|
|
@@ -11097,7 +11420,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
11097
11420
|
const routeInfo = [];
|
|
11098
11421
|
const spawnPromises = [];
|
|
11099
11422
|
for (let i = 0; i < slotCount; i++) {
|
|
11100
|
-
const task = tasks[i];
|
|
11423
|
+
const task = expectDefined9(tasks[i]);
|
|
11101
11424
|
const route = routes[i] ?? null;
|
|
11102
11425
|
const subagentId = `parallel-${this.iterations}-${i}`;
|
|
11103
11426
|
const taskId = randomUUID();
|
|
@@ -11470,7 +11793,7 @@ var InMemoryBridgeTransport = class {
|
|
|
11470
11793
|
}
|
|
11471
11794
|
subscribe(agentId, handler) {
|
|
11472
11795
|
if (!this.subs.has(agentId)) this.subs.set(agentId, /* @__PURE__ */ new Set());
|
|
11473
|
-
this.subs.get(agentId)
|
|
11796
|
+
this.subs.get(agentId)?.add(handler);
|
|
11474
11797
|
return () => this.subs.get(agentId)?.delete(handler);
|
|
11475
11798
|
}
|
|
11476
11799
|
close(agentId) {
|
|
@@ -11588,6 +11911,12 @@ function createMessage(type, from, payload, to) {
|
|
|
11588
11911
|
priority: "normal"
|
|
11589
11912
|
};
|
|
11590
11913
|
}
|
|
11914
|
+
function expectDefined10(value) {
|
|
11915
|
+
if (value === null || value === void 0) {
|
|
11916
|
+
throw new Error("Expected value to be defined");
|
|
11917
|
+
}
|
|
11918
|
+
return value;
|
|
11919
|
+
}
|
|
11591
11920
|
var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
11592
11921
|
var IS_WINDOWS = process.platform === "win32";
|
|
11593
11922
|
var SEP = IS_WINDOWS ? "\\" : "/";
|
|
@@ -11601,7 +11930,7 @@ function globToRegex(pat) {
|
|
|
11601
11930
|
let i = 0;
|
|
11602
11931
|
let re = "^";
|
|
11603
11932
|
while (i < pat.length) {
|
|
11604
|
-
const c = pat[i];
|
|
11933
|
+
const c = expectDefined10(pat[i]);
|
|
11605
11934
|
if (c === "*") {
|
|
11606
11935
|
if (pat[i + 1] === "*") {
|
|
11607
11936
|
re += ".*";
|
|
@@ -11640,7 +11969,7 @@ function globToRegex(pat) {
|
|
|
11640
11969
|
}
|
|
11641
11970
|
function baseDir(pat) {
|
|
11642
11971
|
let i = pat.length - 1;
|
|
11643
|
-
while (i >= 0 && !GLOB_CHARS.has(pat[i]) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
11972
|
+
while (i >= 0 && !GLOB_CHARS.has(expectDefined10(pat[i])) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
11644
11973
|
const cut = i >= 0 ? pat.lastIndexOf(SEP, i) : pat.lastIndexOf("/", i);
|
|
11645
11974
|
return cut < 0 ? "." : pat.slice(0, cut);
|
|
11646
11975
|
}
|
|
@@ -11865,7 +12194,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
11865
12194
|
this.emit("session.error", error);
|
|
11866
12195
|
throw error;
|
|
11867
12196
|
}
|
|
11868
|
-
for (const result of results
|
|
12197
|
+
for (const result of results?.flat() ?? []) {
|
|
11869
12198
|
await this.parseAndEmit(result);
|
|
11870
12199
|
}
|
|
11871
12200
|
const report = this.assembleReport();
|
|
@@ -11926,7 +12255,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
11926
12255
|
}
|
|
11927
12256
|
budgetForRole(role) {
|
|
11928
12257
|
if (this.options.budgetOverrides?.[role]) {
|
|
11929
|
-
return this.options.budgetOverrides[role];
|
|
12258
|
+
return this.options.budgetOverrides[role] ?? { maxIterations: 0, maxToolCalls: 0, timeoutMs: 0 };
|
|
11930
12259
|
}
|
|
11931
12260
|
const defaults = {
|
|
11932
12261
|
"bug-hunter": { maxIterations: 2e3, maxToolCalls: 5e3, timeoutMs: 10 * 60 * 1e3 },
|
|
@@ -12379,7 +12708,7 @@ function makeSpawnTool(director, roster) {
|
|
|
12379
12708
|
});
|
|
12380
12709
|
const dispatchRole = dispatchResult.role;
|
|
12381
12710
|
if (roster?.[dispatchRole]) {
|
|
12382
|
-
cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole]);
|
|
12711
|
+
cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole] ?? {});
|
|
12383
12712
|
} else {
|
|
12384
12713
|
const def = dispatchResult.definition;
|
|
12385
12714
|
cfg = {
|
|
@@ -14676,7 +15005,10 @@ function attachAutoExtend(events, policy = {}) {
|
|
|
14676
15005
|
if (kind === "timeout" || kind === "idle_timeout") {
|
|
14677
15006
|
if (progress > lastTimeoutProgress) {
|
|
14678
15007
|
lastTimeoutProgress = progress;
|
|
14679
|
-
const next2 = Math.min(
|
|
15008
|
+
const next2 = Math.min(
|
|
15009
|
+
Math.ceil(limit * (1 + factor)),
|
|
15010
|
+
ceiling.timeoutMs ?? DEFAULT_CEILING.timeoutMs
|
|
15011
|
+
);
|
|
14680
15012
|
extend({ timeoutMs: next2 });
|
|
14681
15013
|
} else {
|
|
14682
15014
|
deny();
|
|
@@ -14690,7 +15022,7 @@ function attachAutoExtend(events, policy = {}) {
|
|
|
14690
15022
|
}
|
|
14691
15023
|
extendCounts.set(kind, count + 1);
|
|
14692
15024
|
const field = FIELD_BY_KIND[kind];
|
|
14693
|
-
const cap = ceiling[field];
|
|
15025
|
+
const cap = ceiling[field] ?? DEFAULT_CEILING[field];
|
|
14694
15026
|
const next = Math.min(Math.ceil(limit * (1 + factor)), cap);
|
|
14695
15027
|
extend({ [field]: next });
|
|
14696
15028
|
})
|
|
@@ -15989,7 +16321,7 @@ var TaskTracker = class {
|
|
|
15989
16321
|
if (filter.type?.length && !filter.type.includes(n.type)) return false;
|
|
15990
16322
|
if (filter.assignee?.length && n.assignee && !filter.assignee.includes(n.assignee))
|
|
15991
16323
|
return false;
|
|
15992
|
-
if (filter.tags?.length && n.tags && !n.tags.some((t) => filter.tags
|
|
16324
|
+
if (filter.tags?.length && n.tags && !n.tags.some((t) => filter.tags?.includes(t)))
|
|
15993
16325
|
return false;
|
|
15994
16326
|
if (filter.specRequirementId && n.specRequirementId !== filter.specRequirementId)
|
|
15995
16327
|
return false;
|
|
@@ -16503,6 +16835,12 @@ var TaskGraphStore = class {
|
|
|
16503
16835
|
};
|
|
16504
16836
|
|
|
16505
16837
|
// src/sdd/spec-builder.ts
|
|
16838
|
+
function expectDefined11(value) {
|
|
16839
|
+
if (value === null || value === void 0) {
|
|
16840
|
+
throw new Error("Expected value to be defined");
|
|
16841
|
+
}
|
|
16842
|
+
return value;
|
|
16843
|
+
}
|
|
16506
16844
|
function buildQuestioningPrompt(session, min, max) {
|
|
16507
16845
|
const answered = session.answers.length;
|
|
16508
16846
|
const remaining = Math.max(0, min - answered);
|
|
@@ -16548,7 +16886,7 @@ function buildQuestioningPrompt(session, min, max) {
|
|
|
16548
16886
|
if (answered > 0) {
|
|
16549
16887
|
lines.push("", "**Conversation so far:**");
|
|
16550
16888
|
for (let i = 0; i < answered; i++) {
|
|
16551
|
-
const a = session.answers[i];
|
|
16889
|
+
const a = expectDefined11(session.answers[i]);
|
|
16552
16890
|
lines.push(``, `Q${i + 1}: ${a.question}`, `A${i + 1}: ${a.answer}`);
|
|
16553
16891
|
}
|
|
16554
16892
|
}
|
|
@@ -17290,6 +17628,12 @@ function truncate2(str, maxLen) {
|
|
|
17290
17628
|
}
|
|
17291
17629
|
|
|
17292
17630
|
// src/sdd/critical-path.ts
|
|
17631
|
+
function expectDefined12(value) {
|
|
17632
|
+
if (value === null || value === void 0) {
|
|
17633
|
+
throw new Error("Expected value to be defined");
|
|
17634
|
+
}
|
|
17635
|
+
return value;
|
|
17636
|
+
}
|
|
17293
17637
|
function analyzeCriticalPath(graph) {
|
|
17294
17638
|
const nodes = Array.from(graph.nodes.values());
|
|
17295
17639
|
const topoOrder = topologicalSort(graph);
|
|
@@ -17298,9 +17642,9 @@ function analyzeCriticalPath(graph) {
|
|
|
17298
17642
|
for (const edge of graph.edges) {
|
|
17299
17643
|
if (edge.type === "depends_on") {
|
|
17300
17644
|
if (!blockedByMap.has(edge.from)) blockedByMap.set(edge.from, /* @__PURE__ */ new Set());
|
|
17301
|
-
blockedByMap.get(edge.from)
|
|
17645
|
+
blockedByMap.get(edge.from)?.add(edge.to);
|
|
17302
17646
|
if (!blocksMap.has(edge.to)) blocksMap.set(edge.to, /* @__PURE__ */ new Set());
|
|
17303
|
-
blocksMap.get(edge.to)
|
|
17647
|
+
blocksMap.get(edge.to)?.add(edge.from);
|
|
17304
17648
|
}
|
|
17305
17649
|
}
|
|
17306
17650
|
const readyTasks = [];
|
|
@@ -17365,7 +17709,7 @@ function getTransitiveBlocked(_graph, taskId, blocksMap) {
|
|
|
17365
17709
|
const visited = /* @__PURE__ */ new Set();
|
|
17366
17710
|
const queue = [taskId];
|
|
17367
17711
|
while (queue.length > 0) {
|
|
17368
|
-
const current = queue.shift();
|
|
17712
|
+
const current = expectDefined12(queue.shift());
|
|
17369
17713
|
const blocked = blocksMap.get(current);
|
|
17370
17714
|
if (!blocked) continue;
|
|
17371
17715
|
for (const id of blocked) {
|
|
@@ -17390,7 +17734,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
17390
17734
|
for (const [taskId, blockers] of blockedByMap) {
|
|
17391
17735
|
for (const blockerId of blockers) {
|
|
17392
17736
|
if (!blocksMap.has(blockerId)) blocksMap.set(blockerId, /* @__PURE__ */ new Set());
|
|
17393
|
-
blocksMap.get(blockerId)
|
|
17737
|
+
blocksMap.get(blockerId)?.add(taskId);
|
|
17394
17738
|
}
|
|
17395
17739
|
}
|
|
17396
17740
|
const n = allIds.length;
|
|
@@ -17411,7 +17755,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
17411
17755
|
if (!changed) break;
|
|
17412
17756
|
}
|
|
17413
17757
|
let maxDist = 0;
|
|
17414
|
-
let maxId = allIds[0];
|
|
17758
|
+
let maxId = expectDefined12(allIds[0]);
|
|
17415
17759
|
for (const id of allIds) {
|
|
17416
17760
|
const d = dist.get(id) ?? 0;
|
|
17417
17761
|
if (d > maxDist) {
|
|
@@ -17880,6 +18224,12 @@ var SddTaskDecomposer = class {
|
|
|
17880
18224
|
return nodes.some((n) => n.status === "blocked");
|
|
17881
18225
|
}
|
|
17882
18226
|
};
|
|
18227
|
+
function expectDefined13(value) {
|
|
18228
|
+
if (value === null || value === void 0) {
|
|
18229
|
+
throw new Error("Expected value to be defined");
|
|
18230
|
+
}
|
|
18231
|
+
return value;
|
|
18232
|
+
}
|
|
17883
18233
|
var SddParallelRun = class {
|
|
17884
18234
|
constructor(opts) {
|
|
17885
18235
|
this.opts = opts;
|
|
@@ -17980,8 +18330,10 @@ var SddParallelRun = class {
|
|
|
17980
18330
|
"\u2022 Do not ask before routine in-project tool use; if a permission gate appears, wait for that flow.",
|
|
17981
18331
|
"\u2022 Keep output concise \u2014 summarize changes, do not transcribe files."
|
|
17982
18332
|
].join("\n");
|
|
18333
|
+
if (!this.coordinator) throw new Error("SDD parallel runner requires a coordinator");
|
|
18334
|
+
const coordinator = this.coordinator;
|
|
17983
18335
|
const spawns = subagentIds.map(
|
|
17984
|
-
(subagentId) =>
|
|
18336
|
+
(subagentId) => coordinator.spawn({
|
|
17985
18337
|
id: subagentId,
|
|
17986
18338
|
name: subagentId,
|
|
17987
18339
|
role: "executor",
|
|
@@ -17989,12 +18341,12 @@ var SddParallelRun = class {
|
|
|
17989
18341
|
})
|
|
17990
18342
|
);
|
|
17991
18343
|
const spawnResults = await Promise.all(spawns);
|
|
17992
|
-
if (!spawnResults.every((r) => r.subagentId)) {
|
|
18344
|
+
if (!spawnResults.every((r) => Boolean(r.subagentId))) {
|
|
17993
18345
|
throw new Error("One or more subagent spawns failed");
|
|
17994
18346
|
}
|
|
17995
18347
|
const assignPromises = tasks.map((task, i) => {
|
|
17996
18348
|
const spec = {
|
|
17997
|
-
id: taskIds[i],
|
|
18349
|
+
id: taskIds[i] ?? task.id,
|
|
17998
18350
|
description: [
|
|
17999
18351
|
directivePreamble,
|
|
18000
18352
|
"",
|
|
@@ -18003,15 +18355,15 @@ var SddParallelRun = class {
|
|
|
18003
18355
|
"",
|
|
18004
18356
|
task.description
|
|
18005
18357
|
].join("\n"),
|
|
18006
|
-
subagentId: subagentIds[i],
|
|
18358
|
+
subagentId: subagentIds[i] ?? spawnResults[i]?.subagentId ?? task.id,
|
|
18007
18359
|
timeoutMs: this.timeoutMs
|
|
18008
18360
|
};
|
|
18009
|
-
return this.coordinator
|
|
18361
|
+
return this.coordinator?.assign(spec);
|
|
18010
18362
|
});
|
|
18011
18363
|
await Promise.all(assignPromises);
|
|
18012
18364
|
let results;
|
|
18013
18365
|
try {
|
|
18014
|
-
results = await
|
|
18366
|
+
results = await coordinator.awaitTasks(taskIds);
|
|
18015
18367
|
} catch (err) {
|
|
18016
18368
|
results = taskIds.map((id) => ({
|
|
18017
18369
|
subagentId: "",
|
|
@@ -18026,8 +18378,8 @@ var SddParallelRun = class {
|
|
|
18026
18378
|
const successCount = results.filter((r) => r.status === "success").length;
|
|
18027
18379
|
const failCount = results.length - successCount;
|
|
18028
18380
|
for (let i = 0; i < results.length; i++) {
|
|
18029
|
-
const result = results[i];
|
|
18030
|
-
const taskId = taskIds[i];
|
|
18381
|
+
const result = expectDefined13(results[i]);
|
|
18382
|
+
const taskId = expectDefined13(taskIds[i]);
|
|
18031
18383
|
if (result.status === "success") {
|
|
18032
18384
|
this.opts.tracker.updateNodeStatus(taskId, "completed");
|
|
18033
18385
|
} else {
|