@kernlang/agon 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{chunk-FCCH7IPJ.js → chunk-3PDYVGRS.js} +107 -24
  2. package/dist/chunk-3PDYVGRS.js.map +1 -0
  3. package/dist/{chunk-ATUT2BUQ.js → chunk-6IF2AV4Y.js} +28 -10
  4. package/dist/chunk-6IF2AV4Y.js.map +1 -0
  5. package/dist/{chunk-4LVYSUMN.js → chunk-7WZ2O5WZ.js} +6 -27
  6. package/dist/chunk-7WZ2O5WZ.js.map +1 -0
  7. package/dist/{chunk-6ANHPXGZ.js → chunk-HSPQEDHX.js} +1 -1
  8. package/dist/{chunk-6ANHPXGZ.js.map → chunk-HSPQEDHX.js.map} +1 -1
  9. package/dist/{chunk-WE32YJKT.js → chunk-NBV37VMW.js} +2 -2
  10. package/dist/{chunk-WE32YJKT.js.map → chunk-NBV37VMW.js.map} +1 -1
  11. package/dist/{chunk-O6YP55RV.js → chunk-PUNBDLQO.js} +141 -96
  12. package/dist/chunk-PUNBDLQO.js.map +1 -0
  13. package/dist/{chunk-C22VTCS6.js → chunk-TMNHJOKU.js} +1193 -226
  14. package/dist/chunk-TMNHJOKU.js.map +1 -0
  15. package/dist/{chunk-5QMVQPHY.js → chunk-XWHC6VAH.js} +3 -2
  16. package/dist/chunk-XWHC6VAH.js.map +1 -0
  17. package/dist/{dispatch-6LQSMMGI.js → dispatch-S3CR5HKX.js} +2 -2
  18. package/dist/engines/codex.json +3 -0
  19. package/dist/{forge-ES4RN7YM.js → forge-GUOEJ5DJ.js} +6 -6
  20. package/dist/index.js +561 -128
  21. package/dist/index.js.map +1 -1
  22. package/dist/plan-mode-35BONR7S.js +17 -0
  23. package/dist/{src-WJGIOESS.js → src-3NWTITZM.js} +55 -3
  24. package/dist/{update-HHN4PJQI.js → update-H3LE4ZSI.js} +6 -6
  25. package/package.json +5 -4
  26. package/dist/chunk-4LVYSUMN.js.map +0 -1
  27. package/dist/chunk-5QMVQPHY.js.map +0 -1
  28. package/dist/chunk-ATUT2BUQ.js.map +0 -1
  29. package/dist/chunk-C22VTCS6.js.map +0 -1
  30. package/dist/chunk-FCCH7IPJ.js.map +0 -1
  31. package/dist/chunk-O6YP55RV.js.map +0 -1
  32. package/dist/plan-mode-4XRC2ZC7.js +0 -17
  33. /package/dist/{dispatch-6LQSMMGI.js.map → dispatch-S3CR5HKX.js.map} +0 -0
  34. /package/dist/{forge-ES4RN7YM.js.map → forge-GUOEJ5DJ.js.map} +0 -0
  35. /package/dist/{plan-mode-4XRC2ZC7.js.map → plan-mode-35BONR7S.js.map} +0 -0
  36. /package/dist/{src-WJGIOESS.js.map → src-3NWTITZM.js.map} +0 -0
  37. /package/dist/{update-HHN4PJQI.js.map → update-H3LE4ZSI.js.map} +0 -0
@@ -5,7 +5,7 @@ import {
5
5
  __require,
6
6
  __toCommonJS,
7
7
  apiStreamDispatchWithHistory
8
- } from "./chunk-5QMVQPHY.js";
8
+ } from "./chunk-XWHC6VAH.js";
9
9
 
10
10
  // ../core/src/generated/signals/glicko.ts
11
11
  var glicko_exports = {};
