@kody-ade/kody-engine 0.4.183 → 0.4.184
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 +48 -18
- package/dist/executables/goal-scheduler/profile.json +10 -0
- package/dist/executables/goal-scheduler/scheduler.sh +9 -0
- package/dist/executables/release-deploy/deploy.sh +0 -0
- package/dist/executables/release-prepare/prepare.sh +0 -0
- package/dist/executables/release-publish/publish.sh +0 -0
- package/dist/executables/resolve/apply-prefer.sh +0 -0
- package/dist/executables/revert/revert.sh +0 -0
- package/package.json +20 -22
package/dist/bin/kody.js
CHANGED
|
@@ -1309,7 +1309,7 @@ var init_loadPriorArt = __esm({
|
|
|
1309
1309
|
// package.json
|
|
1310
1310
|
var package_default = {
|
|
1311
1311
|
name: "@kody-ade/kody-engine",
|
|
1312
|
-
version: "0.4.
|
|
1312
|
+
version: "0.4.184",
|
|
1313
1313
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
1314
1314
|
license: "MIT",
|
|
1315
1315
|
type: "module",
|
|
@@ -1348,7 +1348,6 @@ var package_default = {
|
|
|
1348
1348
|
"@biomejs/biome": "^2.4.12",
|
|
1349
1349
|
"@types/node": "^22.5.4",
|
|
1350
1350
|
"@vitest/coverage-v8": "^4.1.4",
|
|
1351
|
-
playwright: "^1.60.0",
|
|
1352
1351
|
tsup: "^8.5.1",
|
|
1353
1352
|
tsx: "^4.21.0",
|
|
1354
1353
|
typescript: "~5.7.0",
|
|
@@ -1409,10 +1408,10 @@ var HttpSink = class {
|
|
|
1409
1408
|
signal: AbortSignal.timeout(5e3)
|
|
1410
1409
|
});
|
|
1411
1410
|
if (!res.ok) {
|
|
1412
|
-
this.logger.warn(`HttpSink POST ${url} \u2192 ${res.status}`);
|
|
1411
|
+
this.logger.warn(`HttpSink POST ${redactUrl(url)} \u2192 ${res.status}`);
|
|
1413
1412
|
}
|
|
1414
1413
|
} catch (err) {
|
|
1415
|
-
this.logger.warn(`HttpSink POST ${url} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1414
|
+
this.logger.warn(`HttpSink POST ${redactUrl(url)} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1416
1415
|
}
|
|
1417
1416
|
}
|
|
1418
1417
|
};
|
|
@@ -1425,6 +1424,9 @@ var TeeSink = class {
|
|
|
1425
1424
|
await Promise.all(this.sinks.map((s) => s.emit(event)));
|
|
1426
1425
|
}
|
|
1427
1426
|
};
|
|
1427
|
+
function redactUrl(url) {
|
|
1428
|
+
return url.replace(/([?&]token=)[^&]+/gi, "$1***");
|
|
1429
|
+
}
|
|
1428
1430
|
function withSessionParam(baseUrl, sessionId) {
|
|
1429
1431
|
const joiner = baseUrl.includes("?") ? "&" : "?";
|
|
1430
1432
|
return `${baseUrl}${joiner}sessionId=${encodeURIComponent(sessionId)}`;
|
|
@@ -1654,7 +1656,11 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
1654
1656
|
issueContext: parseIssueContext(raw.issueContext),
|
|
1655
1657
|
testRequirements: parseTestRequirements(raw.testRequirements),
|
|
1656
1658
|
defaultExecutable: typeof raw.defaultExecutable === "string" && raw.defaultExecutable.length > 0 ? raw.defaultExecutable : "run",
|
|
1657
|
-
|
|
1659
|
+
// No bare-PR default ships with the engine (there is no `fix` executable),
|
|
1660
|
+
// so leave this unset unless a consumer configures a real one. Dispatch
|
|
1661
|
+
// treats a missing/unknown default as "unrecognized" rather than routing
|
|
1662
|
+
// to a phantom executable that would crash the executor at load time.
|
|
1663
|
+
defaultPrExecutable: typeof raw.defaultPrExecutable === "string" && raw.defaultPrExecutable.length > 0 ? raw.defaultPrExecutable : void 0,
|
|
1658
1664
|
aliases: mergeAliases(raw.aliases),
|
|
1659
1665
|
classify: parseClassifyConfig(raw.classify),
|
|
1660
1666
|
release: parseReleaseConfig(raw.release),
|
|
@@ -1717,9 +1723,7 @@ function parseJobsConfig(raw) {
|
|
|
1717
1723
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
1718
1724
|
}
|
|
1719
1725
|
var BUILTIN_ALIASES = {
|
|
1720
|
-
build: "run"
|
|
1721
|
-
orchestrate: "bug",
|
|
1722
|
-
orchestrator: "bug"
|
|
1726
|
+
build: "run"
|
|
1723
1727
|
};
|
|
1724
1728
|
function mergeAliases(raw) {
|
|
1725
1729
|
const out = { ...BUILTIN_ALIASES };
|
|
@@ -1969,6 +1973,7 @@ async function runAgent(opts) {
|
|
|
1969
1973
|
let ndjsonWriteFailed = false;
|
|
1970
1974
|
let ndjsonWriteError;
|
|
1971
1975
|
let sawMutatingTool = false;
|
|
1976
|
+
let sawTerminalSuccess = false;
|
|
1972
1977
|
try {
|
|
1973
1978
|
const queryOptions = {
|
|
1974
1979
|
model: opts.model.model,
|
|
@@ -2180,6 +2185,7 @@ async function runAgent(opts) {
|
|
|
2180
2185
|
if (m.subtype === "success") {
|
|
2181
2186
|
outcome = "completed";
|
|
2182
2187
|
outcomeKind = "ok";
|
|
2188
|
+
sawTerminalSuccess = true;
|
|
2183
2189
|
const text = (typeof m.result === "string" ? m.result : "").trim();
|
|
2184
2190
|
if (text) resultTexts.push(text);
|
|
2185
2191
|
} else {
|
|
@@ -2190,9 +2196,13 @@ async function runAgent(opts) {
|
|
|
2190
2196
|
}
|
|
2191
2197
|
}
|
|
2192
2198
|
} catch (e) {
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2199
|
+
if (sawTerminalSuccess) {
|
|
2200
|
+
errorMessage = e instanceof Error ? e.message : String(e);
|
|
2201
|
+
} else {
|
|
2202
|
+
outcome = "failed";
|
|
2203
|
+
outcomeKind = "model_error";
|
|
2204
|
+
errorMessage = e instanceof Error ? e.message : String(e);
|
|
2205
|
+
}
|
|
2196
2206
|
} finally {
|
|
2197
2207
|
try {
|
|
2198
2208
|
fullLog.end();
|
|
@@ -3296,7 +3306,7 @@ function autoDispatch(opts) {
|
|
|
3296
3306
|
}
|
|
3297
3307
|
}
|
|
3298
3308
|
if (!executable && !firstToken) {
|
|
3299
|
-
executable = isPr ? opts?.config?.defaultPrExecutable ??
|
|
3309
|
+
executable = isPr ? opts?.config?.defaultPrExecutable ?? null : opts?.config?.defaultExecutable ?? null;
|
|
3300
3310
|
}
|
|
3301
3311
|
if (isBotAuthor && !consumedFirstToken) {
|
|
3302
3312
|
process.stderr.write(
|
|
@@ -4533,7 +4543,7 @@ var FORBIDDEN_PATH_PREFIXES = [
|
|
|
4533
4543
|
"build/"
|
|
4534
4544
|
];
|
|
4535
4545
|
var ALLOWED_PATH_PREFIXES = [".kody/memory/", ".kody/tasks/"];
|
|
4536
|
-
var FORBIDDEN_PATH_EXACT = /* @__PURE__ */ new Set([".env", ".kody-pip-requirements.txt"]);
|
|
4546
|
+
var FORBIDDEN_PATH_EXACT = /* @__PURE__ */ new Set([".env", ".kody-pip-requirements.txt", "kody.config.json"]);
|
|
4537
4547
|
var FORBIDDEN_PATH_SUFFIXES = [".log"];
|
|
4538
4548
|
var CONVENTIONAL_PREFIXES = [
|
|
4539
4549
|
"feat:",
|
|
@@ -7546,13 +7556,33 @@ var ContentsApiBackend = class {
|
|
|
7546
7556
|
};
|
|
7547
7557
|
if (typeof loaded.handle === "string") payload.sha = loaded.handle;
|
|
7548
7558
|
ensureStateBranch(this.owner, this.repo, this.cwd);
|
|
7549
|
-
|
|
7559
|
+
try {
|
|
7560
|
+
this.put(loaded.path, payload);
|
|
7561
|
+
} catch (err) {
|
|
7562
|
+
if (!isShaConflict(err)) throw err;
|
|
7563
|
+
const current = this.load(slug);
|
|
7564
|
+
if (!current.created && isStateUnchanged(current.state, next)) return false;
|
|
7565
|
+
if (typeof current.handle === "string") payload.sha = current.handle;
|
|
7566
|
+
else delete payload.sha;
|
|
7567
|
+
process.stderr.write(
|
|
7568
|
+
`[kody] jobState: concurrent write detected for ${slug}; reloaded SHA and retrying (last-write-wins)
|
|
7569
|
+
`
|
|
7570
|
+
);
|
|
7571
|
+
this.put(loaded.path, payload);
|
|
7572
|
+
}
|
|
7573
|
+
return true;
|
|
7574
|
+
}
|
|
7575
|
+
put(filePath, payload) {
|
|
7576
|
+
gh(["api", "--method", "PUT", `/repos/${this.owner}/${this.repo}/contents/${filePath}`, "--input", "-"], {
|
|
7550
7577
|
cwd: this.cwd,
|
|
7551
7578
|
input: JSON.stringify(payload)
|
|
7552
7579
|
});
|
|
7553
|
-
return true;
|
|
7554
7580
|
}
|
|
7555
7581
|
};
|
|
7582
|
+
function isShaConflict(err) {
|
|
7583
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7584
|
+
return /HTTP 409/i.test(msg) || /HTTP 422/i.test(msg) || /does not match|is at|but expected/i.test(msg);
|
|
7585
|
+
}
|
|
7556
7586
|
|
|
7557
7587
|
// src/scripts/jobState/localFileBackend.ts
|
|
7558
7588
|
import * as fs28 from "fs";
|
|
@@ -7655,7 +7685,9 @@ var LocalFileBackend = class {
|
|
|
7655
7685
|
const absPath = path27.join(this.cwd, loaded.path);
|
|
7656
7686
|
fs28.mkdirSync(path27.dirname(absPath), { recursive: true });
|
|
7657
7687
|
const body = JSON.stringify(next, null, 2) + "\n";
|
|
7658
|
-
|
|
7688
|
+
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
7689
|
+
fs28.writeFileSync(tmpPath, body, "utf-8");
|
|
7690
|
+
fs28.renameSync(tmpPath, absPath);
|
|
7659
7691
|
return true;
|
|
7660
7692
|
}
|
|
7661
7693
|
cacheKeyPrefix() {
|
|
@@ -12858,8 +12890,6 @@ var saveTaskState = async (ctx, profile) => {
|
|
|
12858
12890
|
if (!target || !number || !state) return;
|
|
12859
12891
|
const executable = profile.name;
|
|
12860
12892
|
const action = ctx.data.action ?? synthesizeAction(ctx);
|
|
12861
|
-
if (ctx.output.prUrl && !state.core.prUrl) state.core.prUrl = ctx.output.prUrl;
|
|
12862
|
-
if (typeof ctx.data.runUrl === "string") state.core.runUrl = ctx.data.runUrl;
|
|
12863
12893
|
const next = reduce(state, executable, action, profile.phase);
|
|
12864
12894
|
if (ctx.output.prUrl) next.core.prUrl = ctx.output.prUrl;
|
|
12865
12895
|
if (typeof ctx.data.runUrl === "string") next.core.runUrl = ctx.data.runUrl;
|
|
@@ -29,6 +29,16 @@
|
|
|
29
29
|
"verify": "gh auth status",
|
|
30
30
|
"usage": "",
|
|
31
31
|
"allowedUses": ["api", "issue", "pr"]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "python3",
|
|
35
|
+
"install": {
|
|
36
|
+
"required": true,
|
|
37
|
+
"checkCommand": "command -v python3"
|
|
38
|
+
},
|
|
39
|
+
"verify": "python3 --version",
|
|
40
|
+
"usage": "scheduler.sh parses each goal's state.json to read its 'state' field",
|
|
41
|
+
"allowedUses": []
|
|
32
42
|
}
|
|
33
43
|
],
|
|
34
44
|
"inputArtifacts": [],
|
|
@@ -11,6 +11,15 @@ set -euo pipefail
|
|
|
11
11
|
|
|
12
12
|
goals_dir=".kody/goals"
|
|
13
13
|
|
|
14
|
+
# python3 parses each goal's state.json below. It is declared as a required
|
|
15
|
+
# cliTool in profile.json, but guard here too: without this check a missing
|
|
16
|
+
# interpreter silently makes EVERY goal read state="" → treated as inactive →
|
|
17
|
+
# nothing ticks, reported as a misleading success. Fail loud instead.
|
|
18
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
19
|
+
echo "[goal-scheduler] FATAL: python3 not found on PATH (required to read goal state)" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
14
23
|
# Goal state lives on the dedicated `kody-state` branch, not the default branch
|
|
15
24
|
# (keeps `chore(goals): …` churn out of code history). Materialize it into the
|
|
16
25
|
# working tree so the glob below sees current state. Best-effort: `kody-state`
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
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.184",
|
|
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",
|
|
@@ -12,24 +12,6 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"kody:run": "tsx bin/kody.ts",
|
|
17
|
-
"serve": "tsx bin/kody.ts serve",
|
|
18
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
19
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
20
|
-
"build": "tsup && node scripts/copy-assets.cjs",
|
|
21
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
22
|
-
"pretest": "pnpm check:modularity",
|
|
23
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
24
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
25
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
26
|
-
"test:all": "vitest run tests --no-coverage",
|
|
27
|
-
"typecheck": "tsc --noEmit",
|
|
28
|
-
"lint": "biome check",
|
|
29
|
-
"lint:fix": "biome check --write",
|
|
30
|
-
"format": "biome format --write",
|
|
31
|
-
"prepublishOnly": "pnpm build"
|
|
32
|
-
},
|
|
33
15
|
"dependencies": {
|
|
34
16
|
"@actions/cache": "^6.0.0",
|
|
35
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -39,7 +21,6 @@
|
|
|
39
21
|
"@biomejs/biome": "^2.4.12",
|
|
40
22
|
"@types/node": "^22.5.4",
|
|
41
23
|
"@vitest/coverage-v8": "^4.1.4",
|
|
42
|
-
"playwright": "^1.60.0",
|
|
43
24
|
"tsup": "^8.5.1",
|
|
44
25
|
"tsx": "^4.21.0",
|
|
45
26
|
"typescript": "~5.7.0",
|
|
@@ -53,5 +34,22 @@
|
|
|
53
34
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
54
35
|
},
|
|
55
36
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
56
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
57
|
-
|
|
37
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
38
|
+
"scripts": {
|
|
39
|
+
"kody:run": "tsx bin/kody.ts",
|
|
40
|
+
"serve": "tsx bin/kody.ts serve",
|
|
41
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
42
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
43
|
+
"build": "tsup && node scripts/copy-assets.cjs",
|
|
44
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
45
|
+
"pretest": "pnpm check:modularity",
|
|
46
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
47
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
48
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
49
|
+
"test:all": "vitest run tests --no-coverage",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"lint": "biome check",
|
|
52
|
+
"lint:fix": "biome check --write",
|
|
53
|
+
"format": "biome format --write"
|
|
54
|
+
}
|
|
55
|
+
}
|