@kody-ade/kody-engine 0.4.646 → 0.4.648

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.646",
18
+ version: "0.4.648",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  repository: {
@@ -4606,6 +4606,8 @@ async function runAgent(opts) {
4606
4606
  let tokens = { input: 0, output: 0, cacheRead: 0, cacheCreate: 0 };
4607
4607
  let costUsd = 0;
4608
4608
  let messageCount = 0;
4609
+ let turns = 0;
4610
+ let modelUsage = {};
4609
4611
  let finalText = "";
4610
4612
  let getSubmitted;
4611
4613
  const invokedSubagents = /* @__PURE__ */ new Set();
@@ -4632,6 +4634,8 @@ async function runAgent(opts) {
4632
4634
  tokens = { input: 0, output: 0, cacheRead: 0, cacheCreate: 0 };
4633
4635
  costUsd = 0;
4634
4636
  messageCount = 0;
4637
+ turns = 0;
4638
+ modelUsage = {};
4635
4639
  let sawMutatingTool = false;
4636
4640
  let sawTerminalSuccess = false;
4637
4641
  let sawLoginRequired = false;
@@ -4940,6 +4944,9 @@ async function runAgent(opts) {
4940
4944
  }
4941
4945
  }
4942
4946
  }
4947
+ if (m.type === "result") {
4948
+ tokens = { input: 0, output: 0, cacheRead: 0, cacheCreate: 0 };
4949
+ }
4943
4950
  const usage = m.usage;
4944
4951
  if (usage && typeof usage === "object") {
4945
4952
  const i = Number(usage.input_tokens ?? 0);
@@ -4966,6 +4973,12 @@ async function runAgent(opts) {
4966
4973
  if (m.type === "result") {
4967
4974
  const reportedCost = Number(m.total_cost_usd ?? 0);
4968
4975
  if (Number.isFinite(reportedCost) && reportedCost >= 0) costUsd = reportedCost;
4976
+ const reportedTurns = Number(m.num_turns ?? 0);
4977
+ if (Number.isFinite(reportedTurns) && reportedTurns >= 0) turns = reportedTurns;
4978
+ const reportedModelUsage = m.modelUsage;
4979
+ if (reportedModelUsage && typeof reportedModelUsage === "object" && !Array.isArray(reportedModelUsage)) {
4980
+ modelUsage = structuredClone(reportedModelUsage);
4981
+ }
4969
4982
  if (m.subtype === "success") {
4970
4983
  outcome = "completed";
4971
4984
  outcomeKind = "ok";
@@ -5051,6 +5064,8 @@ async function runAgent(opts) {
5051
5064
  tokens,
5052
5065
  costUsd,
5053
5066
  messageCount,
5067
+ turns,
5068
+ modelUsage,
5054
5069
  invokedSubagents: [...invokedSubagents]
5055
5070
  };
5056
5071
  }
@@ -7360,17 +7375,177 @@ var init_state = __esm({
7360
7375
  }
7361
7376
  });
7362
7377
 
7363
- // src/prompt.ts
7378
+ // src/usage.ts
7364
7379
  import * as fs25 from "fs";
7380
+ function safeNumber(value) {
7381
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
7382
+ }
7383
+ function tokenBreakdown(tokens) {
7384
+ const input = safeNumber(tokens?.input);
7385
+ const output = safeNumber(tokens?.output);
7386
+ const cacheRead = safeNumber(tokens?.cacheRead);
7387
+ const cacheCreate = safeNumber(tokens?.cacheCreate);
7388
+ return { input, output, cacheRead, cacheCreate, total: input + output + cacheRead + cacheCreate };
7389
+ }
7390
+ function addTokenBreakdown(left, right) {
7391
+ const input = left.input + right.input;
7392
+ const output = left.output + right.output;
7393
+ const cacheRead = left.cacheRead + right.cacheRead;
7394
+ const cacheCreate = left.cacheCreate + right.cacheCreate;
7395
+ return { input, output, cacheRead, cacheCreate, total: input + output + cacheRead + cacheCreate };
7396
+ }
7397
+ function createRunUsage(tokens, costUsd, details = {}) {
7398
+ if (!tokens && costUsd === void 0 && details.turns === void 0) return void 0;
7399
+ const normalizedTokens = tokenBreakdown(tokens);
7400
+ const hasBillableUsage = normalizedTokens.total > 0 || safeNumber(costUsd) > 0;
7401
+ const measurement = details.outcome === "failed" && !hasBillableUsage ? "unknown" : "reported";
7402
+ const modelUsage = {
7403
+ tokens: normalizedTokens,
7404
+ costUsd: safeNumber(costUsd),
7405
+ agentRuns: 1,
7406
+ turns: safeNumber(details.turns),
7407
+ measurement
7408
+ };
7409
+ const reportedModels = Object.entries(details.modelUsage ?? {});
7410
+ const byModel = reportedModels.length > 0 ? Object.fromEntries(
7411
+ reportedModels.map(([model, usage]) => {
7412
+ const modelTokens = tokenBreakdown({
7413
+ input: usage.inputTokens,
7414
+ output: usage.outputTokens,
7415
+ cacheRead: usage.cacheReadInputTokens,
7416
+ cacheCreate: usage.cacheCreationInputTokens
7417
+ });
7418
+ return [
7419
+ model,
7420
+ {
7421
+ tokens: modelTokens,
7422
+ costUsd: safeNumber(usage.costUSD),
7423
+ agentRuns: 1,
7424
+ turns: reportedModels.length === 1 ? safeNumber(details.turns) : 0,
7425
+ measurement
7426
+ }
7427
+ ];
7428
+ })
7429
+ ) : details.model ? { [details.model]: modelUsage } : {};
7430
+ return {
7431
+ version: 1,
7432
+ ...modelUsage,
7433
+ byModel
7434
+ };
7435
+ }
7436
+ function isModelRunUsage(value) {
7437
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
7438
+ const usage = value;
7439
+ if (!usage.tokens || typeof usage.tokens !== "object" || Array.isArray(usage.tokens)) return false;
7440
+ return [
7441
+ usage.tokens.input,
7442
+ usage.tokens.output,
7443
+ usage.tokens.cacheRead,
7444
+ usage.tokens.cacheCreate,
7445
+ usage.tokens.total,
7446
+ usage.costUsd,
7447
+ usage.agentRuns,
7448
+ usage.turns
7449
+ ].every((number) => typeof number === "number" && Number.isFinite(number) && number >= 0);
7450
+ }
7451
+ function isUsageMeasurement(value) {
7452
+ return value === "reported" || value === "partial" || value === "unknown";
7453
+ }
7454
+ function mergeMeasurement(left, right) {
7455
+ const normalizedLeft = left ?? "reported";
7456
+ const normalizedRight = right ?? "reported";
7457
+ if (normalizedLeft === normalizedRight) return normalizedLeft;
7458
+ return "partial";
7459
+ }
7460
+ function parseRunUsage(value) {
7461
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
7462
+ const usage = value;
7463
+ if (usage.version !== 1 || !isModelRunUsage(usage)) return void 0;
7464
+ if (!usage.byModel || typeof usage.byModel !== "object" || Array.isArray(usage.byModel)) return void 0;
7465
+ if (!Object.values(usage.byModel).every(isModelRunUsage)) return void 0;
7466
+ const normalized = structuredClone(usage);
7467
+ normalized.measurement = isUsageMeasurement(usage.measurement) ? usage.measurement : "reported";
7468
+ for (const [model, modelUsage] of Object.entries(normalized.byModel)) {
7469
+ modelUsage.measurement = isUsageMeasurement(usage.byModel[model]?.measurement) ? usage.byModel[model].measurement : "reported";
7470
+ }
7471
+ return normalized;
7472
+ }
7473
+ function mergeRunUsage(left, right) {
7474
+ if (!left) return right ? structuredClone(right) : void 0;
7475
+ if (!right) return structuredClone(left);
7476
+ const byModel = {};
7477
+ for (const model of /* @__PURE__ */ new Set([...Object.keys(left.byModel), ...Object.keys(right.byModel)])) {
7478
+ const first = left.byModel[model];
7479
+ const second = right.byModel[model];
7480
+ if (!first) {
7481
+ byModel[model] = structuredClone(second);
7482
+ } else if (!second) {
7483
+ byModel[model] = structuredClone(first);
7484
+ } else {
7485
+ byModel[model] = {
7486
+ tokens: addTokenBreakdown(first.tokens, second.tokens),
7487
+ costUsd: first.costUsd + second.costUsd,
7488
+ agentRuns: first.agentRuns + second.agentRuns,
7489
+ turns: first.turns + second.turns,
7490
+ measurement: mergeMeasurement(first.measurement, second.measurement)
7491
+ };
7492
+ }
7493
+ }
7494
+ return {
7495
+ version: 1,
7496
+ tokens: addTokenBreakdown(left.tokens, right.tokens),
7497
+ costUsd: left.costUsd + right.costUsd,
7498
+ agentRuns: left.agentRuns + right.agentRuns,
7499
+ turns: left.turns + right.turns,
7500
+ measurement: mergeMeasurement(left.measurement, right.measurement),
7501
+ byModel
7502
+ };
7503
+ }
7504
+ function formatRunUsageMarker(subject, usage) {
7505
+ return `KODY_USAGE=${JSON.stringify({ subject, ...usage })}`;
7506
+ }
7507
+ function appendRunUsageSummary(summaryPath, subject, usage) {
7508
+ if (!summaryPath) return;
7509
+ const tokens = usage.tokens;
7510
+ const tokenLine = usage.measurement === "unknown" ? "- **Tokens:** usage unknown (provider did not report billable usage)" : `- **${usage.measurement === "partial" ? "Known tokens" : "Tokens"}:** ${tokens.input.toLocaleString()} input / ${tokens.cacheRead.toLocaleString()} cache-read / ${tokens.cacheCreate.toLocaleString()} cache-create / ${tokens.output.toLocaleString()} output / ${tokens.total.toLocaleString()} total${usage.measurement === "partial" ? "; some child usage is unknown" : ""}`;
7511
+ const costLine = usage.measurement === "unknown" ? "- **Provider-reported cost:** unknown" : `- **Provider-reported cost:** $${usage.costUsd.toFixed(4)}${usage.measurement === "partial" ? " known; some child cost is unknown" : ""}`;
7512
+ const lines = [
7513
+ `### Kody usage - ${subject}`,
7514
+ "",
7515
+ tokenLine,
7516
+ `- **Agent work:** ${usage.agentRuns.toLocaleString()} runs / ${usage.turns.toLocaleString()} turns`,
7517
+ costLine,
7518
+ ""
7519
+ ];
7520
+ try {
7521
+ fs25.appendFileSync(summaryPath, `${lines.join("\n")}
7522
+ `);
7523
+ } catch {
7524
+ }
7525
+ }
7526
+ function publishRunUsage(subject, usage) {
7527
+ if (!usage) return;
7528
+ process.stdout.write(`${formatRunUsageMarker(subject, usage)}
7529
+ `);
7530
+ appendRunUsageSummary(process.env.GITHUB_STEP_SUMMARY, subject, usage);
7531
+ }
7532
+ var init_usage = __esm({
7533
+ "src/usage.ts"() {
7534
+ "use strict";
7535
+ }
7536
+ });
7537
+
7538
+ // src/prompt.ts
7539
+ import * as fs26 from "fs";
7365
7540
  import * as path25 from "path";
7366
7541
  function loadProjectConventions(projectDir) {
7367
7542
  const out = [];
7368
7543
  for (const rel of CONVENTION_FILES) {
7369
7544
  const abs = path25.join(projectDir, rel);
7370
- if (!fs25.existsSync(abs)) continue;
7545
+ if (!fs26.existsSync(abs)) continue;
7371
7546
  let content;
7372
7547
  try {
7373
- content = fs25.readFileSync(abs, "utf-8");
7548
+ content = fs26.readFileSync(abs, "utf-8");
7374
7549
  } catch {
7375
7550
  continue;
7376
7551
  }
@@ -7621,7 +7796,7 @@ var loadMemoryContext_exports = {};
7621
7796
  __export(loadMemoryContext_exports, {
7622
7797
  loadMemoryContext: () => loadMemoryContext
7623
7798
  });
7624
- import * as fs26 from "fs";
7799
+ import * as fs27 from "fs";
7625
7800
  import * as path26 from "path";
7626
7801
  function formatBlockFromBackend(docs) {
7627
7802
  const pages = docs.flatMap((record2) => {
@@ -7645,13 +7820,13 @@ function collectPages(memoryAbs) {
7645
7820
  walkMd(memoryAbs, (file) => {
7646
7821
  let stat;
7647
7822
  try {
7648
- stat = fs26.statSync(file);
7823
+ stat = fs27.statSync(file);
7649
7824
  } catch {
7650
7825
  return;
7651
7826
  }
7652
7827
  let raw;
7653
7828
  try {
7654
- raw = fs26.readFileSync(file, "utf-8");
7829
+ raw = fs27.readFileSync(file, "utf-8");
7655
7830
  } catch {
7656
7831
  return;
7657
7832
  }
@@ -7727,7 +7902,7 @@ function walkMd(root, visit) {
7727
7902
  const dir = stack.pop();
7728
7903
  let names;
7729
7904
  try {
7730
- names = fs26.readdirSync(dir);
7905
+ names = fs27.readdirSync(dir);
7731
7906
  } catch {
7732
7907
  continue;
7733
7908
  }
@@ -7736,7 +7911,7 @@ function walkMd(root, visit) {
7736
7911
  const full = path26.join(dir, name);
7737
7912
  let stat;
7738
7913
  try {
7739
- stat = fs26.statSync(full);
7914
+ stat = fs27.statSync(full);
7740
7915
  } catch {
7741
7916
  continue;
7742
7917
  }
@@ -7772,7 +7947,7 @@ var init_loadMemoryContext = __esm({
7772
7947
  return;
7773
7948
  }
7774
7949
  const memoryAbs = path26.join(ctx.cwd, MEMORY_DIR_RELATIVE);
7775
- if (!fs26.existsSync(memoryAbs)) {
7950
+ if (!fs27.existsSync(memoryAbs)) {
7776
7951
  ctx.data.memoryContext = "";
7777
7952
  return;
7778
7953
  }
@@ -7816,11 +7991,11 @@ var init_loadCoverageRules = __esm({
7816
7991
 
7817
7992
  // src/container.ts
7818
7993
  import { execFileSync as execFileSync3 } from "child_process";
7819
- import * as fs27 from "fs";
7994
+ import * as fs28 from "fs";
7820
7995
  function getProfileInputsForChild(profileName, _cwd) {
7821
7996
  try {
7822
7997
  const profilePath = resolveProfilePath(profileName);
7823
- if (!fs27.existsSync(profilePath)) return null;
7998
+ if (!fs28.existsSync(profilePath)) return null;
7824
7999
  return loadProfile(profilePath).inputs;
7825
8000
  } catch {
7826
8001
  return null;
@@ -7952,6 +8127,7 @@ async function runContainerLoop(profile, ctx, input) {
7952
8127
  // is off, so children fall back to their own loaders.
7953
8128
  preloadedData: preloadedSnapshot
7954
8129
  });
8130
+ ctx.output.usage = mergeRunUsage(ctx.output.usage, childOut.usage);
7955
8131
  emitEvent(input.cwd, {
7956
8132
  implementation: profile.name,
7957
8133
  kind: "container_child",
@@ -8103,6 +8279,7 @@ var init_container = __esm({
8103
8279
  init_executor();
8104
8280
  init_profile();
8105
8281
  init_state();
8282
+ init_usage();
8106
8283
  CONTAINER_MAX_ITERATIONS = 50;
8107
8284
  }
8108
8285
  });
@@ -8284,7 +8461,7 @@ var init_lifecycleLabels = __esm({
8284
8461
 
8285
8462
  // src/litellm.ts
8286
8463
  import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
8287
- import * as fs28 from "fs";
8464
+ import * as fs29 from "fs";
8288
8465
  import * as net from "net";
8289
8466
  import * as os4 from "os";
8290
8467
  import * as path27 from "path";
@@ -8396,7 +8573,7 @@ function locateLitellmScript() {
8396
8573
  }
8397
8574
  function resolveLitellmCommand() {
8398
8575
  const imageScript = "/opt/venv/bin/litellm";
8399
- if (fs28.existsSync(imageScript)) return imageScript;
8576
+ if (fs29.existsSync(imageScript)) return imageScript;
8400
8577
  try {
8401
8578
  execFileSync4("which", ["litellm"], { timeout: 3e3, stdio: "pipe" });
8402
8579
  return "litellm";
@@ -8460,12 +8637,12 @@ async function startLitellmProxy(input) {
8460
8637
  const portMatch = activeUrl.match(/:(\d+)/);
8461
8638
  const port = portMatch ? portMatch[1] : "4000";
8462
8639
  const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
8463
- fs28.writeFileSync(configPath, input.configYaml);
8640
+ fs29.writeFileSync(configPath, input.configYaml);
8464
8641
  const args = ["--config", configPath, "--port", port];
8465
8642
  const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
8466
- const outFd = fs28.openSync(nextLogPath, "w");
8643
+ const outFd = fs29.openSync(nextLogPath, "w");
8467
8644
  child = spawn4(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
8468
- fs28.closeSync(outFd);
8645
+ fs29.closeSync(outFd);
8469
8646
  logPath = nextLogPath;
8470
8647
  };
8471
8648
  const waitForHealth = async () => {
@@ -8479,7 +8656,7 @@ async function startLitellmProxy(input) {
8479
8656
  const readLogTail = () => {
8480
8657
  if (!logPath) return "";
8481
8658
  try {
8482
- return fs28.readFileSync(logPath, "utf-8").slice(-2e3);
8659
+ return fs29.readFileSync(logPath, "utf-8").slice(-2e3);
8483
8660
  } catch {
8484
8661
  return "";
8485
8662
  }
@@ -8563,9 +8740,9 @@ function canListen(port, host) {
8563
8740
  }
8564
8741
  function readDotenvApiKeys(projectDir) {
8565
8742
  const dotenvPath = path27.join(projectDir, ".env");
8566
- if (!fs28.existsSync(dotenvPath)) return {};
8743
+ if (!fs29.existsSync(dotenvPath)) return {};
8567
8744
  const result = {};
8568
- for (const rawLine of fs28.readFileSync(dotenvPath, "utf-8").split("\n")) {
8745
+ for (const rawLine of fs29.readFileSync(dotenvPath, "utf-8").split("\n")) {
8569
8746
  const line = rawLine.trim();
8570
8747
  if (!line || line.startsWith("#")) continue;
8571
8748
  const match = line.match(/^([A-Z_][A-Z0-9_]*_API_KEY)=(.*)$/);
@@ -8647,7 +8824,8 @@ function finalizedRunIndexRow(row, result) {
8647
8824
  status: result.status,
8648
8825
  updatedAt: result.updatedAt,
8649
8826
  summary: result.reason ?? row.summary,
8650
- ...result.output === void 0 ? {} : { output: result.output }
8827
+ ...result.output === void 0 ? {} : { output: result.output },
8828
+ ...result.usage === void 0 ? {} : { usage: result.usage }
8651
8829
  };
8652
8830
  }
8653
8831
  function runIndexRowFromJobContext(input) {
@@ -8696,7 +8874,8 @@ function runIndexRowFromJobContext(input) {
8696
8874
  reasoningEffort: stringValue(input.data.jobReasoningEffort) ?? void 0,
8697
8875
  target: input.data.jobTarget,
8698
8876
  sourceType: "job",
8699
- output: input.data.capabilityOutput
8877
+ output: input.data.capabilityOutput,
8878
+ usage: input.usage
8700
8879
  });
8701
8880
  }
8702
8881
  function runIndexRowFromGoalEvents(goalId, logPath, events) {
@@ -9239,7 +9418,7 @@ var init_pushWithRetry = __esm({
9239
9418
  // src/commit.ts
9240
9419
  import { execFileSync as execFileSync6 } from "child_process";
9241
9420
  import { isDeepStrictEqual } from "util";
9242
- import * as fs29 from "fs";
9421
+ import * as fs30 from "fs";
9243
9422
  import * as path28 from "path";
9244
9423
  function isGitHubYamlPath(filePath) {
9245
9424
  const normalized = filePath.replace(/^\.\/+/, "");
@@ -9284,17 +9463,17 @@ function ensureGitIdentity(cwd) {
9284
9463
  function abortUnfinishedGitOps(cwd) {
9285
9464
  const aborted = [];
9286
9465
  const gitDir = path28.join(cwd ?? process.cwd(), ".git");
9287
- if (!fs29.existsSync(gitDir)) return aborted;
9288
- if (fs29.existsSync(path28.join(gitDir, "MERGE_HEAD"))) {
9466
+ if (!fs30.existsSync(gitDir)) return aborted;
9467
+ if (fs30.existsSync(path28.join(gitDir, "MERGE_HEAD"))) {
9289
9468
  if (tryGit(["merge", "--abort"], cwd)) aborted.push("merge");
9290
9469
  }
9291
- if (fs29.existsSync(path28.join(gitDir, "CHERRY_PICK_HEAD"))) {
9470
+ if (fs30.existsSync(path28.join(gitDir, "CHERRY_PICK_HEAD"))) {
9292
9471
  if (tryGit(["cherry-pick", "--abort"], cwd)) aborted.push("cherry-pick");
9293
9472
  }
9294
- if (fs29.existsSync(path28.join(gitDir, "REVERT_HEAD"))) {
9473
+ if (fs30.existsSync(path28.join(gitDir, "REVERT_HEAD"))) {
9295
9474
  if (tryGit(["revert", "--abort"], cwd)) aborted.push("revert");
9296
9475
  }
9297
- if (fs29.existsSync(path28.join(gitDir, "rebase-merge")) || fs29.existsSync(path28.join(gitDir, "rebase-apply"))) {
9476
+ if (fs30.existsSync(path28.join(gitDir, "rebase-merge")) || fs30.existsSync(path28.join(gitDir, "rebase-apply"))) {
9298
9477
  if (tryGit(["rebase", "--abort"], cwd)) aborted.push("rebase");
9299
9478
  }
9300
9479
  try {
@@ -9377,7 +9556,7 @@ function isTrustedConfigActivationChange(filePath, deliveryPathAllowlist, delive
9377
9556
  if (filePath !== "kody.config.json" || !deliveryPathAllowlist.includes(filePath)) return false;
9378
9557
  try {
9379
9558
  const before = JSON.parse(git(["show", "HEAD:kody.config.json"], cwd));
9380
- const after = JSON.parse(fs29.readFileSync(path28.join(cwd ?? process.cwd(), filePath), "utf-8"));
9559
+ const after = JSON.parse(fs30.readFileSync(path28.join(cwd ?? process.cwd(), filePath), "utf-8"));
9381
9560
  return isSafeConfigChange(before, after, deliveryConfigAllowlist[filePath] ?? []);
9382
9561
  } catch {
9383
9562
  return false;
@@ -9440,7 +9619,7 @@ function commitAndPush(branch, agentMessage, cwd, deliveryPathAllowlist = [], de
9440
9619
  (f) => isForbiddenPath(f, deliveryPathAllowlist) && !isTrustedConfigActivationChange(f, deliveryPathAllowlist, deliveryConfigAllowlist, cwd)
9441
9620
  );
9442
9621
  const omittedFiles = forbiddenFiles.filter(isReportableDeliveryOmission);
9443
- const mergeHeadExists = fs29.existsSync(path28.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
9622
+ const mergeHeadExists = fs30.existsSync(path28.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
9444
9623
  if (allowedFiles.length === 0 && !mergeHeadExists) {
9445
9624
  return { committed: false, pushed: false, sha: "", message: "", omittedFiles };
9446
9625
  }
@@ -10096,7 +10275,7 @@ var init_state2 = __esm({
10096
10275
  });
10097
10276
 
10098
10277
  // src/goal/runLog.ts
10099
- import * as fs30 from "fs";
10278
+ import * as fs31 from "fs";
10100
10279
  function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
10101
10280
  const logs = goalRunLogs(data);
10102
10281
  const existing = logs[goalId];
@@ -10438,8 +10617,8 @@ function readGithubEvent() {
10438
10617
  const eventPath = process.env.GITHUB_EVENT_PATH;
10439
10618
  if (!eventPath) return null;
10440
10619
  try {
10441
- if (!fs30.existsSync(eventPath)) return null;
10442
- const parsed = JSON.parse(fs30.readFileSync(eventPath, "utf-8"));
10620
+ if (!fs31.existsSync(eventPath)) return null;
10621
+ const parsed = JSON.parse(fs31.readFileSync(eventPath, "utf-8"));
10443
10622
  return recordValue3(parsed);
10444
10623
  } catch {
10445
10624
  return null;
@@ -10549,7 +10728,7 @@ var init_stateStore = __esm({
10549
10728
  });
10550
10729
 
10551
10730
  // src/goal/targetLoopResolution.ts
10552
- import * as fs31 from "fs";
10731
+ import * as fs32 from "fs";
10553
10732
  import * as path29 from "path";
10554
10733
  async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
10555
10734
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
@@ -10631,8 +10810,8 @@ function loadGoalTemplate(cwd, targetId) {
10631
10810
  return readJsonObject2(path29.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
10632
10811
  }
10633
10812
  function readJsonObject2(filePath) {
10634
- if (!fs31.existsSync(filePath)) return null;
10635
- const parsed = JSON.parse(fs31.readFileSync(filePath, "utf8"));
10813
+ if (!fs32.existsSync(filePath)) return null;
10814
+ const parsed = JSON.parse(fs32.readFileSync(filePath, "utf8"));
10636
10815
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
10637
10816
  throw new Error(`goal template ${filePath} must be a JSON object`);
10638
10817
  }
@@ -11007,7 +11186,7 @@ var init_backendStateBackend = __esm({
11007
11186
  });
11008
11187
 
11009
11188
  // src/scripts/jobState/localFileBackend.ts
11010
- import * as fs32 from "fs";
11189
+ import * as fs33 from "fs";
11011
11190
  import * as path30 from "path";
11012
11191
  function sanitizeKey(s) {
11013
11192
  return s.replace(/[^A-Za-z0-9._-]/g, "-");
@@ -11079,7 +11258,7 @@ var init_localFileBackend = __esm({
11079
11258
  `);
11080
11259
  return;
11081
11260
  }
11082
- fs32.mkdirSync(this.absDir, { recursive: true });
11261
+ fs33.mkdirSync(this.absDir, { recursive: true });
11083
11262
  const prefix = this.cacheKeyPrefix();
11084
11263
  const probeKey = `${prefix}probe-${Date.now()}`;
11085
11264
  try {
@@ -11108,7 +11287,7 @@ var init_localFileBackend = __esm({
11108
11287
  `);
11109
11288
  return;
11110
11289
  }
11111
- if (!fs32.existsSync(this.absDir)) {
11290
+ if (!fs33.existsSync(this.absDir)) {
11112
11291
  return;
11113
11292
  }
11114
11293
  const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
@@ -11125,10 +11304,10 @@ var init_localFileBackend = __esm({
11125
11304
  load(slug) {
11126
11305
  const relPath = stateFilePath(this.jobsDir, slug);
11127
11306
  const absPath = path30.resolve(this.cwd, relPath);
11128
- if (!fs32.existsSync(absPath)) {
11307
+ if (!fs33.existsSync(absPath)) {
11129
11308
  return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
11130
11309
  }
11131
- const raw = fs32.readFileSync(absPath, "utf-8");
11310
+ const raw = fs33.readFileSync(absPath, "utf-8");
11132
11311
  let parsed;
11133
11312
  try {
11134
11313
  parsed = JSON.parse(raw);
@@ -11146,12 +11325,12 @@ var init_localFileBackend = __esm({
11146
11325
  return false;
11147
11326
  }
11148
11327
  const absPath = path30.resolve(this.cwd, loaded.path);
11149
- fs32.mkdirSync(path30.dirname(absPath), { recursive: true });
11328
+ fs33.mkdirSync(path30.dirname(absPath), { recursive: true });
11150
11329
  const body = `${JSON.stringify(next, null, 2)}
11151
11330
  `;
11152
11331
  const tmpPath = `${absPath}.${process.pid}.tmp`;
11153
- fs32.writeFileSync(tmpPath, body, "utf-8");
11154
- fs32.renameSync(tmpPath, absPath);
11332
+ fs33.writeFileSync(tmpPath, body, "utf-8");
11333
+ fs33.renameSync(tmpPath, absPath);
11155
11334
  return true;
11156
11335
  }
11157
11336
  cacheKeyPrefix() {
@@ -13060,7 +13239,7 @@ var init_classifyByLabel = __esm({
13060
13239
 
13061
13240
  // src/scripts/commitAndPush.ts
13062
13241
  import { createHash as createHash5 } from "crypto";
13063
- import * as fs33 from "fs";
13242
+ import * as fs34 from "fs";
13064
13243
  import * as path32 from "path";
13065
13244
  function sentinelPathForStage(cwd, profileName, workflowExecutionKey) {
13066
13245
  const runId = resolveRunId();
@@ -13083,9 +13262,9 @@ var init_commitAndPush = __esm({
13083
13262
  }
13084
13263
  const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
13085
13264
  const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name, ctx.data.workflowExecutionKey) : null;
13086
- if (sentinel && fs33.existsSync(sentinel)) {
13265
+ if (sentinel && fs34.existsSync(sentinel)) {
13087
13266
  try {
13088
- const replay = JSON.parse(fs33.readFileSync(sentinel, "utf-8"));
13267
+ const replay = JSON.parse(fs34.readFileSync(sentinel, "utf-8"));
13089
13268
  ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
13090
13269
  if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
13091
13270
  if (Array.isArray(replay.deliveryOmissions)) ctx.data.deliveryOmissions = replay.deliveryOmissions;
@@ -13149,8 +13328,8 @@ var init_commitAndPush = __esm({
13149
13328
  const result = ctx.data.commitResult;
13150
13329
  if (sentinel && result?.committed) {
13151
13330
  try {
13152
- fs33.mkdirSync(path32.dirname(sentinel), { recursive: true });
13153
- fs33.writeFileSync(
13331
+ fs34.mkdirSync(path32.dirname(sentinel), { recursive: true });
13332
+ fs34.writeFileSync(
13154
13333
  sentinel,
13155
13334
  JSON.stringify(
13156
13335
  {
@@ -13277,7 +13456,7 @@ var init_acceptanceCriteria = __esm({
13277
13456
  });
13278
13457
 
13279
13458
  // src/scripts/composePrompt.ts
13280
- import * as fs34 from "fs";
13459
+ import * as fs35 from "fs";
13281
13460
  import * as path33 from "path";
13282
13461
  function fenceUntrusted(value) {
13283
13462
  if (value.trim().length === 0) return value;
@@ -13419,7 +13598,7 @@ var init_composePrompt = __esm({
13419
13598
  break;
13420
13599
  }
13421
13600
  try {
13422
- template = fs34.readFileSync(c, "utf-8");
13601
+ template = fs35.readFileSync(c, "utf-8");
13423
13602
  templatePath = c;
13424
13603
  break;
13425
13604
  } catch (err) {
@@ -13430,7 +13609,7 @@ var init_composePrompt = __esm({
13430
13609
  if (!templatePath) {
13431
13610
  let dirState;
13432
13611
  try {
13433
- dirState = `dir contents: [${fs34.readdirSync(profile.dir).join(", ")}]`;
13612
+ dirState = `dir contents: [${fs35.readdirSync(profile.dir).join(", ")}]`;
13434
13613
  } catch (err) {
13435
13614
  dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
13436
13615
  }
@@ -14168,7 +14347,7 @@ var init_deriveQaScopeFromIssue = __esm({
14168
14347
 
14169
14348
  // src/scripts/diagMcp.ts
14170
14349
  import { execFileSync as execFileSync9 } from "child_process";
14171
- import * as fs35 from "fs";
14350
+ import * as fs36 from "fs";
14172
14351
  import * as os5 from "os";
14173
14352
  import * as path34 from "path";
14174
14353
  var diagMcp;
@@ -14180,7 +14359,7 @@ var init_diagMcp = __esm({
14180
14359
  const cacheDir = path34.join(home, ".cache", "ms-playwright");
14181
14360
  let entries = [];
14182
14361
  try {
14183
- entries = fs35.readdirSync(cacheDir);
14362
+ entries = fs36.readdirSync(cacheDir);
14184
14363
  } catch {
14185
14364
  }
14186
14365
  const hasChromium = entries.some((e) => e.startsWith("chromium"));
@@ -14208,13 +14387,13 @@ var init_diagMcp = __esm({
14208
14387
  });
14209
14388
 
14210
14389
  // src/scripts/frameworkDetectors.ts
14211
- import * as fs36 from "fs";
14390
+ import * as fs37 from "fs";
14212
14391
  import * as path35 from "path";
14213
14392
  function detectFrameworks(cwd) {
14214
14393
  const out = [];
14215
14394
  let deps = {};
14216
14395
  try {
14217
- const pkg = JSON.parse(fs36.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
14396
+ const pkg = JSON.parse(fs37.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
14218
14397
  deps = { ...pkg.dependencies, ...pkg.devDependencies };
14219
14398
  } catch {
14220
14399
  return out;
@@ -14251,7 +14430,7 @@ function detectFrameworks(cwd) {
14251
14430
  }
14252
14431
  function findFile(cwd, candidates) {
14253
14432
  for (const c of candidates) {
14254
- if (fs36.existsSync(path35.join(cwd, c))) return c;
14433
+ if (fs37.existsSync(path35.join(cwd, c))) return c;
14255
14434
  }
14256
14435
  return null;
14257
14436
  }
@@ -14259,17 +14438,17 @@ function discoverPayloadCollections(cwd) {
14259
14438
  const out = [];
14260
14439
  for (const dir of COLLECTION_DIRS) {
14261
14440
  const full = path35.join(cwd, dir);
14262
- if (!fs36.existsSync(full)) continue;
14441
+ if (!fs37.existsSync(full)) continue;
14263
14442
  let files;
14264
14443
  try {
14265
- files = fs36.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
14444
+ files = fs37.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
14266
14445
  } catch {
14267
14446
  continue;
14268
14447
  }
14269
14448
  for (const file of files) {
14270
14449
  try {
14271
14450
  const filePath = path35.join(full, file);
14272
- const content = fs36.readFileSync(filePath, "utf-8").slice(0, 1e4);
14451
+ const content = fs37.readFileSync(filePath, "utf-8").slice(0, 1e4);
14273
14452
  const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
14274
14453
  if (!slugMatch) continue;
14275
14454
  const slug = slugMatch[1];
@@ -14297,10 +14476,10 @@ function discoverAdminComponents(cwd, collections) {
14297
14476
  const out = [];
14298
14477
  for (const dir of ADMIN_COMPONENT_DIRS) {
14299
14478
  const full = path35.join(cwd, dir);
14300
- if (!fs36.existsSync(full)) continue;
14479
+ if (!fs37.existsSync(full)) continue;
14301
14480
  let entries;
14302
14481
  try {
14303
- entries = fs36.readdirSync(full, { withFileTypes: true });
14482
+ entries = fs37.readdirSync(full, { withFileTypes: true });
14304
14483
  } catch {
14305
14484
  continue;
14306
14485
  }
@@ -14310,7 +14489,7 @@ function discoverAdminComponents(cwd, collections) {
14310
14489
  let filePath;
14311
14490
  if (entry.isDirectory()) {
14312
14491
  const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
14313
- (f) => fs36.existsSync(path35.join(entryPath, f))
14492
+ (f) => fs37.existsSync(path35.join(entryPath, f))
14314
14493
  );
14315
14494
  if (!indexFile) continue;
14316
14495
  name = entry.name;
@@ -14325,7 +14504,7 @@ function discoverAdminComponents(cwd, collections) {
14325
14504
  if (collections) {
14326
14505
  for (const col of collections) {
14327
14506
  try {
14328
- const colContent = fs36.readFileSync(path35.join(cwd, col.filePath), "utf-8");
14507
+ const colContent = fs37.readFileSync(path35.join(cwd, col.filePath), "utf-8");
14329
14508
  if (colContent.includes(name)) {
14330
14509
  usedInCollection = col.slug;
14331
14510
  break;
@@ -14344,7 +14523,7 @@ function scanApiRoutes(cwd) {
14344
14523
  const appDirs = ["src/app", "app"];
14345
14524
  for (const appDir of appDirs) {
14346
14525
  const apiDir = path35.join(cwd, appDir, "api");
14347
- if (!fs36.existsSync(apiDir)) continue;
14526
+ if (!fs37.existsSync(apiDir)) continue;
14348
14527
  walkApiRoutes(apiDir, "/api", cwd, out);
14349
14528
  break;
14350
14529
  }
@@ -14353,14 +14532,14 @@ function scanApiRoutes(cwd) {
14353
14532
  function walkApiRoutes(dir, prefix, cwd, out) {
14354
14533
  let entries;
14355
14534
  try {
14356
- entries = fs36.readdirSync(dir, { withFileTypes: true });
14535
+ entries = fs37.readdirSync(dir, { withFileTypes: true });
14357
14536
  } catch {
14358
14537
  return;
14359
14538
  }
14360
14539
  const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
14361
14540
  if (routeFile) {
14362
14541
  try {
14363
- const content = fs36.readFileSync(path35.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
14542
+ const content = fs37.readFileSync(path35.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
14364
14543
  const methods = HTTP_METHODS.filter(
14365
14544
  (m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
14366
14545
  );
@@ -14394,9 +14573,9 @@ function scanEnvVars(cwd) {
14394
14573
  const candidates = [".env.example", ".env.local.example", ".env.template"];
14395
14574
  for (const envFile of candidates) {
14396
14575
  const envPath = path35.join(cwd, envFile);
14397
- if (!fs36.existsSync(envPath)) continue;
14576
+ if (!fs37.existsSync(envPath)) continue;
14398
14577
  try {
14399
- const content = fs36.readFileSync(envPath, "utf-8");
14578
+ const content = fs37.readFileSync(envPath, "utf-8");
14400
14579
  const vars = [];
14401
14580
  for (const line of content.split("\n")) {
14402
14581
  const trimmed = line.trim();
@@ -14441,7 +14620,7 @@ var init_frameworkDetectors = __esm({
14441
14620
  });
14442
14621
 
14443
14622
  // src/scripts/discoverQaContext.ts
14444
- import * as fs37 from "fs";
14623
+ import * as fs38 from "fs";
14445
14624
  import * as path36 from "path";
14446
14625
  function runQaDiscovery(cwd) {
14447
14626
  const out = {
@@ -14473,9 +14652,9 @@ function runQaDiscovery(cwd) {
14473
14652
  }
14474
14653
  function detectDevServer(cwd, out) {
14475
14654
  try {
14476
- const pkg = JSON.parse(fs37.readFileSync(path36.join(cwd, "package.json"), "utf-8"));
14655
+ const pkg = JSON.parse(fs38.readFileSync(path36.join(cwd, "package.json"), "utf-8"));
14477
14656
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
14478
- const pm = fs37.existsSync(path36.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs37.existsSync(path36.join(cwd, "yarn.lock")) ? "yarn" : fs37.existsSync(path36.join(cwd, "bun.lockb")) ? "bun" : "npm";
14657
+ const pm = fs38.existsSync(path36.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs38.existsSync(path36.join(cwd, "yarn.lock")) ? "yarn" : fs38.existsSync(path36.join(cwd, "bun.lockb")) ? "bun" : "npm";
14479
14658
  if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
14480
14659
  if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
14481
14660
  else if (allDeps.vite) out.devPort = 5173;
@@ -14486,7 +14665,7 @@ function scanFrontendRoutes(cwd, out) {
14486
14665
  const appDirs = ["src/app", "app"];
14487
14666
  for (const appDir of appDirs) {
14488
14667
  const full = path36.join(cwd, appDir);
14489
- if (!fs37.existsSync(full)) continue;
14668
+ if (!fs38.existsSync(full)) continue;
14490
14669
  walkFrontendRoutes(full, "", out);
14491
14670
  break;
14492
14671
  }
@@ -14494,7 +14673,7 @@ function scanFrontendRoutes(cwd, out) {
14494
14673
  function walkFrontendRoutes(dir, prefix, out) {
14495
14674
  let entries;
14496
14675
  try {
14497
- entries = fs37.readdirSync(dir, { withFileTypes: true });
14676
+ entries = fs38.readdirSync(dir, { withFileTypes: true });
14498
14677
  } catch {
14499
14678
  return;
14500
14679
  }
@@ -14536,23 +14715,23 @@ function detectAuthFiles(cwd, out) {
14536
14715
  "src/app/api/oauth"
14537
14716
  ];
14538
14717
  for (const c of candidates) {
14539
- if (fs37.existsSync(path36.join(cwd, c))) out.authFiles.push(c);
14718
+ if (fs38.existsSync(path36.join(cwd, c))) out.authFiles.push(c);
14540
14719
  }
14541
14720
  }
14542
14721
  function detectRoles(cwd, out) {
14543
14722
  const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
14544
14723
  for (const rp of rolePaths) {
14545
14724
  const dir = path36.join(cwd, rp);
14546
- if (!fs37.existsSync(dir)) continue;
14725
+ if (!fs38.existsSync(dir)) continue;
14547
14726
  let files;
14548
14727
  try {
14549
- files = fs37.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
14728
+ files = fs38.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
14550
14729
  } catch {
14551
14730
  continue;
14552
14731
  }
14553
14732
  for (const f of files) {
14554
14733
  try {
14555
- const content = fs37.readFileSync(path36.join(dir, f), "utf-8").slice(0, 5e3);
14734
+ const content = fs38.readFileSync(path36.join(dir, f), "utf-8").slice(0, 5e3);
14556
14735
  const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
14557
14736
  if (roleMatches) {
14558
14737
  for (const m of roleMatches) {
@@ -14813,7 +14992,7 @@ var init_dispatchClassified = __esm({
14813
14992
  });
14814
14993
 
14815
14994
  // src/loopDefinitions.ts
14816
- import * as fs38 from "fs";
14995
+ import * as fs39 from "fs";
14817
14996
  import * as path37 from "path";
14818
14997
  function normalizeLoopDefinition(value) {
14819
14998
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -14842,9 +15021,9 @@ function readLoopDefinition(cwd, id) {
14842
15021
  const roots = loopRoots(cwd);
14843
15022
  for (const root of roots) {
14844
15023
  const filePath = path37.join(root, "loops", id, "loop.json");
14845
- if (!fs38.existsSync(filePath)) continue;
15024
+ if (!fs39.existsSync(filePath)) continue;
14846
15025
  try {
14847
- const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
15026
+ const loop = normalizeLoopDefinition(JSON.parse(fs39.readFileSync(filePath, "utf8")));
14848
15027
  if (loop?.id === id) return loop;
14849
15028
  process.stderr.write(`[kody] invalid Loop definition: ${filePath}
14850
15029
  `);
@@ -14864,13 +15043,13 @@ function listLoopDefinitions(cwd) {
14864
15043
  const byId = /* @__PURE__ */ new Map();
14865
15044
  for (const root of roots.reverse()) {
14866
15045
  const loopsDir = path37.join(root, "loops");
14867
- if (!fs38.existsSync(loopsDir)) continue;
14868
- for (const id of fs38.readdirSync(loopsDir).sort()) {
15046
+ if (!fs39.existsSync(loopsDir)) continue;
15047
+ for (const id of fs39.readdirSync(loopsDir).sort()) {
14869
15048
  if (!ID.test(id)) continue;
14870
15049
  const filePath = path37.join(loopsDir, id, "loop.json");
14871
- if (!fs38.existsSync(filePath)) continue;
15050
+ if (!fs39.existsSync(filePath)) continue;
14872
15051
  try {
14873
- const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
15052
+ const loop = normalizeLoopDefinition(JSON.parse(fs39.readFileSync(filePath, "utf8")));
14874
15053
  if (loop?.id === id) byId.set(id, loop);
14875
15054
  } catch {
14876
15055
  process.stderr.write(`[kody] unreadable Loop definition: ${filePath}
@@ -16235,15 +16414,15 @@ var init_fixFlow = __esm({
16235
16414
  });
16236
16415
 
16237
16416
  // src/workflow-template.ts
16238
- import * as fs39 from "fs";
16417
+ import * as fs40 from "fs";
16239
16418
  import * as path38 from "path";
16240
16419
  import { fileURLToPath } from "url";
16241
16420
  function loadKodyWorkflowTemplate() {
16242
16421
  const here = path38.dirname(fileURLToPath(import.meta.url));
16243
16422
  const candidates = [path38.resolve(here, "../templates/kody.yml"), path38.resolve(here, "../../templates/kody.yml")];
16244
- const source = candidates.find((candidate) => fs39.existsSync(candidate));
16423
+ const source = candidates.find((candidate) => fs40.existsSync(candidate));
16245
16424
  if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
16246
- return fs39.readFileSync(source, "utf8");
16425
+ return fs40.readFileSync(source, "utf8");
16247
16426
  }
16248
16427
  var KODY_WORKFLOW_TEMPLATE_PATH;
16249
16428
  var init_workflow_template = __esm({
@@ -16255,7 +16434,7 @@ var init_workflow_template = __esm({
16255
16434
 
16256
16435
  // src/scripts/initFlow.ts
16257
16436
  import { execFileSync as execFileSync14 } from "child_process";
16258
- import * as fs40 from "fs";
16437
+ import * as fs41 from "fs";
16259
16438
  import * as path39 from "path";
16260
16439
  function schemaUrlFromPkg() {
16261
16440
  const fallback = "https://raw.githubusercontent.com/aharonyaircohen/kody-engine/main/kody.config.schema.json";
@@ -16321,21 +16500,21 @@ function performInit(cwd, force, workflowOnly = false) {
16321
16500
  const configPath = path39.join(cwd, "kody.config.json");
16322
16501
  if (workflowOnly) {
16323
16502
  skipped.push("kody.config.json");
16324
- } else if (fs40.existsSync(configPath) && !force) {
16503
+ } else if (fs41.existsSync(configPath) && !force) {
16325
16504
  skipped.push("kody.config.json");
16326
16505
  } else {
16327
16506
  const cfg = makeConfig(cwd, ownerRepo, defaultBranch);
16328
- fs40.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
16507
+ fs41.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
16329
16508
  `);
16330
16509
  wrote.push("kody.config.json");
16331
16510
  }
16332
16511
  const workflowDir = path39.join(cwd, ".github", "workflows");
16333
16512
  const workflowPath = path39.join(workflowDir, "kody.yml");
16334
- if (fs40.existsSync(workflowPath) && !force) {
16513
+ if (fs41.existsSync(workflowPath) && !force) {
16335
16514
  skipped.push(".github/workflows/kody.yml");
16336
16515
  } else {
16337
- fs40.mkdirSync(workflowDir, { recursive: true });
16338
- fs40.writeFileSync(workflowPath, loadKodyWorkflowTemplate());
16516
+ fs41.mkdirSync(workflowDir, { recursive: true });
16517
+ fs41.writeFileSync(workflowPath, loadKodyWorkflowTemplate());
16339
16518
  wrote.push(".github/workflows/kody.yml");
16340
16519
  }
16341
16520
  let labels;
@@ -16388,7 +16567,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
16388
16567
  });
16389
16568
 
16390
16569
  // src/scripts/loadAgentAdhoc.ts
16391
- import * as fs41 from "fs";
16570
+ import * as fs42 from "fs";
16392
16571
  function resolveMessage(messageArg) {
16393
16572
  const fromComment = readCommentBody();
16394
16573
  if (fromComment) return stripDirective(fromComment);
@@ -16396,9 +16575,9 @@ function resolveMessage(messageArg) {
16396
16575
  }
16397
16576
  function readCommentBody() {
16398
16577
  const eventPath = process.env.GITHUB_EVENT_PATH;
16399
- if (!eventPath || !fs41.existsSync(eventPath)) return "";
16578
+ if (!eventPath || !fs42.existsSync(eventPath)) return "";
16400
16579
  try {
16401
- const event = JSON.parse(fs41.readFileSync(eventPath, "utf-8"));
16580
+ const event = JSON.parse(fs42.readFileSync(eventPath, "utf-8"));
16402
16581
  return String(event.comment?.body ?? "");
16403
16582
  } catch {
16404
16583
  return "";
@@ -16452,10 +16631,10 @@ var init_loadAgentAdhoc = __esm({
16452
16631
  throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
16453
16632
  }
16454
16633
  const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
16455
- if (!fs41.existsSync(agentPath)) {
16634
+ if (!fs42.existsSync(agentPath)) {
16456
16635
  throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
16457
16636
  }
16458
- const { title, body } = parseAgentFile(fs41.readFileSync(agentPath, "utf-8"), agentSlug);
16637
+ const { title, body } = parseAgentFile(fs42.readFileSync(agentPath, "utf-8"), agentSlug);
16459
16638
  const message = resolveMessage(ctx.args.message);
16460
16639
  if (!message) {
16461
16640
  throw new Error(
@@ -16824,7 +17003,7 @@ var init_loadIssueStateComment = __esm({
16824
17003
  });
16825
17004
 
16826
17005
  // src/scripts/loadJobFromFile.ts
16827
- import * as fs42 from "fs";
17006
+ import * as fs43 from "fs";
16828
17007
  import * as path40 from "path";
16829
17008
  function parseJobFile(raw, slug) {
16830
17009
  let stripped = raw;
@@ -16877,12 +17056,12 @@ var init_loadJobFromFile = __esm({
16877
17056
  let agentIdentity = "";
16878
17057
  if (agentSlug) {
16879
17058
  const agentPath = resolveAgentFile2(ctx.cwd, agentSlug, agentsDir);
16880
- if (!fs42.existsSync(agentPath)) {
17059
+ if (!fs43.existsSync(agentPath)) {
16881
17060
  throw new Error(
16882
17061
  `loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
16883
17062
  );
16884
17063
  }
16885
- const agentRaw = fs42.readFileSync(agentPath, "utf-8");
17064
+ const agentRaw = fs43.readFileSync(agentPath, "utf-8");
16886
17065
  const parsed = parseJobFile(agentRaw, agentSlug);
16887
17066
  agentTitle = parsed.title;
16888
17067
  agentIdentity = parsed.body;
@@ -16962,7 +17141,7 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
16962
17141
  });
16963
17142
 
16964
17143
  // src/scripts/loadLiveAgent.ts
16965
- import * as fs43 from "fs";
17144
+ import * as fs44 from "fs";
16966
17145
  function tenant(config) {
16967
17146
  const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY ?? "").split("/");
16968
17147
  const owner = config.github?.owner?.trim() || envOwner;
@@ -17005,7 +17184,7 @@ var init_loadLiveAgent = __esm({
17005
17184
  const agent = String(ctx.args.agent ?? ctx.data.jobAgent ?? "").trim();
17006
17185
  if (!agent) throw new Error("loadLiveAgent: agent is required");
17007
17186
  const file = resolveAgentFile2(ctx.cwd, agent, agentsRoot(ctx.cwd));
17008
- const raw = fs43.existsSync(file) ? fs43.readFileSync(file, "utf8") : "";
17187
+ const raw = fs44.existsSync(file) ? fs44.readFileSync(file, "utf8") : "";
17009
17188
  const metadata = frontmatter(raw);
17010
17189
  const assignedIntent = typeof metadata.primaryIntent === "string" ? metadata.primaryIntent : "";
17011
17190
  const requestedIntent = String(ctx.args.intent ?? "").trim();
@@ -17053,13 +17232,13 @@ var init_loadLiveAgent = __esm({
17053
17232
  });
17054
17233
 
17055
17234
  // src/scripts/kodyVariables.ts
17056
- import * as fs44 from "fs";
17235
+ import * as fs45 from "fs";
17057
17236
  import * as path41 from "path";
17058
17237
  function readKodyVariables(cwd) {
17059
17238
  const full = path41.join(cwd, KODY_VARIABLES_REL_PATH);
17060
17239
  let raw;
17061
17240
  try {
17062
- raw = fs44.readFileSync(full, "utf-8");
17241
+ raw = fs45.readFileSync(full, "utf-8");
17063
17242
  } catch {
17064
17243
  return {};
17065
17244
  }
@@ -17084,7 +17263,7 @@ var init_kodyVariables = __esm({
17084
17263
  });
17085
17264
 
17086
17265
  // src/scripts/loadQaContext.ts
17087
- import * as fs45 from "fs";
17266
+ import * as fs46 from "fs";
17088
17267
  import * as path42 from "path";
17089
17268
  function parseSlugList(value) {
17090
17269
  const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
@@ -17115,17 +17294,17 @@ function readProfileAgents(raw) {
17115
17294
  }
17116
17295
  function readProfile(cwd) {
17117
17296
  const dir = path42.join(cwd, CONTEXT_DIR_REL_PATH);
17118
- if (!fs45.existsSync(dir)) return "";
17297
+ if (!fs46.existsSync(dir)) return "";
17119
17298
  let entries;
17120
17299
  try {
17121
- entries = fs45.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
17300
+ entries = fs46.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
17122
17301
  } catch {
17123
17302
  return "";
17124
17303
  }
17125
17304
  const blocks = [];
17126
17305
  for (const file of entries) {
17127
17306
  try {
17128
- const raw = fs45.readFileSync(path42.join(dir, file), "utf-8");
17307
+ const raw = fs46.readFileSync(path42.join(dir, file), "utf-8");
17129
17308
  const { agent, body } = readProfileAgents(raw);
17130
17309
  if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
17131
17310
  blocks.push(`## ${file}
@@ -17175,7 +17354,7 @@ var init_loadQaContext = __esm({
17175
17354
 
17176
17355
  // src/scripts/loadSimpleCapability.ts
17177
17356
  import { randomUUID as randomUUID2 } from "crypto";
17178
- import * as fs46 from "fs";
17357
+ import * as fs47 from "fs";
17179
17358
  import * as os6 from "os";
17180
17359
  import * as path43 from "path";
17181
17360
  function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
@@ -17190,7 +17369,7 @@ function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
17190
17369
  profile.subagentTemplates = {
17191
17370
  ...profile.subagentTemplates ?? {},
17192
17371
  ...Object.fromEntries(
17193
- subagentFiles.map(({ name, file }) => [name, fs46.readFileSync(path43.join(toolRoot, file), "utf-8")])
17372
+ subagentFiles.map(({ name, file }) => [name, fs47.readFileSync(path43.join(toolRoot, file), "utf-8")])
17194
17373
  )
17195
17374
  };
17196
17375
  if (!profile.claudeCode.tools.includes("Agent")) {
@@ -17231,10 +17410,10 @@ function scalar(value) {
17231
17410
  return value;
17232
17411
  }
17233
17412
  function listFiles(root) {
17234
- if (!fs46.existsSync(root)) return [];
17413
+ if (!fs47.existsSync(root)) return [];
17235
17414
  const files = [];
17236
17415
  const visit = (dir) => {
17237
- for (const entry of fs46.readdirSync(dir, { withFileTypes: true })) {
17416
+ for (const entry of fs47.readdirSync(dir, { withFileTypes: true })) {
17238
17417
  const absolute = path43.join(dir, entry.name);
17239
17418
  if (entry.isSymbolicLink()) continue;
17240
17419
  if (entry.isDirectory()) visit(absolute);
@@ -17327,7 +17506,7 @@ var init_loadSimpleCapability = __esm({
17327
17506
  ...skillFiles.flatMap((file) => [
17328
17507
  `### ${file}`,
17329
17508
  "",
17330
- fs46.readFileSync(path43.join(skillRoot, file), "utf-8"),
17509
+ fs47.readFileSync(path43.join(skillRoot, file), "utf-8"),
17331
17510
  ""
17332
17511
  ])
17333
17512
  ] : [],
@@ -17367,7 +17546,7 @@ var init_loadSimpleCapability = __esm({
17367
17546
  });
17368
17547
 
17369
17548
  // src/taskContext.ts
17370
- import * as fs47 from "fs";
17549
+ import * as fs48 from "fs";
17371
17550
  import * as path44 from "path";
17372
17551
  function buildTaskContext(args) {
17373
17552
  return {
@@ -17384,9 +17563,9 @@ function buildTaskContext(args) {
17384
17563
  function persistTaskContext(cwd, ctx) {
17385
17564
  try {
17386
17565
  const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
17387
- fs47.mkdirSync(dir, { recursive: true });
17566
+ fs48.mkdirSync(dir, { recursive: true });
17388
17567
  const file = path44.join(dir, "task-context.json");
17389
- fs47.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
17568
+ fs48.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
17390
17569
  `);
17391
17570
  return file;
17392
17571
  } catch (err) {
@@ -18309,7 +18488,7 @@ var init_parseReproOutput = __esm({
18309
18488
  });
18310
18489
 
18311
18490
  // src/scripts/parseSimpleCapabilityOutput.ts
18312
- import * as fs48 from "fs";
18491
+ import * as fs49 from "fs";
18313
18492
  function acceptAuthoritativeCapabilityOutput(ctx, profile, output) {
18314
18493
  ctx.data.agentDone = true;
18315
18494
  delete ctx.data.agentFailureReason;
@@ -18326,11 +18505,11 @@ function stringList2(value) {
18326
18505
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
18327
18506
  }
18328
18507
  function readOutputFile(outputPath) {
18329
- if (!outputPath || !fs48.existsSync(outputPath)) return { found: false };
18508
+ if (!outputPath || !fs49.existsSync(outputPath)) return { found: false };
18330
18509
  try {
18331
- return { found: true, value: JSON.parse(fs48.readFileSync(outputPath, "utf-8")) };
18510
+ return { found: true, value: JSON.parse(fs49.readFileSync(outputPath, "utf-8")) };
18332
18511
  } finally {
18333
- fs48.rmSync(outputPath, { force: true });
18512
+ fs49.rmSync(outputPath, { force: true });
18334
18513
  }
18335
18514
  }
18336
18515
  function parseOutput(text2) {
@@ -18992,7 +19171,7 @@ var init_postResearchComment = __esm({
18992
19171
  });
18993
19172
 
18994
19173
  // src/scripts/prepareBrowserAuth.ts
18995
- import * as fs49 from "fs";
19174
+ import * as fs50 from "fs";
18996
19175
  import * as os7 from "os";
18997
19176
  import * as path45 from "path";
18998
19177
  function appendAuthMessage(ctx, message) {
@@ -19038,8 +19217,8 @@ async function githubJson(url, token, checkName) {
19038
19217
  throw new Error(`GitHub ${checkName} check failed`);
19039
19218
  }
19040
19219
  function writeKodyStorageState(input) {
19041
- const directory = fs49.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
19042
- fs49.chmodSync(directory, 448);
19220
+ const directory = fs50.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
19221
+ fs50.chmodSync(directory, 448);
19043
19222
  const file = path45.join(directory, "storage-state.json");
19044
19223
  const now = Date.now();
19045
19224
  const repoEntry = {
@@ -19071,7 +19250,7 @@ function writeKodyStorageState(input) {
19071
19250
  }
19072
19251
  ]
19073
19252
  };
19074
- fs49.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
19253
+ fs50.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
19075
19254
  return { directory, file, auth };
19076
19255
  }
19077
19256
  function parseSetCookie(value, hostname) {
@@ -19098,10 +19277,10 @@ function parseSetCookie(value, hostname) {
19098
19277
  }
19099
19278
  function writeCookieStorageState(targetUrl, setCookies) {
19100
19279
  const target = new URL(targetUrl);
19101
- const directory = fs49.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
19102
- fs49.chmodSync(directory, 448);
19280
+ const directory = fs50.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
19281
+ fs50.chmodSync(directory, 448);
19103
19282
  const file = path45.join(directory, "storage-state.json");
19104
- fs49.writeFileSync(
19283
+ fs50.writeFileSync(
19105
19284
  file,
19106
19285
  JSON.stringify({
19107
19286
  cookies: setCookies.map((cookie) => parseSetCookie(cookie, target.hostname)),
@@ -19122,9 +19301,9 @@ function currentStorageStatePath(args) {
19122
19301
  function browserSessionCookieHeader(profile, targetUrl) {
19123
19302
  const playwright = profile.claudeCode.mcpServers.find((server) => server.name === "playwright");
19124
19303
  const storagePath = currentStorageStatePath(playwright?.args ?? []);
19125
- if (!storagePath || !fs49.existsSync(storagePath)) return void 0;
19304
+ if (!storagePath || !fs50.existsSync(storagePath)) return void 0;
19126
19305
  const hostname = new URL(targetUrl).hostname;
19127
- const state = JSON.parse(fs49.readFileSync(storagePath, "utf-8"));
19306
+ const state = JSON.parse(fs50.readFileSync(storagePath, "utf-8"));
19128
19307
  const cookies = (state.cookies ?? []).filter((cookie) => {
19129
19308
  const domain = cookie.domain.replace(/^\./, "");
19130
19309
  return hostname === domain || hostname.endsWith(`.${domain}`);
@@ -19191,9 +19370,9 @@ async function prepareAccountModelSettings(ctx, profile, input) {
19191
19370
  return true;
19192
19371
  }
19193
19372
  function mergeStorageStates(existingPath, nextPath) {
19194
- if (existingPath === nextPath || !fs49.existsSync(existingPath)) return;
19195
- const existing = JSON.parse(fs49.readFileSync(existingPath, "utf-8"));
19196
- const next = JSON.parse(fs49.readFileSync(nextPath, "utf-8"));
19373
+ if (existingPath === nextPath || !fs50.existsSync(existingPath)) return;
19374
+ const existing = JSON.parse(fs50.readFileSync(existingPath, "utf-8"));
19375
+ const next = JSON.parse(fs50.readFileSync(nextPath, "utf-8"));
19197
19376
  const cookies = /* @__PURE__ */ new Map();
19198
19377
  for (const cookie of [...existing.cookies ?? [], ...next.cookies ?? []]) {
19199
19378
  cookies.set(`${cookie.name}\0${cookie.domain}\0${cookie.path}`, cookie);
@@ -19207,7 +19386,7 @@ function mergeStorageStates(existingPath, nextPath) {
19207
19386
  }
19208
19387
  origins.set(entry.origin, { origin: entry.origin, localStorage: [...localStorage.values()] });
19209
19388
  }
19210
- fs49.writeFileSync(nextPath, JSON.stringify({ cookies: [...cookies.values()], origins: [...origins.values()] }), {
19389
+ fs50.writeFileSync(nextPath, JSON.stringify({ cookies: [...cookies.values()], origins: [...origins.values()] }), {
19211
19390
  mode: 384
19212
19391
  });
19213
19392
  }
@@ -19302,7 +19481,7 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
19302
19481
  configurePlaywright(profile, state.file);
19303
19482
  const authDirectory = state.directory;
19304
19483
  registerRuntimeCleanup(ctx, () => {
19305
- fs49.rmSync(authDirectory, { recursive: true, force: true });
19484
+ fs50.rmSync(authDirectory, { recursive: true, force: true });
19306
19485
  });
19307
19486
  appendAuthMessage(
19308
19487
  ctx,
@@ -19310,7 +19489,7 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
19310
19489
  );
19311
19490
  return true;
19312
19491
  } catch (error) {
19313
- if (state) fs49.rmSync(state.directory, { recursive: true, force: true });
19492
+ if (state) fs50.rmSync(state.directory, { recursive: true, force: true });
19314
19493
  const reason = error instanceof Error ? error.message : String(error);
19315
19494
  appendAuthMessage(
19316
19495
  ctx,
@@ -19337,11 +19516,11 @@ async function prepareEmailPasswordBrowserAuth(ctx, profile, input) {
19337
19516
  state = writeCookieStorageState(input.targetUrl, cookies);
19338
19517
  configurePlaywright(profile, state.file);
19339
19518
  const authDirectory = state.directory;
19340
- registerRuntimeCleanup(ctx, () => fs49.rmSync(authDirectory, { recursive: true, force: true }));
19519
+ registerRuntimeCleanup(ctx, () => fs50.rmSync(authDirectory, { recursive: true, force: true }));
19341
19520
  ctx.data.qaAuthBlock = "Auth: the app is already signed in through an engine-provided browser session. The login credentials are not available to you; never request, reveal, or report them.";
19342
19521
  return true;
19343
19522
  } catch (error) {
19344
- if (state) fs49.rmSync(state.directory, { recursive: true, force: true });
19523
+ if (state) fs50.rmSync(state.directory, { recursive: true, force: true });
19345
19524
  const reason = error instanceof Error ? error.message : String(error);
19346
19525
  ctx.data.qaAuthBlock = `Auth: the engine could not prepare the app login (${reason}). Note this authenticated surface as a gap.`;
19347
19526
  return false;
@@ -21308,7 +21487,7 @@ var init_tickShellRunner = __esm({
21308
21487
  });
21309
21488
 
21310
21489
  // src/scripts/runScheduledImplementationTick.ts
21311
- import * as fs50 from "fs";
21490
+ import * as fs51 from "fs";
21312
21491
  import * as path48 from "path";
21313
21492
  var runScheduledImplementationTick;
21314
21493
  var init_runScheduledImplementationTick = __esm({
@@ -21337,7 +21516,7 @@ var init_runScheduledImplementationTick = __esm({
21337
21516
  return;
21338
21517
  }
21339
21518
  const shellPath = path48.join(profile.dir, shell);
21340
- if (!fs50.existsSync(shellPath)) {
21519
+ if (!fs51.existsSync(shellPath)) {
21341
21520
  ctx.output.exitCode = 99;
21342
21521
  ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
21343
21522
  return;
@@ -21396,13 +21575,13 @@ var init_runtimeConnections = __esm({
21396
21575
 
21397
21576
  // src/scripts/runSimpleCapabilityScript.ts
21398
21577
  import { spawnSync as spawnSync3 } from "child_process";
21399
- import * as fs51 from "fs";
21578
+ import * as fs52 from "fs";
21400
21579
  function formatDuration2(timeoutMs) {
21401
21580
  return timeoutMs % 6e4 === 0 ? `${timeoutMs / 6e4} minutes` : `${timeoutMs}ms`;
21402
21581
  }
21403
21582
  function isRegularFile2(filePath) {
21404
21583
  try {
21405
- const stat = fs51.lstatSync(filePath);
21584
+ const stat = fs52.lstatSync(filePath);
21406
21585
  return stat.isFile() && !stat.isSymbolicLink();
21407
21586
  } catch {
21408
21587
  return false;
@@ -21494,7 +21673,7 @@ var init_runSimpleCapabilityScript = __esm({
21494
21673
  });
21495
21674
 
21496
21675
  // src/scripts/runTickScript.ts
21497
- import * as fs52 from "fs";
21676
+ import * as fs53 from "fs";
21498
21677
  import * as path49 from "path";
21499
21678
  var runTickScript;
21500
21679
  var init_runTickScript = __esm({
@@ -21528,7 +21707,7 @@ var init_runTickScript = __esm({
21528
21707
  return;
21529
21708
  }
21530
21709
  const scriptPath = path49.isAbsolute(tickScript) ? tickScript : path49.join(ctx.cwd, tickScript);
21531
- if (!fs52.existsSync(scriptPath)) {
21710
+ if (!fs53.existsSync(scriptPath)) {
21532
21711
  ctx.output.exitCode = 99;
21533
21712
  ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
21534
21713
  return;
@@ -22735,7 +22914,7 @@ var init_warmupMcp = __esm({
22735
22914
  });
22736
22915
 
22737
22916
  // src/scripts/writeAgentRunSummary.ts
22738
- import * as fs53 from "fs";
22917
+ import * as fs54 from "fs";
22739
22918
  var writeAgentRunSummary;
22740
22919
  var init_writeAgentRunSummary = __esm({
22741
22920
  "src/scripts/writeAgentRunSummary.ts"() {
@@ -22761,7 +22940,7 @@ var init_writeAgentRunSummary = __esm({
22761
22940
  if (reason) lines.push(`- **Reason:** ${reason}`);
22762
22941
  lines.push("");
22763
22942
  try {
22764
- fs53.appendFileSync(summaryPath, `${lines.join("\n")}
22943
+ fs54.appendFileSync(summaryPath, `${lines.join("\n")}
22765
22944
  `);
22766
22945
  } catch {
22767
22946
  }
@@ -23103,7 +23282,7 @@ var init_scripts = __esm({
23103
23282
  });
23104
23283
 
23105
23284
  // src/stateWorkspace.ts
23106
- import * as fs54 from "fs";
23285
+ import * as fs55 from "fs";
23107
23286
  import * as path51 from "path";
23108
23287
  function tenantId(config) {
23109
23288
  const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
@@ -23112,8 +23291,8 @@ function tenantId(config) {
23112
23291
  }
23113
23292
  function writeRuntimeFile(cwd, relativePath, content) {
23114
23293
  const target = path51.join(cwd, RUNTIME_ROOT, relativePath);
23115
- fs54.mkdirSync(path51.dirname(target), { recursive: true });
23116
- fs54.writeFileSync(target, content, "utf8");
23294
+ fs55.mkdirSync(path51.dirname(target), { recursive: true });
23295
+ fs55.writeFileSync(target, content, "utf8");
23117
23296
  }
23118
23297
  function record(value) {
23119
23298
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -23182,7 +23361,7 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
23182
23361
  if (hydratedWorkspaces.has(key)) return;
23183
23362
  const backend = backendOverride ?? createStateBackendFromEnv();
23184
23363
  const root = path51.join(cwd, RUNTIME_ROOT);
23185
- fs54.rmSync(root, { recursive: true, force: true });
23364
+ fs55.rmSync(root, { recursive: true, force: true });
23186
23365
  await Promise.all([
23187
23366
  hydratePrefix(backend, tenant2, cwd, "context:"),
23188
23367
  hydratePrefix(backend, tenant2, cwd, "memory:"),
@@ -23269,7 +23448,7 @@ var init_tools = __esm({
23269
23448
 
23270
23449
  // src/executor.ts
23271
23450
  import { spawn as spawn8 } from "child_process";
23272
- import * as fs55 from "fs";
23451
+ import * as fs56 from "fs";
23273
23452
  import * as os8 from "os";
23274
23453
  import * as path52 from "path";
23275
23454
  function isMutatingPostflight(scriptName) {
@@ -23367,6 +23546,7 @@ async function runImplementation(profileName, input) {
23367
23546
  `);
23368
23547
  else if (out.exitCode !== 0 && out.reason) process.stdout.write(`PR_URL=FAILED: ${out.reason}
23369
23548
  `);
23549
+ publishRunUsage(`implementation:${profileName}`, out.usage);
23370
23550
  return out;
23371
23551
  };
23372
23552
  const resolved = loadRunnableProfile(profileName, input.cwd);
@@ -23490,14 +23670,16 @@ async function runImplementation(profileName, input) {
23490
23670
  status,
23491
23671
  startedAt: runIndexStartedAt,
23492
23672
  updatedAt: finishedAt,
23493
- reason: out.reason
23673
+ reason: out.reason,
23674
+ usage: out.usage
23494
23675
  })
23495
23676
  );
23496
23677
  await finalizeStagedRunIndexRowsAsync(config, input.cwd, ctx.data, {
23497
23678
  status,
23498
23679
  updatedAt: finishedAt,
23499
23680
  reason: out.reason,
23500
- output: ctx.data.capabilityOutput
23681
+ output: ctx.data.capabilityOutput,
23682
+ usage: out.usage
23501
23683
  });
23502
23684
  };
23503
23685
  }
@@ -23725,10 +23907,12 @@ async function runImplementation(profileName, input) {
23725
23907
  reason: err instanceof Error ? err.message : String(err)
23726
23908
  });
23727
23909
  }
23728
- ctx.output.usage = {
23729
- tokens: agentResult.tokens ? agentResult.tokens.input + agentResult.tokens.output + agentResult.tokens.cacheRead + agentResult.tokens.cacheCreate : 0,
23730
- costUsd: agentResult.costUsd ?? 0
23731
- };
23910
+ ctx.output.usage = createRunUsage(agentResult.tokens, agentResult.costUsd, {
23911
+ model: `${model.provider}/${model.model}`,
23912
+ turns: agentResult.turns,
23913
+ modelUsage: agentResult.modelUsage,
23914
+ outcome: agentResult.outcome
23915
+ });
23732
23916
  emitEvent(input.cwd, {
23733
23917
  implementation: profileName,
23734
23918
  kind: "agent_end",
@@ -23850,7 +24034,8 @@ async function runImplementation(profileName, input) {
23850
24034
  } catch (error) {
23851
24035
  return finishAndEnd({
23852
24036
  exitCode: 99,
23853
- reason: error instanceof Error ? error.message : String(error)
24037
+ reason: error instanceof Error ? error.message : String(error),
24038
+ usage: ctx.output.usage
23854
24039
  });
23855
24040
  }
23856
24041
  }
@@ -23858,6 +24043,7 @@ async function runImplementation(profileName, input) {
23858
24043
  exitCode: ctx.output.exitCode ?? 0,
23859
24044
  prUrl: ctx.output.prUrl,
23860
24045
  reason: ctx.output.reason,
24046
+ usage: ctx.output.usage,
23861
24047
  action: ctx.data.action,
23862
24048
  nextDispatch: ctx.output.nextDispatch,
23863
24049
  nextJob: ctx.output.nextJob,
@@ -23868,7 +24054,7 @@ async function runImplementation(profileName, input) {
23868
24054
  });
23869
24055
  } catch (err) {
23870
24056
  const msg = err instanceof Error ? err.message : String(err);
23871
- return finishAndEnd({ exitCode: 99, reason: ctx.output.reason ?? msg });
24057
+ return finishAndEnd({ exitCode: 99, reason: ctx.output.reason ?? msg, usage: ctx.output.usage });
23872
24058
  } finally {
23873
24059
  runRuntimeCleanup(ctx);
23874
24060
  clearStampedLifecycleLabels(profile, ctx);
@@ -23921,6 +24107,8 @@ function lastIndexOfScript(entries, names) {
23921
24107
  }
23922
24108
  async function runImplementationChain(profileName, input) {
23923
24109
  let result = await runImplementation(profileName, input);
24110
+ let aggregateUsage = result.usage;
24111
+ let followedHandoff = false;
23924
24112
  let chainConfig = input.config;
23925
24113
  const configForHandoff = () => {
23926
24114
  if (chainConfig || input.skipConfig) return chainConfig;
@@ -23932,6 +24120,7 @@ async function runImplementationChain(profileName, input) {
23932
24120
  ...result.taskState ? { taskState: result.taskState } : {}
23933
24121
  };
23934
24122
  for (let hops = 1; (result.nextDispatch || result.nextJob) && hops <= MAX_CHAIN_HOPS; hops++) {
24123
+ followedHandoff = true;
23935
24124
  if (result.nextJob) {
23936
24125
  const next2 = result.nextJob;
23937
24126
  const after = result.afterNextJob;
@@ -23947,6 +24136,7 @@ async function runImplementationChain(profileName, input) {
23947
24136
  quiet: input.quiet,
23948
24137
  preloadedData: chainData
23949
24138
  });
24139
+ aggregateUsage = mergeRunUsage(aggregateUsage, childResult.usage);
23950
24140
  if (after && childResult.exitCode === 0 && !childResult.nextDispatch && !childResult.nextJob && !childResult.afterNextJob) {
23951
24141
  chainData = {
23952
24142
  ...chainData,
@@ -23972,6 +24162,7 @@ async function runImplementationChain(profileName, input) {
23972
24162
  quiet: input.quiet,
23973
24163
  preloadedData: chainData
23974
24164
  });
24165
+ aggregateUsage = mergeRunUsage(aggregateUsage, result.usage);
23975
24166
  chainData = {
23976
24167
  ...chainData,
23977
24168
  ...result.taskState ? { taskState: result.taskState } : {}
@@ -24006,6 +24197,7 @@ async function runImplementationChain(profileName, input) {
24006
24197
  quiet: input.quiet,
24007
24198
  preloadedData: chainData
24008
24199
  });
24200
+ aggregateUsage = mergeRunUsage(aggregateUsage, result.usage);
24009
24201
  chainData = {
24010
24202
  ...chainData,
24011
24203
  ...result.taskState ? { taskState: result.taskState } : {}
@@ -24016,7 +24208,9 @@ async function runImplementationChain(profileName, input) {
24016
24208
  process.stderr.write(`[kody] in-process hand-off cap (${MAX_CHAIN_HOPS}) reached; not running ${pending}
24017
24209
  `);
24018
24210
  }
24019
- return result;
24211
+ const output = aggregateUsage ? { ...result, usage: aggregateUsage } : result;
24212
+ if (followedHandoff) publishRunUsage(`chain:${profileName}`, output.usage);
24213
+ return output;
24020
24214
  }
24021
24215
  function handoffToJob(handoff) {
24022
24216
  const capabilityOrAction = handoff.workflow ?? handoff.action ?? handoff.capability;
@@ -24063,7 +24257,7 @@ function resolveProfilePath(profileName, cwd = process.cwd()) {
24063
24257
  // fallback
24064
24258
  ];
24065
24259
  for (const c of candidates) {
24066
- if (fs55.existsSync(c)) return c;
24260
+ if (fs56.existsSync(c)) return c;
24067
24261
  }
24068
24262
  return candidates[0];
24069
24263
  }
@@ -24179,7 +24373,7 @@ function resolveShellTimeoutMs(entry) {
24179
24373
  async function runShellEntry(entry, ctx, profile) {
24180
24374
  const shellName = entry.shell;
24181
24375
  const shellPath = path52.join(profile.dir, shellName);
24182
- if (!fs55.existsSync(shellPath)) {
24376
+ if (!fs56.existsSync(shellPath)) {
24183
24377
  ctx.skipAgent = true;
24184
24378
  ctx.output.exitCode = 99;
24185
24379
  ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
@@ -24253,9 +24447,9 @@ async function runShellEntry(entry, ctx, profile) {
24253
24447
  }
24254
24448
  let sideChannelText = "";
24255
24449
  try {
24256
- if (fs55.existsSync(outputFile)) {
24257
- sideChannelText = fs55.readFileSync(outputFile, "utf-8");
24258
- fs55.rmSync(outputFile, { force: true });
24450
+ if (fs56.existsSync(outputFile)) {
24451
+ sideChannelText = fs56.readFileSync(outputFile, "utf-8");
24452
+ fs56.rmSync(outputFile, { force: true });
24259
24453
  }
24260
24454
  } catch {
24261
24455
  }
@@ -24321,6 +24515,7 @@ var init_executor = __esm({
24321
24515
  init_subagents();
24322
24516
  init_task_artifacts();
24323
24517
  init_tools();
24518
+ init_usage();
24324
24519
  MUTATING_POSTFLIGHTS = /* @__PURE__ */ new Set([
24325
24520
  "commitAndPush",
24326
24521
  "ensurePr",
@@ -24471,6 +24666,7 @@ function parseWorkflowRunState(raw) {
24471
24666
  const artifacts = Array.isArray(state.artifacts) ? state.artifacts.filter(
24472
24667
  (artifact) => !!artifact && typeof artifact === "object" && typeof artifact.label === "string" && (artifact.url === void 0 || typeof artifact.url === "string") && (artifact.path === void 0 || typeof artifact.path === "string")
24473
24668
  ) : [];
24669
+ const usage = parseRunUsage(state.usage);
24474
24670
  return {
24475
24671
  status: state.status,
24476
24672
  ...typeof state.currentStepId === "string" ? { currentStepId: state.currentStepId } : {},
@@ -24483,6 +24679,7 @@ function parseWorkflowRunState(raw) {
24483
24679
  facts: { ...facts },
24484
24680
  evidence: Object.fromEntries(evidenceEntries),
24485
24681
  artifacts: artifacts.map((artifact) => ({ ...artifact })),
24682
+ ...usage ? { usage } : {},
24486
24683
  ...typeof state.blocker === "string" ? { blocker: state.blocker } : {}
24487
24684
  };
24488
24685
  }
@@ -24546,6 +24743,7 @@ var init_workflowRunState = __esm({
24546
24743
  "src/workflowRunState.ts"() {
24547
24744
  "use strict";
24548
24745
  init_state_backend();
24746
+ init_usage();
24549
24747
  SAFE_ID = /^[a-z0-9][a-z0-9_-]{0,79}$/;
24550
24748
  }
24551
24749
  });
@@ -24766,6 +24964,7 @@ async function runJob(job, base) {
24766
24964
  ...parentRow,
24767
24965
  status: result.workflowState?.status === "waiting-approval" ? "waiting" : result.exitCode === 0 ? "success" : "failed",
24768
24966
  summary: result.reason,
24967
+ usage: result.usage,
24769
24968
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
24770
24969
  });
24771
24970
  }
@@ -24784,6 +24983,7 @@ async function runJob(job, base) {
24784
24983
  ...Object.keys(facts).length > 0 ? { output: facts } : {}
24785
24984
  });
24786
24985
  }
24986
+ publishRunUsage(`workflow:${workflowIdentity}`, result.usage);
24787
24987
  return result;
24788
24988
  } finally {
24789
24989
  await lease?.release().catch((error) => {
@@ -24932,16 +25132,17 @@ async function runCapabilityWorkflow(parent, workflow, capability, base, checkpo
24932
25132
  return { exitCode: 64, reason: resumeBlocker, workflowState: state };
24933
25133
  }
24934
25134
  const result = isGraphWorkflow(workflow) ? await runGraphCapabilityWorkflow(parent, workflow, capability, base, checkpoint) : await runLinearCapabilityWorkflow(parent, workflow, capability, base, checkpoint);
24935
- if (workflow.report && result.workflowState) {
25135
+ const resultWithUsage = result.workflowState?.usage ? { ...result, usage: result.workflowState.usage } : result;
25136
+ if (workflow.report && resultWithUsage.workflowState) {
24936
25137
  await publishWorkflowReport({
24937
25138
  config: base.config ?? loadConfig(base.cwd),
24938
25139
  publication: workflow.report,
24939
25140
  workflowId: capability.slug,
24940
25141
  workflowTitle: capability.title,
24941
- state: result.workflowState
25142
+ state: resultWithUsage.workflowState
24942
25143
  });
24943
25144
  }
24944
- return result;
25145
+ return resultWithUsage;
24945
25146
  }
24946
25147
  async function runLinearCapabilityWorkflow(parent, workflow, capability, base, checkpoint) {
24947
25148
  const state = initialWorkflowState(parent, workflow);
@@ -25070,7 +25271,8 @@ function initialWorkflowState(parent, workflow) {
25070
25271
  ...prior.steps ? { steps: cloneWorkflowSteps(prior.steps) } : {},
25071
25272
  facts: { ...prior.facts },
25072
25273
  evidence: { ...prior.evidence },
25073
- artifacts: prior.artifacts.map((artifact) => ({ ...artifact }))
25274
+ artifacts: prior.artifacts.map((artifact) => ({ ...artifact })),
25275
+ ...prior.usage ? { usage: structuredClone(prior.usage) } : {}
25074
25276
  };
25075
25277
  }
25076
25278
  const firstStepId = workflow.startAt ?? workflow.steps[0]?.id;
@@ -25090,7 +25292,8 @@ function initialWorkflowState(parent, workflow) {
25090
25292
  ...prior?.facts ?? {}
25091
25293
  },
25092
25294
  evidence: { ...prior?.evidence ?? {} },
25093
- artifacts: (prior?.artifacts ?? []).map((artifact) => ({ ...artifact }))
25295
+ artifacts: (prior?.artifacts ?? []).map((artifact) => ({ ...artifact })),
25296
+ ...prior?.usage ? { usage: structuredClone(prior.usage) } : {}
25094
25297
  };
25095
25298
  }
25096
25299
  function workflowChainData(parent, capability, base, state) {
@@ -25479,6 +25682,7 @@ function finishWorkflowStep(state, step, result) {
25479
25682
  ...result.capabilityOutput !== void 0 ? { output: result.capabilityOutput } : {},
25480
25683
  completedAt: (/* @__PURE__ */ new Date()).toISOString()
25481
25684
  };
25685
+ state.usage = mergeRunUsage(state.usage, result.usage);
25482
25686
  }
25483
25687
  function usesGenericCapabilityInput(action, cwd) {
25484
25688
  const inputs = getCapabilityActionInputs(action, hydratedCapabilitiesRoot(cwd));
@@ -25714,6 +25918,7 @@ var init_job = __esm({
25714
25918
  init_publishReport();
25715
25919
  init_simpleCapabilityRuntime();
25716
25920
  init_state_backend();
25921
+ init_usage();
25717
25922
  init_workflowDefinitionIdentity();
25718
25923
  init_workflowDefinitions();
25719
25924
  init_workflowRunLease();
@@ -27083,7 +27288,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
27083
27288
 
27084
27289
  // src/kody-cli.ts
27085
27290
  import { execFileSync as execFileSync24 } from "child_process";
27086
- import * as fs57 from "fs";
27291
+ import * as fs58 from "fs";
27087
27292
  import * as path53 from "path";
27088
27293
 
27089
27294
  // src/app-auth.ts
@@ -27616,7 +27821,7 @@ init_loopDefinitions();
27616
27821
 
27617
27822
  // src/mergedPrLifecycle.ts
27618
27823
  init_lifecycleLabels();
27619
- import * as fs56 from "fs";
27824
+ import * as fs57 from "fs";
27620
27825
  var DONE3 = {
27621
27826
  label: "kody:done",
27622
27827
  color: "0e8a16",
@@ -27657,8 +27862,8 @@ function finalizeMergedPullRequestEvent(event, cwd, writeLabel = setKodyLabel) {
27657
27862
  }
27658
27863
  function readGitHubEvent(env = process.env) {
27659
27864
  const eventPath = env.GITHUB_EVENT_PATH;
27660
- if (!eventPath || !fs56.existsSync(eventPath)) return null;
27661
- return JSON.parse(fs56.readFileSync(eventPath, "utf-8"));
27865
+ if (!eventPath || !fs57.existsSync(eventPath)) return null;
27866
+ return JSON.parse(fs57.readFileSync(eventPath, "utf-8"));
27662
27867
  }
27663
27868
 
27664
27869
  // src/kody-cli.ts
@@ -27886,9 +28091,9 @@ async function resolveAuthToken(env = process.env) {
27886
28091
  return void 0;
27887
28092
  }
27888
28093
  function detectPackageManager(cwd) {
27889
- if (fs57.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
27890
- if (fs57.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
27891
- if (fs57.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
28094
+ if (fs58.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
28095
+ if (fs58.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
28096
+ if (fs58.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
27892
28097
  return "npm";
27893
28098
  }
27894
28099
  function shouldChainScheduledWatch(match) {
@@ -27929,7 +28134,7 @@ function ensurePackageManagerInstalled(pm, cwd) {
27929
28134
  return shellOut("npm", ["install", "-g", spec], cwd);
27930
28135
  }
27931
28136
  function installDeps(pm, cwd) {
27932
- if (!fs57.existsSync(path53.join(cwd, "package.json"))) {
28137
+ if (!fs58.existsSync(path53.join(cwd, "package.json"))) {
27933
28138
  process.stdout.write("\u2192 kody: no package.json found \u2014 skipping consumer dependency install\n");
27934
28139
  return 0;
27935
28140
  }
@@ -27995,8 +28200,8 @@ function postFailureTail(issueNumber, cwd, reason) {
27995
28200
  const logPath = lastRunLogPath(cwd);
27996
28201
  let tail = "";
27997
28202
  try {
27998
- if (fs57.existsSync(logPath)) {
27999
- const content = fs57.readFileSync(logPath, "utf-8");
28203
+ if (fs58.existsSync(logPath)) {
28204
+ const content = fs58.readFileSync(logPath, "utf-8");
28000
28205
  tail = content.slice(-3e3);
28001
28206
  }
28002
28207
  } catch {
@@ -28113,9 +28318,9 @@ async function runCi(argv) {
28113
28318
  forceRunCliArgs = { goal: envForceMessage };
28114
28319
  }
28115
28320
  }
28116
- if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs57.existsSync(dispatchEventPath)) {
28321
+ if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs58.existsSync(dispatchEventPath)) {
28117
28322
  try {
28118
- const evt = JSON.parse(fs57.readFileSync(dispatchEventPath, "utf-8"));
28323
+ const evt = JSON.parse(fs58.readFileSync(dispatchEventPath, "utf-8"));
28119
28324
  const inputs = objectValue2(evt.inputs);
28120
28325
  const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
28121
28326
  const sessionInput = String(inputs?.sessionId ?? "");
@@ -28531,7 +28736,7 @@ init_repoWorkspace();
28531
28736
 
28532
28737
  // src/scripts/brainTurnLog.ts
28533
28738
  init_runtimePaths();
28534
- import * as fs58 from "fs";
28739
+ import * as fs59 from "fs";
28535
28740
  import * as path54 from "path";
28536
28741
  import posixPath4 from "path/posix";
28537
28742
  var live = /* @__PURE__ */ new Map();
@@ -28540,8 +28745,8 @@ function brainEventsFilePath(dir, chatId) {
28540
28745
  }
28541
28746
  function lastPersistedSeq(dir, chatId) {
28542
28747
  const p = brainEventsFilePath(dir, chatId);
28543
- if (!fs58.existsSync(p)) return 0;
28544
- const lines = fs58.readFileSync(p, "utf-8").split("\n").filter(Boolean);
28748
+ if (!fs59.existsSync(p)) return 0;
28749
+ const lines = fs59.readFileSync(p, "utf-8").split("\n").filter(Boolean);
28545
28750
  if (lines.length === 0) return 0;
28546
28751
  try {
28547
28752
  return JSON.parse(lines[lines.length - 1]).seq || 0;
@@ -28551,9 +28756,9 @@ function lastPersistedSeq(dir, chatId) {
28551
28756
  }
28552
28757
  function readSince(dir, chatId, since) {
28553
28758
  const p = brainEventsFilePath(dir, chatId);
28554
- if (!fs58.existsSync(p)) return [];
28759
+ if (!fs59.existsSync(p)) return [];
28555
28760
  const out = [];
28556
- for (const line of fs58.readFileSync(p, "utf-8").split("\n")) {
28761
+ for (const line of fs59.readFileSync(p, "utf-8").split("\n")) {
28557
28762
  if (!line) continue;
28558
28763
  try {
28559
28764
  const rec = JSON.parse(line);
@@ -28579,12 +28784,12 @@ function beginTurn(dir, chatId) {
28579
28784
  };
28580
28785
  live.set(chatId, state);
28581
28786
  const p = brainEventsFilePath(dir, chatId);
28582
- fs58.mkdirSync(path54.dirname(p), { recursive: true });
28787
+ fs59.mkdirSync(path54.dirname(p), { recursive: true });
28583
28788
  return (event) => {
28584
28789
  state.seq += 1;
28585
28790
  const rec = { seq: state.seq, turn, ts: Date.now(), event };
28586
28791
  try {
28587
- fs58.appendFileSync(p, `${JSON.stringify(rec)}
28792
+ fs59.appendFileSync(p, `${JSON.stringify(rec)}
28588
28793
  `);
28589
28794
  } catch (err) {
28590
28795
  process.stderr.write(
@@ -28623,7 +28828,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
28623
28828
  event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
28624
28829
  };
28625
28830
  try {
28626
- fs58.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
28831
+ fs59.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
28627
28832
  `);
28628
28833
  } catch {
28629
28834
  }
@@ -31287,7 +31492,7 @@ async function poolServe() {
31287
31492
 
31288
31493
  // src/servers/runner-serve.ts
31289
31494
  import { spawn as spawn10 } from "child_process";
31290
- import * as fs59 from "fs";
31495
+ import * as fs60 from "fs";
31291
31496
  import { createServer as createServer6 } from "http";
31292
31497
  var DEFAULT_PORT2 = 8080;
31293
31498
  var DEFAULT_WORKDIR = "/workspace/repo";
@@ -31363,8 +31568,8 @@ async function defaultRunJob(job) {
31363
31568
  const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
31364
31569
  const branch = job.ref ?? "main";
31365
31570
  const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
31366
- fs59.rmSync(workdir, { recursive: true, force: true });
31367
- fs59.mkdirSync(workdir, { recursive: true });
31571
+ fs60.rmSync(workdir, { recursive: true, force: true });
31572
+ fs60.mkdirSync(workdir, { recursive: true });
31368
31573
  const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
31369
31574
  const target = job.runRequest.target;
31370
31575
  const interactive = target.type === "chat";