@kody-ade/kody-engine 0.4.474 → 0.4.476

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 +29 -9
  2. package/package.json +1 -1
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.474",
18
+ version: "0.4.476",
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
  type: "module",
@@ -1737,8 +1737,15 @@ function parseCapabilityContract(raw) {
1737
1737
  if (secrets && parsed.execution !== "script") {
1738
1738
  throw new Error('contract.json secrets are supported only when execution is "script"');
1739
1739
  }
1740
+ const timeoutMs = parsed.timeoutMs === void 0 ? void 0 : typeof parsed.timeoutMs === "number" && Number.isInteger(parsed.timeoutMs) && parsed.timeoutMs >= 1e3 && parsed.timeoutMs <= 6 * 60 * 60 * 1e3 ? parsed.timeoutMs : null;
1741
+ if (timeoutMs === null) {
1742
+ throw new Error("contract.json timeoutMs must be an integer from 1000 to 21600000");
1743
+ }
1744
+ if (timeoutMs !== void 0 && parsed.execution !== "script") {
1745
+ throw new Error('contract.json timeoutMs is supported only when execution is "script"');
1746
+ }
1740
1747
  const unsupported = Object.keys(parsed).filter(
1741
- (key) => key !== "execution" && key !== "secrets" && key !== "input" && key !== "output"
1748
+ (key) => key !== "execution" && key !== "secrets" && key !== "timeoutMs" && key !== "input" && key !== "output"
1742
1749
  );
1743
1750
  if (unsupported.length > 0) {
1744
1751
  throw new Error(`contract.json contains unsupported fields: ${unsupported.join(", ")}`);
@@ -1746,6 +1753,7 @@ function parseCapabilityContract(raw) {
1746
1753
  return {
1747
1754
  ...parsed.execution ? { execution: parsed.execution } : {},
1748
1755
  ...secrets ? { secrets } : {},
1756
+ ...timeoutMs !== void 0 ? { timeoutMs } : {},
1749
1757
  input: parsed.input,
1750
1758
  output: parsed.output
1751
1759
  };
@@ -15564,6 +15572,7 @@ var init_loadSimpleCapability = __esm({
15564
15572
  if (capability.contract?.execution === "script") {
15565
15573
  ctx.data.capabilityScriptPath = path40.join(capability.dir, "tools", "run.sh");
15566
15574
  ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
15575
+ ctx.data.capabilityScriptTimeoutMs = capability.contract.timeoutMs;
15567
15576
  }
15568
15577
  if (capability.config.outputSchema) {
15569
15578
  ctx.data.capabilityOutputSchema = capability.config.outputSchema;
@@ -19030,6 +19039,9 @@ var init_runScheduledImplementationTick = __esm({
19030
19039
  // src/scripts/runSimpleCapabilityScript.ts
19031
19040
  import { spawnSync as spawnSync3 } from "child_process";
19032
19041
  import * as fs47 from "fs";
19042
+ function formatDuration2(timeoutMs) {
19043
+ return timeoutMs % 6e4 === 0 ? `${timeoutMs / 6e4} minutes` : `${timeoutMs}ms`;
19044
+ }
19033
19045
  function declaredSecrets(names, parent) {
19034
19046
  if (!Array.isArray(names)) return {};
19035
19047
  const secrets = {};
@@ -19051,12 +19063,13 @@ function isRegularFile2(filePath) {
19051
19063
  function isStringRecord(value) {
19052
19064
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
19053
19065
  }
19054
- var SCRIPT_TIMEOUT_MS, SCRIPT_MAX_OUTPUT_BYTES, runSimpleCapabilityScript;
19066
+ var DEFAULT_SCRIPT_TIMEOUT_MS, SCRIPT_MAX_OUTPUT_BYTES, runSimpleCapabilityScript;
19055
19067
  var init_runSimpleCapabilityScript = __esm({
19056
19068
  "src/scripts/runSimpleCapabilityScript.ts"() {
19057
19069
  "use strict";
19070
+ init_capabilityResult();
19058
19071
  init_tickShellRunner();
19059
- SCRIPT_TIMEOUT_MS = 5 * 60 * 1e3;
19072
+ DEFAULT_SCRIPT_TIMEOUT_MS = 5 * 60 * 1e3;
19060
19073
  SCRIPT_MAX_OUTPUT_BYTES = 1024 * 1024;
19061
19074
  runSimpleCapabilityScript = async (ctx) => {
19062
19075
  ctx.skipAgent = true;
@@ -19068,6 +19081,7 @@ var init_runSimpleCapabilityScript = __esm({
19068
19081
  }
19069
19082
  const capabilityEnvironment2 = isStringRecord(ctx.data.capabilityEnvironment) ? ctx.data.capabilityEnvironment : {};
19070
19083
  const capabilitySecrets = declaredSecrets(ctx.data.capabilitySecretNames, process.env);
19084
+ const timeoutMs = typeof ctx.data.capabilityScriptTimeoutMs === "number" ? ctx.data.capabilityScriptTimeoutMs : DEFAULT_SCRIPT_TIMEOUT_MS;
19071
19085
  const result = spawnSync3("bash", [scriptPath], {
19072
19086
  cwd: ctx.cwd,
19073
19087
  env: {
@@ -19077,14 +19091,14 @@ var init_runSimpleCapabilityScript = __esm({
19077
19091
  },
19078
19092
  stdio: ["ignore", "pipe", "pipe"],
19079
19093
  encoding: "utf-8",
19080
- timeout: SCRIPT_TIMEOUT_MS,
19094
+ timeout: timeoutMs,
19081
19095
  maxBuffer: SCRIPT_MAX_OUTPUT_BYTES
19082
19096
  });
19083
19097
  if (result.stderr) process.stderr.write(result.stderr);
19084
19098
  if (result.error) {
19085
19099
  const timedOut = result.error.code === "ETIMEDOUT";
19086
19100
  ctx.output.exitCode = timedOut ? 124 : 99;
19087
- ctx.output.reason = timedOut ? "Capability script timed out after 5 minutes" : `Capability script failed to start: ${result.error.message}`;
19101
+ ctx.output.reason = timedOut ? `Capability script timed out after ${formatDuration2(timeoutMs)}` : `Capability script failed to start: ${result.error.message}`;
19088
19102
  return;
19089
19103
  }
19090
19104
  if (result.signal) {
@@ -19097,11 +19111,17 @@ var init_runSimpleCapabilityScript = __esm({
19097
19111
  ctx.output.reason = `Capability script exited ${result.status ?? 99}`;
19098
19112
  return;
19099
19113
  }
19114
+ const stdout = result.stdout ?? "";
19100
19115
  try {
19101
- ctx.data.capabilityScriptOutput = JSON.parse(result.stdout ?? "");
19116
+ ctx.data.capabilityScriptOutput = JSON.parse(stdout);
19102
19117
  } catch {
19118
+ const structuredResult = parseCapabilityResultsFromText(stdout).at(-1);
19119
+ if (structuredResult) {
19120
+ ctx.data.capabilityScriptOutput = structuredResult;
19121
+ return;
19122
+ }
19103
19123
  ctx.output.exitCode = 64;
19104
- ctx.output.reason = "Capability script must return exactly one valid JSON value on stdout";
19124
+ ctx.output.reason = "Capability script must return exactly one valid JSON value or emit a valid KODY_CAPABILITY_RESULT marker";
19105
19125
  }
19106
19126
  };
19107
19127
  }
@@ -22518,7 +22538,7 @@ function valueMatches(actual, expected) {
22518
22538
  return actual === expected;
22519
22539
  }
22520
22540
  function workflowStepTargetNumber(step, parent, chainData) {
22521
- if (step.target === "pr") return workflowPrNumber(chainData) ?? workflowTargetFactNumber(step, chainData);
22541
+ if (step.target === "pr") return workflowTargetFactNumber(step, chainData) ?? workflowPrNumber(chainData);
22522
22542
  if (step.target === "issue") return workflowIssueNumber(parent) ?? workflowTargetFactNumber(step, chainData);
22523
22543
  return typeof parent.target === "number" ? parent.target : targetFromCliArgs(parent.cliArgs);
22524
22544
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.474",
3
+ "version": "0.4.476",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",