@kody-ade/kody-engine 0.4.575 → 0.4.577
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.577",
|
|
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",
|
|
@@ -3068,6 +3068,12 @@ function createStateBackendFromEnv(env = process.env, client) {
|
|
|
3068
3068
|
transport = createConvexClientFromEnv(env);
|
|
3069
3069
|
}
|
|
3070
3070
|
return {
|
|
3071
|
+
async listLoops(tenantId2) {
|
|
3072
|
+
const result = await transport.query(anyApi.agencyRequestLoops.list, {
|
|
3073
|
+
tenantId: requireTenant(tenantId2)
|
|
3074
|
+
});
|
|
3075
|
+
return Array.isArray(result) ? result : [];
|
|
3076
|
+
},
|
|
3071
3077
|
async get(tenantId2, taskKey, kind) {
|
|
3072
3078
|
const result = await transport.query(anyApi.taskState.get, {
|
|
3073
3079
|
tenantId: requireTenant(tenantId2),
|
|
@@ -14154,6 +14160,11 @@ var init_loopDefinitions = __esm({
|
|
|
14154
14160
|
|
|
14155
14161
|
// src/scripts/dispatchLoops.ts
|
|
14156
14162
|
import { randomUUID } from "crypto";
|
|
14163
|
+
function loopRunId(loopId, nonce) {
|
|
14164
|
+
const safeNonce = nonce.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
14165
|
+
const loopPrefixLength = MAX_WORKFLOW_RUN_ID_LENGTH - "loop--".length - safeNonce.length;
|
|
14166
|
+
return `loop-${loopId.slice(0, Math.max(1, loopPrefixLength))}-${safeNonce}`;
|
|
14167
|
+
}
|
|
14157
14168
|
function assertLoopDispatchesSucceeded(results) {
|
|
14158
14169
|
const didNotRun = results.filter((result) => result.status === "failed" || result.status === "blocked");
|
|
14159
14170
|
if (didNotRun.length === 0) return;
|
|
@@ -14195,7 +14206,7 @@ async function dispatchLoopsWith(input) {
|
|
|
14195
14206
|
results.push({ loopId: loop.id, status: status2, reason: reason2 });
|
|
14196
14207
|
continue;
|
|
14197
14208
|
}
|
|
14198
|
-
const runId =
|
|
14209
|
+
const runId = loopRunId(loop.id, input.nonce());
|
|
14199
14210
|
const startedAt = input.now.toISOString();
|
|
14200
14211
|
const running = {
|
|
14201
14212
|
id: runId,
|
|
@@ -14215,7 +14226,7 @@ async function dispatchLoopsWith(input) {
|
|
|
14215
14226
|
let reason = "target did not complete";
|
|
14216
14227
|
let runFailed = false;
|
|
14217
14228
|
try {
|
|
14218
|
-
const result = await input.run(loopJob(loop), runId);
|
|
14229
|
+
const result = await input.run(loopJob(loop, runId), runId, loop.id);
|
|
14219
14230
|
exitCode = result.exitCode;
|
|
14220
14231
|
reason = result.reason ?? (exitCode === 0 ? "dispatched" : "target failed");
|
|
14221
14232
|
} catch (error) {
|
|
@@ -14285,6 +14296,14 @@ function selectRunnableLoops(loops, now, options) {
|
|
|
14285
14296
|
(loop) => loop.enabled && (!options.loopId || loop.id === options.loopId) && (options.force || loop.trigger.type === "schedule" && dueSlot(loop, now) !== null)
|
|
14286
14297
|
);
|
|
14287
14298
|
}
|
|
14299
|
+
function mergeLoopDefinitions(repositoryLoops, runtimeLoops) {
|
|
14300
|
+
const byId = new Map(repositoryLoops.map((loop) => [loop.id, loop]));
|
|
14301
|
+
for (const candidate of runtimeLoops) {
|
|
14302
|
+
const loop = normalizeLoopDefinition(candidate);
|
|
14303
|
+
if (loop) byId.set(loop.id, loop);
|
|
14304
|
+
}
|
|
14305
|
+
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
14306
|
+
}
|
|
14288
14307
|
function loopDispatchSlot(loop, now, force, nonce) {
|
|
14289
14308
|
return force ? `manual:${now.toISOString()}:${nonce}` : dueSlot(loop, now);
|
|
14290
14309
|
}
|
|
@@ -14318,9 +14337,9 @@ function dueSlot(loop, now) {
|
|
|
14318
14337
|
const day = parts.find((part) => part.type === "day")?.value;
|
|
14319
14338
|
return `${year}-${month}-${day}T${loop.trigger.at.time}[${loop.trigger.at.timezone}]`;
|
|
14320
14339
|
}
|
|
14321
|
-
function loopJob(loop) {
|
|
14340
|
+
function loopJob(loop, runId) {
|
|
14322
14341
|
const cliArgs = { ...loop.input };
|
|
14323
|
-
return loop.target.kind === "workflow" ? { workflow: loop.target.id, cliArgs, flavor: "scheduled" } : { capability: loop.target.id, cliArgs, flavor: "scheduled" };
|
|
14342
|
+
return loop.target.kind === "workflow" ? { workflow: loop.target.id, workflowRunId: runId, cliArgs, flavor: "scheduled" } : { capability: loop.target.id, cliArgs, flavor: "scheduled" };
|
|
14324
14343
|
}
|
|
14325
14344
|
function repositoryTenant(config) {
|
|
14326
14345
|
const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY ?? "").split("/");
|
|
@@ -14328,7 +14347,7 @@ function repositoryTenant(config) {
|
|
|
14328
14347
|
const repo = config.github?.repo?.trim() || envRepo?.trim();
|
|
14329
14348
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
14330
14349
|
}
|
|
14331
|
-
var LOOP_DISPATCH_LEASE_MS, LOOP_DISPATCH_RENEW_INTERVAL_MS, dispatchLoops;
|
|
14350
|
+
var LOOP_DISPATCH_LEASE_MS, LOOP_DISPATCH_RENEW_INTERVAL_MS, MAX_WORKFLOW_RUN_ID_LENGTH, dispatchLoops;
|
|
14332
14351
|
var init_dispatchLoops = __esm({
|
|
14333
14352
|
"src/scripts/dispatchLoops.ts"() {
|
|
14334
14353
|
"use strict";
|
|
@@ -14337,19 +14356,21 @@ var init_dispatchLoops = __esm({
|
|
|
14337
14356
|
init_state_backend();
|
|
14338
14357
|
LOOP_DISPATCH_LEASE_MS = 10 * 60 * 1e3;
|
|
14339
14358
|
LOOP_DISPATCH_RENEW_INTERVAL_MS = 60 * 1e3;
|
|
14359
|
+
MAX_WORKFLOW_RUN_ID_LENGTH = 80;
|
|
14340
14360
|
dispatchLoops = async (ctx) => {
|
|
14341
14361
|
const tenantId2 = repositoryTenant(ctx.config);
|
|
14342
14362
|
if (!tenantId2) throw new Error("Repository identity is required for Loop dispatch");
|
|
14343
14363
|
const now = /* @__PURE__ */ new Date();
|
|
14344
14364
|
const force = ctx.data.jobForce === true;
|
|
14345
14365
|
const requestedLoopId = typeof ctx.args.loop === "string" ? ctx.args.loop.trim() : "";
|
|
14346
|
-
const
|
|
14366
|
+
const backend = createStateBackendFromEnv();
|
|
14367
|
+
const loops = mergeLoopDefinitions(listLoopDefinitions(ctx.cwd), await backend.listLoops(tenantId2));
|
|
14368
|
+
const due = selectRunnableLoops(loops, now, {
|
|
14347
14369
|
force,
|
|
14348
14370
|
...requestedLoopId ? { loopId: requestedLoopId } : {}
|
|
14349
14371
|
});
|
|
14350
14372
|
process.stdout.write(`\u2192 kody: Loop scheduler found ${due.length} runnable Loop(s)${force ? " (manual)" : ""}
|
|
14351
14373
|
`);
|
|
14352
|
-
const backend = createStateBackendFromEnv();
|
|
14353
14374
|
const results = await dispatchLoopsWith({
|
|
14354
14375
|
loops: due,
|
|
14355
14376
|
tenantId: tenantId2,
|
|
@@ -14357,13 +14378,13 @@ var init_dispatchLoops = __esm({
|
|
|
14357
14378
|
now,
|
|
14358
14379
|
force,
|
|
14359
14380
|
nonce: randomUUID,
|
|
14360
|
-
run: (job, parentRunId) => runJob(job, {
|
|
14381
|
+
run: (job, parentRunId, loopId) => runJob(job, {
|
|
14361
14382
|
cwd: ctx.cwd,
|
|
14362
14383
|
config: ctx.config,
|
|
14363
14384
|
verbose: ctx.verbose,
|
|
14364
14385
|
quiet: ctx.quiet,
|
|
14365
14386
|
chain: false,
|
|
14366
|
-
preloadedData: { parentRunId }
|
|
14387
|
+
preloadedData: { parentRunId, loopId }
|
|
14367
14388
|
})
|
|
14368
14389
|
});
|
|
14369
14390
|
for (const result of results) {
|
|
@@ -23364,6 +23385,7 @@ async function runJob(job, base) {
|
|
|
23364
23385
|
await notifyWorkflowCompleted({
|
|
23365
23386
|
workflowId: workflowIdentity,
|
|
23366
23387
|
runId: valid.workflowRunId,
|
|
23388
|
+
...typeof base.preloadedData?.loopId === "string" ? { loopId: base.preloadedData.loopId } : {},
|
|
23367
23389
|
status: result.workflowState?.status === "blocked" ? "blocked" : result.exitCode === 0 ? "success" : "failed",
|
|
23368
23390
|
...result.reason ? { summary: result.reason } : {},
|
|
23369
23391
|
...Object.keys(facts).length > 0 ? { output: facts } : {}
|
|
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.577",
|
|
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,30 @@
|
|
|
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
|
+
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
29
|
+
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
30
|
+
"test:all": "vitest run tests --no-coverage",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"lint": "biome check",
|
|
33
|
+
"lint:fix": "biome check --write",
|
|
34
|
+
"format": "biome format --write",
|
|
35
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
36
|
+
"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",
|
|
37
|
+
"prepublishOnly": "pnpm typecheck && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
38
|
+
},
|
|
15
39
|
"dependencies": {
|
|
16
40
|
"@actions/cache": "^6.0.0",
|
|
17
41
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -38,28 +62,5 @@
|
|
|
38
62
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
39
63
|
},
|
|
40
64
|
"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
|
-
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
56
|
-
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
57
|
-
"test:all": "vitest run tests --no-coverage",
|
|
58
|
-
"typecheck": "tsc --noEmit",
|
|
59
|
-
"lint": "biome check",
|
|
60
|
-
"lint:fix": "biome check --write",
|
|
61
|
-
"format": "biome format --write",
|
|
62
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
63
|
-
"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"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
65
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
66
|
+
}
|