@kody-ade/kody-engine 0.4.278 → 0.4.279

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 (2) hide show
  1. package/dist/bin/kody.js +169 -97
  2. package/package.json +24 -23
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.278",
18
+ version: "0.4.279",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -147,11 +147,11 @@ var init_claudeBinary = __esm({
147
147
  // src/issue.ts
148
148
  import { execFileSync } from "child_process";
149
149
  function ghToken(preferRepoToken = false) {
150
- const githubToken = process.env.GITHUB_TOKEN?.trim();
150
+ const githubToken2 = process.env.GITHUB_TOKEN?.trim();
151
151
  const kodyToken = process.env.KODY_TOKEN?.trim();
152
152
  const ghToken3 = process.env.GH_TOKEN?.trim();
153
153
  const ghPat = process.env.GH_PAT?.trim();
154
- return preferRepoToken ? githubToken || kodyToken || ghToken3 || ghPat : ghPat || ghToken3 || kodyToken || githubToken;
154
+ return preferRepoToken ? githubToken2 || kodyToken || ghToken3 || ghPat : ghPat || ghToken3 || kodyToken || githubToken2;
155
155
  }
156
156
  function gh(args, options) {
157
157
  const token = ghToken(options?.preferRepoToken);
@@ -532,11 +532,11 @@ function branchApiPath(config, targetPath) {
532
532
  }
533
533
  function ensureStateBranch(config, cwd) {
534
534
  const parsed = parseStateRepo(config);
535
- const cacheKey2 = `${parsed.owner}/${parsed.repo}:${STATE_BRANCH}`;
536
- if (ensuredStateBranches.has(cacheKey2)) return;
535
+ const cacheKey3 = `${parsed.owner}/${parsed.repo}:${STATE_BRANCH}`;
536
+ if (ensuredStateBranches.has(cacheKey3)) return;
537
537
  try {
538
538
  gh(["api", `/repos/${parsed.owner}/${parsed.repo}/git/ref/heads/${STATE_BRANCH}`], { cwd });
539
- ensuredStateBranches.add(cacheKey2);
539
+ ensuredStateBranches.add(cacheKey3);
540
540
  return;
541
541
  } catch (err) {
542
542
  if (!is404(err)) throw err;
@@ -555,7 +555,7 @@ function ensureStateBranch(config, cwd) {
555
555
  } catch (err) {
556
556
  if (!isAlreadyExists(err)) throw err;
557
557
  }
558
- ensuredStateBranches.add(cacheKey2);
558
+ ensuredStateBranches.add(cacheKey3);
559
559
  }
560
560
  function readStateText(config, cwd, filePath) {
561
561
  const targetPath = stateRepoPath(config, filePath);
@@ -1208,7 +1208,7 @@ var init_events = __esm({
1208
1208
  // src/verify.ts
1209
1209
  import { spawn } from "child_process";
1210
1210
  function runCommand(command, cwd) {
1211
- return new Promise((resolve8) => {
1211
+ return new Promise((resolve9) => {
1212
1212
  const start = Date.now();
1213
1213
  const child = spawn(command, {
1214
1214
  cwd,
@@ -1237,11 +1237,11 @@ function runCommand(command, cwd) {
1237
1237
  child.on("exit", (code) => {
1238
1238
  clearTimeout(timer);
1239
1239
  const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
1240
- resolve8({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
1240
+ resolve9({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
1241
1241
  });
1242
1242
  child.on("error", (err) => {
1243
1243
  clearTimeout(timer);
1244
- resolve8({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
1244
+ resolve9({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
1245
1245
  });
1246
1246
  });
1247
1247
  }
@@ -2884,7 +2884,7 @@ var init_repoWorkspace = __esm({
2884
2884
  defaultCloneRepo = (repo, token, dir) => {
2885
2885
  fs7.mkdirSync(path9.dirname(dir), { recursive: true });
2886
2886
  const authUrl = token ? `https://x-access-token:${token}@github.com/${repo}.git` : `https://github.com/${repo}.git`;
2887
- return new Promise((resolve8, reject) => {
2887
+ return new Promise((resolve9, reject) => {
2888
2888
  const child = spawn2("git", ["clone", "--depth=1", authUrl, dir], {
2889
2889
  stdio: "inherit"
2890
2890
  });
@@ -2900,7 +2900,7 @@ var init_repoWorkspace = __esm({
2900
2900
  spawnSync("git", ["-C", dir, "config", "user.email", email]);
2901
2901
  } catch {
2902
2902
  }
2903
- resolve8();
2903
+ resolve9();
2904
2904
  });
2905
2905
  child.on("error", reject);
2906
2906
  });
@@ -3208,10 +3208,10 @@ async function runAgent(opts) {
3208
3208
  let timer;
3209
3209
  let next;
3210
3210
  if (turnTimeoutMs > 0) {
3211
- const timeoutPromise = new Promise((resolve8) => {
3211
+ const timeoutPromise = new Promise((resolve9) => {
3212
3212
  timer = setTimeout(() => {
3213
3213
  timedOut = true;
3214
- resolve8({ done: true, value: void 0 });
3214
+ resolve9({ done: true, value: void 0 });
3215
3215
  }, turnTimeoutMs);
3216
3216
  });
3217
3217
  next = await Promise.race([nextPromise, timeoutPromise]);
@@ -12658,7 +12658,7 @@ function retryDelaysMs() {
12658
12658
  }
12659
12659
  function sleep(ms) {
12660
12660
  if (ms <= 0) return Promise.resolve();
12661
- return new Promise((resolve8) => setTimeout(resolve8, ms));
12661
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
12662
12662
  }
12663
12663
  async function fetchGoalStateWithRetry(config, goalId, cwd) {
12664
12664
  let state = fetchGoalState(config, goalId, cwd);
@@ -15326,7 +15326,7 @@ var init_previewBuildHelpers = __esm({
15326
15326
  // src/scripts/previewBuildRun.ts
15327
15327
  import { spawn as spawn4 } from "child_process";
15328
15328
  async function runCmd(cmd, args, opts = {}) {
15329
- await new Promise((resolve8, reject) => {
15329
+ await new Promise((resolve9, reject) => {
15330
15330
  const child = spawn4(cmd, args, {
15331
15331
  cwd: opts.cwd,
15332
15332
  env: { ...process.env, ...opts.env ?? {} },
@@ -15338,7 +15338,7 @@ async function runCmd(cmd, args, opts = {}) {
15338
15338
  }
15339
15339
  child.on("error", reject);
15340
15340
  child.on("close", (code) => {
15341
- if (code === 0) resolve8();
15341
+ if (code === 0) resolve9();
15342
15342
  else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
15343
15343
  });
15344
15344
  });
@@ -16462,7 +16462,7 @@ function stripAnsi2(s) {
16462
16462
  return s.replace(ANSI_RE2, "");
16463
16463
  }
16464
16464
  function runCommand2(command, cwd) {
16465
- return new Promise((resolve8) => {
16465
+ return new Promise((resolve9) => {
16466
16466
  const child = spawn5(command, {
16467
16467
  cwd,
16468
16468
  shell: true,
@@ -16489,11 +16489,11 @@ function runCommand2(command, cwd) {
16489
16489
  }, TEST_TIMEOUT_MS);
16490
16490
  child.on("exit", (code) => {
16491
16491
  clearTimeout(timer);
16492
- resolve8({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
16492
+ resolve9({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
16493
16493
  });
16494
16494
  child.on("error", (err) => {
16495
16495
  clearTimeout(timer);
16496
- resolve8({ exitCode: -1, output: err.message });
16496
+ resolve9({ exitCode: -1, output: err.message });
16497
16497
  });
16498
16498
  });
16499
16499
  }
@@ -16898,21 +16898,21 @@ function lineStream(stream) {
16898
16898
  tryDeliver();
16899
16899
  });
16900
16900
  return {
16901
- next: (timeoutMs) => new Promise((resolve8) => {
16901
+ next: (timeoutMs) => new Promise((resolve9) => {
16902
16902
  if (queue.length > 0) {
16903
- resolve8(queue.shift());
16903
+ resolve9(queue.shift());
16904
16904
  return;
16905
16905
  }
16906
16906
  if (ended) {
16907
- resolve8(null);
16907
+ resolve9(null);
16908
16908
  return;
16909
16909
  }
16910
- waiter = resolve8;
16910
+ waiter = resolve9;
16911
16911
  const t = setTimeout(
16912
16912
  () => {
16913
- if (waiter === resolve8) {
16913
+ if (waiter === resolve9) {
16914
16914
  waiter = null;
16915
- resolve8(null);
16915
+ resolve9(null);
16916
16916
  }
16917
16917
  },
16918
16918
  Math.max(0, timeoutMs)
@@ -17295,42 +17295,111 @@ var init_scripts = __esm({
17295
17295
  });
17296
17296
 
17297
17297
  // src/stateWorkspace.ts
17298
+ import { execFileSync as execFileSync24 } from "child_process";
17299
+ import * as crypto3 from "crypto";
17298
17300
  import * as fs43 from "fs";
17301
+ import * as os7 from "os";
17299
17302
  import * as path41 from "path";
17300
17303
  function writeLocalFile(cwd, relativePath, content) {
17301
17304
  const fullPath = path41.join(cwd, relativePath);
17302
17305
  fs43.mkdirSync(path41.dirname(fullPath), { recursive: true });
17303
17306
  fs43.writeFileSync(fullPath, content);
17304
17307
  }
17305
- function hydrateDirectory(config, cwd, stateDir, localDir) {
17306
- const entries = listStateDirectory(config, cwd, stateDir);
17307
- if (entries.length === 0) return;
17308
- for (const entry of entries) {
17309
- if (!entry.name || !entry.type) continue;
17310
- const childState = path41.posix.join(stateDir, entry.name);
17311
- const childLocal = path41.join(localDir, entry.name);
17312
- if (entry.type === "dir") {
17313
- fs43.rmSync(path41.join(cwd, childLocal), { recursive: true, force: true });
17314
- hydrateDirectory(config, cwd, childState, childLocal);
17315
- } else if (entry.type === "file") {
17316
- const file = readStateText(config, cwd, childState);
17317
- if (file) writeLocalFile(cwd, childLocal, file.content);
17318
- }
17308
+ function copyPath(source, target) {
17309
+ const st = fs43.lstatSync(source);
17310
+ fs43.rmSync(target, { recursive: true, force: true });
17311
+ if (st.isSymbolicLink()) return;
17312
+ fs43.mkdirSync(path41.dirname(target), { recursive: true });
17313
+ fs43.cpSync(source, target, { recursive: true, force: true });
17314
+ }
17315
+ function overlayDirectoryChildren(cwd, sourceDir, localDir) {
17316
+ if (!fs43.existsSync(sourceDir)) return;
17317
+ for (const entry of fs43.readdirSync(sourceDir, { withFileTypes: true })) {
17318
+ const source = path41.join(sourceDir, entry.name);
17319
+ const target = path41.join(cwd, localDir, entry.name);
17320
+ copyPath(source, target);
17319
17321
  }
17320
17322
  }
17321
17323
  function hydrateStateWorkspace(config, cwd) {
17324
+ if (process.env.VITEST && process.env[TEST_FETCH_ENV] !== "1") return;
17325
+ const parsed = parseStateRepo(config);
17326
+ const hydrateKey = `${path41.resolve(cwd)}|${parsed.owner}/${parsed.repo}|${parsed.basePath}|${STATE_BRANCH}`;
17327
+ if (hydratedWorkspaces.has(hydrateKey)) return;
17328
+ const snapshotRoot = fetchStateSnapshot(parsed);
17322
17329
  for (const mapping of DIR_MAPPINGS) {
17323
- hydrateDirectory(config, cwd, mapping.stateDir, mapping.localDir);
17330
+ overlayDirectoryChildren(cwd, path41.join(snapshotRoot, mapping.stateDir), mapping.localDir);
17324
17331
  }
17325
17332
  for (const mapping of FILE_MAPPINGS) {
17326
- const file = readStateText(config, cwd, mapping.statePath);
17327
- if (file) writeLocalFile(cwd, mapping.localPath, file.content);
17333
+ const source = path41.join(snapshotRoot, mapping.statePath);
17334
+ if (fs43.existsSync(source) && !fs43.lstatSync(source).isSymbolicLink() && fs43.statSync(source).isFile()) {
17335
+ writeLocalFile(cwd, mapping.localPath, fs43.readFileSync(source, "utf-8"));
17336
+ }
17328
17337
  }
17338
+ hydratedWorkspaces.add(hydrateKey);
17329
17339
  }
17330
- var DIR_MAPPINGS, FILE_MAPPINGS;
17340
+ function fetchStateSnapshot(parsed) {
17341
+ const cacheDir = path41.join(cacheRoot2(), cacheKey2(parsed));
17342
+ const url = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
17343
+ try {
17344
+ fs43.mkdirSync(path41.dirname(cacheDir), { recursive: true });
17345
+ if (!fs43.existsSync(path41.join(cacheDir, ".git"))) {
17346
+ fs43.rmSync(cacheDir, { recursive: true, force: true });
17347
+ runGit3(["clone", "--no-checkout", "--filter=blob:none", url, cacheDir]);
17348
+ }
17349
+ runGit3(["-C", cacheDir, "remote", "set-url", "origin", url]);
17350
+ runGit3(["-C", cacheDir, "fetch", "--depth=1", "origin", STATE_BRANCH]);
17351
+ runGit3(["-C", cacheDir, "sparse-checkout", "init", "--cone"]);
17352
+ runGit3(["-C", cacheDir, "sparse-checkout", "set", parsed.basePath]);
17353
+ runGit3(["-C", cacheDir, "checkout", "--force", "--detach", "FETCH_HEAD"]);
17354
+ runGit3(["-C", cacheDir, "clean", "-fdx"]);
17355
+ } catch (err) {
17356
+ const msg = err instanceof Error ? err.message : String(err);
17357
+ throw new Error(
17358
+ `stateWorkspace: failed to fetch ${parsed.owner}/${parsed.repo}:${parsed.basePath}@${STATE_BRANCH}: ${msg}`
17359
+ );
17360
+ }
17361
+ return path41.join(cacheDir, parsed.basePath);
17362
+ }
17363
+ function cacheRoot2() {
17364
+ return process.env[CACHE_ENV2]?.trim() || path41.join(os7.homedir(), ".cache", "kody", "state-repo");
17365
+ }
17366
+ function cacheKey2(parsed) {
17367
+ return crypto3.createHash("sha256").update(`${parsed.owner}/${parsed.repo}#${STATE_BRANCH}#${parsed.basePath}`).digest("hex").slice(0, 24);
17368
+ }
17369
+ function runGit3(args) {
17370
+ try {
17371
+ execFileSync24("git", args, {
17372
+ encoding: "utf-8",
17373
+ env: githubAuthEnv(),
17374
+ stdio: ["ignore", "ignore", "pipe"],
17375
+ timeout: 12e4
17376
+ });
17377
+ } catch (err) {
17378
+ const stderr = err.stderr;
17379
+ const detail = Buffer.isBuffer(stderr) ? stderr.toString("utf-8").trim() : typeof stderr === "string" ? stderr.trim() : "";
17380
+ throw new Error(detail || `git ${args[0] ?? "command"} failed`);
17381
+ }
17382
+ }
17383
+ function githubAuthEnv() {
17384
+ const token = githubToken();
17385
+ if (!token) return process.env;
17386
+ const encoded = Buffer.from(`x-access-token:${token}`).toString("base64");
17387
+ const existingCount = /^\d+$/.test(process.env.GIT_CONFIG_COUNT ?? "") ? Number(process.env.GIT_CONFIG_COUNT) : 0;
17388
+ return {
17389
+ ...process.env,
17390
+ GIT_CONFIG_COUNT: String(existingCount + 1),
17391
+ [`GIT_CONFIG_KEY_${existingCount}`]: "http.https://github.com/.extraheader",
17392
+ [`GIT_CONFIG_VALUE_${existingCount}`]: `AUTHORIZATION: basic ${encoded}`
17393
+ };
17394
+ }
17395
+ function githubToken() {
17396
+ return process.env.KODY_TOKEN?.trim() || process.env.GH_TOKEN?.trim() || process.env.GITHUB_TOKEN?.trim() || process.env.GH_PAT?.trim() || void 0;
17397
+ }
17398
+ var DIR_MAPPINGS, FILE_MAPPINGS, CACHE_ENV2, TEST_FETCH_ENV, hydratedWorkspaces;
17331
17399
  var init_stateWorkspace = __esm({
17332
17400
  "src/stateWorkspace.ts"() {
17333
17401
  "use strict";
17402
+ init_stateBranch();
17334
17403
  init_stateRepo();
17335
17404
  DIR_MAPPINGS = [
17336
17405
  { stateDir: "executables", localDir: path41.join(".kody", "executables") },
@@ -17344,11 +17413,14 @@ var init_stateWorkspace = __esm({
17344
17413
  { statePath: "variables.json", localPath: path41.join(".kody", "variables.json") },
17345
17414
  { statePath: "secrets.enc", localPath: path41.join(".kody", "secrets.enc") }
17346
17415
  ];
17416
+ CACHE_ENV2 = "KODY_STATE_REPO_CACHE";
17417
+ TEST_FETCH_ENV = "KODY_STATE_WORKSPACE_FETCH_FOR_TESTS";
17418
+ hydratedWorkspaces = /* @__PURE__ */ new Set();
17347
17419
  }
17348
17420
  });
17349
17421
 
17350
17422
  // src/tools.ts
17351
- import { execFileSync as execFileSync24 } from "child_process";
17423
+ import { execFileSync as execFileSync25 } from "child_process";
17352
17424
  function verifyCliTools(tools, cwd) {
17353
17425
  const out = [];
17354
17426
  for (const t of tools) out.push(verifyOne(t, cwd));
@@ -17385,7 +17457,7 @@ function verifyOne(tool6, cwd) {
17385
17457
  }
17386
17458
  function runShell(cmd, cwd, timeoutMs = 3e4) {
17387
17459
  try {
17388
- const stdout = execFileSync24("sh", ["-c", cmd], {
17460
+ const stdout = execFileSync25("sh", ["-c", cmd], {
17389
17461
  cwd,
17390
17462
  stdio: ["ignore", "pipe", "pipe"],
17391
17463
  timeout: timeoutMs,
@@ -18131,14 +18203,14 @@ async function runShellEntry(entry, ctx, profile) {
18131
18203
  let killTimer;
18132
18204
  let escalateTimer;
18133
18205
  const result = await new Promise(
18134
- (resolve8) => {
18206
+ (resolve9) => {
18135
18207
  let settled = false;
18136
18208
  const settle = (code, signal, spawnErr) => {
18137
18209
  if (settled) return;
18138
18210
  settled = true;
18139
18211
  if (killTimer) clearTimeout(killTimer);
18140
18212
  if (escalateTimer) clearTimeout(escalateTimer);
18141
- resolve8({ code, signal, spawnErr });
18213
+ resolve9({ code, signal, spawnErr });
18142
18214
  };
18143
18215
  child.on("error", (err) => settle(null, null, err));
18144
18216
  child.on("close", (code, signal) => settle(code, signal));
@@ -19377,7 +19449,7 @@ _\u2026 (instructions truncated)_` : trimmed;
19377
19449
  init_config();
19378
19450
 
19379
19451
  // src/kody-cli.ts
19380
- import { execFileSync as execFileSync25 } from "child_process";
19452
+ import { execFileSync as execFileSync26 } from "child_process";
19381
19453
  import * as fs46 from "fs";
19382
19454
  import * as path45 from "path";
19383
19455
 
@@ -20034,7 +20106,7 @@ function recoverCheckoutToken(env = process.env, cwd = process.cwd()) {
20034
20106
  if (env.GITHUB_TOKEN?.trim()) return env.GITHUB_TOKEN.trim();
20035
20107
  let header = "";
20036
20108
  try {
20037
- header = execFileSync25("git", ["config", "--local", "--get", "http.https://github.com/.extraheader"], {
20109
+ header = execFileSync26("git", ["config", "--local", "--get", "http.https://github.com/.extraheader"], {
20038
20110
  cwd,
20039
20111
  encoding: "utf-8",
20040
20112
  stdio: ["ignore", "pipe", "ignore"]
@@ -20096,7 +20168,7 @@ function shouldChainScheduledWatch(match) {
20096
20168
  }
20097
20169
  function shellOut(cmd, args, cwd, stream = true) {
20098
20170
  try {
20099
- execFileSync25(cmd, args, {
20171
+ execFileSync26(cmd, args, {
20100
20172
  cwd,
20101
20173
  stdio: stream ? "inherit" : "pipe",
20102
20174
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" }
@@ -20109,7 +20181,7 @@ function shellOut(cmd, args, cwd, stream = true) {
20109
20181
  }
20110
20182
  function isOnPath(bin) {
20111
20183
  try {
20112
- execFileSync25("which", [bin], { stdio: "pipe" });
20184
+ execFileSync26("which", [bin], { stdio: "pipe" });
20113
20185
  return true;
20114
20186
  } catch {
20115
20187
  return false;
@@ -20150,7 +20222,7 @@ function installLitellmIfNeeded(cwd) {
20150
20222
  } catch {
20151
20223
  }
20152
20224
  try {
20153
- execFileSync25("python3", ["-c", "import litellm"], { stdio: "pipe" });
20225
+ execFileSync26("python3", ["-c", "import litellm"], { stdio: "pipe" });
20154
20226
  process.stdout.write("\u2192 kody: litellm already installed\n");
20155
20227
  return 0;
20156
20228
  } catch {
@@ -20160,16 +20232,16 @@ function installLitellmIfNeeded(cwd) {
20160
20232
  }
20161
20233
  function configureGitIdentity(cwd) {
20162
20234
  try {
20163
- const name = execFileSync25("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
20235
+ const name = execFileSync26("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
20164
20236
  if (name) return;
20165
20237
  } catch {
20166
20238
  }
20167
20239
  try {
20168
- execFileSync25("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
20240
+ execFileSync26("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
20169
20241
  } catch {
20170
20242
  }
20171
20243
  try {
20172
- execFileSync25("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
20244
+ execFileSync26("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
20173
20245
  cwd,
20174
20246
  stdio: "pipe"
20175
20247
  });
@@ -20779,17 +20851,17 @@ function authOk(req, expected) {
20779
20851
  return false;
20780
20852
  }
20781
20853
  function readJsonBody(req) {
20782
- return new Promise((resolve8, reject) => {
20854
+ return new Promise((resolve9, reject) => {
20783
20855
  const chunks = [];
20784
20856
  req.on("data", (c) => chunks.push(c));
20785
20857
  req.on("end", () => {
20786
20858
  const raw = Buffer.concat(chunks).toString("utf-8");
20787
20859
  if (!raw.trim()) {
20788
- resolve8({});
20860
+ resolve9({});
20789
20861
  return;
20790
20862
  }
20791
20863
  try {
20792
- resolve8(JSON.parse(raw));
20864
+ resolve9(JSON.parse(raw));
20793
20865
  } catch (err) {
20794
20866
  reject(err instanceof Error ? err : new Error(String(err)));
20795
20867
  }
@@ -21141,11 +21213,11 @@ async function brainServe(opts) {
21141
21213
  model,
21142
21214
  litellmUrl
21143
21215
  });
21144
- await new Promise((resolve8) => {
21216
+ await new Promise((resolve9) => {
21145
21217
  server.listen(port, "0.0.0.0", () => {
21146
21218
  process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
21147
21219
  `);
21148
- resolve8();
21220
+ resolve9();
21149
21221
  });
21150
21222
  });
21151
21223
  const shutdown = (signal) => {
@@ -21398,14 +21470,14 @@ async function startBrainProxy(opts) {
21398
21470
  const { httpServer, handler } = buildBrainProxy(opts);
21399
21471
  const port = opts.port ?? 0;
21400
21472
  const host = opts.host ?? "127.0.0.1";
21401
- await new Promise((resolve8) => httpServer.listen(port, host, () => resolve8()));
21473
+ await new Promise((resolve9) => httpServer.listen(port, host, () => resolve9()));
21402
21474
  const addr = httpServer.address();
21403
21475
  return {
21404
21476
  httpServer,
21405
21477
  port: addr.port,
21406
21478
  url: `http://${host}:${addr.port}`,
21407
- stop: () => new Promise((resolve8) => {
21408
- httpServer.close(() => resolve8());
21479
+ stop: () => new Promise((resolve9) => {
21480
+ httpServer.close(() => resolve9());
21409
21481
  }),
21410
21482
  handler
21411
21483
  };
@@ -21555,23 +21627,23 @@ function buildMcpHttpServer(opts) {
21555
21627
  httpServer,
21556
21628
  routes,
21557
21629
  port,
21558
- stop: () => new Promise((resolve8) => {
21630
+ stop: () => new Promise((resolve9) => {
21559
21631
  let pending = transports.size;
21560
21632
  if (pending === 0) {
21561
- httpServer.close(() => resolve8());
21633
+ httpServer.close(() => resolve9());
21562
21634
  return;
21563
21635
  }
21564
21636
  for (const transport of transports.values()) {
21565
21637
  void transport.close().finally(() => {
21566
21638
  pending--;
21567
- if (pending === 0) httpServer.close(() => resolve8());
21639
+ if (pending === 0) httpServer.close(() => resolve9());
21568
21640
  });
21569
21641
  }
21570
21642
  })
21571
21643
  };
21572
21644
  }
21573
21645
  function listenMcpHttpServer(server, host = "127.0.0.1") {
21574
- return new Promise((resolve8, reject) => {
21646
+ return new Promise((resolve9, reject) => {
21575
21647
  server.httpServer.once("error", reject);
21576
21648
  server.httpServer.listen(server.port, host, () => {
21577
21649
  server.httpServer.off("error", reject);
@@ -21579,7 +21651,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
21579
21651
  if (addr && typeof addr === "object") {
21580
21652
  server.port = addr.port;
21581
21653
  }
21582
- resolve8();
21654
+ resolve9();
21583
21655
  });
21584
21656
  });
21585
21657
  }
@@ -21668,7 +21740,7 @@ import * as fs50 from "fs";
21668
21740
  import * as path49 from "path";
21669
21741
 
21670
21742
  // src/chat/inbox.ts
21671
- import { execFileSync as execFileSync26 } from "child_process";
21743
+ import { execFileSync as execFileSync27 } from "child_process";
21672
21744
  var DEFAULT_POLL_MS = 3e3;
21673
21745
  async function waitForNextUserMessage(opts) {
21674
21746
  const pollMs = opts.pollIntervalMs ?? DEFAULT_POLL_MS;
@@ -21692,13 +21764,13 @@ async function waitForNextUserMessage(opts) {
21692
21764
  try {
21693
21765
  const branch = currentBranch(opts.cwd);
21694
21766
  if (branch) {
21695
- execFileSync26("git", ["fetch", "--quiet", "origin", branch], { cwd: opts.cwd, stdio: "pipe" });
21696
- execFileSync26("git", ["merge", "--ff-only", "--quiet", `origin/${branch}`], {
21767
+ execFileSync27("git", ["fetch", "--quiet", "origin", branch], { cwd: opts.cwd, stdio: "pipe" });
21768
+ execFileSync27("git", ["merge", "--ff-only", "--quiet", `origin/${branch}`], {
21697
21769
  cwd: opts.cwd,
21698
21770
  stdio: "pipe"
21699
21771
  });
21700
21772
  } else {
21701
- execFileSync26("git", ["fetch", "--quiet", "--all"], { cwd: opts.cwd, stdio: "pipe" });
21773
+ execFileSync27("git", ["fetch", "--quiet", "--all"], { cwd: opts.cwd, stdio: "pipe" });
21702
21774
  }
21703
21775
  } catch (err) {
21704
21776
  const msg = err instanceof Error ? err.message : String(err);
@@ -21720,11 +21792,11 @@ async function waitForNextUserMessage(opts) {
21720
21792
  }
21721
21793
  }
21722
21794
  function sleep3(ms) {
21723
- return new Promise((resolve8) => setTimeout(resolve8, ms));
21795
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
21724
21796
  }
21725
21797
  function currentBranch(cwd) {
21726
21798
  try {
21727
- const out = execFileSync26("git", ["symbolic-ref", "--short", "HEAD"], {
21799
+ const out = execFileSync27("git", ["symbolic-ref", "--short", "HEAD"], {
21728
21800
  cwd,
21729
21801
  stdio: ["ignore", "pipe", "ignore"]
21730
21802
  });
@@ -22823,14 +22895,14 @@ function sendJson2(res, status, body) {
22823
22895
  res.end(JSON.stringify(body));
22824
22896
  }
22825
22897
  function readJsonBody2(req) {
22826
- return new Promise((resolve8, reject) => {
22898
+ return new Promise((resolve9, reject) => {
22827
22899
  const chunks = [];
22828
22900
  req.on("data", (c) => chunks.push(c));
22829
22901
  req.on("end", () => {
22830
22902
  const raw = Buffer.concat(chunks).toString("utf-8");
22831
- if (!raw.trim()) return resolve8({});
22903
+ if (!raw.trim()) return resolve9({});
22832
22904
  try {
22833
- resolve8(JSON.parse(raw));
22905
+ resolve9(JSON.parse(raw));
22834
22906
  } catch (err) {
22835
22907
  reject(err instanceof Error ? err : new Error(String(err)));
22836
22908
  }
@@ -22921,8 +22993,8 @@ function synthesizeLegacyClaimRequest(input) {
22921
22993
  async function poolServe() {
22922
22994
  const masterRaw = process.env.KODY_MASTER_KEY?.trim();
22923
22995
  if (!masterRaw) throw new Error("KODY_MASTER_KEY required for pool-serve");
22924
- const githubToken = process.env.GITHUB_TOKEN?.trim();
22925
- if (!githubToken) throw new Error("GITHUB_TOKEN required for pool-serve (reads per-repo vaults)");
22996
+ const githubToken2 = process.env.GITHUB_TOKEN?.trim();
22997
+ if (!githubToken2) throw new Error("GITHUB_TOKEN required for pool-serve (reads per-repo vaults)");
22926
22998
  const master = masterKeyBytes(masterRaw);
22927
22999
  const poolApiKey = derivePoolApiKey(master);
22928
23000
  const runnerApiKey = deriveRunnerApiKey(master);
@@ -22935,7 +23007,7 @@ async function poolServe() {
22935
23007
  const apiPort = envInt2("POOL_API_PORT", 4100);
22936
23008
  const healthTimeoutMs = envInt2("POOL_HEALTH_TIMEOUT_MS", 12e4);
22937
23009
  const registry = new PoolRegistry({
22938
- githubToken,
23010
+ githubToken: githubToken2,
22939
23011
  masterKey: master,
22940
23012
  base: {
22941
23013
  min,
@@ -23012,10 +23084,10 @@ async function poolServe() {
23012
23084
  }
23013
23085
  });
23014
23086
  const apiHost = process.env.POOL_API_HOST ?? "::";
23015
- await new Promise((resolve8) => {
23087
+ await new Promise((resolve9) => {
23016
23088
  server.listen(apiPort, apiHost, () => {
23017
23089
  log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
23018
- resolve8();
23090
+ resolve9();
23019
23091
  });
23020
23092
  });
23021
23093
  const shutdown = (signal) => {
@@ -23054,17 +23126,17 @@ function authOk2(req, expected) {
23054
23126
  return false;
23055
23127
  }
23056
23128
  function readJsonBody3(req) {
23057
- return new Promise((resolve8, reject) => {
23129
+ return new Promise((resolve9, reject) => {
23058
23130
  const chunks = [];
23059
23131
  req.on("data", (c) => chunks.push(c));
23060
23132
  req.on("end", () => {
23061
23133
  const raw = Buffer.concat(chunks).toString("utf-8");
23062
23134
  if (!raw.trim()) {
23063
- resolve8({});
23135
+ resolve9({});
23064
23136
  return;
23065
23137
  }
23066
23138
  try {
23067
- resolve8(JSON.parse(raw));
23139
+ resolve9(JSON.parse(raw));
23068
23140
  } catch (err) {
23069
23141
  reject(err instanceof Error ? err : new Error(String(err)));
23070
23142
  }
@@ -23083,8 +23155,8 @@ function parseJob(body) {
23083
23155
  if (!jobId) return { error: "jobId required" };
23084
23156
  const repo = typeof b.repo === "string" ? b.repo.trim() : "";
23085
23157
  if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) return { error: "repo must be 'owner/name'" };
23086
- const githubToken = typeof b.githubToken === "string" ? b.githubToken.trim() : "";
23087
- if (!githubToken) return { error: "githubToken required" };
23158
+ const githubToken2 = typeof b.githubToken === "string" ? b.githubToken.trim() : "";
23159
+ if (!githubToken2) return { error: "githubToken required" };
23088
23160
  const action = typeof b.action === "string" && b.action.trim() ? b.action.trim() : void 0;
23089
23161
  const message = typeof b.message === "string" && b.message.trim() ? b.message.trim() : void 0;
23090
23162
  const mode = b.mode === "interactive" ? "interactive" : b.mode === "scheduled" ? "scheduled" : "issue";
@@ -23096,7 +23168,7 @@ function parseJob(body) {
23096
23168
  message
23097
23169
  });
23098
23170
  if ("error" in runRequest) return { error: runRequest.error };
23099
- const job = { jobId, repo, githubToken, runRequest: runRequest.request };
23171
+ const job = { jobId, repo, githubToken: githubToken2, runRequest: runRequest.request };
23100
23172
  if (job.runRequest.target.type === "issue") {
23101
23173
  job.issueNumber = job.runRequest.target.id;
23102
23174
  } else if (job.runRequest.target.type === "chat") {
@@ -23198,13 +23270,13 @@ async function defaultRunJob(job) {
23198
23270
  ...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
23199
23271
  ...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
23200
23272
  };
23201
- const run = (cmd, args, cwd) => new Promise((resolve8) => {
23273
+ const run = (cmd, args, cwd) => new Promise((resolve9) => {
23202
23274
  const child = spawn8(cmd, args, { stdio: "inherit", env: childEnv, cwd });
23203
- child.on("exit", (code) => resolve8(code ?? 0));
23275
+ child.on("exit", (code) => resolve9(code ?? 0));
23204
23276
  child.on("error", (err) => {
23205
23277
  process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
23206
23278
  `);
23207
- resolve8(1);
23279
+ resolve9(1);
23208
23280
  });
23209
23281
  });
23210
23282
  process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
@@ -23280,11 +23352,11 @@ async function runnerServe() {
23280
23352
  const port = Number(process.env.PORT ?? DEFAULT_PORT2);
23281
23353
  const server = buildServer2({ apiKey });
23282
23354
  const host = process.env.RUNNER_HOST ?? "::";
23283
- await new Promise((resolve8) => {
23355
+ await new Promise((resolve9) => {
23284
23356
  server.listen(port, host, () => {
23285
23357
  process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
23286
23358
  `);
23287
- resolve8();
23359
+ resolve9();
23288
23360
  });
23289
23361
  });
23290
23362
  const shutdown = (signal) => {
@@ -23353,14 +23425,14 @@ async function serve(opts) {
23353
23425
  `);
23354
23426
  const args = ["--dangerously-skip-permissions", "--model", model.model];
23355
23427
  const child = spawn9("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
23356
- const exitCode = await new Promise((resolve8) => {
23357
- child.on("exit", (code) => resolve8(code ?? 0));
23428
+ const exitCode = await new Promise((resolve9) => {
23429
+ child.on("exit", (code) => resolve9(code ?? 0));
23358
23430
  child.on("error", (err) => {
23359
23431
  process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
23360
23432
  `);
23361
23433
  process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
23362
23434
  `);
23363
- resolve8(1);
23435
+ resolve9(1);
23364
23436
  });
23365
23437
  });
23366
23438
  killProxy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.278",
3
+ "version": "0.4.279",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,6 +12,27 @@
12
12
  "templates",
13
13
  "kody.config.schema.json"
14
14
  ],
15
+ "scripts": {
16
+ "kody:run": "tsx bin/kody.ts",
17
+ "serve": "tsx bin/kody.ts serve",
18
+ "serve:vscode": "tsx bin/kody.ts serve vscode",
19
+ "serve:claude": "tsx bin/kody.ts serve claude",
20
+ "clean:dist": "node scripts/clean-dist.cjs",
21
+ "build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
22
+ "check:modularity": "tsx scripts/check-script-modularity.ts",
23
+ "pretest": "pnpm check:modularity",
24
+ "test": "vitest run tests/unit tests/int --coverage",
25
+ "posttest": "tsx scripts/check-coverage-floor.ts",
26
+ "test:smoke": "vitest run tests/smoke --no-coverage",
27
+ "test:e2e": "vitest run tests/e2e --no-coverage",
28
+ "test:all": "vitest run tests --no-coverage",
29
+ "typecheck": "tsc --noEmit",
30
+ "lint": "biome check",
31
+ "lint:fix": "biome check --write",
32
+ "format": "biome format --write",
33
+ "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
34
+ "prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build"
35
+ },
15
36
  "dependencies": {
16
37
  "@actions/cache": "^6.0.0",
17
38
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
@@ -35,25 +56,5 @@
35
56
  "url": "git+https://github.com/aharonyaircohen/kody-engine.git"
36
57
  },
37
58
  "homepage": "https://github.com/aharonyaircohen/kody-engine",
38
- "bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
39
- "scripts": {
40
- "kody:run": "tsx bin/kody.ts",
41
- "serve": "tsx bin/kody.ts serve",
42
- "serve:vscode": "tsx bin/kody.ts serve vscode",
43
- "serve:claude": "tsx bin/kody.ts serve claude",
44
- "clean:dist": "node scripts/clean-dist.cjs",
45
- "build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
46
- "check:modularity": "tsx scripts/check-script-modularity.ts",
47
- "pretest": "pnpm check:modularity",
48
- "test": "vitest run tests/unit tests/int --coverage",
49
- "posttest": "tsx scripts/check-coverage-floor.ts",
50
- "test:smoke": "vitest run tests/smoke --no-coverage",
51
- "test:e2e": "vitest run tests/e2e --no-coverage",
52
- "test:all": "vitest run tests --no-coverage",
53
- "typecheck": "tsc --noEmit",
54
- "lint": "biome check",
55
- "lint:fix": "biome check --write",
56
- "format": "biome format --write",
57
- "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
58
- }
59
- }
59
+ "bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
60
+ }