@kody-ade/kody-engine 0.4.475 → 0.4.477

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.475",
18
+ version: "0.4.477",
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",
@@ -457,6 +457,23 @@ function parseReleaseConfig(raw) {
457
457
  if (typeof r.allowAdminMerge === "boolean") out.allowAdminMerge = r.allowAdminMerge;
458
458
  if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
459
459
  if (typeof r.timeoutMs === "number" && r.timeoutMs > 0) out.timeoutMs = Math.floor(r.timeoutMs);
460
+ if (r.validation && typeof r.validation === "object") {
461
+ const validation = r.validation;
462
+ const workflow = typeof validation.workflow === "string" ? validation.workflow.trim() : "";
463
+ if (workflow) {
464
+ const inputs = validation.inputs && typeof validation.inputs === "object" ? Object.fromEntries(
465
+ Object.entries(
466
+ validation.inputs
467
+ ).filter(
468
+ (entry) => /^[a-z][a-z0-9_]*$/.test(entry[0]) && (typeof entry[1] === "string" || typeof entry[1] === "number" || typeof entry[1] === "boolean")
469
+ )
470
+ ) : void 0;
471
+ out.validation = {
472
+ workflow,
473
+ ...inputs && Object.keys(inputs).length > 0 ? { inputs } : {}
474
+ };
475
+ }
476
+ }
460
477
  return Object.keys(out).length > 0 ? out : void 0;
461
478
  }
