@kody-ade/kody-engine 0.4.566 → 0.4.567
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 +64 -19
- package/dist/implementations/types.ts +2 -0
- 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.
|
|
18
|
+
version: "0.4.567",
|
|
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",
|
|
@@ -1143,14 +1143,23 @@ function buildVerifyEnv(source = process.env) {
|
|
|
1143
1143
|
env.CI = source.CI ?? "1";
|
|
1144
1144
|
return env;
|
|
1145
1145
|
}
|
|
1146
|
-
function
|
|
1146
|
+
function abortMessage(signal) {
|
|
1147
|
+
const reason = signal.reason;
|
|
1148
|
+
return reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "verification aborted";
|
|
1149
|
+
}
|
|
1150
|
+
function runCommand(command, cwd, signal) {
|
|
1147
1151
|
return new Promise((resolve23) => {
|
|
1148
1152
|
const start = Date.now();
|
|
1153
|
+
if (signal?.aborted) {
|
|
1154
|
+
resolve23({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1149
1157
|
const child = spawn(command, {
|
|
1150
1158
|
cwd,
|
|
1151
1159
|
shell: true,
|
|
1152
1160
|
env: buildVerifyEnv(),
|
|
1153
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1161
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1162
|
+
detached: process.platform !== "win32"
|
|
1154
1163
|
});
|
|
1155
1164
|
const buffers = [];
|
|
1156
1165
|
let totalSize = 0;
|
|
@@ -1164,24 +1173,46 @@ function runCommand(command, cwd) {
|
|
|
1164
1173
|
};
|
|
1165
1174
|
child.stdout?.on("data", collect);
|
|
1166
1175
|
child.stderr?.on("data", collect);
|
|
1176
|
+
let settled = false;
|
|
1177
|
+
const killTree = (killSignal) => {
|
|
1178
|
+
try {
|
|
1179
|
+
if (process.platform !== "win32" && child.pid) process.kill(-child.pid, killSignal);
|
|
1180
|
+
else child.kill(killSignal);
|
|
1181
|
+
} catch {
|
|
1182
|
+
child.kill(killSignal);
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
const finish = (exitCode, extraTail = "") => {
|
|
1186
|
+
if (settled) return;
|
|
1187
|
+
settled = true;
|
|
1188
|
+
clearTimeout(timer);
|
|
1189
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1190
|
+
const output = Buffer.concat(buffers).toString("utf-8");
|
|
1191
|
+
const tail = [output, extraTail].filter(Boolean).join("\n").slice(-TAIL_CHARS);
|
|
1192
|
+
resolve23({ exitCode, durationMs: Date.now() - start, tail });
|
|
1193
|
+
};
|
|
1194
|
+
const terminate = () => {
|
|
1195
|
+
killTree("SIGTERM");
|
|
1196
|
+
setTimeout(() => killTree("SIGKILL"), 5e3).unref();
|
|
1197
|
+
};
|
|
1198
|
+
const onAbort = () => {
|
|
1199
|
+
terminate();
|
|
1200
|
+
finish(-1, signal ? abortMessage(signal) : "verification aborted");
|
|
1201
|
+
};
|
|
1202
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1167
1203
|
const timer = setTimeout(() => {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
if (!child.killed) child.kill("SIGKILL");
|
|
1171
|
-
}, 5e3);
|
|
1204
|
+
terminate();
|
|
1205
|
+
finish(-1, "verification command timed out");
|
|
1172
1206
|
}, COMMAND_TIMEOUT_MS);
|
|
1173
1207
|
child.on("exit", (code) => {
|
|
1174
|
-
|
|
1175
|
-
const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
|
|
1176
|
-
resolve23({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
|
|
1208
|
+
finish(code ?? -1);
|
|
1177
1209
|
});
|
|
1178
1210
|
child.on("error", (err) => {
|
|
1179
|
-
|
|
1180
|
-
resolve23({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
|
|
1211
|
+
finish(-1, err.message);
|
|
1181
1212
|
});
|
|
1182
1213
|
});
|
|
1183
1214
|
}
|
|
1184
|
-
async function verifyAll(config, cwd) {
|
|
1215
|
+
async function verifyAll(config, cwd, opts) {
|
|
1185
1216
|
const commands = [];
|
|
1186
1217
|
if (config.quality.typecheck) commands.push({ name: "typecheck", cmd: config.quality.typecheck });
|
|
1187
1218
|
if (config.quality.testUnit) commands.push({ name: "test", cmd: config.quality.testUnit });
|
|
@@ -1190,20 +1221,21 @@ async function verifyAll(config, cwd) {
|
|
|
1190
1221
|
const failed = [];
|
|
1191
1222
|
const details = {};
|
|
1192
1223
|
for (const { name, cmd } of commands) {
|
|
1193
|
-
const result = await runCommand(cmd, cwd);
|
|
1224
|
+
const result = await runCommand(cmd, cwd, opts?.signal);
|
|
1194
1225
|
details[name] = result;
|
|
1195
1226
|
if (result.exitCode !== 0) failed.push(name);
|
|
1196
1227
|
}
|
|
1197
1228
|
return { ok: failed.length === 0, failed, details };
|
|
1198
1229
|
}
|
|
1199
|
-
async function applyTestRetries(initial, testCommand, cwd, runner, testRetries = DEFAULT_TEST_RETRIES) {
|
|
1230
|
+
async function applyTestRetries(initial, testCommand, cwd, runner, testRetries = DEFAULT_TEST_RETRIES, signal) {
|
|
1200
1231
|
if (initial.ok) return { ...initial, recovered: [] };
|
|
1201
1232
|
const recovered = [];
|
|
1202
1233
|
const details = { ...initial.details };
|
|
1203
1234
|
let failed = [...initial.failed];
|
|
1204
1235
|
if (failed.includes("test") && testCommand && testRetries > 0) {
|
|
1205
1236
|
for (let attempt = 1; attempt <= testRetries; attempt++) {
|
|
1206
|
-
|
|
1237
|
+
if (signal?.aborted) break;
|
|
1238
|
+
const retry = await runner(testCommand, cwd, signal);
|
|
1207
1239
|
details[`test (retry ${attempt})`] = retry;
|
|
1208
1240
|
if (retry.exitCode === 0) {
|
|
1209
1241
|
failed = failed.filter((f) => f !== "test");
|
|
@@ -1215,8 +1247,8 @@ async function applyTestRetries(initial, testCommand, cwd, runner, testRetries =
|
|
|
1215
1247
|
return { ok: failed.length === 0, failed, details, recovered };
|
|
1216
1248
|
}
|
|
1217
1249
|
async function verifyAllWithRetry(config, cwd, opts) {
|
|
1218
|
-
const initial = await verifyAll(config, cwd);
|
|
1219
|
-
return applyTestRetries(initial, config.quality.testUnit, cwd, runCommand, opts?.testRetries);
|
|
1250
|
+
const initial = await verifyAll(config, cwd, { signal: opts?.signal });
|
|
1251
|
+
return applyTestRetries(initial, config.quality.testUnit, cwd, runCommand, opts?.testRetries, opts?.signal);
|
|
1220
1252
|
}
|
|
1221
1253
|
function stripAnsi(s) {
|
|
1222
1254
|
return s.replace(ANSI_RE, "");
|
|
@@ -20889,7 +20921,7 @@ var init_verifyReproFails = __esm({
|
|
|
20889
20921
|
// src/scripts/verifyWithRetry.ts
|
|
20890
20922
|
async function runVerify(ctx) {
|
|
20891
20923
|
try {
|
|
20892
|
-
const result = await verifyAllWithRetry(ctx.config, ctx.cwd);
|
|
20924
|
+
const result = await verifyAllWithRetry(ctx.config, ctx.cwd, { signal: ctx.abortSignal });
|
|
20893
20925
|
ctx.data.verifyOk = result.ok;
|
|
20894
20926
|
ctx.data.verifyReason = result.ok ? "" : summarizeFailure(result);
|
|
20895
20927
|
ctx.data.verifyRecovered = result.recovered ?? [];
|
|
@@ -20934,6 +20966,10 @@ var init_verifyWithRetry = __esm({
|
|
|
20934
20966
|
verifyWithRetry = async (ctx) => {
|
|
20935
20967
|
await runVerify(ctx);
|
|
20936
20968
|
if (ctx.data.verifyOk !== false) return;
|
|
20969
|
+
if (ctx.abortSignal?.aborted) {
|
|
20970
|
+
downgradeActionOnFailure(ctx);
|
|
20971
|
+
return;
|
|
20972
|
+
}
|
|
20937
20973
|
if (!ctx.data.agentDone) {
|
|
20938
20974
|
downgradeActionOnFailure(ctx);
|
|
20939
20975
|
return;
|
|
@@ -20970,6 +21006,10 @@ var init_verifyWithRetry = __esm({
|
|
|
20970
21006
|
process.stderr.write(`[kody] verify retry crashed: ${err instanceof Error ? err.message : String(err)}
|
|
20971
21007
|
`);
|
|
20972
21008
|
}
|
|
21009
|
+
if (ctx.abortSignal?.aborted) {
|
|
21010
|
+
downgradeActionOnFailure(ctx);
|
|
21011
|
+
return;
|
|
21012
|
+
}
|
|
20973
21013
|
await runVerify(ctx);
|
|
20974
21014
|
if (ctx.data.verifyOk === true) {
|
|
20975
21015
|
upgradeActionOnPass(ctx);
|
|
@@ -21973,6 +22013,7 @@ async function runImplementation(profileName, input) {
|
|
|
21973
22013
|
config,
|
|
21974
22014
|
verbose: input.verbose,
|
|
21975
22015
|
quiet: input.quiet,
|
|
22016
|
+
abortSignal: input.abortController?.signal,
|
|
21976
22017
|
// Phase 5 foundation: seed ctx.data with any preloaded values handed
|
|
21977
22018
|
// in by a parent (typically a container loop). Loaders that see
|
|
21978
22019
|
// their field already populated take the fast path and skip the
|
|
@@ -22054,6 +22095,10 @@ async function runImplementation(profileName, input) {
|
|
|
22054
22095
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
22055
22096
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
22056
22097
|
const invokeAgent = async (prompt) => {
|
|
22098
|
+
if (input.abortController?.signal.aborted) {
|
|
22099
|
+
const reason = input.abortController.signal.reason;
|
|
22100
|
+
throw reason instanceof Error ? reason : new Error("agent invocation aborted");
|
|
22101
|
+
}
|
|
22057
22102
|
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path51.isAbsolute(p) ? p : path51.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
22058
22103
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
22059
22104
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
@@ -456,6 +456,8 @@ export interface Context {
|
|
|
456
456
|
/** Stream-output verbosity. */
|
|
457
457
|
verbose?: boolean
|
|
458
458
|
quiet?: boolean
|
|
459
|
+
/** Cancellation owned by the enclosing job or workflow step. */
|
|
460
|
+
abortSignal?: AbortSignal
|
|
459
461
|
/** Opaque bag scripts populate during preflight (issue, pr, diff, logs, …). */
|
|
460
462
|
data: Record<string, unknown>
|
|
461
463
|
/** Final output the executor returns. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.567",
|
|
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",
|