@kody-ade/kody-engine 0.3.51 → 0.3.53

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
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@kody-ade/kody-engine",
6
- version: "0.3.51",
6
+ version: "0.3.53",
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",
@@ -1313,6 +1313,12 @@ function parseScriptList(p, key, raw) {
1313
1313
  if (r.with && typeof r.with === "object") {
1314
1314
  entry.with = r.with;
1315
1315
  }
1316
+ if (typeof r.timeoutSec === "number" && r.timeoutSec > 0) {
1317
+ if (!hasShell) {
1318
+ throw new ProfileError(p, `scripts.${key}[${i}] "timeoutSec" only applies to shell entries`);
1319
+ }
1320
+ entry.timeoutSec = r.timeoutSec;
1321
+ }
1316
1322
  out.push(entry);
1317
1323
  }
1318
1324
  return out;
@@ -1934,7 +1940,10 @@ function parseAgentResult(finalText) {
1934
1940
  priorArt: "",
1935
1941
  failureReason: "agent produced no final message"
1936
1942
  };
1937
- const failedMatch = text.match(/(?:^|\n)\s*FAILED\s*:\s*(.+?)\s*$/s);
1943
+ const MARKDOWN_PREFIX = "[\\s>*_#`~\\-]*";
1944
+ const FAILED_RE = new RegExp(`(?:^|\\n)${MARKDOWN_PREFIX}FAILED${MARKDOWN_PREFIX}\\s*:\\s*(.+?)\\s*$`, "is");
1945
+ const DONE_RE = new RegExp(`(?:^|\\n)${MARKDOWN_PREFIX}DONE\\b`, "i");
1946
+ const failedMatch = text.match(FAILED_RE);
1938
1947
  if (failedMatch) {
1939
1948
  return {
1940
1949
  done: false,
@@ -1943,11 +1952,11 @@ function parseAgentResult(finalText) {
1943
1952
  feedbackActions: "",
1944
1953
  planDeviations: "",
1945
1954
  priorArt: "",
1946
- failureReason: failedMatch[1].trim()
1955
+ failureReason: stripMarkdownEmphasis(failedMatch[1])
1947
1956
  };
1948
1957
  }
1949
- const hasDoneMarker = /(^|\n)\s*DONE\b/i.test(text);
1950
- const hasCommitMsg = /^[ \t]*COMMIT_MSG\s*:/im.test(text);
1958
+ const hasDoneMarker = DONE_RE.test(text);
1959
+ const hasCommitMsg = /^[\s>*_#`~\-]*COMMIT_MSG\s*:/im.test(text);
1951
1960
  if (!hasDoneMarker && !hasCommitMsg) {
1952
1961
  return {
1953
1962
  done: false,
@@ -1959,8 +1968,8 @@ function parseAgentResult(finalText) {
1959
1968
  failureReason: "no DONE or FAILED marker in agent output"
1960
1969
  };
1961
1970
  }
1962
- const commitMatch = text.match(/^[ \t]*COMMIT_MSG\s*:\s*(.+)$/im);
1963
- const commitMessage = commitMatch ? commitMatch[1].trim() : "";
1971
+ const commitMatch = text.match(/^[\s>*_#`~\-]*COMMIT_MSG[\s>*_#`~\-]*\s*:\s*(.+)$/im);
1972
+ const commitMessage = commitMatch ? stripMarkdownEmphasis(commitMatch[1]) : "";
1964
1973
  const feedbackActions = extractBlock(
1965
1974
  text,
1966
1975
  /(?:^|\n)[ \t]*FEEDBACK_ACTIONS\s*:[ \t]*\n/i,
@@ -1986,6 +1995,9 @@ function parseAgentResult(finalText) {
1986
1995
  }
1987
1996
  return { done: true, commitMessage, prSummary, feedbackActions, planDeviations, priorArt, failureReason: "" };
1988
1997
  }
1998
+ function stripMarkdownEmphasis(s) {
1999
+ return s.trim().replace(/^[*_`~]+|[*_`~]+$/g, "").trim();
2000
+ }
1989
2001
  function extractBlock(text, startMarker, endMarker) {
1990
2002
  const startIdx = text.search(startMarker);
1991
2003
  if (startIdx === -1) return "";
@@ -6725,7 +6737,17 @@ function finish(out) {
6725
6737
  `);
6726
6738
  return out;
6727
6739
  }
6728
- var SHELL_TIMEOUT_MS = 3e5;
6740
+ var DEFAULT_SHELL_TIMEOUT_MS = 3e5;
6741
+ function resolveShellTimeoutMs(entry) {
6742
+ if (typeof entry.timeoutSec === "number" && entry.timeoutSec > 0) {
6743
+ return Math.floor(entry.timeoutSec * 1e3);
6744
+ }
6745
+ const envSec = Number(process.env.KODY_SHELL_TIMEOUT_SEC);
6746
+ if (Number.isFinite(envSec) && envSec > 0) {
6747
+ return Math.floor(envSec * 1e3);
6748
+ }
6749
+ return DEFAULT_SHELL_TIMEOUT_MS;
6750
+ }
6729
6751
  function runShellEntry(entry, ctx, profile) {
6730
6752
  const shellName = entry.shell;
6731
6753
  const shellPath = path21.join(profile.dir, shellName);
@@ -6744,12 +6766,13 @@ function runShellEntry(entry, ctx, profile) {
6744
6766
  for (const [k, v] of flattenConfig(ctx.config)) {
6745
6767
  env[`KODY_CFG_${k}`] = v;
6746
6768
  }
6769
+ const timeoutMs = resolveShellTimeoutMs(entry);
6747
6770
  const r = spawnSync("bash", [shellPath, ...positional], {
6748
6771
  cwd: ctx.cwd,
6749
6772
  encoding: "utf-8",
6750
6773
  env,
6751
6774
  stdio: ["pipe", "pipe", "pipe"],
6752
- timeout: SHELL_TIMEOUT_MS
6775
+ timeout: timeoutMs
6753
6776
  });
6754
6777
  const stdout = r.stdout ?? "";
6755
6778
  const stderr = r.stderr ?? "";
@@ -6763,6 +6786,18 @@ function runShellEntry(entry, ctx, profile) {
6763
6786
  if (prUrlMatch?.[1]) ctx.output.prUrl = prUrlMatch[1].trim();
6764
6787
  const reasonMatch = stdout.match(/^KODY_REASON=(.+)$/m);
6765
6788
  if (reasonMatch?.[1]) ctx.output.reason = reasonMatch[1].trim();
6789
+ const timedOut = r.status === null && r.signal !== null;
6790
+ if (timedOut) {
6791
+ ctx.skipAgent = true;
6792
+ const seconds = Math.round(timeoutMs / 1e3);
6793
+ if (ctx.output.exitCode === void 0 || ctx.output.exitCode === 0) {
6794
+ ctx.output.exitCode = 124;
6795
+ }
6796
+ if (!ctx.output.reason) {
6797
+ ctx.output.reason = `shell '${shellName}' timed out after ${seconds}s (signal=${r.signal})`;
6798
+ }
6799
+ return;
6800
+ }
6766
6801
  const exit = r.status ?? -1;
6767
6802
  if (exit !== 0) {
6768
6803
  ctx.skipAgent = true;
@@ -185,6 +185,14 @@ export interface ScriptEntry {
185
185
  * dispatcher script can be reused with different `next` targets.
186
186
  */
187
187
  with?: Record<string, string | number | boolean>
188
+ /**
189
+ * Optional shell-script timeout in seconds. Only honored on `shell` entries.
190
+ * Falls back to `KODY_SHELL_TIMEOUT_SEC` env var, then the 300s default.
191
+ * Long-running shells (release publish, large repo verify) should declare
192
+ * a higher value rather than relying on the default and getting SIGKILLed
193
+ * with an opaque "exited -1".
194
+ */
195
+ timeoutSec?: number
188
196
  }
189
197
 
190
198
  export interface OutputContract {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.3.51",
3
+ "version": "0.3.53",
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",