@kody-ade/kody-engine 0.4.472 → 0.4.474
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.
|
|
18
|
+
version: "0.4.474",
|
|
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",
|
|
@@ -454,6 +454,7 @@ function parseReleaseConfig(raw) {
|
|
|
454
454
|
if (typeof r.productionUrl === "string") out.productionUrl = r.productionUrl;
|
|
455
455
|
if (typeof r.smokeCommand === "string") out.smokeCommand = r.smokeCommand;
|
|
456
456
|
if (typeof r.draftRelease === "boolean") out.draftRelease = r.draftRelease;
|
|
457
|
+
if (typeof r.allowAdminMerge === "boolean") out.allowAdminMerge = r.allowAdminMerge;
|
|
457
458
|
if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
|
|
458
459
|
if (typeof r.timeoutMs === "number" && r.timeoutMs > 0) out.timeoutMs = Math.floor(r.timeoutMs);
|
|
459
460
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
@@ -1729,12 +1730,22 @@ function parseCapabilityContract(raw) {
|
|
|
1729
1730
|
if (parsed.execution !== void 0 && parsed.execution !== "agent" && parsed.execution !== "script") {
|
|
1730
1731
|
throw new Error('contract.json execution must be "agent" or "script"');
|
|
1731
1732
|
}
|
|
1732
|
-
const
|
|
1733
|
+
const secrets = parsed.secrets === void 0 ? void 0 : Array.isArray(parsed.secrets) && parsed.secrets.every((name) => typeof name === "string" && /^[A-Z][A-Z0-9_]*$/.test(name)) ? [...new Set(parsed.secrets)] : null;
|
|
1734
|
+
if (secrets === null) {
|
|
1735
|
+
throw new Error("contract.json secrets must contain valid environment variable names");
|
|
1736
|
+
}
|
|
1737
|
+
if (secrets && parsed.execution !== "script") {
|
|
1738
|
+
throw new Error('contract.json secrets are supported only when execution is "script"');
|
|
1739
|
+
}
|
|
1740
|
+
const unsupported = Object.keys(parsed).filter(
|
|
1741
|
+
(key) => key !== "execution" && key !== "secrets" && key !== "input" && key !== "output"
|
|
1742
|
+
);
|
|
1733
1743
|
if (unsupported.length > 0) {
|
|
1734
1744
|
throw new Error(`contract.json contains unsupported fields: ${unsupported.join(", ")}`);
|
|
1735
1745
|
}
|
|
1736
1746
|
return {
|
|
1737
1747
|
...parsed.execution ? { execution: parsed.execution } : {},
|
|
1748
|
+
...secrets ? { secrets } : {},
|
|
1738
1749
|
input: parsed.input,
|
|
1739
1750
|
output: parsed.output
|
|
1740
1751
|
};
|
|
@@ -2316,7 +2327,7 @@ var init_convex_client = __esm({
|
|
|
2316
2327
|
|
|
2317
2328
|
// src/kody-api-client.ts
|
|
2318
2329
|
import { getFunctionName } from "convex/server";
|
|
2319
|
-
function
|
|
2330
|
+
function resolveKodyApiUrl(env) {
|
|
2320
2331
|
return (env.KODY_API_URL?.trim() || env.KODY_DASHBOARD_URL?.trim() || env.DASHBOARD_URL?.trim() || DEFAULT_KODY_API_URL).replace(/\/$/, "");
|
|
2321
2332
|
}
|
|
2322
2333
|
function oidcRequestUrl(env) {
|
|
@@ -2355,7 +2366,7 @@ function operationName(fn) {
|
|
|
2355
2366
|
async function callKodyApi(kind, fn, args, env) {
|
|
2356
2367
|
const call = async (forceToken) => {
|
|
2357
2368
|
const token = await githubOidcToken(env, forceToken);
|
|
2358
|
-
return fetch(`${
|
|
2369
|
+
return fetch(`${resolveKodyApiUrl(env)}/api/kody/engine/backend`, {
|
|
2359
2370
|
method: "POST",
|
|
2360
2371
|
headers: {
|
|
2361
2372
|
Authorization: `Bearer ${token}`,
|
|
@@ -2385,7 +2396,7 @@ function createKodyApiBackendClient(env = process.env) {
|
|
|
2385
2396
|
}
|
|
2386
2397
|
async function readRuntimeSecretFromKody(name, env = process.env) {
|
|
2387
2398
|
const token = await githubOidcToken(env);
|
|
2388
|
-
const response = await fetch(`${
|
|
2399
|
+
const response = await fetch(`${resolveKodyApiUrl(env)}/api/kody/engine/secret`, {
|
|
2389
2400
|
method: "POST",
|
|
2390
2401
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
2391
2402
|
body: JSON.stringify({ name }),
|
|
@@ -2398,7 +2409,7 @@ async function readRuntimeSecretFromKody(name, env = process.env) {
|
|
|
2398
2409
|
}
|
|
2399
2410
|
async function readPreviewContextFromKody(env = process.env) {
|
|
2400
2411
|
const token = await githubOidcToken(env);
|
|
2401
|
-
const response = await fetch(`${
|
|
2412
|
+
const response = await fetch(`${resolveKodyApiUrl(env)}/api/kody/engine/preview-context`, {
|
|
2402
2413
|
method: "POST",
|
|
2403
2414
|
headers: { Authorization: `Bearer ${token}` },
|
|
2404
2415
|
signal: AbortSignal.timeout(3e4)
|
|
@@ -2410,7 +2421,7 @@ var DEFAULT_KODY_API_URL, OIDC_AUDIENCE, cachedToken;
|
|
|
2410
2421
|
var init_kody_api_client = __esm({
|
|
2411
2422
|
"src/kody-api-client.ts"() {
|
|
2412
2423
|
"use strict";
|
|
2413
|
-
DEFAULT_KODY_API_URL = "https://dashboard-
|
|
2424
|
+
DEFAULT_KODY_API_URL = "https://kody-dashboard-aguy.vercel.app";
|
|
2414
2425
|
OIDC_AUDIENCE = "kody-api";
|
|
2415
2426
|
cachedToken = null;
|
|
2416
2427
|
}
|
|
@@ -13259,6 +13270,13 @@ var init_loopDefinitions = __esm({
|
|
|
13259
13270
|
|
|
13260
13271
|
// src/scripts/dispatchLoops.ts
|
|
13261
13272
|
import { randomUUID } from "crypto";
|
|
13273
|
+
function assertLoopDispatchesSucceeded(results) {
|
|
13274
|
+
const failed = results.filter((result) => result.status === "failed");
|
|
13275
|
+
if (failed.length === 0) return;
|
|
13276
|
+
throw new Error(
|
|
13277
|
+
`Loop dispatch failed: ${failed.map((result) => `${result.loopId}: ${result.reason}`).join("; ")}`
|
|
13278
|
+
);
|
|
13279
|
+
}
|
|
13262
13280
|
async function dispatchLoopsWith(input) {
|
|
13263
13281
|
const results = [];
|
|
13264
13282
|
for (const loop of input.loops) {
|
|
@@ -13421,6 +13439,7 @@ var init_dispatchLoops = __esm({
|
|
|
13421
13439
|
`);
|
|
13422
13440
|
}
|
|
13423
13441
|
ctx.data.loopDispatchResults = results;
|
|
13442
|
+
assertLoopDispatchesSucceeded(results);
|
|
13424
13443
|
};
|
|
13425
13444
|
}
|
|
13426
13445
|
});
|
|
@@ -15544,6 +15563,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
15544
15563
|
ctx.data.capabilityExecution = capability.contract?.execution ?? "agent";
|
|
15545
15564
|
if (capability.contract?.execution === "script") {
|
|
15546
15565
|
ctx.data.capabilityScriptPath = path40.join(capability.dir, "tools", "run.sh");
|
|
15566
|
+
ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
|
|
15547
15567
|
}
|
|
15548
15568
|
if (capability.config.outputSchema) {
|
|
15549
15569
|
ctx.data.capabilityOutputSchema = capability.config.outputSchema;
|
|
@@ -16569,6 +16589,7 @@ var init_parseSimpleCapabilityOutput = __esm({
|
|
|
16569
16589
|
"src/scripts/parseSimpleCapabilityOutput.ts"() {
|
|
16570
16590
|
"use strict";
|
|
16571
16591
|
init_capability_contract_validation();
|
|
16592
|
+
init_capabilityResult();
|
|
16572
16593
|
parseSimpleCapabilityOutput = async (ctx, _profile, agentResult) => {
|
|
16573
16594
|
const output = Object.hasOwn(ctx.data, "capabilityScriptOutput") ? ctx.data.capabilityScriptOutput : parseOutput(agentResult?.finalText);
|
|
16574
16595
|
if (output === void 0) {
|
|
@@ -16617,6 +16638,12 @@ var init_parseSimpleCapabilityOutput = __esm({
|
|
|
16617
16638
|
}
|
|
16618
16639
|
}
|
|
16619
16640
|
ctx.data.capabilityOutput = output;
|
|
16641
|
+
const structuredResult = parseCapabilityResult(output);
|
|
16642
|
+
if (structuredResult) {
|
|
16643
|
+
ctx.output.reason = structuredResult.summary;
|
|
16644
|
+
ctx.data.capabilityResults = [structuredResult];
|
|
16645
|
+
return;
|
|
16646
|
+
}
|
|
16620
16647
|
const result = isObject2(output) ? output : {};
|
|
16621
16648
|
const data = isObject2(result.data) ? result.data : isObject2(output) ? output : { output };
|
|
16622
16649
|
const summary = typeof result.summary === "string" ? result.summary : "Capability completed";
|
|
@@ -19003,6 +19030,16 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
19003
19030
|
// src/scripts/runSimpleCapabilityScript.ts
|
|
19004
19031
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
19005
19032
|
import * as fs47 from "fs";
|
|
19033
|
+
function declaredSecrets(names, parent) {
|
|
19034
|
+
if (!Array.isArray(names)) return {};
|
|
19035
|
+
const secrets = {};
|
|
19036
|
+
for (const name of names) {
|
|
19037
|
+
if (typeof name !== "string" || !/^[A-Z][A-Z0-9_]*$/.test(name)) continue;
|
|
19038
|
+
const value = parent[name];
|
|
19039
|
+
if (value !== void 0) secrets[name] = value;
|
|
19040
|
+
}
|
|
19041
|
+
return secrets;
|
|
19042
|
+
}
|
|
19006
19043
|
function isRegularFile2(filePath) {
|
|
19007
19044
|
try {
|
|
19008
19045
|
const stat = fs47.lstatSync(filePath);
|
|
@@ -19030,10 +19067,12 @@ var init_runSimpleCapabilityScript = __esm({
|
|
|
19030
19067
|
return;
|
|
19031
19068
|
}
|
|
19032
19069
|
const capabilityEnvironment2 = isStringRecord(ctx.data.capabilityEnvironment) ? ctx.data.capabilityEnvironment : {};
|
|
19070
|
+
const capabilitySecrets = declaredSecrets(ctx.data.capabilitySecretNames, process.env);
|
|
19033
19071
|
const result = spawnSync3("bash", [scriptPath], {
|
|
19034
19072
|
cwd: ctx.cwd,
|
|
19035
19073
|
env: {
|
|
19036
19074
|
...buildTickChildEnv(process.env, false),
|
|
19075
|
+
...capabilitySecrets,
|
|
19037
19076
|
...capabilityEnvironment2
|
|
19038
19077
|
},
|
|
19039
19078
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -22251,11 +22290,7 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22251
22290
|
return withWorkflowBoundaryEval(capability, { ...result, workflowState: state });
|
|
22252
22291
|
}
|
|
22253
22292
|
if (!step.next || step.next.length === 0) {
|
|
22254
|
-
state
|
|
22255
|
-
delete state.currentStepId;
|
|
22256
|
-
delete state.blocker;
|
|
22257
|
-
await checkpoint?.(state);
|
|
22258
|
-
return withWorkflowBoundaryEval(capability, { ...result, workflowState: state });
|
|
22293
|
+
return completeWorkflowAtTerminal(capability, state, result, checkpoint);
|
|
22259
22294
|
}
|
|
22260
22295
|
const resultConditionPaths = workflowResultConditionPaths(step.next);
|
|
22261
22296
|
if (resultConditionPaths.length > 0 && !result.capabilityResults?.at(-1)) {
|
|
@@ -22278,11 +22313,7 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22278
22313
|
state.transitionCounts[key] = (state.transitionCounts[key] ?? 0) + 1;
|
|
22279
22314
|
}
|
|
22280
22315
|
if (transition.to === "$end") {
|
|
22281
|
-
state
|
|
22282
|
-
delete state.currentStepId;
|
|
22283
|
-
delete state.blocker;
|
|
22284
|
-
await checkpoint?.(state);
|
|
22285
|
-
return withWorkflowBoundaryEval(capability, { ...result, workflowState: state });
|
|
22316
|
+
return completeWorkflowAtTerminal(capability, state, result, checkpoint);
|
|
22286
22317
|
}
|
|
22287
22318
|
state.currentStepId = transition.to;
|
|
22288
22319
|
state.status = "running";
|
|
@@ -22293,6 +22324,25 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22293
22324
|
await checkpoint?.(state);
|
|
22294
22325
|
return withWorkflowBoundaryEval(capability, { ...result, workflowState: state });
|
|
22295
22326
|
}
|
|
22327
|
+
async function completeWorkflowAtTerminal(capability, state, output, checkpoint) {
|
|
22328
|
+
const result = output.capabilityResults?.at(-1);
|
|
22329
|
+
if (result?.status === "fail" || result?.status === "blocked") {
|
|
22330
|
+
state.status = result.status === "fail" ? "failed" : "blocked";
|
|
22331
|
+
state.blocker = result.summary;
|
|
22332
|
+
await checkpoint?.(state);
|
|
22333
|
+
return withWorkflowBoundaryEval(capability, {
|
|
22334
|
+
...output,
|
|
22335
|
+
exitCode: result.status === "fail" ? 1 : 64,
|
|
22336
|
+
reason: result.summary,
|
|
22337
|
+
workflowState: state
|
|
22338
|
+
});
|
|
22339
|
+
}
|
|
22340
|
+
state.status = "done";
|
|
22341
|
+
delete state.currentStepId;
|
|
22342
|
+
delete state.blocker;
|
|
22343
|
+
await checkpoint?.(state);
|
|
22344
|
+
return withWorkflowBoundaryEval(capability, { ...output, workflowState: state });
|
|
22345
|
+
}
|
|
22296
22346
|
function graphWorkflowExecutionKey(parentExecutionKey, workflowSlug, stepId, transitionCounts) {
|
|
22297
22347
|
const transitionHistory = Object.entries(transitionCounts).filter(([, count]) => count > 0).sort(([left], [right]) => left.localeCompare(right)).map(([transition, count]) => `${transition}=${count}`).join(",");
|
|
22298
22348
|
return [
|
|
File without changes
|
package/kody.config.schema.json
CHANGED
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.474",
|
|
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",
|
|
@@ -12,6 +12,29 @@
|
|
|
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
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
21
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
22
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
23
|
+
"pretest": "pnpm check:modularity",
|
|
24
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
25
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
26
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
27
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
28
|
+
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
29
|
+
"test:all": "vitest run tests --no-coverage",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"lint": "biome check",
|
|
32
|
+
"lint:fix": "biome check --write",
|
|
33
|
+
"format": "biome format --write",
|
|
34
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
35
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
36
|
+
"prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
37
|
+
},
|
|
15
38
|
"dependencies": {
|
|
16
39
|
"@actions/cache": "^6.0.0",
|
|
17
40
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -38,27 +61,5 @@
|
|
|
38
61
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
39
62
|
},
|
|
40
63
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
41
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
42
|
-
|
|
43
|
-
"kody:run": "tsx bin/kody.ts",
|
|
44
|
-
"serve": "tsx bin/kody.ts serve",
|
|
45
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
46
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
47
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
48
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
49
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
50
|
-
"pretest": "pnpm check:modularity",
|
|
51
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
52
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
53
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
54
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
55
|
-
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
56
|
-
"test:all": "vitest run tests --no-coverage",
|
|
57
|
-
"typecheck": "tsc --noEmit",
|
|
58
|
-
"lint": "biome check",
|
|
59
|
-
"lint:fix": "biome check --write",
|
|
60
|
-
"format": "biome format --write",
|
|
61
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
62
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
64
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
65
|
+
}
|