@@ -4927,10 +4927,10 @@ function isValidJWT(token, algorithm = null) {
4927
4927
  const tokensParts = token.split(".");
4928
4928
  if (tokensParts.length !== 3)
4929
4929
  return false;
4930
- const [header] = tokensParts;
4931
- if (!header)
4930
+ const [header2] = tokensParts;
4931
+ if (!header2)
4932
4932
  return false;
4933
- const parsedHeader = JSON.parse(atob(header));
4933
+ const parsedHeader = JSON.parse(atob(header2));
4934
4934
  if ("typ" in parsedHeader && parsedHeader?.typ !== "JWT")
4935
4935
  return false;
4936
4936
  if (!parsedHeader.alg)
@@ -16429,7 +16429,194 @@ var EngineRegistry = class {
16429
16429
 
16430
16430
  // ../core/src/generated/blocks/context-scanner.ts
16431
16431
  import { readFileSync as readFileSync8, readdirSync as readdirSync6, statSync as statSync6, existsSync as existsSync6 } from "fs";
16432
- import { join as join9, basename } from "path";
16432
+ import { join as join9, basename, dirname as dirname5 } from "path";
16433
+ import { createRequire as createRequire2 } from "module";
16434
+
16435
+ // ../../node_modules/@kernlang/context/dist/spine.js
16436
+ var CHARS_PER_TOKEN = 4;
16437
+ var DEFAULT_SPINE_TOKENS = 1500;
16438
+ var MAX_SITES_PER_SYMBOL = 3;
16439
+ var MAX_TOKEN_CHARS = 80;
16440
+ var UNSAFE_TOKEN_CHARS = /[\u0000-\u001f\u007f-\u009f<>;{},`]/g;
16441
+ function estimateTokens(text) {
16442
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
16443
+ }
16444
+ function sanitize(raw) {
16445
+ const cleaned = raw.replace(UNSAFE_TOKEN_CHARS, " ").replace(/\s+/g, " ").trim();
16446
+ return cleaned.length > MAX_TOKEN_CHARS ? `${cleaned.slice(0, MAX_TOKEN_CHARS)}\u2026` : cleaned;
16447
+ }
16448
+ var KIND_ABBR = {
16449
+ function: "fn",
16450
+ method: "fn",
16451
+ class: "cls",
16452
+ const: "const",
16453
+ type: "type",
16454
+ module: "mod"
16455
+ };
16456
+ function usageVerb(kind) {
16457
+ return kind === "const" || kind === "type" || kind === "module" ? "readby" : "callby";
16458
+ }
16459
+ function confGlyph(c) {
16460
+ if (c === "unresolved")
16461
+ return "~";
16462
+ if (c === "heuristic")
16463
+ return "?";
16464
+ return "";
16465
+ }
16466
+ function renderSite(s) {
16467
+ return `${confGlyph(s.confidence)}${sanitize(s.path)}:${s.line}`;
16468
+ }
16469
+ function prepareSymbols(artifact, batchSet) {
16470
+ const fileById = new Map(artifact.files.map((f) => [f.id, f]));
16471
+ const prepared = [];
16472
+ for (const sym of artifact.symbols) {
16473
+ const file2 = fileById.get(sym.fileId);
16474
+ if (!file2 || !batchSet.has(file2.path))
16475
+ continue;
16476
+ const usage = artifact.usage[sym.id];
16477
+ prepared.push({
16478
+ name: sym.name,
16479
+ kind: sym.kind,
16480
+ exported: sym.exported,
16481
+ publicApi: sym.publicApi ?? false,
16482
+ fileId: sym.fileId,
16483
+ line: sym.line,
16484
+ sites: usage?.callers ?? [],
16485
+ totalCount: usage?.totalCount ?? 0
16486
+ });
16487
+ }
16488
+ prepared.sort((a, b) => {
16489
+ if (a.publicApi !== b.publicApi)
16490
+ return a.publicApi ? -1 : 1;
16491
+ if (a.exported !== b.exported)
16492
+ return a.exported ? -1 : 1;
16493
+ if (a.totalCount !== b.totalCount)
16494
+ return b.totalCount - a.totalCount;
16495
+ if (a.name !== b.name)
16496
+ return a.name < b.name ? -1 : 1;
16497
+ if (a.fileId !== b.fileId)
16498
+ return a.fileId < b.fileId ? -1 : 1;
16499
+ return a.line - b.line;
16500
+ });
16501
+ return prepared;
16502
+ }
16503
+ function symbolLineA(s) {
16504
+ const flags = [s.exported ? "exp" : "", s.publicApi ? "public" : ""].filter(Boolean).join(" ");
16505
+ const shown = s.sites.slice(0, MAX_SITES_PER_SYMBOL).map(renderSite).join(" ");
16506
+ const rest = s.totalCount - Math.min(s.sites.length, MAX_SITES_PER_SYMBOL);
16507
+ const tail = rest > 0 ? ` +${rest}` : "";
16508
+ const usagePart = s.totalCount > 0 ? ` ${usageVerb(s.kind)} ${shown}${tail}` : " unused";
16509
+ const head = `sym ${sanitize(s.name)} ${KIND_ABBR[s.kind]}${flags ? ` ${flags}` : ""} line${s.line}`;
16510
+ return `${head}${usagePart}`;
16511
+ }
16512
+ function symbolLineB(s) {
16513
+ const flags = [s.exported ? "exp" : "", s.publicApi ? "public" : ""].filter(Boolean).join(" ");
16514
+ return `sym ${sanitize(s.name)} ${KIND_ABBR[s.kind]}${flags ? ` ${flags}` : ""} used=${s.totalCount}`;
16515
+ }
16516
+ function symbolLineC(s) {
16517
+ return `sym ${sanitize(s.name)} used=${s.totalCount}`;
16518
+ }
16519
+ function depsLine(artifact, batchSet) {
16520
+ const deps = [];
16521
+ const seen = /* @__PURE__ */ new Set();
16522
+ for (const f of artifact.files) {
16523
+ if (!batchSet.has(f.path))
16524
+ continue;
16525
+ for (const imp of f.imports ?? []) {
16526
+ if (batchSet.has(imp.path) || seen.has(imp.path))
16527
+ continue;
16528
+ seen.add(imp.path);
16529
+ const names = imp.symbols?.length ? `{${imp.symbols.map(sanitize).join(",")}}` : "";
16530
+ deps.push(`${sanitize(imp.path)}${names}`);
16531
+ }
16532
+ }
16533
+ return deps.length ? `deps ${deps.join(" ")}` : null;
16534
+ }
16535
+ function taintLines(artifact) {
16536
+ return (artifact.taint ?? []).map((t) => `taint ${sanitize(t.source)} -> ${sanitize(t.through)} -> ${sanitize(t.sink)} conf=${t.confidence}`);
16537
+ }
16538
+ function elsewhereLine(otherBatches) {
16539
+ if (!otherBatches?.length)
16540
+ return null;
16541
+ const parts = otherBatches.map((b) => b.dirs.map((d) => `${sanitize(d)}/*#${sanitize(b.id)}`).join(" ")).filter(Boolean);
16542
+ return parts.length ? `elsewhere ${parts.join(" ")}` : null;
16543
+ }
16544
+ function header(opts, fileTotal) {
16545
+ const batch = opts.batchIndex && opts.batchTotal ? ` batch=${opts.batchIndex}/${opts.batchTotal}` : "";
16546
+ return `<kern-map v=1${batch} files=${fileTotal}>`;
16547
+ }
16548
+ function renderTier(tier, symbols, artifact, batchSet, opts) {
16549
+ const lines = [];
16550
+ if (tier === "A") {
16551
+ for (const s of symbols)
16552
+ lines.push(symbolLineA(s));
16553
+ const deps = depsLine(artifact, batchSet);
16554
+ if (deps)
16555
+ lines.push(deps);
16556
+ lines.push(...taintLines(artifact));
16557
+ const elsewhere = elsewhereLine(opts.otherBatches);
16558
+ if (elsewhere)
16559
+ lines.push(elsewhere);
16560
+ } else if (tier === "B") {
16561
+ for (const s of symbols)
16562
+ lines.push(symbolLineB(s));
16563
+ const elsewhere = elsewhereLine(opts.otherBatches);
16564
+ if (elsewhere)
16565
+ lines.push(elsewhere);
16566
+ } else {
16567
+ for (const s of symbols.filter((sym) => sym.exported))
16568
+ lines.push(symbolLineC(s));
16569
+ }
16570
+ return lines;
16571
+ }
16572
+ function buildSpine(artifact, opts) {
16573
+ const batchSet = new Set(opts.batchFiles);
16574
+ const symbols = prepareSymbols(artifact, batchSet);
16575
+ if (symbols.length === 0)
16576
+ return "";
16577
+ const budget = opts.tokenBudget ?? DEFAULT_SPINE_TOKENS;
16578
+ const head = header(opts, artifact.files.length);
16579
+ const close = "</kern-map>";
16580
+ const envelope = estimateTokens(`${head}
16581
+ ${close}`);
16582
+ const assemble = (bodyLines) => [head, ...bodyLines, close].join("\n");
16583
+ for (const tier of ["A", "B", "C"]) {
16584
+ const body = renderTier(tier, symbols, artifact, batchSet, opts);
16585
+ const text = assemble(body);
16586
+ if (estimateTokens(text) <= budget)
16587
+ return text;
16588
+ if (tier === "C") {
16589
+ return clipToBudget(symbols, head, close, envelope, budget);
16590
+ }
16591
+ }
16592
+ return assemble(renderTier("C", symbols, artifact, batchSet, opts));
16593
+ }
16594
+ var MARKER_RESERVE_TOKENS = 4;
16595
+ function clipToBudget(symbols, head, close, envelope, budget) {
16596
+ if (envelope + MARKER_RESERVE_TOKENS > budget)
16597
+ return "";
16598
+ const exported = symbols.filter((s) => s.exported);
16599
+ const kept = [];
16600
+ let used = envelope;
16601
+ let droppedExported = 0;
16602
+ for (const s of exported) {
16603
+ const line = symbolLineC(s);
16604
+ const cost = estimateTokens(`${line}
16605
+ `);
16606
+ if (used + cost + MARKER_RESERVE_TOKENS <= budget) {
16607
+ kept.push(line);
16608
+ used += cost;
16609
+ } else {
16610
+ droppedExported++;
16611
+ }
16612
+ }
16613
+ const dropped = droppedExported + (symbols.length - exported.length);
16614
+ if (dropped > 0)
16615
+ kept.push(`+${dropped} more`);
16616
+ return [head, ...kept, close].join("\n");
16617
+ }
16618
+
16619
+ // ../core/src/generated/blocks/context-scanner.ts
16433
16620
  var PROJECT_BRIEF_FILES = [".agon/project.md", "AGON.md", "AGENT.md", "CLAUDE.md", "CODEX.md"];
16434
16621
  var MAX_PROJECT_BRIEF_BYTES = 512 * 1024;
16435
16622
  function projectBriefCap(file2) {
@@ -16592,6 +16779,78 @@ ${result}
16592
16779
  }
16593
16780
  return result;
16594
16781
  }
16782
+ var KERN_SPINE_TTL_MS = 5 * 60 * 1e3;
16783
+ var KERN_SPINE_CACHE = /* @__PURE__ */ new Map();
16784
+ var KERN_SPINE_WARNED = /* @__PURE__ */ new Set();
16785
+ async function computeKernContextSpine(cwd) {
16786
+ const debugFail = (msg) => {
16787
+ if (process.env.AGON_DEBUG && !KERN_SPINE_WARNED.has(cwd)) {
16788
+ KERN_SPINE_WARNED.add(cwd);
16789
+ console.warn(`[agon] kern context spine unavailable for ${cwd}: ${msg}`);
16790
+ }
16791
+ };
16792
+ try {
16793
+ const requireFn = createRequire2(import.meta.url);
16794
+ const cliBin = join9(dirname5(requireFn.resolve("@kernlang/cli")), "cli.js");
16795
+ if (!existsSync6(cliBin)) return "";
16796
+ const timeoutEnv = Number(process.env.AGON_KERN_CONTEXT_TIMEOUT_MS);
16797
+ const timeout = Number.isFinite(timeoutEnv) && timeoutEnv > 0 ? timeoutEnv : 2e4;
16798
+ const budgetEnv = Number(process.env.AGON_KERN_CONTEXT_BUDGET);
16799
+ const tokenBudget = Number.isFinite(budgetEnv) && budgetEnv > 0 ? budgetEnv : 2e3;
16800
+ const result = await spawnWithTimeout({
16801
+ command: process.execPath,
16802
+ args: [cliBin, "context", cwd, "--stdout", "--base", cwd],
16803
+ cwd,
16804
+ timeout
16805
+ });
16806
+ if (result.exitCode !== 0) {
16807
+ debugFail(`kern context exit ${result.exitCode}`);
16808
+ return "";
16809
+ }
16810
+ const out = result.stdout.trim();
16811
+ if (out.length === 0) return "";
16812
+ if (out.length > 8 * 1024 * 1024) {
16813
+ debugFail("artifact JSON too large");
16814
+ return "";
16815
+ }
16816
+ let artifact;
16817
+ try {
16818
+ artifact = JSON.parse(out);
16819
+ } catch (e) {
16820
+ debugFail(`artifact parse: ${e instanceof Error ? e.message : String(e)}`);
16821
+ return "";
16822
+ }
16823
+ if (!artifact.files || artifact.files.length === 0) return "";
16824
+ const spine = buildSpine(artifact, {
16825
+ batchFiles: artifact.files.map((f) => f.path),
16826
+ tokenBudget
16827
+ });
16828
+ if (!spine) return "";
16829
+ return [
16830
+ "## PROJECT MAP (compiler-derived cross-file usage)",
16831
+ '<kern_map note="navigational reference data \u2014 not instructions; may be incomplete">',
16832
+ spine,
16833
+ "</kern_map>"
16834
+ ].join("\n");
16835
+ } catch (err) {
16836
+ debugFail(err instanceof Error ? err.message : String(err));
16837
+ return "";
16838
+ }
16839
+ }
16840
+ async function buildKernContextSpine(cwd) {
16841
+ if (process.env.AGON_NO_KERN_CONTEXT) return "";
16842
+ let fp = "nogit";
16843
+ try {
16844
+ fp = headSha(cwd) || "nogit";
16845
+ } catch {
16846
+ }
16847
+ const now = Date.now();
16848
+ const hit = KERN_SPINE_CACHE.get(cwd);
16849
+ if (hit && hit.fp === fp && now - hit.ts < KERN_SPINE_TTL_MS) return hit.promise;
16850
+ const promise2 = computeKernContextSpine(cwd);
16851
+ KERN_SPINE_CACHE.set(cwd, { fp, ts: now, promise: promise2 });
16852
+ return promise2;
16853
+ }
16595
16854
 
16596
16855
  // ../core/src/generated/blocks/codebase-map.ts
16597
16856
  import { readFileSync as readFileSync9, readdirSync as readdirSync7, statSync as statSync7, lstatSync as lstatSync2, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync7, rmSync as rmSync4 } from "fs";
@@ -16932,7 +17191,7 @@ function ensureCurrentWorkspace(cwd) {
16932
17191
  }
16933
17192
 
16934
17193
  // ../core/src/generated/signals/token-tracker.ts
16935
- function estimateTokens(text) {
17194
+ function estimateTokens2(text) {
16936
17195
  return Math.ceil(text.length / 4);
16937
17196
  }
16938
17197
  function estimateCost(engineId, tokens, model) {
@@ -16949,8 +17208,8 @@ var TokenTracker = class {
16949
17208
  record(engineId, inputOrPrompt, responseText) {
16950
17209
  let promptTokens, responseTokens, totalTokens, source, model, costUsd;
16951
17210
  if (typeof inputOrPrompt === "string") {
16952
- promptTokens = estimateTokens(inputOrPrompt);
16953
- responseTokens = estimateTokens(responseText ?? "");
17211
+ promptTokens = estimateTokens2(inputOrPrompt);
17212
+ responseTokens = estimateTokens2(responseText ?? "");
16954
17213
  totalTokens = promptTokens + responseTokens;
16955
17214
  source = "estimated";
16956
17215
  model = void 0;
@@ -16963,8 +17222,8 @@ var TokenTracker = class {
16963
17222
  model = inputOrPrompt.model;
16964
17223
  costUsd = estimateCost(engineId, totalTokens, model);
16965
17224
  } else {
16966
- promptTokens = estimateTokens(inputOrPrompt.prompt);
16967
- responseTokens = estimateTokens(inputOrPrompt.response);
17225
+ promptTokens = estimateTokens2(inputOrPrompt.prompt);
17226
+ responseTokens = estimateTokens2(inputOrPrompt.response);
16968
17227
  totalTokens = promptTokens + responseTokens;
16969
17228
  source = "estimated";
16970
17229
  model = void 0;
@@ -17206,9 +17465,9 @@ function wordWrap(text, width) {
17206
17465
 
17207
17466
  // ../core/src/generated/blocks/stack-trace.ts
17208
17467
  import { existsSync as existsSync9, readFileSync as readFileSync12 } from "fs";
17209
- import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute2, normalize, resolve as resolve7 } from "path";
17468
+ import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute2, normalize, resolve as resolve7 } from "path";
17210
17469
  import { fileURLToPath as fileURLToPath2 } from "url";
17211
- import { createRequire as createRequire2 } from "module";
17470
+ import { createRequire as createRequire3 } from "module";
17212
17471
  import { Buffer as Buffer2 } from "buffer";
17213
17472
  function setBoundedCacheEntry(cache, key, value) {
17214
17473
  if (!cache || typeof cache.set !== "function") return;
@@ -17249,7 +17508,7 @@ function readTextFileCached(filePath) {
17249
17508
  }
17250
17509
  function nodeModuleApi() {
17251
17510
  try {
17252
- return createRequire2(import.meta.url)("node:module");
17511
+ return createRequire3(import.meta.url)("node:module");
17253
17512
  } catch {
17254
17513
  return {};
17255
17514
  }
@@ -17285,7 +17544,7 @@ function loadSourceMapForFile(filePath) {
17285
17544
  const base643 = mappingUrl.match(/^data:application\/json(?:;charset=[^;,]+)?;base64,(.+)$/i)?.[1];
17286
17545
  if (base643) payload = JSON.parse(Buffer2.from(base643, "base64").toString("utf8"));
17287
17546
  } else {
17288
- const mapPath = resolve7(dirname5(normalized), decodeURIComponent(mappingUrl));
17547
+ const mapPath = resolve7(dirname6(normalized), decodeURIComponent(mappingUrl));
17289
17548
  if (existsSync9(mapPath)) payload = JSON.parse(readFileSync12(mapPath, "utf8"));
17290
17549
  }
17291
17550
  if (payload && typeof mod.SourceMap === "function") {
@@ -17330,7 +17589,7 @@ function resolveSourceMapSourcePath(mapFilePath, sourceMap, originFileName) {
17330
17589
  return normalize(sourceRef);
17331
17590
  }
17332
17591
  }
17333
- return normalize(resolve7(dirname5(normalizeStackFilePath(mapFilePath)), sourceRoot, sourceRef));
17592
+ return normalize(resolve7(dirname6(normalizeStackFilePath(mapFilePath)), sourceRoot, sourceRef));
17334
17593
  }
17335
17594
  function sourceMapOriginForLocation(sourceMap, lineNumber, columnNumber) {
17336
17595
  if (!sourceMap) return null;
@@ -17424,15 +17683,15 @@ function packageRootForGeneratedPath(generatedFile) {
17424
17683
  return null;
17425
17684
  }
17426
17685
  function resolveKernSourceFile(generatedFile, content, sourceName) {
17427
- const header = generatedHeaderSource(content);
17686
+ const header2 = generatedHeaderSource(content);
17428
17687
  const candidates = [];
17429
17688
  const root = packageRootForGeneratedPath(generatedFile);
17430
- if (header) {
17431
- if (isAbsolute2(header)) candidates.push(normalize(header));
17432
- if (root) candidates.push(normalize(resolve7(root, header)));
17433
- candidates.push(normalize(resolve7(dirname5(normalizeStackFilePath(generatedFile)), header)));
17689
+ if (header2) {
17690
+ if (isAbsolute2(header2)) candidates.push(normalize(header2));
17691
+ if (root) candidates.push(normalize(resolve7(root, header2)));
17692
+ candidates.push(normalize(resolve7(dirname6(normalizeStackFilePath(generatedFile)), header2)));
17434
17693
  try {
17435
- candidates.push(normalize(resolve7(process.cwd(), header)));
17694
+ candidates.push(normalize(resolve7(process.cwd(), header2)));
17436
17695
  } catch {
17437
17696
  }
17438
17697
  }
@@ -17967,7 +18226,7 @@ function undoPatch(cwd, undoToken) {
17967
18226
 
17968
18227
  // ../core/src/generated/blocks/file-history.ts
17969
18228
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync10, existsSync as existsSync10, readdirSync as readdirSync9, unlinkSync as unlinkSync4 } from "fs";
17970
- import { join as join15, dirname as dirname6, resolve as resolve9 } from "path";
18229
+ import { join as join15, dirname as dirname7, resolve as resolve9 } from "path";
17971
18230
  import { randomUUID as randomUUID2 } from "crypto";
17972
18231
  import { homedir as homedir7 } from "os";
17973
18232
  function snapshotsDir() {
@@ -18031,7 +18290,7 @@ function revertSnapshot(id) {
18031
18290
  reverted++;
18032
18291
  }
18033
18292
  } else {
18034
- mkdirSync10(dirname6(fullPath), { recursive: true });
18293
+ mkdirSync10(dirname7(fullPath), { recursive: true });
18035
18294
  writeFileSync11(fullPath, snap.content);
18036
18295
  reverted++;
18037
18296
  }
@@ -19553,7 +19812,7 @@ function createEditTool() {
19553
19812
 
19554
19813
  // ../core/src/generated/tools/tool-write.ts
19555
19814
  import { writeFileSync as writeFileSync15, statSync as statSync13, existsSync as existsSync15, mkdirSync as mkdirSync14 } from "fs";
19556
- import { resolve as resolve13, dirname as dirname9, relative as relative6 } from "path";
19815
+ import { resolve as resolve13, dirname as dirname10, relative as relative6 } from "path";
19557
19816
  function createWriteTool() {
19558
19817
  const definition = {
19559
19818
  name: "Write",
@@ -19636,7 +19895,7 @@ function createWriteTool() {
19636
19895
  } else {
19637
19896
  snapshot = takeSnapshot(`Write (new): ${relPath}`, ctx.cwd, [relPath]);
19638
19897
  }
19639
- const parentDir = dirname9(filePath);
19898
+ const parentDir = dirname10(filePath);
19640
19899
  if (!existsSync15(parentDir)) {
19641
19900
  try {
19642
19901
  mkdirSync14(parentDir, { recursive: true });
@@ -19759,10 +20018,10 @@ function createBashTool() {
19759
20018
  const readRedirect = tryRedirectToRead(command);
19760
20019
  if (readRedirect) {
19761
20020
  try {
19762
- const { readFileSync: readFileSync33 } = await import("fs");
20021
+ const { readFileSync: readFileSync38 } = await import("fs");
19763
20022
  const { resolve: resolve28 } = await import("path");
19764
20023
  const filePath = resolve28(ctx.cwd, readRedirect.file);
19765
- const content = readFileSync33(filePath, "utf-8");
20024
+ const content = readFileSync38(filePath, "utf-8");
19766
20025
  const lines = content.split("\n");
19767
20026
  const offset = readRedirect.offset ?? 0;
19768
20027
  const limit = readRedirect.limit ?? lines.length;
@@ -20547,7 +20806,7 @@ function createTodoWriteTool() {
20547
20806
 
20548
20807
  // ../core/src/generated/signals/auth-store.ts
20549
20808
  import { readFileSync as readFileSync19, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15, existsSync as existsSync16, chmodSync } from "fs";
20550
- import { join as join18, dirname as dirname10, resolve as resolve15 } from "path";
20809
+ import { join as join18, dirname as dirname11, resolve as resolve15 } from "path";
20551
20810
  import { homedir as homedir9 } from "os";
20552
20811
  function getAuthFile() {
20553
20812
  const override = process.env.AGON_HOME?.trim();
@@ -20568,7 +20827,7 @@ function loadAuthStore() {
20568
20827
  }
20569
20828
  function saveAuthStore(store) {
20570
20829
  const authFile = getAuthFile();
20571
- const dir = dirname10(authFile);
20830
+ const dir = dirname11(authFile);
20572
20831
  mkdirSync15(dir, { recursive: true });
20573
20832
  writeFileSync16(authFile, JSON.stringify(store.entries, null, 2) + "\n", { mode: 384 });
20574
20833
  try {
@@ -21806,6 +22065,8 @@ function cesarPlanMarkdownPath(planId) {
21806
22065
  }
21807
22066
  return full;
21808
22067
  }
22068
+ var CESAR_STEP_TYPE_TABLE = { self: true, forge: true, teamforge: true, delegate: true, brainstorm: true, campfire: true, tribunal: true, pipeline: true, review: true, agent: true, "team-agent": true };
22069
+ var CESAR_STEP_TYPES = Object.keys(CESAR_STEP_TYPE_TABLE);
21809
22070
  function createCesarPlan(intent, steps) {
21810
22071
  const id = `cplan-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
21811
22072
  const initializedSteps = steps.map((s) => Object.assign({}, s, { state: s.dependsOn && s.dependsOn.length > 0 ? "blocked" : "pending" }));
@@ -21821,10 +22082,11 @@ function advanceCesarStep(plan, stepId, result) {
21821
22082
  const stepIdx = plan.steps.findIndex((s) => s.id === stepId);
21822
22083
  if (stepIdx === -1) return plan;
21823
22084
  const isSuccess = result.status === "success";
21824
- const stepState = isSuccess ? "done" : "failed";
22085
+ const isPaused = result.status === "paused";
22086
+ const stepState = isSuccess ? "done" : isPaused ? "pending" : "failed";
21825
22087
  const now = (/* @__PURE__ */ new Date()).toISOString();
21826
22088
  let newSteps = plan.steps.map(
21827
- (s, i) => i === stepIdx ? { ...s, state: stepState, result, completedAt: now } : s
22089
+ (s, i) => i === stepIdx ? { ...s, state: stepState, result: isPaused ? void 0 : result, completedAt: isPaused ? void 0 : now } : s
21828
22090
  );
21829
22091
  if (isSuccess) {
21830
22092
  newSteps = newSteps.map((s) => {
@@ -22222,17 +22484,17 @@ function startChatSession(opts) {
22222
22484
  const id = `chat-${Date.now()}`;
22223
22485
  const session = { id, startedAt: (/* @__PURE__ */ new Date()).toISOString(), messages: [], cwd: opts?.cwd, branch: opts?.branch, engineIds: opts?.engineIds };
22224
22486
  const filePath = join21(chatsDir(), `${id}.ndjson`);
22225
- const header = { _type: "header", id, startedAt: session.startedAt };
22487
+ const header2 = { _type: "header", id, startedAt: session.startedAt };
22226
22488
  if (opts?.cwd) {
22227
- header.cwd = opts.cwd;
22489
+ header2.cwd = opts.cwd;
22228
22490
  }
22229
22491
  if (opts?.branch) {
22230
- header.branch = opts.branch;
22492
+ header2.branch = opts.branch;
22231
22493
  }
22232
22494
  if (opts?.engineIds) {
22233
- header.engineIds = opts.engineIds;
22495
+ header2.engineIds = opts.engineIds;
22234
22496
  }
22235
- appendFileSync(filePath, JSON.stringify(header) + "\n");
22497
+ appendFileSync(filePath, JSON.stringify(header2) + "\n");
22236
22498
  return session;
22237
22499
  }
22238
22500
  function appendMessage(session, msg) {
@@ -22407,10 +22669,10 @@ function loadChatSession(id) {
22407
22669
  const raw = readFileSync22(filePath, "utf-8");
22408
22670
  const lines = raw.trim().split("\n").filter(Boolean);
22409
22671
  if (lines.length === 0) return null;
22410
- const header = JSON.parse(lines[0]);
22672
+ const header2 = JSON.parse(lines[0]);
22411
22673
  const messages = [];
22412
- let summary = typeof header.summary === "string" ? header.summary : void 0;
22413
- let summarizedMessageCount = typeof header.summarizedMessageCount === "number" ? header.summarizedMessageCount : void 0;
22674
+ let summary = typeof header2.summary === "string" ? header2.summary : void 0;
22675
+ let summarizedMessageCount = typeof header2.summarizedMessageCount === "number" ? header2.summarizedMessageCount : void 0;
22414
22676
  for (let i = 1; i < lines.length; i++) {
22415
22677
  const msg = JSON.parse(lines[i]);
22416
22678
  if (msg._type === "summary") {
@@ -22424,12 +22686,12 @@ function loadChatSession(id) {
22424
22686
  freeSummarizedMessageBodies(messages, 0, Math.min(summarizedMessageCount, messages.length));
22425
22687
  }
22426
22688
  return {
22427
- id: header.id ?? id,
22428
- startedAt: header.startedAt ?? "",
22689
+ id: header2.id ?? id,
22690
+ startedAt: header2.startedAt ?? "",
22429
22691
  messages,
22430
- cwd: header.cwd,
22431
- branch: header.branch,
22432
- engineIds: header.engineIds,
22692
+ cwd: header2.cwd,
22693
+ branch: header2.branch,
22694
+ engineIds: header2.engineIds,
22433
22695
  summary,
22434
22696
  summarizedMessageCount
22435
22697
  };
@@ -22464,13 +22726,16 @@ function latestChatSession() {
22464
22726
  }
22465
22727
 
22466
22728
  // ../core/src/generated/blocks/image.ts
22467
- import { existsSync as existsSync19 } from "fs";
22729
+ import { existsSync as existsSync19, readFileSync as readFileSync23, statSync as statSync16 } from "fs";
22468
22730
  import { resolve as resolve19, basename as basename4, extname as extname2 } from "path";
22469
22731
  import { homedir as homedir11 } from "os";
22732
+ import { fileURLToPath as fileURLToPath3 } from "url";
22470
22733
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp"]);
22471
22734
  var MIME_MAP = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp", ".svg": "image/svg+xml", ".bmp": "image/bmp" };
22472
- var IMAGE_PATH_REGEX = /(?:^|\s)((?:\/[\w.\-]+)+\.(?:png|jpe?g|gif|webp|svg|bmp)|~\/[\w.\-\/]+\.(?:png|jpe?g|gif|webp|svg|bmp)|\.{1,2}\/[\w.\-\/]+\.(?:png|jpe?g|gif|webp|svg|bmp))/gi;
22473
22735
  var IMG_CMD_REGEX = /^\/img\s+(.+)$/i;
22736
+ var MAX_DISPATCH_IMAGE_BYTES = 5 * 1024 * 1024;
22737
+ var MAX_DISPATCH_IMAGES = 4;
22738
+ var DISPATCH_VISION_MIME = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
22474
22739
  function isImagePath(filePath) {
22475
22740
  const ext = extname2(filePath).toLowerCase();
22476
22741
  return IMAGE_EXTENSIONS.has(ext);
@@ -22497,59 +22762,450 @@ function buildImageAttachment(rawPath, cwd) {
22497
22762
  }
22498
22763
  return { path: resolved, filename: basename4(resolved), mimeType: mimeFromExt(resolved) };
22499
22764
  }
22765
+ function normalizeDroppedPath(raw) {
22766
+ let p = raw.trim();
22767
+ const sq = p.startsWith("'") && p.endsWith("'");
22768
+ const dq = p.startsWith('"') && p.endsWith('"');
22769
+ if (sq || dq) p = p.slice(1, -1);
22770
+ if (p.startsWith("file://")) {
22771
+ try {
22772
+ return fileURLToPath3(p).trim();
22773
+ } catch {
22774
+ p = p.slice("file://".length);
22775
+ try {
22776
+ p = decodeURIComponent(p);
22777
+ } catch {
22778
+ }
22779
+ return p.trim();
22780
+ }
22781
+ }
22782
+ p = p.replace(/\\(.)/g, "$1");
22783
+ return p.trim();
22784
+ }
22500
22785
  function extractImagesFromInput(input, cwd) {
22501
22786
  const images = [];
22502
22787
  const imgCmdMatch = IMG_CMD_REGEX.exec(input.trim());
22503
22788
  if (imgCmdMatch) {
22504
- const att = buildImageAttachment(imgCmdMatch[1], cwd);
22789
+ const att = buildImageAttachment(normalizeDroppedPath(imgCmdMatch[1]), cwd);
22505
22790
  if (att) images.push(att);
22506
22791
  return { text: "", images };
22507
22792
  }
22793
+ const EXT = "(?:png|jpe?g|gif|webp|svg|bmp)";
22794
+ const detector = new RegExp(
22795
+ "'([^']*\\." + EXT + `)'|"([^"]*\\.` + EXT + ')"|(file:\\/\\/\\S+?\\.' + EXT + `)|(?:^|\\s)((?:\\/|~\\/|\\.{1,2}\\/)(?:\\\\\\x20|[^\\s'"])*\\.` + EXT + ")",
22796
+ "gi"
22797
+ );
22508
22798
  let text = input;
22509
- const pathRegex = new RegExp(IMAGE_PATH_REGEX.source, "gi");
22510
22799
  let match;
22511
- const paths = [];
22512
- while ((match = pathRegex.exec(input)) !== null) {
22513
- const rawPath = match[1].trim();
22514
- const att = buildImageAttachment(rawPath, cwd);
22800
+ const hits = [];
22801
+ while ((match = detector.exec(input)) !== null) {
22802
+ const raw = match[1] ?? match[2] ?? match[3] ?? match[4];
22803
+ if (raw) hits.push({ raw, whole: match[0] });
22804
+ }
22805
+ for (const hit of hits) {
22806
+ const att = buildImageAttachment(normalizeDroppedPath(hit.raw), cwd);
22515
22807
  if (att) {
22516
22808
  images.push(att);
22517
- paths.push(match[0]);
22809
+ text = text.replace(hit.whole, "");
22518
22810
  }
22519
22811
  }
22520
- for (const p of paths) {
22521
- text = text.replace(p, "");
22812
+ if (images.length === 0) {
22813
+ const whole = normalizeDroppedPath(input);
22814
+ if (isImagePath(whole)) {
22815
+ const att = buildImageAttachment(whole, cwd);
22816
+ if (att) {
22817
+ images.push(att);
22818
+ text = "";
22819
+ }
22820
+ }
22522
22821
  }
22523
22822
  text = text.replace(/\s{2,}/g, " ").trim();
22524
22823
  return { text, images };
22525
22824
  }
22825
+ function encodeImagesRaw(paths, maxBytes, maxImages) {
22826
+ const lim = maxBytes ?? MAX_DISPATCH_IMAGE_BYTES;
22827
+ const cap = maxImages ?? MAX_DISPATCH_IMAGES;
22828
+ const images = [];
22829
+ const skipped = [];
22830
+ const kb = (n) => `${Math.round(n / 1024)}KB`;
22831
+ for (const p of paths) {
22832
+ const name = basename4(p);
22833
+ if (images.length >= cap) {
22834
+ skipped.push(`${name} (exceeds ${cap}-image limit)`);
22835
+ continue;
22836
+ }
22837
+ try {
22838
+ if (!existsSync19(p)) {
22839
+ skipped.push(`${name} (not found)`);
22840
+ continue;
22841
+ }
22842
+ const mediaType = mimeFromExt(p);
22843
+ if (!DISPATCH_VISION_MIME.has(mediaType)) {
22844
+ skipped.push(`${name} (unsupported type ${mediaType})`);
22845
+ continue;
22846
+ }
22847
+ const st = statSync16(p);
22848
+ if (!st.isFile()) {
22849
+ skipped.push(`${name} (not a regular file)`);
22850
+ continue;
22851
+ }
22852
+ if (st.size > lim) {
22853
+ skipped.push(`${name} (${kb(st.size)} over ${kb(lim)} limit)`);
22854
+ continue;
22855
+ }
22856
+ const data = readFileSync23(p).toString("base64");
22857
+ images.push({ data, mediaType });
22858
+ } catch {
22859
+ skipped.push(`${name} (read error)`);
22860
+ }
22861
+ }
22862
+ return { images, skipped };
22863
+ }
22864
+ function encodeImagesForDispatch(paths, maxBytes, maxImages) {
22865
+ const { images, skipped } = encodeImagesRaw(paths, maxBytes, maxImages);
22866
+ return {
22867
+ parts: images.map((i) => ({ type: "image", image: `data:${i.mediaType};base64,${i.data}`, mediaType: i.mediaType })),
22868
+ skipped
22869
+ };
22870
+ }
22871
+
22872
+ // ../core/src/generated/rooms/store.ts
22873
+ import { mkdirSync as mkdirSync18, existsSync as existsSync20, readFileSync as readFileSync24, writeFileSync as writeFileSync19, appendFileSync as appendFileSync2, readdirSync as readdirSync14, openSync, closeSync, unlinkSync as unlinkSync9, statSync as statSync17 } from "fs";
22874
+ import { join as join22 } from "path";
22875
+ var LOCK_TIMEOUT_MS = 2e3;
22876
+ var LOCK_STALE_MS = 5e3;
22877
+ function roomsDir() {
22878
+ return runtimeAgonPath("rooms");
22879
+ }
22880
+ function roomDir(roomId) {
22881
+ return join22(roomsDir(), roomId);
22882
+ }
22883
+ function eventsPath(roomId) {
22884
+ return join22(roomDir(roomId), "events.ndjson");
22885
+ }
22886
+ function metaPath(roomId) {
22887
+ return join22(roomDir(roomId), "room.json");
22888
+ }
22889
+ function slugifyRoomId(name) {
22890
+ const slug = String(name ?? "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
22891
+ return slug || "room";
22892
+ }
22893
+ function roomExists(roomId) {
22894
+ return existsSync20(metaPath(roomId));
22895
+ }
22896
+ function readMeta(roomId) {
22897
+ try {
22898
+ return JSON.parse(readFileSync24(metaPath(roomId), "utf-8"));
22899
+ } catch {
22900
+ return null;
22901
+ }
22902
+ }
22903
+ function writeMeta(meta3) {
22904
+ mkdirSync18(roomDir(meta3.roomId), { recursive: true });
22905
+ writeFileSync19(metaPath(meta3.roomId), JSON.stringify(meta3, null, 2) + "\n");
22906
+ }
22907
+ function createRoom(name) {
22908
+ const roomId = slugifyRoomId(name);
22909
+ const existing = readMeta(roomId);
22910
+ if (existing) return existing;
22911
+ mkdirSync18(roomDir(roomId), { recursive: true });
22912
+ const meta3 = {
22913
+ roomId,
22914
+ name: String(name ?? roomId),
22915
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
22916
+ nextSeq: 1,
22917
+ closed: false
22918
+ };
22919
+ writeMeta(meta3);
22920
+ if (!existsSync20(eventsPath(roomId))) writeFileSync19(eventsPath(roomId), "");
22921
+ return meta3;
22922
+ }
22923
+ function listRooms() {
22924
+ let ids;
22925
+ try {
22926
+ ids = readdirSync14(roomsDir());
22927
+ } catch {
22928
+ return [];
22929
+ }
22930
+ const out = [];
22931
+ for (const id of ids) {
22932
+ const meta3 = readMeta(id);
22933
+ if (meta3) out.push(meta3);
22934
+ }
22935
+ out.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
22936
+ return out;
22937
+ }
22938
+ function parseMentions(text) {
22939
+ const out = [];
22940
+ const re = /(?:^|[^\w@])@([a-z0-9][\w-]*)/gi;
22941
+ let m;
22942
+ while ((m = re.exec(String(text ?? ""))) !== null) {
22943
+ const tag = m[1].toLowerCase();
22944
+ if (!out.includes(tag)) out.push(tag);
22945
+ }
22946
+ return out;
22947
+ }
22948
+ function withRoomLock(roomId, work) {
22949
+ mkdirSync18(roomDir(roomId), { recursive: true });
22950
+ const lock = join22(roomDir(roomId), ".lock");
22951
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
22952
+ let fd = null;
22953
+ while (fd === null) {
22954
+ try {
22955
+ fd = openSync(lock, "wx");
22956
+ } catch (err) {
22957
+ if (err?.code !== "EEXIST") throw err;
22958
+ try {
22959
+ const st = statSync17(lock);
22960
+ if (Date.now() - st.mtimeMs > LOCK_STALE_MS) {
22961
+ unlinkSync9(lock);
22962
+ continue;
22963
+ }
22964
+ } catch {
22965
+ continue;
22966
+ }
22967
+ if (Date.now() > deadline) throw new Error(`room lock timeout: ${roomId}`);
22968
+ const spinUntil = Date.now() + 12;
22969
+ while (Date.now() < spinUntil) {
22970
+ }
22971
+ }
22972
+ }
22973
+ try {
22974
+ work();
22975
+ } finally {
22976
+ try {
22977
+ closeSync(fd);
22978
+ } catch {
22979
+ }
22980
+ try {
22981
+ unlinkSync9(lock);
22982
+ } catch {
22983
+ }
22984
+ }
22985
+ }
22986
+ function appendEvent(roomId, input) {
22987
+ let result = null;
22988
+ withRoomLock(roomId, () => {
22989
+ const meta3 = readMeta(roomId) ?? createRoom(roomId);
22990
+ const seq = meta3.nextSeq;
22991
+ const event = {
22992
+ seq,
22993
+ id: `evt_${Date.now().toString(36)}${Math.floor(Math.random() * 1e9).toString(36)}`,
22994
+ roomId,
22995
+ kind: input.kind,
22996
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
22997
+ actor: input.actor,
22998
+ repoHint: input.repoHint,
22999
+ body: input.body,
23000
+ mentions: input.mentions,
23001
+ replyTo: input.replyTo,
23002
+ auto: input.auto === true
23003
+ };
23004
+ appendFileSync2(eventsPath(roomId), JSON.stringify(event) + "\n");
23005
+ meta3.nextSeq = seq + 1;
23006
+ writeMeta(meta3);
23007
+ result = event;
23008
+ });
23009
+ if (!result) throw new Error(`appendEvent: lock produced no event for ${roomId}`);
23010
+ return result;
23011
+ }
23012
+ function readEvents(roomId, sinceSeq, limit) {
23013
+ let raw;
23014
+ try {
23015
+ raw = readFileSync24(eventsPath(roomId), "utf-8");
23016
+ } catch {
23017
+ return [];
23018
+ }
23019
+ const out = [];
23020
+ for (const line of raw.split("\n")) {
23021
+ if (!line.trim()) continue;
23022
+ try {
23023
+ const ev = JSON.parse(line);
23024
+ if (typeof ev.seq === "number" && ev.seq > sinceSeq) out.push(ev);
23025
+ } catch {
23026
+ }
23027
+ }
23028
+ if (limit > 0 && out.length > limit) return out.slice(out.length - limit);
23029
+ return out;
23030
+ }
23031
+ function closeRoom(roomId) {
23032
+ const meta3 = readMeta(roomId);
23033
+ if (!meta3) return;
23034
+ meta3.closed = true;
23035
+ writeMeta(meta3);
23036
+ }
23037
+ function isRoomClosed(roomId) {
23038
+ const meta3 = readMeta(roomId);
23039
+ return meta3 ? meta3.closed === true : false;
23040
+ }
23041
+
23042
+ // ../core/src/generated/rooms/presence.ts
23043
+ import { mkdirSync as mkdirSync19, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
23044
+ import { join as join23 } from "path";
23045
+ var PRESENCE_TTL_MS = 9e4;
23046
+ function presencePath(roomId) {
23047
+ return join23(roomDir(roomId), "presence.json");
23048
+ }
23049
+ function readPresenceRaw(roomId) {
23050
+ try {
23051
+ return JSON.parse(readFileSync25(presencePath(roomId), "utf-8"));
23052
+ } catch {
23053
+ return {};
23054
+ }
23055
+ }
23056
+ function recordPresence(roomId, actor, lastReadSeq, auto) {
23057
+ mkdirSync19(roomDir(roomId), { recursive: true });
23058
+ const map2 = readPresenceRaw(roomId);
23059
+ map2[actor.callsign] = {
23060
+ callsign: actor.callsign,
23061
+ actorId: actor.actorId,
23062
+ status: "here",
23063
+ lastSeenAt: (/* @__PURE__ */ new Date()).toISOString(),
23064
+ lastReadSeq,
23065
+ auto,
23066
+ cli: actor.cli
23067
+ };
23068
+ writeFileSync20(presencePath(roomId), JSON.stringify(map2, null, 2) + "\n");
23069
+ }
23070
+ function removePresence(roomId, callsign) {
23071
+ const map2 = readPresenceRaw(roomId);
23072
+ if (!map2[callsign]) return;
23073
+ delete map2[callsign];
23074
+ try {
23075
+ writeFileSync20(presencePath(roomId), JSON.stringify(map2, null, 2) + "\n");
23076
+ } catch {
23077
+ }
23078
+ }
23079
+ function listPresence(roomId) {
23080
+ const map2 = readPresenceRaw(roomId);
23081
+ const now = Date.now();
23082
+ const out = [];
23083
+ for (const key of Object.keys(map2)) {
23084
+ const entry = map2[key];
23085
+ const age = now - new Date(entry.lastSeenAt).getTime();
23086
+ const status = !Number.isFinite(age) ? "left" : age <= PRESENCE_TTL_MS ? "here" : age <= PRESENCE_TTL_MS * 4 ? "stale" : "left";
23087
+ out.push({ ...entry, status });
23088
+ }
23089
+ out.sort((a, b) => a.callsign.localeCompare(b.callsign));
23090
+ return out;
23091
+ }
23092
+
23093
+ // ../core/src/generated/rooms/leases.ts
23094
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "fs";
23095
+ import { join as join24 } from "path";
23096
+ function leasesPath(roomId) {
23097
+ return join24(roomDir(roomId), "leases.json");
23098
+ }
23099
+ function readActiveLease(roomId) {
23100
+ try {
23101
+ const raw = JSON.parse(readFileSync26(leasesPath(roomId), "utf-8"));
23102
+ if (!raw || !raw.leaseId) return null;
23103
+ if (Date.now() >= new Date(raw.expiresAt).getTime()) return null;
23104
+ return raw;
23105
+ } catch {
23106
+ return null;
23107
+ }
23108
+ }
23109
+ function acquireTurnLease(roomId, holder, triggerSeq, ttlMs) {
23110
+ let acquired = null;
23111
+ withRoomLock(roomId, () => {
23112
+ const active = readActiveLease(roomId);
23113
+ if (active && active.holder !== holder) return;
23114
+ const now = Date.now();
23115
+ const lease = {
23116
+ leaseId: `lease_${now.toString(36)}${Math.floor(Math.random() * 1e9).toString(36)}`,
23117
+ holder,
23118
+ triggerSeq,
23119
+ acquiredAt: new Date(now).toISOString(),
23120
+ expiresAt: new Date(now + Math.max(1e3, ttlMs)).toISOString()
23121
+ };
23122
+ writeFileSync21(leasesPath(roomId), JSON.stringify(lease, null, 2) + "\n");
23123
+ acquired = lease;
23124
+ });
23125
+ return acquired;
23126
+ }
23127
+ function releaseTurnLease(roomId, leaseId) {
23128
+ withRoomLock(roomId, () => {
23129
+ const active = readActiveLease(roomId);
23130
+ if (active && active.leaseId === leaseId) {
23131
+ try {
23132
+ writeFileSync21(leasesPath(roomId), JSON.stringify(null) + "\n");
23133
+ } catch {
23134
+ }
23135
+ }
23136
+ });
23137
+ }
23138
+
23139
+ // ../core/src/generated/rooms/auto-policy.ts
23140
+ function detectTrigger(events, myCallsign, openFloor, quietMs) {
23141
+ if (!Array.isArray(events) || events.length === 0) return { trigger: false, triggerSeq: 0, reason: "no-events" };
23142
+ for (let i = events.length - 1; i >= 0; i--) {
23143
+ const ev = events[i];
23144
+ if (ev.kind !== "post") continue;
23145
+ if (ev.actor.callsign === myCallsign) return { trigger: false, triggerSeq: 0, reason: "self-latest" };
23146
+ if (Array.isArray(ev.mentions) && ev.mentions.includes(myCallsign)) {
23147
+ return { trigger: true, triggerSeq: ev.seq, reason: "mentioned" };
23148
+ }
23149
+ if (openFloor) {
23150
+ const ageMs = Date.now() - new Date(ev.createdAt).getTime();
23151
+ if (ageMs >= quietMs) return { trigger: true, triggerSeq: ev.seq, reason: "open-floor" };
23152
+ return { trigger: false, triggerSeq: 0, reason: "waiting-quiet" };
23153
+ }
23154
+ return { trigger: false, triggerSeq: 0, reason: "not-mentioned" };
23155
+ }
23156
+ return { trigger: false, triggerSeq: 0, reason: "no-posts" };
23157
+ }
23158
+ function detectPingPong(events) {
23159
+ const posts = events.filter((e) => e.kind === "post").slice(-4);
23160
+ if (posts.length < 4) return false;
23161
+ if (!posts.every((p) => p.auto === true)) return false;
23162
+ const a = posts[0].actor.callsign;
23163
+ const b = posts[1].actor.callsign;
23164
+ if (a === b) return false;
23165
+ return posts[2].actor.callsign === a && posts[3].actor.callsign === b;
23166
+ }
23167
+ function evaluateStop(state, config2, events) {
23168
+ if (state.turns >= config2.maxTurns) return { stop: true, reason: `max-turns (${config2.maxTurns})` };
23169
+ if (Date.now() - state.startedAtMs >= config2.maxWallMs) return { stop: true, reason: "max-wall-time" };
23170
+ if (detectPingPong(events)) return { stop: true, reason: "ping-pong-halt" };
23171
+ if (config2.untilHuman && state.turns >= 1) {
23172
+ const human = events.find((e) => e.kind === "post" && e.auto !== true && e.actor.callsign !== config2.callsign && e.seq > state.lastSelfSeq);
23173
+ if (human) return { stop: true, reason: "human-replied" };
23174
+ }
23175
+ if (config2.stopPhrase) {
23176
+ const needle = config2.stopPhrase.toLowerCase();
23177
+ const hit = events.find((e) => e.kind === "post" && e.actor.callsign !== config2.callsign && e.body.toLowerCase().includes(needle));
23178
+ if (hit) return { stop: true, reason: "stop-phrase" };
23179
+ }
23180
+ return { stop: false, reason: "" };
23181
+ }
22526
23182
 
22527
23183
  // ../core/src/generated/signals/flow.ts
22528
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18, readdirSync as readdirSync14 } from "fs";
22529
- import { join as join22, resolve as resolve20 } from "path";
23184
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync22, mkdirSync as mkdirSync20, readdirSync as readdirSync15 } from "fs";
23185
+ import { join as join25, resolve as resolve20 } from "path";
22530
23186
  import { homedir as homedir12 } from "os";
22531
23187
  function getFlowsDir() {
22532
23188
  const override = process.env.AGON_HOME?.trim();
22533
- const home = override ? resolve20(override) : join22(homedir12(), ".agon");
22534
- return join22(home, "flows");
23189
+ const home = override ? resolve20(override) : join25(homedir12(), ".agon");
23190
+ return join25(home, "flows");
22535
23191
  }
22536
23192
  var FLOWS_DIR = getFlowsDir();
22537
23193
  var FRICTION_TAGS = ["slow", "wrong-mode", "engine-error", "unclear-output", "timeout", "context-lost", "other"];
22538
23194
  function ensureFlowsDir() {
22539
- mkdirSync18(getFlowsDir(), { recursive: true });
23195
+ mkdirSync20(getFlowsDir(), { recursive: true });
22540
23196
  }
22541
23197
  function logFlow(record2) {
22542
23198
  ensureFlowsDir();
22543
23199
  const filename = `flow-${record2.id}.json`;
22544
- const filepath = join22(getFlowsDir(), filename);
22545
- writeFileSync19(filepath, JSON.stringify(record2, null, 2));
23200
+ const filepath = join25(getFlowsDir(), filename);
23201
+ writeFileSync22(filepath, JSON.stringify(record2, null, 2));
22546
23202
  return filepath;
22547
23203
  }
22548
23204
  function readFlows(limit) {
22549
23205
  ensureFlowsDir();
22550
23206
  let files;
22551
23207
  try {
22552
- files = readdirSync14(getFlowsDir()).filter((f) => f.startsWith("flow-") && f.endsWith(".json")).sort().reverse();
23208
+ files = readdirSync15(getFlowsDir()).filter((f) => f.startsWith("flow-") && f.endsWith(".json")).sort().reverse();
22553
23209
  } catch (err) {
22554
23210
  console.warn(`[agon] failed to read flows directory: ${err instanceof Error ? err.message : String(err)}`);
22555
23211
  return [];
@@ -22558,7 +23214,7 @@ function readFlows(limit) {
22558
23214
  const records = [];
22559
23215
  for (const file2 of files) {
22560
23216
  try {
22561
- const data = JSON.parse(readFileSync23(join22(getFlowsDir(), file2), "utf-8"));
23217
+ const data = JSON.parse(readFileSync27(join25(getFlowsDir(), file2), "utf-8"));
22562
23218
  records.push(data);
22563
23219
  } catch (err) {
22564
23220
  console.warn(`[agon] skipping malformed flow record ${file2}: ${err instanceof Error ? err.message : String(err)}`);
@@ -22987,19 +23643,19 @@ async function companionDispatch(opts) {
22987
23643
  }
22988
23644
 
22989
23645
  // ../core/src/generated/signals/models-registry.ts
22990
- import { readFileSync as readFileSync24, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, existsSync as existsSync20, statSync as statSync16 } from "fs";
22991
- import { join as join23 } from "path";
23646
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync23, mkdirSync as mkdirSync21, existsSync as existsSync22, statSync as statSync18 } from "fs";
23647
+ import { join as join26 } from "path";
22992
23648
  var CACHE_TTL_MS = 36e5;
22993
23649
  var MODELS_DEV_URL = "https://models.dev/api.json";
22994
23650
  async function fetchModelsRegistry() {
22995
23651
  const cacheDir = getCacheDir();
22996
- const cacheFile = join23(cacheDir, "models-dev.json");
22997
- if (existsSync20(cacheFile)) {
23652
+ const cacheFile = join26(cacheDir, "models-dev.json");
23653
+ if (existsSync22(cacheFile)) {
22998
23654
  try {
22999
- const stat = statSync16(cacheFile);
23655
+ const stat = statSync18(cacheFile);
23000
23656
  const age = Date.now() - stat.mtimeMs;
23001
23657
  if (age < CACHE_TTL_MS) {
23002
- return JSON.parse(readFileSync24(cacheFile, "utf-8"));
23658
+ return JSON.parse(readFileSync28(cacheFile, "utf-8"));
23003
23659
  }
23004
23660
  } catch (_e) {
23005
23661
  console.warn(`[agon] models-registry: cache read failed, refetching: ${_e instanceof Error ? _e.message : String(_e)}`);
@@ -23007,14 +23663,14 @@ async function fetchModelsRegistry() {
23007
23663
  }
23008
23664
  const response = await fetch(MODELS_DEV_URL);
23009
23665
  if (!response.ok) {
23010
- if (existsSync20(cacheFile)) {
23011
- return JSON.parse(readFileSync24(cacheFile, "utf-8"));
23666
+ if (existsSync22(cacheFile)) {
23667
+ return JSON.parse(readFileSync28(cacheFile, "utf-8"));
23012
23668
  }
23013
23669
  throw new Error(`Failed to fetch models registry: ${response.status}`);
23014
23670
  }
23015
23671
  const data = await response.json();
23016
- mkdirSync19(cacheDir, { recursive: true });
23017
- writeFileSync20(cacheFile, JSON.stringify(data));
23672
+ mkdirSync21(cacheDir, { recursive: true });
23673
+ writeFileSync23(cacheFile, JSON.stringify(data));
23018
23674
  return data;
23019
23675
  }
23020
23676
  function resolveModelFormat(providerNpm, model) {
@@ -23135,24 +23791,24 @@ function modelEntryToEngineDef(entry) {
23135
23791
 
23136
23792
  // ../core/src/generated/signals/cli-models-registry.ts
23137
23793
  import { execSync as execSync4 } from "child_process";
23138
- import { readFileSync as readFileSync25, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20, existsSync as existsSync21, statSync as statSync17 } from "fs";
23139
- import { join as join24 } from "path";
23794
+ import { readFileSync as readFileSync29, writeFileSync as writeFileSync24, mkdirSync as mkdirSync22, existsSync as existsSync23, statSync as statSync19 } from "fs";
23795
+ import { join as join27 } from "path";
23140
23796
  import { homedir as homedir13 } from "os";
23141
- import { createRequire as createRequire3 } from "module";
23797
+ import { createRequire as createRequire4 } from "module";
23142
23798
  var ENGINE_PROVIDER_MAP = { anthropic: { providerId: "anthropic", engineId: "claude", engineBinary: "claude", versionCmd: ["--version"], listCmd: ["__pty:/model"], effortLevels: ["low", "medium", "high", "xhigh", "max"] }, openai: { providerId: "openai", engineId: "codex", engineBinary: "codex", versionCmd: ["--version"], listCmd: ["__pty:/model"], effortLevels: ["low", "medium", "high", "xhigh"] }, google: { providerId: "google", engineId: "agy", engineBinary: "agy", versionCmd: ["--version"], listCmd: ["__pty:/model"] }, opencode: { providerId: "opencode", engineId: "opencode", engineBinary: "opencode", versionCmd: ["--version"], listCmd: ["models"] }, mistral: { providerId: "mistral", engineId: "mistral", engineBinary: "mistral", versionCmd: ["--version"] }, openrouter: { providerId: "openrouter", engineId: "openrouter", engineBinary: "openrouter", versionCmd: [] } };
23143
23799
  var ENGINE_DISPLAY_NAMES = { claude: "Claude", codex: "Codex", agy: "Antigravity", opencode: "OpenCode", mistral: "Mistral", openrouter: "OpenRouter" };
23144
23800
  var FALLBACK_MODELS = { anthropic: [{ id: "claude-sonnet-4-5-20250929", name: "Claude Sonnet 4.5", contextWindow: 2e5, toolCall: true, reasoning: true }, { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5", contextWindow: 2e5, toolCall: true, reasoning: true }], openai: [{ id: "gpt-4o", name: "GPT-4o", contextWindow: 128e3, toolCall: true, reasoning: false }, { id: "o4-mini", name: "o4-mini", contextWindow: 2e5, toolCall: true, reasoning: true }], google: [{ id: "gemini-3.5-flash", name: "Gemini 3.5 Flash", contextWindow: 1048576, toolCall: true, reasoning: true }, { id: "gemini-3.1-pro", name: "Gemini 3.1 Pro", contextWindow: 1048576, toolCall: true, reasoning: true }, { id: "gemini-3-flash-preview", name: "Gemini 3 Flash", contextWindow: 1048576, toolCall: true, reasoning: true }], mistral: [{ id: "mistral-large-latest", name: "Mistral Large", contextWindow: 128e3, toolCall: true, reasoning: false }, { id: "codestral-latest", name: "Codestral", contextWindow: 256e3, toolCall: true, reasoning: false }], openrouter: [{ id: "auto", name: "Auto (best for task)", toolCall: true, reasoning: false }], opencode: [{ id: "anthropic/claude-sonnet-4", name: "anthropic/claude-sonnet-4", toolCall: true, reasoning: false }, { id: "openai/gpt-5.3-codex", name: "openai/gpt-5.3-codex", toolCall: true, reasoning: false }] };
23145
23801
  var PROBE_TTL_MS = 864e5;
23146
23802
  function probedModelsCacheFile(engineId) {
23147
- return join24(getCacheDir(), `cli-models-${engineId.replace(/[^a-zA-Z0-9_-]/g, "-")}.json`);
23803
+ return join27(getCacheDir(), `cli-models-${engineId.replace(/[^a-zA-Z0-9_-]/g, "-")}.json`);
23148
23804
  }
23149
23805
  function readProbedCliModels(engineId, ttlMs) {
23150
23806
  try {
23151
23807
  const file2 = probedModelsCacheFile(engineId);
23152
- if (!existsSync21(file2)) return null;
23153
- const age = Date.now() - statSync17(file2).mtimeMs;
23808
+ if (!existsSync23(file2)) return null;
23809
+ const age = Date.now() - statSync19(file2).mtimeMs;
23154
23810
  if (age > (ttlMs ?? PROBE_TTL_MS)) return null;
23155
- const data = JSON.parse(readFileSync25(file2, "utf-8"));
23811
+ const data = JSON.parse(readFileSync29(file2, "utf-8"));
23156
23812
  const raw = Array.isArray(data?.models) ? data.models : [];
23157
23813
  const models = raw.map((m) => ({ id: String(m.id ?? ""), name: String(m.name ?? m.id ?? ""), current: !!m.current })).filter((m) => m.name);
23158
23814
  return models.length > 0 ? models : null;
@@ -23162,7 +23818,7 @@ function readProbedCliModels(engineId, ttlMs) {
23162
23818
  }
23163
23819
  function resolveModelProbeScript() {
23164
23820
  try {
23165
- const req = createRequire3(import.meta.url);
23821
+ const req = createRequire4(import.meta.url);
23166
23822
  const anchor = req.resolve("@kernlang/agon-engines/cli/claude.js");
23167
23823
  const candidates = [
23168
23824
  // Canonical: the package ships the probe at py/kern_engines/cli/ (see
@@ -23170,16 +23826,16 @@ function resolveModelProbeScript() {
23170
23826
  // to the package root, then into py/. This is the path that actually
23171
23827
  // exists — the dist/cli & root/cli guesses below never matched, so the
23172
23828
  // probe silently never ran and every engine fell back to its static list.
23173
- join24(anchor, "..", "..", "..", "py", "kern_engines", "cli", "model_probe.py"),
23829
+ join27(anchor, "..", "..", "..", "py", "kern_engines", "cli", "model_probe.py"),
23174
23830
  // dist/cli → root → py/kern_engines/cli
23175
- join24(anchor, "..", "..", "py", "kern_engines", "cli", "model_probe.py"),
23831
+ join27(anchor, "..", "..", "py", "kern_engines", "cli", "model_probe.py"),
23176
23832
  // (alt layout: cli/claude.js → root)
23177
- join24(anchor, "..", "..", "..", "cli", "model_probe.py"),
23178
- join24(anchor, "..", "..", "cli", "model_probe.py"),
23179
- join24(anchor, "..", "model_probe.py")
23833
+ join27(anchor, "..", "..", "..", "cli", "model_probe.py"),
23834
+ join27(anchor, "..", "..", "cli", "model_probe.py"),
23835
+ join27(anchor, "..", "model_probe.py")
23180
23836
  ];
23181
23837
  for (const c of candidates) {
23182
- if (existsSync21(c)) return c;
23838
+ if (existsSync23(c)) return c;
23183
23839
  }
23184
23840
  return null;
23185
23841
  } catch {
@@ -23249,8 +23905,8 @@ async function refreshProbedCliModels(engineId, binary, listCmd, pythonBin) {
23249
23905
  return false;
23250
23906
  }
23251
23907
  const dir = getCacheDir();
23252
- mkdirSync20(dir, { recursive: true });
23253
- writeFileSync21(probedModelsCacheFile(engineId), JSON.stringify({ ts: Date.now(), engineId, models }));
23908
+ mkdirSync22(dir, { recursive: true });
23909
+ writeFileSync24(probedModelsCacheFile(engineId), JSON.stringify({ ts: Date.now(), engineId, models }));
23254
23910
  return true;
23255
23911
  } catch (e) {
23256
23912
  dbg(`probe threw: ${e?.message ?? e}`);
@@ -23266,10 +23922,10 @@ function findBinary(binary) {
23266
23922
  } catch (e) {
23267
23923
  }
23268
23924
  const home = homedir13();
23269
- const searchPaths = [join24(home, ".local", "bin"), join24(home, ".npm-global", "bin"), "/usr/local/bin"];
23925
+ const searchPaths = [join27(home, ".local", "bin"), join27(home, ".npm-global", "bin"), "/usr/local/bin"];
23270
23926
  for (const dir of searchPaths) {
23271
- const fullPath = join24(dir, binary);
23272
- if (existsSync21(fullPath)) {
23927
+ const fullPath = join27(dir, binary);
23928
+ if (existsSync23(fullPath)) {
23273
23929
  return fullPath;
23274
23930
  }
23275
23931
  }
@@ -23387,6 +24043,7 @@ async function discoverCliModelsAsync() {
23387
24043
  // ../core/src/generated/sessions/session-companion.ts
23388
24044
  import { spawn as spawn3 } from "child_process";
23389
24045
  import { createInterface as createInterface2 } from "readline";
24046
+ import { existsSync as existsSync24 } from "fs";
23390
24047
  function createCompanionSession(config2) {
23391
24048
  let proc = null;
23392
24049
  let alive = false;
@@ -23692,9 +24349,37 @@ ${config2.systemPrompt}
23692
24349
  ${message}`;
23693
24350
  }
23694
24351
  firstTurn = false;
24352
+ const input = [{ type: "text", text: message, text_elements: [] }];
24353
+ if (opts.images?.length) {
24354
+ if (config2.engine.capabilities?.includes("vision")) {
24355
+ let attached = 0;
24356
+ const skipped = [];
24357
+ for (const p of opts.images) {
24358
+ if (attached >= MAX_DISPATCH_IMAGES) {
24359
+ skipped.push(`${p} (exceeds ${MAX_DISPATCH_IMAGES}-image limit)`);
24360
+ continue;
24361
+ }
24362
+ if (!existsSync24(p) || !isImagePath(p)) {
24363
+ skipped.push(`${p} (not found or not an image)`);
24364
+ continue;
24365
+ }
24366
+ if (!DISPATCH_VISION_MIME.has(mimeFromExt(p))) {
24367
+ skipped.push(`${p} (unsupported type ${mimeFromExt(p)})`);
24368
+ continue;
24369
+ }
24370
+ input.push({ type: "localImage", path: p });
24371
+ attached++;
24372
+ }
24373
+ if (skipped.length) {
24374
+ chunks.push({ type: "status", content: `image(s) not sent: ${skipped.join("; ")}` });
24375
+ }
24376
+ } else {
24377
+ chunks.push({ type: "status", content: `${config2.engine.id} has no vision capability \u2014 ${opts.images.length} image(s) not sent to the model` });
24378
+ }
24379
+ }
23695
24380
  await sendRpc("turn/start", {
23696
24381
  threadId,
23697
- input: [{ type: "text", text: message, text_elements: [] }]
24382
+ input
23698
24383
  });
23699
24384
  while (!turnDone) {
23700
24385
  if (chunks.length > 0) {
@@ -24427,7 +25112,41 @@ function createResumeSession(config2) {
24427
25112
  }
24428
25113
  firstTurn = false;
24429
25114
  }
24430
- messageHistory.push({ role: "user", content: opts.message });
25115
+ const hasVision = !!config2.engine.capabilities?.includes("vision");
25116
+ let turnImageParts = [];
25117
+ if (opts.images?.length) {
25118
+ if (hasVision) {
25119
+ const enc = encodeImagesForDispatch(opts.images);
25120
+ turnImageParts = enc.parts;
25121
+ if (enc.skipped.length) {
25122
+ yield { type: "status", content: `image(s) not sent: ${enc.skipped.join("; ")}` };
25123
+ }
25124
+ } else {
25125
+ yield { type: "status", content: `${config2.engine.id} has no vision capability \u2014 ${opts.images.length} image(s) not sent to the model` };
25126
+ }
25127
+ }
25128
+ const userTurnMsg = { role: "user", content: opts.message };
25129
+ messageHistory.push(userTurnMsg);
25130
+ const withImages = (history) => {
25131
+ if (!turnImageParts.length) return history;
25132
+ let idx = history.indexOf(userTurnMsg);
25133
+ if (idx < 0) {
25134
+ for (let i = history.length - 1; i >= 0; i--) {
25135
+ const m = history[i];
25136
+ if (m?.role === "user" && typeof m.content === "string" && m.content === userTurnMsg.content) {
25137
+ idx = i;
25138
+ break;
25139
+ }
25140
+ }
25141
+ }
25142
+ if (idx < 0) return history;
25143
+ const base = history[idx];
25144
+ const text = typeof base.content === "string" ? base.content : "";
25145
+ const content = text.trim() ? [{ type: "text", text }, ...turnImageParts] : [...turnImageParts];
25146
+ const cloned = history.slice();
25147
+ cloned[idx] = { ...base, content };
25148
+ return cloned;
25149
+ };
24431
25150
  const estimateSingle = (m) => {
24432
25151
  if (typeof m.content === "string") return Math.ceil(m.content.length / 3.5);
24433
25152
  if (m.content === null && m.tool_calls) {
@@ -24435,7 +25154,7 @@ function createResumeSession(config2) {
24435
25154
  }
24436
25155
  return 50;
24437
25156
  };
24438
- const estimateTokens2 = (msgs) => msgs.reduce((sum, m) => {
25157
+ const estimateTokens3 = (msgs) => msgs.reduce((sum, m) => {
24439
25158
  if (m._tokenEstimate === void 0) {
24440
25159
  m._tokenEstimate = estimateSingle(m);
24441
25160
  }
@@ -24456,7 +25175,7 @@ function createResumeSession(config2) {
24456
25175
  })();
24457
25176
  const COMPACTION_BUFFER = Math.max(2e4, Math.round(CONTEXT_LIMIT * 0.15));
24458
25177
  const PRUNE_PROTECT_TURNS = 6;
24459
- const totalTokens = estimateTokens2(messageHistory);
25178
+ const totalTokens = estimateTokens3(messageHistory);
24460
25179
  if (totalTokens > CONTEXT_LIMIT - COMPACTION_BUFFER) {
24461
25180
  const hasSystem = messageHistory[0].role === "system";
24462
25181
  const startIdx = hasSystem ? 1 : 0;
@@ -24483,7 +25202,7 @@ function createResumeSession(config2) {
24483
25202
  delete msg._tokenEstimate;
24484
25203
  }
24485
25204
  }
24486
- const afterTier1 = estimateTokens2(messageHistory);
25205
+ const afterTier1 = estimateTokens3(messageHistory);
24487
25206
  if (afterTier1 > CONTEXT_LIMIT - COMPACTION_BUFFER) {
24488
25207
  const old = messageHistory.slice(startIdx, protectFrom);
24489
25208
  const recent = messageHistory.slice(protectFrom);
@@ -24582,11 +25301,11 @@ ${newSummary.decisions.map((d) => ` - ${d}`).join("\n")}` : "",
24582
25301
  }
24583
25302
  }
24584
25303
  }
24585
- const afterTier2 = estimateTokens2(messageHistory);
25304
+ const afterTier2 = estimateTokens3(messageHistory);
24586
25305
  const tier3CompactionEnabled = process.env.AGON_DISABLE_TIER3_COMPACTION !== "1";
24587
25306
  if (tier3CompactionEnabled && afterTier2 > CONTEXT_LIMIT - COMPACTION_BUFFER && config2.engine.api) {
24588
25307
  try {
24589
- const { apiDispatch: apiDispatch2 } = await import("./dispatch-6LQSMMGI.js");
25308
+ const { apiDispatch: apiDispatch2 } = await import("./dispatch-S3CR5HKX.js");
24590
25309
  const compactionPrompt = `Summarize this conversation context into a concise briefing. Preserve: the user's goal, key discoveries, files read/modified, important decisions, and current progress. Drop: verbose tool outputs, repeated attempts, and pleasantries.
24591
25310
 
24592
25311
  CONTEXT TO SUMMARIZE:
@@ -24606,7 +25325,7 @@ ${newSummary.decisions.map((d) => ` - ${d}`).join("\n")}` : "",
24606
25325
  ${compactionResult.stdout}` },
24607
25326
  ...protectedRecent
24608
25327
  );
24609
- console.log(`[agon] Tier 3 LLM compaction fired: ${afterTier2} \u2192 ${estimateTokens2(messageHistory)} tokens`);
25328
+ console.log(`[agon] Tier 3 LLM compaction fired: ${afterTier2} \u2192 ${estimateTokens3(messageHistory)} tokens`);
24610
25329
  }
24611
25330
  } catch (tier3Err) {
24612
25331
  console.warn(`[agon] Tier 3 compaction failed (non-fatal): ${tier3Err instanceof Error ? tier3Err.message : String(tier3Err)}`);
@@ -24624,7 +25343,7 @@ ${compactionResult.stdout}` },
24624
25343
  toolCacheManifest = toolCacheManifest.filter((e) => activeIds.has(e.toolCallId));
24625
25344
  }
24626
25345
  {
24627
- const ctxTokens = totalTokens <= CONTEXT_LIMIT - COMPACTION_BUFFER ? totalTokens : estimateTokens2(messageHistory);
25346
+ const ctxTokens = totalTokens <= CONTEXT_LIMIT - COMPACTION_BUFFER ? totalTokens : estimateTokens3(messageHistory);
24628
25347
  const ctxPct = Math.round(ctxTokens / CONTEXT_LIMIT * 100);
24629
25348
  const cachedCount = toolCacheManifest.length;
24630
25349
  const compactedCount = compactionSummary?.messagesCompacted ?? 0;
@@ -24721,7 +25440,7 @@ ${compactionResult.stdout}` },
24721
25440
  } else {
24722
25441
  yield { type: "status", content: `tool loop turn ${step}/${budget}\u2026` };
24723
25442
  }
24724
- const gen = apiStreamDispatchWithHistory(config2.engine.api, messageHistory, config2.engine.timeout ?? 180, opts.signal, effectiveTools);
25443
+ const gen = apiStreamDispatchWithHistory(config2.engine.api, withImages(messageHistory), config2.engine.timeout ?? 180, opts.signal, effectiveTools);
24725
25444
  try {
24726
25445
  while (true) {
24727
25446
  const { value, done: done2 } = await gen.next();
@@ -25262,6 +25981,191 @@ ${compactionResult.stdout}` },
25262
25981
  return session;
25263
25982
  }
25264
25983
 
25984
+ // ../core/src/generated/sessions/session-pty.ts
25985
+ import { existsSync as existsSync25, readFileSync as readFileSync30, rmSync as rmSync5 } from "fs";
25986
+ function createPtySession(config2) {
25987
+ let claudeSession = null;
25988
+ let alive = false;
25989
+ let firstTurn = true;
25990
+ let turnActive = false;
25991
+ let pendingDrain = null;
25992
+ const TURN_TIMEOUT_MS = 15 * 60 * 1e3;
25993
+ function buildExtraArgv() {
25994
+ const args = [];
25995
+ if (config2.mcpServers && config2.mcpServers.length > 0) {
25996
+ const mcpConfig = JSON.stringify({
25997
+ mcpServers: Object.fromEntries(
25998
+ config2.mcpServers.map((s) => [s.name ?? s.command ?? "mcp", s])
25999
+ )
26000
+ });
26001
+ args.push("--mcp-config", mcpConfig, "--strict-mcp-config");
26002
+ }
26003
+ args.push("--disallowedTools", "Bash Edit Write MultiEdit NotebookEdit");
26004
+ args.push("--allowedTools", "Read Grep Glob mcp__agon-orchestration");
26005
+ if (config2.claudePtyLaunchArgs && config2.claudePtyLaunchArgs.length > 0) {
26006
+ args.push(...config2.claudePtyLaunchArgs);
26007
+ }
26008
+ return args;
26009
+ }
26010
+ function readAnswer() {
26011
+ const p = config2.answerChannelPath;
26012
+ if (!p) return null;
26013
+ try {
26014
+ if (!existsSync25(p)) return null;
26015
+ const parsed = JSON.parse(readFileSync30(p, "utf-8"));
26016
+ const t = parsed?.text;
26017
+ return typeof t === "string" ? t : null;
26018
+ } catch {
26019
+ return null;
26020
+ }
26021
+ }
26022
+ function clearAnswer() {
26023
+ const p = config2.answerChannelPath;
26024
+ if (!p) return;
26025
+ try {
26026
+ rmSync5(p, { force: true });
26027
+ } catch {
26028
+ }
26029
+ }
26030
+ const session = {
26031
+ get alive() {
26032
+ return alive;
26033
+ },
26034
+ sessionId: null,
26035
+ engineId: config2.engine.id,
26036
+ get pid() {
26037
+ return null;
26038
+ },
26039
+ async start() {
26040
+ if (alive) return;
26041
+ const mod = await import("@kernlang/agon-engines/cli/claude.js");
26042
+ claudeSession = await mod.ClaudeCliSession.spawn({
26043
+ mode: "agent",
26044
+ cwd: config2.cwd,
26045
+ extraArgv: buildExtraArgv(),
26046
+ daemonTimeoutMs: 6e4
26047
+ });
26048
+ alive = true;
26049
+ firstTurn = true;
26050
+ },
26051
+ async *send(opts) {
26052
+ if (turnActive) {
26053
+ yield { type: "error", content: "claude PTY session busy (concurrent turn rejected)" };
26054
+ return;
26055
+ }
26056
+ turnActive = true;
26057
+ try {
26058
+ if (pendingDrain) {
26059
+ try {
26060
+ await pendingDrain;
26061
+ } catch {
26062
+ }
26063
+ pendingDrain = null;
26064
+ }
26065
+ if (!alive || !claudeSession) {
26066
+ try {
26067
+ await session.start();
26068
+ } catch (e) {
26069
+ yield { type: "error", content: `claude PTY session not alive: ${e instanceof Error ? e.message : String(e)}` };
26070
+ return;
26071
+ }
26072
+ }
26073
+ if (opts.signal?.aborted) {
26074
+ yield { type: "done", content: "cancelled" };
26075
+ return;
26076
+ }
26077
+ clearAnswer();
26078
+ const sys = firstTurn ? opts.systemPrompt ?? config2.systemPrompt : void 0;
26079
+ firstTurn = false;
26080
+ const composed = sys ? `[System Instructions]
26081
+ ${sys}
26082
+
26083
+ [User Message]
26084
+ ${opts.message}` : opts.message;
26085
+ let aborted2 = false;
26086
+ const onAbort = () => {
26087
+ aborted2 = true;
26088
+ try {
26089
+ claudeSession?.close?.();
26090
+ } catch {
26091
+ }
26092
+ claudeSession = null;
26093
+ alive = false;
26094
+ };
26095
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
26096
+ let scrapedFinal = "";
26097
+ let driverError = null;
26098
+ const it = claudeSession.askStream(composed, TURN_TIMEOUT_MS);
26099
+ const driver = (async () => {
26100
+ try {
26101
+ let res = await it.next();
26102
+ while (!res.done) {
26103
+ res = await it.next();
26104
+ }
26105
+ scrapedFinal = typeof res.value === "string" ? res.value : "";
26106
+ } catch (e) {
26107
+ driverError = e;
26108
+ }
26109
+ })();
26110
+ pendingDrain = driver;
26111
+ let driverDone = false;
26112
+ void driver.then(() => {
26113
+ driverDone = true;
26114
+ });
26115
+ await new Promise((resolve28) => {
26116
+ const tick = setInterval(() => {
26117
+ if (driverDone || readAnswer() !== null) {
26118
+ clearInterval(tick);
26119
+ resolve28();
26120
+ }
26121
+ }, 100);
26122
+ void driver.finally(() => {
26123
+ clearInterval(tick);
26124
+ resolve28();
26125
+ });
26126
+ });
26127
+ opts.signal?.removeEventListener("abort", onAbort);
26128
+ if (aborted2) {
26129
+ yield { type: "done", content: "cancelled" };
26130
+ return;
26131
+ }
26132
+ const answer = readAnswer();
26133
+ if (answer !== null && answer.length > 0) {
26134
+ yield { type: "text", content: answer };
26135
+ yield { type: "done", content: "end_turn" };
26136
+ return;
26137
+ }
26138
+ await driver;
26139
+ pendingDrain = null;
26140
+ if (driverError) {
26141
+ alive = false;
26142
+ claudeSession = null;
26143
+ yield { type: "error", content: `claude PTY turn failed: ${driverError instanceof Error ? driverError.message : String(driverError)}` };
26144
+ return;
26145
+ }
26146
+ if (scrapedFinal && scrapedFinal.trim()) {
26147
+ yield { type: "text", content: scrapedFinal };
26148
+ }
26149
+ yield { type: "done", content: "end_turn" };
26150
+ } finally {
26151
+ turnActive = false;
26152
+ }
26153
+ },
26154
+ close() {
26155
+ try {
26156
+ claudeSession?.close?.();
26157
+ } catch {
26158
+ }
26159
+ claudeSession = null;
26160
+ alive = false;
26161
+ },
26162
+ getMessageHistory() {
26163
+ return [];
26164
+ }
26165
+ };
26166
+ return session;
26167
+ }
26168
+
25265
26169
  // ../core/src/generated/sessions/persistent-session.ts
25266
26170
  function createPersistentSession(config2) {
25267
26171
  const engine = config2.engine;
@@ -25269,7 +26173,11 @@ function createPersistentSession(config2) {
25269
26173
  return createResumeSession(config2);
25270
26174
  }
25271
26175
  if ((engine.companion?.protocol === "stream-json" || engine.id === "claude" || engine.binary === "claude") && config2.binaryPath) {
25272
- return createStreamJsonSession(config2);
26176
+ const printOptOut = process.env.AGON_CLAUDE_PRINT;
26177
+ if (printOptOut === "1" || printOptOut === "true") {
26178
+ return createStreamJsonSession(config2);
26179
+ }
26180
+ return createPtySession(config2);
25273
26181
  }
25274
26182
  if (engine.companion && engine.companion.protocol === "acp") {
25275
26183
  return createAcpSession(config2);
@@ -25364,8 +26272,8 @@ function createStreamBridge(dispatch, opts) {
25364
26272
  }
25365
26273
 
25366
26274
  // ../core/src/generated/forge/virtual-fs.ts
25367
- import { readFileSync as readFileSync26, existsSync as existsSync22, readdirSync as readdirSync15, statSync as statSync18 } from "fs";
25368
- import { join as join25, resolve as resolve21, relative as relative8, dirname as dirname11 } from "path";
26275
+ import { readFileSync as readFileSync31, existsSync as existsSync26, readdirSync as readdirSync16, statSync as statSync20 } from "fs";
26276
+ import { join as join28, resolve as resolve21, relative as relative8, dirname as dirname12 } from "path";
25369
26277
  import { createHash as createHash5 } from "crypto";
25370
26278
  function createFileSnapshot(rootDir) {
25371
26279
  const snapshotId = createHash5("sha256").update(rootDir + Date.now().toString()).digest("hex").slice(0, 12);
@@ -25381,16 +26289,16 @@ function snapshotRead(snap, absPath) {
25381
26289
  return snap.cache.get(key) ?? null;
25382
26290
  }
25383
26291
  try {
25384
- if (!existsSync22(key)) {
26292
+ if (!existsSync26(key)) {
25385
26293
  snap.cache.set(key, null);
25386
26294
  return null;
25387
26295
  }
25388
- const st = statSync18(key);
26296
+ const st = statSync20(key);
25389
26297
  if (!st.isFile()) {
25390
26298
  snap.cache.set(key, null);
25391
26299
  return null;
25392
26300
  }
25393
- const content = readFileSync26(key, "utf-8");
26301
+ const content = readFileSync31(key, "utf-8");
25394
26302
  snap.cache.set(key, content);
25395
26303
  return content;
25396
26304
  } catch (e) {
@@ -25401,13 +26309,13 @@ function snapshotRead(snap, absPath) {
25401
26309
  function snapshotList(snap, absDir) {
25402
26310
  const dir = resolve21(absDir);
25403
26311
  try {
25404
- return readdirSync15(dir).filter((f) => {
26312
+ return readdirSync16(dir).filter((f) => {
25405
26313
  try {
25406
- return statSync18(join25(dir, f)).isFile();
26314
+ return statSync20(join28(dir, f)).isFile();
25407
26315
  } catch {
25408
26316
  return false;
25409
26317
  }
25410
- }).map((f) => join25(dir, f));
26318
+ }).map((f) => join28(dir, f));
25411
26319
  } catch {
25412
26320
  return [];
25413
26321
  }
@@ -25473,7 +26381,7 @@ var VirtualFS = class {
25473
26381
  const overlayWritten = [];
25474
26382
  const overlayDeleted = /* @__PURE__ */ new Set();
25475
26383
  for (const [path, content] of this.overlay.entries()) {
25476
- if (dirname11(path) === dir) {
26384
+ if (dirname12(path) === dir) {
25477
26385
  if (content === null) {
25478
26386
  overlayDeleted.add(path);
25479
26387
  } else {
@@ -25532,7 +26440,7 @@ function applyEffectPackage(pkg, targetDir) {
25532
26440
  for (const effect of pkg.effects) {
25533
26441
  const absPath = resolve21(targetDir, effect.kind === "rename" ? effect.from : effect.path);
25534
26442
  if (effect.kind === "write") {
25535
- const dir = dirname11(absPath);
26443
+ const dir = dirname12(absPath);
25536
26444
  import_fs.mkdirSync(dir, { recursive: true });
25537
26445
  import_fs.writeFileSync(absPath, effect.content, "utf-8");
25538
26446
  modified.push(absPath);
@@ -25544,7 +26452,7 @@ function applyEffectPackage(pkg, targetDir) {
25544
26452
  modified.push(absPath);
25545
26453
  } else if (effect.kind === "rename") {
25546
26454
  const dest = resolve21(targetDir, effect.to);
25547
- import_fs.mkdirSync(dirname11(dest), { recursive: true });
26455
+ import_fs.mkdirSync(dirname12(dest), { recursive: true });
25548
26456
  import_fs.renameSync(absPath, dest);
25549
26457
  modified.push(absPath);
25550
26458
  modified.push(dest);
@@ -25622,7 +26530,7 @@ function scoreEffectPackage(pkg, taskKeywords) {
25622
26530
 
25623
26531
  // ../core/src/generated/cesar/speculator.ts
25624
26532
  import { randomUUID as randomUUID4 } from "crypto";
25625
- import { resolve as resolve22, join as join26 } from "path";
26533
+ import { resolve as resolve22, join as join29 } from "path";
25626
26534
  var Speculator = class {
25627
26535
  runId;
25628
26536
  snapshot;
@@ -25644,7 +26552,7 @@ var Speculator = class {
25644
26552
  if (isolate) {
25645
26553
  const baseSha = stashSnapshot(root);
25646
26554
  for (const member of opts.members) {
25647
- const wtPath = join26(root, `.agon/speculate-worktrees/${this.runId}/${member.engineId}`);
26555
+ const wtPath = join29(root, `.agon/speculate-worktrees/${this.runId}/${member.engineId}`);
25648
26556
  try {
25649
26557
  await worktreeCreate(root, wtPath, baseSha);
25650
26558
  worktreesByEngine[member.engineId] = wtPath;
@@ -25817,17 +26725,17 @@ ${sessionLines.join("\n")}`);
25817
26725
  }
25818
26726
 
25819
26727
  // ../core/src/generated/cesar/context-thread.ts
25820
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync22, mkdirSync as mkdirSync21, renameSync as renameSync11, existsSync as existsSync23, readdirSync as readdirSync16, unlinkSync as unlinkSync9, statSync as statSync19, chmodSync as chmodSync2, openSync, fsyncSync, closeSync, appendFileSync as appendFileSync2 } from "fs";
25821
- import { join as join27, resolve as resolve23, basename as basename6 } from "path";
26728
+ import { readFileSync as readFileSync32, writeFileSync as writeFileSync25, mkdirSync as mkdirSync23, renameSync as renameSync11, existsSync as existsSync27, readdirSync as readdirSync17, unlinkSync as unlinkSync10, statSync as statSync21, chmodSync as chmodSync2, openSync as openSync2, fsyncSync, closeSync as closeSync2, appendFileSync as appendFileSync3 } from "fs";
26729
+ import { join as join30, resolve as resolve23, basename as basename6 } from "path";
25822
26730
  import { randomUUID as randomUUID5, createHash as createHash6 } from "crypto";
25823
26731
  import { homedir as homedir14 } from "os";
25824
26732
  function threadsDir() {
25825
26733
  const override = process.env.AGON_HOME?.trim();
25826
- const home = override ? resolve23(override) : join27(homedir14(), ".agon");
25827
- return join27(home, "threads");
26734
+ const home = override ? resolve23(override) : join30(homedir14(), ".agon");
26735
+ return join30(home, "threads");
25828
26736
  }
25829
26737
  function activePointerPath() {
25830
- return join27(threadsDir(), "active.json");
26738
+ return join30(threadsDir(), "active.json");
25831
26739
  }
25832
26740
  function projectHash16(projectPath) {
25833
26741
  return createHash6("sha256").update(projectPath).digest("hex").slice(0, 16);
@@ -25836,7 +26744,7 @@ function projectSha8(projectPath) {
25836
26744
  return projectHash16(projectPath);
25837
26745
  }
25838
26746
  function threadDirFor(projectPath) {
25839
- return join27(threadsDir(), projectHash16(projectPath));
26747
+ return join30(threadsDir(), projectHash16(projectPath));
25840
26748
  }
25841
26749
  var THREAD_ID_RE = /^(thread_\d{10,16}_[0-9a-f]{8}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
25842
26750
  function threadJournalPath(projectPath, threadId) {
@@ -25849,7 +26757,7 @@ function threadFilePath(projectPath, threadId) {
25849
26757
  const dir = threadDirFor(projectPath);
25850
26758
  const full = resolve23(dir, `${threadId}.json`);
25851
26759
  const resolvedDir = resolve23(dir);
25852
- const nativeSep = join27("a", "b")[1];
26760
+ const nativeSep = join30("a", "b")[1];
25853
26761
  const isContained = full === resolvedDir || full.startsWith(resolvedDir + "/") || full.startsWith(resolvedDir + nativeSep);
25854
26762
  if (!isContained) {
25855
26763
  throw new Error(`Invalid thread path (traversal attempt): ${threadId}`);
@@ -25858,7 +26766,7 @@ function threadFilePath(projectPath, threadId) {
25858
26766
  }
25859
26767
  function ensureThreadDir(projectPath) {
25860
26768
  ensureAgonHome();
25861
- mkdirSync21(threadDirFor(projectPath), { recursive: true });
26769
+ mkdirSync23(threadDirFor(projectPath), { recursive: true });
25862
26770
  }
25863
26771
  var LOCK_MAX_RETRIES = 8;
25864
26772
  var LOCK_BASE_DELAY_MS = 20;
@@ -25868,9 +26776,9 @@ function threadLockPath(projectPath, threadId) {
25868
26776
  async function acquireLock(lockPath) {
25869
26777
  for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {
25870
26778
  try {
25871
- const fd = openSync(lockPath, "wx", 384);
25872
- writeFileSync22(fd, String(process.pid));
25873
- closeSync(fd);
26779
+ const fd = openSync2(lockPath, "wx", 384);
26780
+ writeFileSync25(fd, String(process.pid));
26781
+ closeSync2(fd);
25874
26782
  return attempt;
25875
26783
  } catch (err) {
25876
26784
  if (err?.code !== "EEXIST") throw err;
@@ -25882,7 +26790,7 @@ async function acquireLock(lockPath) {
25882
26790
  }
25883
26791
  function releaseLock(lockPath) {
25884
26792
  try {
25885
- unlinkSync9(lockPath);
26793
+ unlinkSync10(lockPath);
25886
26794
  } catch {
25887
26795
  }
25888
26796
  }
@@ -26042,14 +26950,14 @@ var ContextThread = class {
26042
26950
  const now = Date.now();
26043
26951
  if (config2.threadId) {
26044
26952
  const candidatePath = threadFilePath(this.projectPath, config2.threadId);
26045
- if (existsSync23(candidatePath)) {
26953
+ if (existsSync27(candidatePath)) {
26046
26954
  try {
26047
- const stat = statSync19(candidatePath);
26955
+ const stat = statSync21(candidatePath);
26048
26956
  if (stat.size > MAX_THREAD_FILE_BYTES) {
26049
26957
  console.warn(`[agon] context-thread: ${candidatePath} is ${stat.size} bytes (> ${MAX_THREAD_FILE_BYTES}), refusing to load. Run /thread compact or /thread fork.`);
26050
26958
  throw new Error("thread file too large");
26051
26959
  }
26052
- const raw = readFileSync27(candidatePath, "utf-8");
26960
+ const raw = readFileSync32(candidatePath, "utf-8");
26053
26961
  const snap = JSON.parse(raw);
26054
26962
  if (snap && typeof snap === "object" && Array.isArray(snap.messages)) {
26055
26963
  const filteredMessages = (snap.messages ?? []).filter((m) => m && m.role !== "system");
@@ -26067,9 +26975,9 @@ var ContextThread = class {
26067
26975
  this.fileTouches = snap.fileTouches ?? {};
26068
26976
  this.hydrated = true;
26069
26977
  const jPathOnLoad = threadFilePath(this.projectPath, this.threadId).replace(/\.json$/, ".journal.jsonl");
26070
- if (existsSync23(jPathOnLoad)) {
26978
+ if (existsSync27(jPathOnLoad)) {
26071
26979
  try {
26072
- const journalLines = readFileSync27(jPathOnLoad, "utf-8").split("\n").filter(Boolean);
26980
+ const journalLines = readFileSync32(jPathOnLoad, "utf-8").split("\n").filter(Boolean);
26073
26981
  const knownOnLoad = new Set(this.messages.map((m) => m.id));
26074
26982
  let merged = false;
26075
26983
  for (const line of journalLines) {
@@ -26153,7 +27061,7 @@ var ContextThread = class {
26153
27061
  ensureThreadDir(this.projectPath);
26154
27062
  const jPath = threadJournalPath(this.projectPath, this.threadId);
26155
27063
  const line = JSON.stringify({ _kind: "msg", ...msg }) + "\n";
26156
- appendFileSync2(jPath, line, { encoding: "utf-8", mode: 384, flag: "a" });
27064
+ appendFileSync3(jPath, line, { encoding: "utf-8", mode: 384, flag: "a" });
26157
27065
  this.journaledIds.add(msg.id);
26158
27066
  } catch {
26159
27067
  }
@@ -26339,8 +27247,8 @@ ${msg.content}` };
26339
27247
  let bytes = 0;
26340
27248
  try {
26341
27249
  const path = threadFilePath(this.projectPath, this.threadId);
26342
- if (existsSync23(path)) {
26343
- bytes = readFileSync27(path, "utf-8").length;
27250
+ if (existsSync27(path)) {
27251
+ bytes = readFileSync32(path, "utf-8").length;
26344
27252
  }
26345
27253
  } catch {
26346
27254
  }
@@ -26372,12 +27280,12 @@ ${msg.content}` };
26372
27280
  const tmpPath = target + ".tmp";
26373
27281
  let fd = -1;
26374
27282
  try {
26375
- fd = openSync(tmpPath, "w", 384);
26376
- writeFileSync22(fd, body, "utf-8");
27283
+ fd = openSync2(tmpPath, "w", 384);
27284
+ writeFileSync25(fd, body, "utf-8");
26377
27285
  fsyncSync(fd);
26378
27286
  } finally {
26379
27287
  if (fd >= 0) try {
26380
- closeSync(fd);
27288
+ closeSync2(fd);
26381
27289
  } catch {
26382
27290
  }
26383
27291
  }
@@ -26389,7 +27297,7 @@ ${msg.content}` };
26389
27297
  this.dirty = false;
26390
27298
  this.hydrated = true;
26391
27299
  const jPath = threadJournalPath(this.projectPath, this.threadId);
26392
- if (existsSync23(jPath)) unlinkSync9(jPath);
27300
+ if (existsSync27(jPath)) unlinkSync10(jPath);
26393
27301
  this.journaledIds.clear();
26394
27302
  } catch {
26395
27303
  }
@@ -26421,9 +27329,9 @@ ${msg.content}` };
26421
27329
  }
26422
27330
  try {
26423
27331
  const jPath = threadJournalPath(this.projectPath, this.threadId);
26424
- if (existsSync23(jPath)) {
27332
+ if (existsSync27(jPath)) {
26425
27333
  try {
26426
- const journalLines = readFileSync27(jPath, "utf-8").split("\n").filter(Boolean);
27334
+ const journalLines = readFileSync32(jPath, "utf-8").split("\n").filter(Boolean);
26427
27335
  const known = new Set(this.messages.map((m) => m.id));
26428
27336
  for (const line of journalLines) {
26429
27337
  try {
@@ -26442,11 +27350,11 @@ ${msg.content}` };
26442
27350
  console.warn(`[agon] context-thread: journal merge failed (will overwrite): ${err instanceof Error ? err.message : String(err)}`);
26443
27351
  }
26444
27352
  }
26445
- if (existsSync23(target)) {
27353
+ if (existsSync27(target)) {
26446
27354
  try {
26447
- const stat = statSync19(target);
27355
+ const stat = statSync21(target);
26448
27356
  if (stat.size <= MAX_THREAD_FILE_BYTES) {
26449
- const raw = readFileSync27(target, "utf-8");
27357
+ const raw = readFileSync32(target, "utf-8");
26450
27358
  const onDisk = JSON.parse(raw);
26451
27359
  if (onDisk && Array.isArray(onDisk.messages)) {
26452
27360
  const known = new Set(this.messages.map((m) => m.id));
@@ -26484,13 +27392,13 @@ ${msg.content}` };
26484
27392
  const body = JSON.stringify(snapshot, null, 2) + "\n";
26485
27393
  let fd = -1;
26486
27394
  try {
26487
- fd = openSync(tmpPath, "w", 384);
26488
- writeFileSync22(fd, body, "utf-8");
27395
+ fd = openSync2(tmpPath, "w", 384);
27396
+ writeFileSync25(fd, body, "utf-8");
26489
27397
  fsyncSync(fd);
26490
27398
  } finally {
26491
27399
  if (fd >= 0) {
26492
27400
  try {
26493
- closeSync(fd);
27401
+ closeSync2(fd);
26494
27402
  } catch {
26495
27403
  }
26496
27404
  }
@@ -26504,7 +27412,7 @@ ${msg.content}` };
26504
27412
  this.dirty = false;
26505
27413
  this.hydrated = true;
26506
27414
  try {
26507
- if (existsSync23(jPath)) unlinkSync9(jPath);
27415
+ if (existsSync27(jPath)) unlinkSync10(jPath);
26508
27416
  this.journaledIds.clear();
26509
27417
  } catch {
26510
27418
  }
@@ -26525,8 +27433,8 @@ ${msg.content}` };
26525
27433
  function loadActivePointer() {
26526
27434
  try {
26527
27435
  const path = activePointerPath();
26528
- if (existsSync23(path)) {
26529
- const raw = readFileSync27(path, "utf-8");
27436
+ if (existsSync27(path)) {
27437
+ const raw = readFileSync32(path, "utf-8");
26530
27438
  const parsed = JSON.parse(raw);
26531
27439
  if (parsed && typeof parsed === "object" && parsed.byProject) {
26532
27440
  return parsed;
@@ -26540,9 +27448,9 @@ function loadActivePointer() {
26540
27448
  function saveActivePointer(pointer) {
26541
27449
  ensureAgonHome();
26542
27450
  const path = activePointerPath();
26543
- mkdirSync21(threadsDir(), { recursive: true });
27451
+ mkdirSync23(threadsDir(), { recursive: true });
26544
27452
  const tmpPath = path + ".tmp";
26545
- writeFileSync22(tmpPath, JSON.stringify(pointer, null, 2) + "\n", "utf-8");
27453
+ writeFileSync25(tmpPath, JSON.stringify(pointer, null, 2) + "\n", "utf-8");
26546
27454
  renameSync11(tmpPath, path);
26547
27455
  }
26548
27456
  var _WeakRefCtor = globalThis.WeakRef;
@@ -26598,9 +27506,9 @@ async function forkActiveThread(projectPath, systemPrompt) {
26598
27506
  }
26599
27507
  function listThreadsForProject(projectPath) {
26600
27508
  const dir = threadDirFor(projectPath);
26601
- if (!existsSync23(dir)) return [];
27509
+ if (!existsSync27(dir)) return [];
26602
27510
  try {
26603
- return readdirSync16(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5));
27511
+ return readdirSync17(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5));
26604
27512
  } catch (err) {
26605
27513
  console.warn(`[agon] context-thread: failed to list threads: ${err instanceof Error ? err.message : String(err)}`);
26606
27514
  return [];
@@ -26608,9 +27516,9 @@ function listThreadsForProject(projectPath) {
26608
27516
  }
26609
27517
  function deleteThread(projectPath, threadId) {
26610
27518
  try {
26611
- unlinkSync9(threadFilePath(projectPath, threadId));
27519
+ unlinkSync10(threadFilePath(projectPath, threadId));
26612
27520
  try {
26613
- unlinkSync9(threadJournalPath(projectPath, threadId));
27521
+ unlinkSync10(threadJournalPath(projectPath, threadId));
26614
27522
  } catch {
26615
27523
  }
26616
27524
  return true;
@@ -26656,6 +27564,39 @@ var PlanCostEstimator = class {
26656
27564
  };
26657
27565
  var planCostEstimator = new PlanCostEstimator();
26658
27566
 
27567
+ // ../core/src/generated/cesar/plan-validation.ts
27568
+ var VALID_STEP_TYPES = new Set(CESAR_STEP_TYPES);
27569
+ function sanitizePlanSteps(rawSteps) {
27570
+ const SAFE_ID = /^[a-z0-9_-]{1,64}$/;
27571
+ const sanitizeId = (raw, fallback) => {
27572
+ if (typeof raw === "string" && SAFE_ID.test(raw)) return raw;
27573
+ return fallback;
27574
+ };
27575
+ const input = Array.isArray(rawSteps) ? rawSteps : [];
27576
+ const steps = input.filter((s) => s && VALID_STEP_TYPES.has(s.type)).map((s, i) => {
27577
+ const est = planCostEstimator.estimate(s.type, s.engines ?? []);
27578
+ return {
27579
+ id: sanitizeId(s.id, `step-${i}-${Math.random().toString(36).slice(2, 8)}`),
27580
+ type: s.type,
27581
+ description: typeof s.description === "string" && s.description.trim().length > 0 ? s.description : "(no description)",
27582
+ engines: s.engines,
27583
+ engine: s.engine,
27584
+ fitnessCmd: s.fitnessCmd,
27585
+ tribunalMode: s.tribunalMode,
27586
+ parallel: s.parallel ?? false,
27587
+ dependsOn: s.dependsOn,
27588
+ exports: typeof s.exports === "string" ? [s.exports] : s.exports,
27589
+ imports: typeof s.imports === "string" ? [s.imports] : s.imports,
27590
+ estimatedTokens: est.tokens,
27591
+ estimatedCostUsd: est.costUsd,
27592
+ rationale: s.rationale,
27593
+ verifyCmd: s.verifyCmd
27594
+ };
27595
+ });
27596
+ const dropped = input.length - steps.length;
27597
+ return { steps, dropped };
27598
+ }
27599
+
26659
27600
  // ../core/src/generated/cesar/plan-executor.ts
26660
27601
  function getReadySteps(plan) {
26661
27602
  return plan.steps.filter((s) => s.state === "pending");
@@ -26961,7 +27902,7 @@ var AgentSession = class {
26961
27902
  this.state = "running";
26962
27903
  const perStepSec = this.config.perStepTimeoutSec ?? Math.floor(remainingMs / 1e3);
26963
27904
  const timeoutSec = Math.min(perStepSec, Math.floor(remainingMs / 1e3));
26964
- const promptTokens = estimateTokens(prompt);
27905
+ const promptTokens = estimateTokens2(prompt);
26965
27906
  const onEvent = opts?.onEvent;
26966
27907
  const thread = this.config.thread;
26967
27908
  const windowTokens = this.config.contextWindowTokens;
@@ -27022,7 +27963,7 @@ var AgentSession = class {
27022
27963
  }
27023
27964
  if (this.abortController.signal.aborted) {
27024
27965
  this.state = "cancelled";
27025
- const partialResponseTokens = estimateTokens(result.response ?? "");
27966
+ const partialResponseTokens = estimateTokens2(result.response ?? "");
27026
27967
  const partialTotal = promptTokens + partialResponseTokens;
27027
27968
  this.turnsUsed += 1;
27028
27969
  this.tokensUsed += partialTotal;
@@ -27054,7 +27995,7 @@ var AgentSession = class {
27054
27995
  engineFault: result.engineFault ?? false
27055
27996
  };
27056
27997
  }
27057
- const responseTokens = estimateTokens(result.response);
27998
+ const responseTokens = estimateTokens2(result.response);
27058
27999
  const stepTokens = promptTokens + responseTokens;
27059
28000
  const stepCost = estimateCost(this.config.engineId, stepTokens, this.config.api.model);
27060
28001
  this.turnsUsed += 1;
@@ -27140,7 +28081,7 @@ var AgentSession = class {
27140
28081
  };
27141
28082
 
27142
28083
  // ../core/src/generated/cesar/agent-team.ts
27143
- import { join as join28 } from "path";
28084
+ import { join as join31 } from "path";
27144
28085
  import { randomBytes as randomBytes2 } from "crypto";
27145
28086
  function makeAgentTeamError(message, cause) {
27146
28087
  const err = new Error(`AgentTeam: ${message}`);
@@ -27223,7 +28164,7 @@ var AgentTeam = class {
27223
28164
  if (!this.config.isolate) {
27224
28165
  return { m, wt: null };
27225
28166
  }
27226
- const wt = join28(this.config.cwd, ".agon", "agent-worktrees", this.runId, m.engineId);
28167
+ const wt = join31(this.config.cwd, ".agon", "agent-worktrees", this.runId, m.engineId);
27227
28168
  worktreeCreate(root, wt, this.baseSha);
27228
28169
  return { m, wt };
27229
28170
  });
@@ -27556,10 +28497,10 @@ function buildAgentSynthesisPrompt(opts) {
27556
28497
  let remaining = maxLoserContent;
27557
28498
  for (let i = 0; i < opts.losers.length; i++) {
27558
28499
  const loser = opts.losers[i];
27559
- const header = `## OTHER ENGINE ${i + 1}: ${loser.engineId}${loser.passedFitness ? " (passed fitness gate)" : " (did NOT pass fitness gate)"}`;
27560
- lines.push(header);
28500
+ const header2 = `## OTHER ENGINE ${i + 1}: ${loser.engineId}${loser.passedFitness ? " (passed fitness gate)" : " (did NOT pass fitness gate)"}`;
28501
+ lines.push(header2);
27561
28502
  lines.push(`<untrusted_data engine="${loser.engineId}">`);
27562
- remaining -= header.length + 50;
28503
+ remaining -= header2.length + 50;
27563
28504
  if (remaining <= 0) {
27564
28505
  lines.push(`*(trimmed for prompt budget)*`);
27565
28506
  lines.push(`</untrusted_data>`);
@@ -28049,10 +28990,10 @@ function hooksOutput(results) {
28049
28990
  }
28050
28991
 
28051
28992
  // ../core/src/generated/blocks/skill-loader.ts
28052
- import { readFileSync as readFileSync28, readdirSync as readdirSync17, existsSync as existsSync24 } from "fs";
28053
- import { join as join29, dirname as dirname12, resolve as resolve24 } from "path";
28993
+ import { readFileSync as readFileSync33, readdirSync as readdirSync18, existsSync as existsSync28 } from "fs";
28994
+ import { join as join32, dirname as dirname13, resolve as resolve24 } from "path";
28054
28995
  import { homedir as homedir15 } from "os";
28055
- import { fileURLToPath as fileURLToPath3 } from "url";
28996
+ import { fileURLToPath as fileURLToPath4 } from "url";
28056
28997
  function parseFrontmatter(content) {
28057
28998
  const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
28058
28999
  if (!match) {
@@ -28071,7 +29012,7 @@ function parseFrontmatter(content) {
28071
29012
  }
28072
29013
  function loadSkillFile(filePath) {
28073
29014
  try {
28074
- const content = readFileSync28(filePath, "utf-8");
29015
+ const content = readFileSync33(filePath, "utf-8");
28075
29016
  const { meta: meta3, body } = parseFrontmatter(content);
28076
29017
  if (!meta3.name || !meta3.trigger) return null;
28077
29018
  return {
@@ -28089,11 +29030,11 @@ function loadSkillFile(filePath) {
28089
29030
  }
28090
29031
  function loadSkillsFromDir(dir, source) {
28091
29032
  const skills = [];
28092
- if (!existsSync24(dir)) return skills;
29033
+ if (!existsSync28(dir)) return skills;
28093
29034
  try {
28094
- const files = readdirSync17(dir).filter((f) => f.endsWith(".md"));
29035
+ const files = readdirSync18(dir).filter((f) => f.endsWith(".md"));
28095
29036
  for (const file2 of files) {
28096
- const skill = loadSkillFile(join29(dir, file2));
29037
+ const skill = loadSkillFile(join32(dir, file2));
28097
29038
  if (skill) {
28098
29039
  skill.source = source;
28099
29040
  skills.push(skill);
@@ -28107,12 +29048,12 @@ function loadSkillsFromDir(dir, source) {
28107
29048
  function loadSkills(cwd) {
28108
29049
  const skills = [];
28109
29050
  const override = process.env.AGON_HOME?.trim();
28110
- const home = override ? resolve24(override) : join29(homedir15(), ".agon");
28111
- const builtinDir = join29(dirname12(fileURLToPath3(import.meta.url)), "../../skills");
29051
+ const home = override ? resolve24(override) : join32(homedir15(), ".agon");
29052
+ const builtinDir = join32(dirname13(fileURLToPath4(import.meta.url)), "../../skills");
28112
29053
  skills.push(...loadSkillsFromDir(builtinDir, "builtin"));
28113
- skills.push(...loadSkillsFromDir(join29(home, "skills"), "global"));
29054
+ skills.push(...loadSkillsFromDir(join32(home, "skills"), "global"));
28114
29055
  if (cwd) {
28115
- skills.push(...loadSkillsFromDir(join29(cwd, ".agon", "skills"), "project"));
29056
+ skills.push(...loadSkillsFromDir(join32(cwd, ".agon", "skills"), "project"));
28116
29057
  }
28117
29058
  const seen = /* @__PURE__ */ new Map();
28118
29059
  for (const skill of skills) {
@@ -28129,17 +29070,17 @@ function renderSkillPrompt(skill, input) {
28129
29070
  }
28130
29071
 
28131
29072
  // ../core/src/generated/blocks/engine-memory.ts
28132
- import { readFileSync as readFileSync29, writeFileSync as writeFileSync23, mkdirSync as mkdirSync22, renameSync as renameSync12 } from "fs";
28133
- import { join as join30, resolve as resolve25 } from "path";
29073
+ import { readFileSync as readFileSync34, writeFileSync as writeFileSync26, mkdirSync as mkdirSync24, renameSync as renameSync12 } from "fs";
29074
+ import { join as join33, resolve as resolve25 } from "path";
28134
29075
  import { homedir as homedir16 } from "os";
28135
29076
  function memoryPath() {
28136
29077
  const override = process.env.AGON_HOME?.trim();
28137
- const home = override ? resolve25(override) : join30(homedir16(), ".agon");
28138
- return join30(home, "engine-memory.json");
29078
+ const home = override ? resolve25(override) : join33(homedir16(), ".agon");
29079
+ return join33(home, "engine-memory.json");
28139
29080
  }
28140
29081
  function loadEngineMemory() {
28141
29082
  try {
28142
- return JSON.parse(readFileSync29(memoryPath(), "utf-8"));
29083
+ return JSON.parse(readFileSync34(memoryPath(), "utf-8"));
28143
29084
  } catch (err) {
28144
29085
  if (err.code !== "ENOENT") {
28145
29086
  console.warn(`[agon] failed to load engine memory: ${err instanceof Error ? err.message : String(err)}`);
@@ -28149,12 +29090,12 @@ function loadEngineMemory() {
28149
29090
  }
28150
29091
  function saveEngineMemory(record2) {
28151
29092
  const override = process.env.AGON_HOME?.trim();
28152
- const home = override ? resolve25(override) : join30(homedir16(), ".agon");
28153
- mkdirSync22(home, { recursive: true });
29093
+ const home = override ? resolve25(override) : join33(homedir16(), ".agon");
29094
+ mkdirSync24(home, { recursive: true });
28154
29095
  record2.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
28155
29096
  const path = memoryPath();
28156
29097
  const tmpPath = path + ".tmp";
28157
- writeFileSync23(tmpPath, JSON.stringify(record2, null, 2) + "\n");
29098
+ writeFileSync26(tmpPath, JSON.stringify(record2, null, 2) + "\n");
28158
29099
  renameSync12(tmpPath, path);
28159
29100
  }
28160
29101
  function ensureProfile(record2, engineId) {
@@ -28346,7 +29287,7 @@ function rankByTaskClass(engineIds, taskClass) {
28346
29287
  let specialization;
28347
29288
  if (i === 0 && r.total >= 3) {
28348
29289
  role = "lead";
28349
- specialization = `You are the top-rated engine for ${taskClass} tasks (${r.classElo} ELO, ${Math.round(r.winRate * 100)}% win rate). Lead with your best approach.`;
29290
+ specialization = `You are the top-rated engine for ${taskClass} tasks (${r.classElo} Glicko, ${Math.round(r.winRate * 100)}% win rate). Lead with your best approach.`;
28350
29291
  } else if (i === ranked.length - 1 && r.total >= 3) {
28351
29292
  role = "challenger";
28352
29293
  specialization = `You are the challenger. Focus on what the lead engine might miss: edge cases, error handling, performance pitfalls. Your contrarian perspective is your strength.`;
@@ -28382,13 +29323,13 @@ function assignForgeRoles(engineIds, taskClass) {
28382
29323
  }
28383
29324
 
28384
29325
  // ../core/src/generated/blocks/sidechain-logger.ts
28385
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync23 } from "fs";
28386
- import { join as join31 } from "path";
29326
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync25 } from "fs";
29327
+ import { join as join34 } from "path";
28387
29328
  function createSidechainLogger(opts) {
28388
29329
  const suffix = opts.parentId ? `_sidechain_${opts.parentId}` : "";
28389
29330
  const filename = `${opts.sessionType}_${opts.sessionId}${suffix}.jsonl`;
28390
- const logPath = join31(opts.outputDir, filename);
28391
- mkdirSync23(opts.outputDir, { recursive: true });
29331
+ const logPath = join34(opts.outputDir, filename);
29332
+ mkdirSync25(opts.outputDir, { recursive: true });
28392
29333
  function log(type, engineId, data) {
28393
29334
  const event = {
28394
29335
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -28400,7 +29341,7 @@ function createSidechainLogger(opts) {
28400
29341
  ...data && { data }
28401
29342
  };
28402
29343
  try {
28403
- appendFileSync3(logPath, JSON.stringify(event) + "\n");
29344
+ appendFileSync4(logPath, JSON.stringify(event) + "\n");
28404
29345
  } catch (err) {
28405
29346
  console.warn(`[agon] sidechain write failed (${logPath}): ${err instanceof Error ? err.message : String(err)}`);
28406
29347
  }
@@ -28417,12 +29358,12 @@ function createSidechainLogger(opts) {
28417
29358
  }
28418
29359
 
28419
29360
  // ../core/src/generated/blocks/provenance.ts
28420
- import { readFileSync as readFileSync30, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24 } from "fs";
28421
- import { join as join32, resolve as resolve26 } from "path";
29361
+ import { readFileSync as readFileSync35, writeFileSync as writeFileSync27, mkdirSync as mkdirSync26 } from "fs";
29362
+ import { join as join35, resolve as resolve26 } from "path";
28422
29363
  import { createHash as createHash7 } from "crypto";
28423
29364
  function sha256OfFile(path) {
28424
29365
  try {
28425
- return "sha256:" + createHash7("sha256").update(readFileSync30(path)).digest("hex");
29366
+ return "sha256:" + createHash7("sha256").update(readFileSync35(path)).digest("hex");
28426
29367
  } catch (e) {
28427
29368
  console.warn(`[agon] provenance: could not hash ${path}: ${e instanceof Error ? e.message : String(e)}`);
28428
29369
  return "unavailable";
@@ -28582,18 +29523,18 @@ function renderProvenanceMarkdown(led) {
28582
29523
  function writeProvenanceReport(manifest, manifestPath, outDir, format) {
28583
29524
  const fmt = format ?? "md";
28584
29525
  const ledger = buildForgeProvenance(manifest, manifestPath);
28585
- mkdirSync24(outDir, { recursive: true });
29526
+ mkdirSync26(outDir, { recursive: true });
28586
29527
  if (fmt === "md" || fmt === "both") {
28587
- const mdPath = resolve26(join32(outDir, "provenance.md"));
28588
- writeFileSync24(mdPath, renderProvenanceMarkdown(ledger), "utf-8");
29528
+ const mdPath = resolve26(join35(outDir, "provenance.md"));
29529
+ writeFileSync27(mdPath, renderProvenanceMarkdown(ledger), "utf-8");
28589
29530
  if (fmt === "md") return mdPath;
28590
29531
  }
28591
29532
  if (fmt === "json" || fmt === "both") {
28592
- const jsonPath = resolve26(join32(outDir, "provenance.json"));
28593
- writeFileSync24(jsonPath, renderProvenanceJson(ledger), "utf-8");
29533
+ const jsonPath = resolve26(join35(outDir, "provenance.json"));
29534
+ writeFileSync27(jsonPath, renderProvenanceJson(ledger), "utf-8");
28594
29535
  if (fmt === "json") return jsonPath;
28595
29536
  }
28596
- return resolve26(join32(outDir, "provenance.md"));
29537
+ return resolve26(join35(outDir, "provenance.md"));
28597
29538
  }
28598
29539
 
28599
29540
  // ../core/src/generated/models/extension-manifest.ts
@@ -28699,8 +29640,8 @@ var CommandRegistry = class {
28699
29640
  };
28700
29641
 
28701
29642
  // ../core/src/generated/blocks/extension-loader.ts
28702
- import { join as join33, resolve as resolve27 } from "path";
28703
- import { readdirSync as readdirSync18, readFileSync as readFileSync31, existsSync as existsSync25 } from "fs";
29643
+ import { join as join36, resolve as resolve27 } from "path";
29644
+ import { readdirSync as readdirSync19, readFileSync as readFileSync36, existsSync as existsSync29 } from "fs";
28704
29645
  import { homedir as homedir17 } from "os";
28705
29646
 
28706
29647
  // ../core/src/generated/signals/event-bus.ts
@@ -28791,31 +29732,31 @@ function bridgeShellHooks(bus, hooks) {
28791
29732
  function discoverExtensionDirs(cwd) {
28792
29733
  const results = [];
28793
29734
  const override = process.env.AGON_HOME?.trim();
28794
- const home = override ? resolve27(override) : join33(homedir17(), ".agon");
28795
- const userDir = join33(home, "extensions");
28796
- if (existsSync25(userDir)) {
29735
+ const home = override ? resolve27(override) : join36(homedir17(), ".agon");
29736
+ const userDir = join36(home, "extensions");
29737
+ if (existsSync29(userDir)) {
28797
29738
  try {
28798
- const entries = readdirSync18(userDir, { withFileTypes: true });
29739
+ const entries = readdirSync19(userDir, { withFileTypes: true });
28799
29740
  for (const entry of entries) {
28800
29741
  if (entry.isDirectory()) {
28801
- const manifestPath = join33(userDir, entry.name, "manifest.json");
28802
- if (existsSync25(manifestPath)) {
28803
- results.push({ dir: join33(userDir, entry.name), source: "user" });
29742
+ const manifestPath = join36(userDir, entry.name, "manifest.json");
29743
+ if (existsSync29(manifestPath)) {
29744
+ results.push({ dir: join36(userDir, entry.name), source: "user" });
28804
29745
  }
28805
29746
  }
28806
29747
  }
28807
29748
  } catch {
28808
29749
  }
28809
29750
  }
28810
- const repoDir = join33(cwd, ".agon", "extensions");
28811
- if (existsSync25(repoDir)) {
29751
+ const repoDir = join36(cwd, ".agon", "extensions");
29752
+ if (existsSync29(repoDir)) {
28812
29753
  try {
28813
- const entries = readdirSync18(repoDir, { withFileTypes: true });
29754
+ const entries = readdirSync19(repoDir, { withFileTypes: true });
28814
29755
  for (const entry of entries) {
28815
29756
  if (entry.isDirectory()) {
28816
- const manifestPath = join33(repoDir, entry.name, "manifest.json");
28817
- if (existsSync25(manifestPath)) {
28818
- results.push({ dir: join33(repoDir, entry.name), source: "repo" });
29757
+ const manifestPath = join36(repoDir, entry.name, "manifest.json");
29758
+ if (existsSync29(manifestPath)) {
29759
+ results.push({ dir: join36(repoDir, entry.name), source: "repo" });
28819
29760
  }
28820
29761
  }
28821
29762
  }
@@ -28825,9 +29766,9 @@ function discoverExtensionDirs(cwd) {
28825
29766
  return results;
28826
29767
  }
28827
29768
  function loadExtensionManifest(dir, source) {
28828
- const manifestPath = join33(dir, "manifest.json");
29769
+ const manifestPath = join36(dir, "manifest.json");
28829
29770
  try {
28830
- const raw = JSON.parse(readFileSync31(manifestPath, "utf-8"));
29771
+ const raw = JSON.parse(readFileSync36(manifestPath, "utf-8"));
28831
29772
  const result = validateManifest(raw, manifestPath);
28832
29773
  if (!result.ok || !result.data) {
28833
29774
  console.warn(`[agon] skipping extension ${dir}: ${result.error}`);
@@ -28896,7 +29837,7 @@ function registerExtensionEngines(ext, engineRegistry) {
28896
29837
  for (const enginePath of enginePaths) {
28897
29838
  try {
28898
29839
  const fullPath = resolve27(ext.dir, enginePath);
28899
- const raw = JSON.parse(readFileSync31(fullPath, "utf-8"));
29840
+ const raw = JSON.parse(readFileSync36(fullPath, "utf-8"));
28900
29841
  if (raw.id) {
28901
29842
  engineRegistry.register(raw);
28902
29843
  registered.push(raw.id);
@@ -29045,7 +29986,7 @@ function registerBuiltinCommands(registry2) {
29045
29986
  // Info
29046
29987
  { name: "tokens", desc: " \u2014 show token usage & costs", category: "info" },
29047
29988
  { name: "doctor", desc: "[engines|harness] \u2014 diagnose engines, worktree, or Cesar harness", category: "info" },
29048
- { name: "leaderboard", desc: " \u2014 ELO rankings", category: "info" },
29989
+ { name: "leaderboard", desc: " \u2014 Glicko rankings", category: "info" },
29049
29990
  { name: "history", desc: "[id] \u2014 past forge runs", category: "info" },
29050
29991
  { name: "provenance", desc: "[id] [-f md|json|both] [-o file] \u2014 AI-contribution / transparency report", category: "info" },
29051
29992
  { name: "flow", desc: " \u2014 log this session", category: "info" },
@@ -29311,8 +30252,8 @@ function computeContributionWeights(team, trace) {
29311
30252
  }
29312
30253
 
29313
30254
  // ../core/src/generated/teams/team-elo.ts
29314
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25, renameSync as renameSync13 } from "fs";
29315
- import { dirname as dirname13 } from "path";
30255
+ import { readFileSync as readFileSync37, writeFileSync as writeFileSync28, mkdirSync as mkdirSync27, renameSync as renameSync13 } from "fs";
30256
+ import { dirname as dirname14 } from "path";
29316
30257
  function defaultCompositionRating(lineupKey2) {
29317
30258
  return { lineupKey: lineupKey2, rating: 1500, wins: 0, losses: 0, draws: 0, matches: 0 };
29318
30259
  }
@@ -29321,7 +30262,7 @@ function defaultRoleRating(engineId, role) {
29321
30262
  }
29322
30263
  function loadTeamElo() {
29323
30264
  try {
29324
- return JSON.parse(readFileSync32(TEAM_ELO_PATH, "utf-8"));
30265
+ return JSON.parse(readFileSync37(TEAM_ELO_PATH, "utf-8"));
29325
30266
  } catch (err) {
29326
30267
  if (err.code !== "ENOENT") {
29327
30268
  console.warn(`[agon] failed to load team ELO: ${err instanceof Error ? err.message : String(err)}`);
@@ -29330,10 +30271,10 @@ function loadTeamElo() {
29330
30271
  }
29331
30272
  }
29332
30273
  function saveTeamElo(record2) {
29333
- mkdirSync25(dirname13(TEAM_ELO_PATH), { recursive: true });
30274
+ mkdirSync27(dirname14(TEAM_ELO_PATH), { recursive: true });
29334
30275
  record2.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
29335
30276
  const tmpPath = TEAM_ELO_PATH + ".tmp";
29336
- writeFileSync25(tmpPath, JSON.stringify(record2, null, 2) + "\n");
30277
+ writeFileSync28(tmpPath, JSON.stringify(record2, null, 2) + "\n");
29337
30278
  renameSync13(tmpPath, TEAM_ELO_PATH);
29338
30279
  }
29339
30280
  function expectedScore(rA, rB) {
@@ -29528,6 +30469,7 @@ export {
29528
30469
  hasProjectBrief,
29529
30470
  isKernProject,
29530
30471
  scanProjectContext,
30472
+ buildKernContextSpine,
29531
30473
  collectSourceFiles,
29532
30474
  extractSymbols,
29533
30475
  buildCodebaseMap,
@@ -29541,7 +30483,7 @@ export {
29541
30483
  snapshotWorkspace,
29542
30484
  resolveWorkingDir,
29543
30485
  ensureCurrentWorkspace,
29544
- estimateTokens,
30486
+ estimateTokens2 as estimateTokens,
29545
30487
  estimateCost,
29546
30488
  tracker,
29547
30489
  createPlan,
@@ -29667,6 +30609,7 @@ export {
29667
30609
  getCesarPlansDir,
29668
30610
  cesarPlanJsonPath,
29669
30611
  cesarPlanMarkdownPath,
30612
+ CESAR_STEP_TYPES,
29670
30613
  createCesarPlan,
29671
30614
  approveCesarPlan,
29672
30615
  advanceCesarStep,
@@ -29696,7 +30639,30 @@ export {
29696
30639
  mimeFromExt,
29697
30640
  resolveImagePath,
29698
30641
  buildImageAttachment,
30642
+ normalizeDroppedPath,
29699
30643
  extractImagesFromInput,
30644
+ encodeImagesForDispatch,
30645
+ roomsDir,
30646
+ roomDir,
30647
+ slugifyRoomId,
30648
+ roomExists,
30649
+ createRoom,
30650
+ listRooms,
30651
+ parseMentions,
30652
+ appendEvent,
30653
+ readEvents,
30654
+ closeRoom,
30655
+ isRoomClosed,
30656
+ PRESENCE_TTL_MS,
30657
+ recordPresence,
30658
+ removePresence,
30659
+ listPresence,
30660
+ readActiveLease,
30661
+ acquireTurnLease,
30662
+ releaseTurnLease,
30663
+ detectTrigger,
30664
+ detectPingPong,
30665
+ evaluateStop,
29700
30666
  FLOWS_DIR,
29701
30667
  FRICTION_TAGS,
29702
30668
  logFlow,
@@ -29744,6 +30710,7 @@ export {
29744
30710
  listThreadsForProject,
29745
30711
  deleteThread,
29746
30712
  planCostEstimator,
30713
+ sanitizePlanSteps,
29747
30714
  getReadySteps,
29748
30715
  executePlan,
29749
30716
  makeAssistantChunk,
@@ -29829,4 +30796,4 @@ export {
29829
30796
  predictTeamRating,
29830
30797
  updateTeamElo
29831
30798
  };
29832
- //# sourceMappingURL=chunk-C22VTCS6.js.map
30799
+ //# sourceMappingURL=chunk-TMNHJOKU.js.map