@kody-ade/kody-engine 0.4.610 → 0.4.612

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.610",
18
+ version: "0.4.612",
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",
@@ -3109,7 +3109,7 @@ var DEFAULT_KODY_API_URL, OIDC_AUDIENCE, WORKFLOW_COMPLETION_SUMMARY_MAX_LENGTH,
3109
3109
  var init_kody_api_client = __esm({
3110
3110
  "src/kody-api-client.ts"() {
3111
3111
  "use strict";
3112
- DEFAULT_KODY_API_URL = "https://kody-dashboard-aguy.vercel.app";
3112
+ DEFAULT_KODY_API_URL = "https://kody-dashboard-khaki.vercel.app";
3113
3113
  OIDC_AUDIENCE = "kody-api";
3114
3114
  WORKFLOW_COMPLETION_SUMMARY_MAX_LENGTH = 1e3;
3115
3115
  cachedToken = null;
@@ -3158,10 +3158,19 @@ function createStateBackendFromEnv(env = process.env, client) {
3158
3158
  });
3159
3159
  return Array.isArray(result) ? result : [];
3160
3160
  },
3161
- async replaceLoopWakeRegistrations(tenantId2, loopIds, updatedAt) {
3161
+ async replaceLoopWakeRegistrations(tenantId2, loops, updatedAt) {
3162
3162
  await transport.mutation(anyApi.loopWakes.replaceRegistrations, {
3163
3163
  tenantId: requireTenant(tenantId2),
3164
- loopIds: [...new Set(loopIds.map((id) => requireNonEmpty(id, "loopId")))],
3164
+ loops,
3165
+ updatedAt: requireNonEmpty(updatedAt, "updatedAt")
3166
+ });
3167
+ },
3168
+ async markLoopWakeExecution(tenantId2, wakeId, status, detail, updatedAt) {
3169
+ await transport.mutation(anyApi.loopWakes.markExecution, {
3170
+ tenantId: requireTenant(tenantId2),
3171
+ wakeId: requireNonEmpty(wakeId, "wakeId"),
3172
+ status,
3173
+ detail,
3165
3174
  updatedAt: requireNonEmpty(updatedAt, "updatedAt")
3166
3175
  });
3167
3176
  },
@@ -14484,7 +14493,7 @@ function assertLoopDispatchesSucceeded(results) {
14484
14493
  async function dispatchLoopsWith(input) {
14485
14494
  const results = [];
14486
14495
  for (const loop of input.loops) {
14487
- const slot = loopDispatchSlot(loop, input.now, input.force, input.nonce());
14496
+ const slot = input.scheduledFor ?? loopDispatchSlot(loop, input.now, input.force, input.nonce());
14488
14497
  if (!slot) continue;
14489
14498
  const reservationId = `reservation-${input.nonce()}`;
14490
14499
  const idempotencyKey = `${loop.id}:${slot}`;
@@ -14493,7 +14502,7 @@ async function dispatchLoopsWith(input) {
14493
14502
  loopId: loop.id,
14494
14503
  decision: {
14495
14504
  kind: "fire",
14496
- reason: input.force ? "manual Loop run requested" : "local Loop schedule is due",
14505
+ reason: input.scheduledFor ? "Convex scheduled Loop run" : input.force ? "manual Loop run requested" : "local Loop schedule is due",
14497
14506
  scheduledAt: slot
14498
14507
  },
14499
14508
  leaseUntil: new Date(input.now.getTime() + LOOP_DISPATCH_LEASE_MS).toISOString(),
@@ -14613,12 +14622,13 @@ function mergeLoopDefinitions(repositoryLoops, runtimeLoops) {
14613
14622
  }
14614
14623
  return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
14615
14624
  }
14616
- function loopWakeRegistrationIds(loops) {
14617
- return loops.filter((loop) => loop.enabled && loop.trigger.type === "schedule").map((loop) => loop.id).sort();
14618
- }
14619
14625
  async function syncLoopWakeRegistrations(backend, tenantId2, loops, updatedAt, log2) {
14620
14626
  try {
14621
- await backend.replaceLoopWakeRegistrations(tenantId2, loopWakeRegistrationIds(loops), updatedAt);
14627
+ await backend.replaceLoopWakeRegistrations(
14628
+ tenantId2,
14629
+ loops.filter((loop) => loop.enabled && loop.trigger.type === "schedule"),
14630
+ updatedAt
14631
+ );
14622
14632
  return true;
14623
14633
  } catch {
14624
14634
  log2("\u2192 kody: Convex Loop wake registration backfill skipped; existing Loop execution continues");
@@ -14682,9 +14692,14 @@ var init_dispatchLoops = __esm({
14682
14692
  const tenantId2 = repositoryTenant(ctx.config);
14683
14693
  if (!tenantId2) throw new Error("Repository identity is required for Loop dispatch");
14684
14694
  const now = /* @__PURE__ */ new Date();
14685
- const force = ctx.data.jobForce === true;
14695
+ const scheduledFor = typeof ctx.data.scheduledFor === "string" ? ctx.data.scheduledFor.trim() : "";
14696
+ const force = ctx.data.jobForce === true && !scheduledFor;
14686
14697
  const requestedLoopId = typeof ctx.args.loop === "string" ? ctx.args.loop.trim() : "";
14687
14698
  const backend = createStateBackendFromEnv();
14699
+ const wakeId = typeof ctx.data.wakeId === "string" ? ctx.data.wakeId : "";
14700
+ if (wakeId) {
14701
+ await backend.markLoopWakeExecution(tenantId2, wakeId, "running", "Engine started Loop", now.toISOString());
14702
+ }
14688
14703
  const loops = mergeLoopDefinitions(listLoopDefinitions(ctx.cwd), await backend.listLoops(tenantId2));
14689
14704
  await syncLoopWakeRegistrations(
14690
14705
  backend,
@@ -14695,7 +14710,7 @@ var init_dispatchLoops = __esm({
14695
14710
  `)
14696
14711
  );
14697
14712
  const due = selectRunnableLoops(loops, now, {
14698
- force,
14713
+ force: force || Boolean(scheduledFor),
14699
14714
  ...requestedLoopId ? { loopId: requestedLoopId } : {}
14700
14715
  });
14701
14716
  process.stdout.write(`\u2192 kody: Loop scheduler found ${due.length} runnable Loop(s)${force ? " (manual)" : ""}
@@ -14706,6 +14721,7 @@ var init_dispatchLoops = __esm({
14706
14721
  backend,
14707
14722
  now,
14708
14723
  force,
14724
+ scheduledFor: scheduledFor || void 0,
14709
14725
  nonce: randomUUID,
14710
14726
  run: (job, parentRunId, loopId) => runJob(job, {
14711
14727
  cwd: ctx.cwd,
@@ -14721,6 +14737,16 @@ var init_dispatchLoops = __esm({
14721
14737
  `);
14722
14738
  }
14723
14739
  ctx.data.loopDispatchResults = results;
14740
+ if (wakeId) {
14741
+ const failed = results.find((result) => result.status === "failed" || result.status === "blocked");
14742
+ await backend.markLoopWakeExecution(
14743
+ tenantId2,
14744
+ wakeId,
14745
+ failed ? "failed" : "succeeded",
14746
+ failed?.reason ?? "Loop completed",
14747
+ (/* @__PURE__ */ new Date()).toISOString()
14748
+ );
14749
+ }
14724
14750
  assertLoopDispatchesSucceeded(results);
14725
14751
  };
14726
14752
  }
@@ -27018,7 +27044,8 @@ function routeRunRequest(request) {
27018
27044
  return {
27019
27045
  kind: "action",
27020
27046
  action: "loop-scheduler",
27021
- cliArgs: { loop: target.id }
27047
+ cliArgs: { loop: target.id },
27048
+ ...typeof request.input?.scheduledFor === "string" ? { scheduledFor: request.input.scheduledFor } : {}
27022
27049
  };
27023
27050
  }
27024
27051
  if (target.type === "workflow") {
@@ -27286,6 +27313,8 @@ async function runCi(argv) {
27286
27313
  let forceRunAction = null;
27287
27314
  let forceRunCliArgs = {};
27288
27315
  let forceWorkflowRunId;
27316
+ let forceRunScheduledFor;
27317
+ let forceRunWakeId;
27289
27318
  let forceRunTargetKind = "action";
27290
27319
  let runRequestFanOut = false;
27291
27320
  let runRequestFanOutForce = false;
@@ -27310,6 +27339,8 @@ async function runCi(argv) {
27310
27339
  forceRunAction = route.action;
27311
27340
  forceRunCliArgs = route.cliArgs;
27312
27341
  forceWorkflowRunId = route.workflowRunId;
27342
+ forceRunScheduledFor = route.scheduledFor;
27343
+ if (route.scheduledFor) forceRunWakeId = parsedRunRequest.request.requestId;
27313
27344
  } else if (route.kind === "workflow") {
27314
27345
  forceRunAction = route.workflow;
27315
27346
  forceRunTargetKind = "workflow";
@@ -27453,7 +27484,8 @@ async function runCi(argv) {
27453
27484
  cwd,
27454
27485
  config,
27455
27486
  verbose: args.verbose,
27456
- quiet: args.quiet
27487
+ quiet: args.quiet,
27488
+ ...forceRunScheduledFor ? { preloadedData: { scheduledFor: forceRunScheduledFor, wakeId: forceRunWakeId } } : {}
27457
27489
  }
27458
27490
  );
27459
27491
  const ec = result.exitCode;
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.610",
3
+ "version": "0.4.612",
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
- "scripts": {
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
+ }