462
479
  function parseIssueContext(raw) {
@@ -1737,8 +1754,15 @@ function parseCapabilityContract(raw) {
1737
1754
  if (secrets && parsed.execution !== "script") {
1738
1755
  throw new Error('contract.json secrets are supported only when execution is "script"');
1739
1756
  }
1757
+ 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;
1758
+ if (timeoutMs === null) {
1759
+ throw new Error("contract.json timeoutMs must be an integer from 1000 to 21600000");
1760
+ }
1761
+ if (timeoutMs !== void 0 && parsed.execution !== "script") {
1762
+ throw new Error('contract.json timeoutMs is supported only when execution is "script"');
1763
+ }
1740
1764
  const unsupported = Object.keys(parsed).filter(
1741
- (key) => key !== "execution" && key !== "secrets" && key !== "input" && key !== "output"
1765
+ (key) => key !== "execution" && key !== "secrets" && key !== "timeoutMs" && key !== "input" && key !== "output"
1742
1766
  );
1743
1767
  if (unsupported.length > 0) {
1744
1768
  throw new Error(`contract.json contains unsupported fields: ${unsupported.join(", ")}`);
@@ -1746,6 +1770,7 @@ function parseCapabilityContract(raw) {
1746
1770
  return {
1747
1771
  ...parsed.execution ? { execution: parsed.execution } : {},
1748
1772
  ...secrets ? { secrets } : {},
1773
+ ...timeoutMs !== void 0 ? { timeoutMs } : {},
1749
1774
  input: parsed.input,
1750
1775
  output: parsed.output
1751
1776
  };
@@ -15564,6 +15589,7 @@ var init_loadSimpleCapability = __esm({
15564
15589
  if (capability.contract?.execution === "script") {
15565
15590
  ctx.data.capabilityScriptPath = path40.join(capability.dir, "tools", "run.sh");
15566
15591
  ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
15592
+ ctx.data.capabilityScriptTimeoutMs = capability.contract.timeoutMs;
15567
15593
  }
15568
15594
  if (capability.config.outputSchema) {
15569
15595
  ctx.data.capabilityOutputSchema = capability.config.outputSchema;
@@ -19030,6 +19056,9 @@ var init_runScheduledImplementationTick = __esm({
19030
19056
  // src/scripts/runSimpleCapabilityScript.ts
19031
19057
  import { spawnSync as spawnSync3 } from "child_process";
19032
19058
  import * as fs47 from "fs";
19059
+ function formatDuration2(timeoutMs) {
19060
+ return timeoutMs % 6e4 === 0 ? `${timeoutMs / 6e4} minutes` : `${timeoutMs}ms`;
19061
+ }
19033
19062
  function declaredSecrets(names, parent) {
19034
19063
  if (!Array.isArray(names)) return {};
19035
19064
  const secrets = {};
@@ -19051,13 +19080,13 @@ function isRegularFile2(filePath) {
19051
19080
  function isStringRecord(value) {
19052
19081
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
19053
19082
  }
19054
- var SCRIPT_TIMEOUT_MS, SCRIPT_MAX_OUTPUT_BYTES, runSimpleCapabilityScript;
19083
+ var DEFAULT_SCRIPT_TIMEOUT_MS, SCRIPT_MAX_OUTPUT_BYTES, runSimpleCapabilityScript;
19055
19084
  var init_runSimpleCapabilityScript = __esm({
19056
19085
  "src/scripts/runSimpleCapabilityScript.ts"() {
19057
19086
  "use strict";
19058
19087
  init_capabilityResult();
19059
19088
  init_tickShellRunner();
19060
- SCRIPT_TIMEOUT_MS = 5 * 60 * 1e3;
19089
+ DEFAULT_SCRIPT_TIMEOUT_MS = 5 * 60 * 1e3;
19061
19090
  SCRIPT_MAX_OUTPUT_BYTES = 1024 * 1024;
19062
19091
  runSimpleCapabilityScript = async (ctx) => {
19063
19092
  ctx.skipAgent = true;
@@ -19069,6 +19098,7 @@ var init_runSimpleCapabilityScript = __esm({
19069
19098
  }
19070
19099
  const capabilityEnvironment2 = isStringRecord(ctx.data.capabilityEnvironment) ? ctx.data.capabilityEnvironment : {};
19071
19100
  const capabilitySecrets = declaredSecrets(ctx.data.capabilitySecretNames, process.env);
19101
+ const timeoutMs = typeof ctx.data.capabilityScriptTimeoutMs === "number" ? ctx.data.capabilityScriptTimeoutMs : DEFAULT_SCRIPT_TIMEOUT_MS;
19072
19102
  const result = spawnSync3("bash", [scriptPath], {
19073
19103
  cwd: ctx.cwd,
19074
19104
  env: {
@@ -19078,14 +19108,14 @@ var init_runSimpleCapabilityScript = __esm({
19078
19108
  },
19079
19109
  stdio: ["ignore", "pipe", "pipe"],
19080
19110
  encoding: "utf-8",
19081
- timeout: SCRIPT_TIMEOUT_MS,
19111
+ timeout: timeoutMs,
19082
19112
  maxBuffer: SCRIPT_MAX_OUTPUT_BYTES
19083
19113
  });
19084
19114
  if (result.stderr) process.stderr.write(result.stderr);
19085
19115
  if (result.error) {
19086
19116
  const timedOut = result.error.code === "ETIMEDOUT";
19087
19117
  ctx.output.exitCode = timedOut ? 124 : 99;
19088
- ctx.output.reason = timedOut ? "Capability script timed out after 5 minutes" : `Capability script failed to start: ${result.error.message}`;
19118
+ ctx.output.reason = timedOut ? `Capability script timed out after ${formatDuration2(timeoutMs)}` : `Capability script failed to start: ${result.error.message}`;
19089
19119
  return;
19090
19120
  }
19091
19121
  if (result.signal) {
@@ -150,6 +150,26 @@
150
150
  "draftRelease": { "type": "boolean" },
151
151
  "releaseBranch": { "type": "string" },
152
152
  "allowAdminMerge": { "type": "boolean" },
153
+ "validation": {
154
+ "type": "object",
155
+ "additionalProperties": false,
156
+ "required": ["workflow"],
157
+ "properties": {
158
+ "workflow": {
159
+ "type": "string",
160
+ "minLength": 1
161
+ },
162
+ "inputs": {
163
+ "type": "object",
164
+ "propertyNames": {
165
+ "pattern": "^[a-z][a-z0-9_]*$"
166
+ },
167
+ "additionalProperties": {
168
+ "type": ["string", "number", "boolean"]
169
+ }
170
+ }
171
+ }
172
+ },
153
173
  "timeoutMs": {
154
174
  "type": "integer",
155
175
  "minimum": 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.475",
3
+ "version": "0.4.477",
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",