@kody-ade/kody-engine 0.3.57 → 0.3.58

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 +61 -15
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@kody-ade/kody-engine",
6
- version: "0.3.57",
6
+ version: "0.3.58",
7
7
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
8
8
  license: "MIT",
9
9
  type: "module",
@@ -959,7 +959,7 @@ function coerceBare(spec, value) {
959
959
  }
960
960
 
961
961
  // src/executor.ts
962
- import { spawnSync } from "child_process";
962
+ import { spawn as spawn3 } from "child_process";
963
963
  import * as fs24 from "fs";
964
964
  import * as path21 from "path";
965
965
 
@@ -6648,7 +6648,7 @@ async function runExecutable(profileName, input) {
6648
6648
  for (const entry of profile.scripts.preflight) {
6649
6649
  if (!shouldRun(entry, ctx)) continue;
6650
6650
  if (entry.shell) {
6651
- runShellEntry(entry, ctx, profile);
6651
+ await runShellEntry(entry, ctx, profile);
6652
6652
  } else {
6653
6653
  const fn = preflightScripts[entry.script];
6654
6654
  if (!fn) return finish({ exitCode: 99, reason: `preflight script not registered: ${entry.script}` });
@@ -6671,7 +6671,7 @@ async function runExecutable(profileName, input) {
6671
6671
  const label = entry.script ?? entry.shell ?? "<unknown>";
6672
6672
  try {
6673
6673
  if (entry.shell) {
6674
- runShellEntry(entry, ctx, profile);
6674
+ await runShellEntry(entry, ctx, profile);
6675
6675
  } else {
6676
6676
  const fn = postflightScripts[entry.script];
6677
6677
  if (!fn) return finish({ exitCode: 99, reason: `postflight script not registered: ${entry.script}` });
@@ -6812,7 +6812,8 @@ function resolveShellTimeoutMs(entry) {
6812
6812
  }
6813
6813
  return DEFAULT_SHELL_TIMEOUT_MS;
6814
6814
  }
6815
- function runShellEntry(entry, ctx, profile) {
6815
+ var SIGKILL_GRACE_MS = 5e3;
6816
+ async function runShellEntry(entry, ctx, profile) {
6816
6817
  const shellName = entry.shell;
6817
6818
  const shellPath = path21.join(profile.dir, shellName);
6818
6819
  if (!fs24.existsSync(shellPath)) {
@@ -6831,17 +6832,63 @@ function runShellEntry(entry, ctx, profile) {
6831
6832
  env[`KODY_CFG_${k}`] = v;
6832
6833
  }
6833
6834
  const timeoutMs = resolveShellTimeoutMs(entry);
6834
- const r = spawnSync("bash", [shellPath, ...positional], {
6835
+ const child = spawn3("bash", [shellPath, ...positional], {
6835
6836
  cwd: ctx.cwd,
6836
- encoding: "utf-8",
6837
6837
  env,
6838
6838
  stdio: ["pipe", "pipe", "pipe"],
6839
- timeout: timeoutMs
6839
+ detached: true
6840
+ });
6841
+ let stdout = "";
6842
+ let stderr = "";
6843
+ child.stdout?.on("data", (chunk) => {
6844
+ const s = chunk.toString("utf-8");
6845
+ stdout += s;
6846
+ process.stdout.write(s);
6840
6847
  });
6841
- const stdout = r.stdout ?? "";
6842
- const stderr = r.stderr ?? "";
6843
- if (stdout) process.stdout.write(stdout);
6844
- if (stderr) process.stderr.write(stderr);
6848
+ child.stderr?.on("data", (chunk) => {
6849
+ const s = chunk.toString("utf-8");
6850
+ stderr += s;
6851
+ process.stderr.write(s);
6852
+ });
6853
+ let timedOut = false;
6854
+ let killTimer;
6855
+ let escalateTimer;
6856
+ const result = await new Promise(
6857
+ (resolve4) => {
6858
+ let settled = false;
6859
+ const settle = (code, signal, spawnErr) => {
6860
+ if (settled) return;
6861
+ settled = true;
6862
+ if (killTimer) clearTimeout(killTimer);
6863
+ if (escalateTimer) clearTimeout(escalateTimer);
6864
+ resolve4({ code, signal, spawnErr });
6865
+ };
6866
+ child.on("error", (err) => settle(null, null, err));
6867
+ child.on("close", (code, signal) => settle(code, signal));
6868
+ if (typeof child.pid === "number") {
6869
+ const pgid = child.pid;
6870
+ killTimer = setTimeout(() => {
6871
+ timedOut = true;
6872
+ try {
6873
+ process.kill(-pgid, "SIGTERM");
6874
+ } catch {
6875
+ }
6876
+ escalateTimer = setTimeout(() => {
6877
+ try {
6878
+ process.kill(-pgid, "SIGKILL");
6879
+ } catch {
6880
+ }
6881
+ }, SIGKILL_GRACE_MS);
6882
+ }, timeoutMs);
6883
+ }
6884
+ }
6885
+ );
6886
+ if (result.spawnErr) {
6887
+ ctx.skipAgent = true;
6888
+ ctx.output.exitCode = 99;
6889
+ ctx.output.reason = `shell '${shellName}' failed to spawn: ${result.spawnErr.message}`;
6890
+ return;
6891
+ }
6845
6892
  if (/^KODY_SKIP_AGENT=true\s*$/m.test(stdout)) {
6846
6893
  ctx.skipAgent = true;
6847
6894
  if (ctx.output.exitCode === void 0) ctx.output.exitCode = 0;
@@ -6850,7 +6897,6 @@ function runShellEntry(entry, ctx, profile) {
6850
6897
  if (prUrlMatch?.[1]) ctx.output.prUrl = prUrlMatch[1].trim();
6851
6898
  const reasonMatch = stdout.match(/^KODY_REASON=(.+)$/m);
6852
6899
  if (reasonMatch?.[1]) ctx.output.reason = reasonMatch[1].trim();
6853
- const timedOut = r.status === null && r.signal !== null;
6854
6900
  if (timedOut) {
6855
6901
  ctx.skipAgent = true;
6856
6902
  const seconds = Math.round(timeoutMs / 1e3);
@@ -6858,11 +6904,11 @@ function runShellEntry(entry, ctx, profile) {
6858
6904
  ctx.output.exitCode = 124;
6859
6905
  }
6860
6906
  if (!ctx.output.reason) {
6861
- ctx.output.reason = `shell '${shellName}' timed out after ${seconds}s (signal=${r.signal})`;
6907
+ ctx.output.reason = `shell '${shellName}' timed out after ${seconds}s (process group signalled SIGTERM/SIGKILL)`;
6862
6908
  }
6863
6909
  return;
6864
6910
  }
6865
- const exit = r.status ?? -1;
6911
+ const exit = result.code ?? -1;
6866
6912
  if (exit !== 0) {
6867
6913
  ctx.skipAgent = true;
6868
6914
  if (ctx.output.exitCode === void 0 || ctx.output.exitCode === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.3.57",
3
+ "version": "0.3.58",
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",