@kody-ade/kody-engine 0.4.386 → 0.4.388

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.
Files changed (2) hide show
  1. package/dist/bin/kody.js +98 -16
  2. 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.386",
18
+ version: "0.4.388",
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",
@@ -3892,6 +3892,34 @@ function createStateBackendFromEnv(env = process.env, client) {
3892
3892
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3893
3893
  ...expectedUpdatedAt ? { expectedUpdatedAt } : {}
3894
3894
  });
3895
+ },
3896
+ async getGoal(tenantId, goalId) {
3897
+ const result = await transport.query(anyApi.goals.get, {
3898
+ tenantId: requireTenant(tenantId),
3899
+ goalId: requireNonEmpty(goalId, "goalId")
3900
+ });
3901
+ return result ?? null;
3902
+ },
3903
+ async listGoals(tenantId) {
3904
+ const result = await transport.query(anyApi.goals.list, { tenantId: requireTenant(tenantId) });
3905
+ return Array.isArray(result) ? result : [];
3906
+ },
3907
+ async saveGoal(tenantId, goalId, state, updatedAt, expectedUpdatedAt) {
3908
+ await transport.mutation(anyApi.goals.save, {
3909
+ tenantId: requireTenant(tenantId),
3910
+ goalId: requireNonEmpty(goalId, "goalId"),
3911
+ state,
3912
+ updatedAt,
3913
+ ...expectedUpdatedAt ? { expectedUpdatedAt } : {}
3914
+ });
3915
+ },
3916
+ async appendDailyLog(tenantId, stream, date, entry) {
3917
+ await transport.mutation(anyApi.dailyLogs.append, {
3918
+ tenantId: requireTenant(tenantId),
3919
+ stream,
3920
+ date: requireNonEmpty(date, "date"),
3921
+ entry
3922
+ });
3895
3923
  }
3896
3924
  };
3897
3925
  }
@@ -8114,6 +8142,24 @@ function flushGoalRunLogEvents(config, cwd, data) {
8114
8142
  log2.events = [];
8115
8143
  }
8116
8144
  }
8145
+ async function flushGoalRunLogEventsAsync(config, cwd, data) {
8146
+ const tenantId = config.github?.owner && config.github.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY;
8147
+ const backendConfigured = Boolean(process.env.CONVEX_URL?.trim() && process.env.KODY_SERVICE_KEY?.trim() && tenantId);
8148
+ if (!backendConfigured) {
8149
+ if (process.env.GITHUB_ACTIONS === "true") throw new Error("Convex backend is required for goal run logs in GitHub Actions");
8150
+ flushGoalRunLogEvents(config, cwd, data);
8151
+ return;
8152
+ }
8153
+ const backend = createStateBackendFromEnv();
8154
+ for (const [goalId, log2] of Object.entries(goalRunLogs(data))) {
8155
+ if (log2.events.length === 0) continue;
8156
+ const enrichedEvents = log2.events.map((event) => enrichGoalRunLogEvent(config, data, log2.path, event));
8157
+ for (const event of enrichedEvents) {
8158
+ await backend.appendDailyLog(tenantId, "events", event.time.slice(0, 10), event);
8159
+ }
8160
+ log2.events = [];
8161
+ }
8162
+ }
8117
8163
  function goalRunLogPath(goalId, data) {
8118
8164
  const startedAt = goalRunStartedAt(data);
8119
8165
  const runId = goalRunId(data);
@@ -8536,6 +8582,7 @@ var init_runLog = __esm({
8536
8582
  "use strict";
8537
8583
  init_runIndex();
8538
8584
  init_stateRepo();
8585
+ init_state_backend();
8539
8586
  init_state2();
8540
8587
  LOGS_KEY = "__goalRunLogs";
8541
8588
  LOG_RUN_KEY = "__goalRunLogRunId";
@@ -8714,7 +8761,7 @@ import * as path24 from "path";
8714
8761
  function goalStatePath(goalId) {
8715
8762
  return `todos/${goalId}.json`;
8716
8763
  }
8717
- function fetchGoalState(config, goalId, cwd) {
8764
+ function fetchGoalStateLegacy(config, goalId, cwd) {
8718
8765
  const filePath = goalStatePath(goalId);
8719
8766
  const loaded = readStateText(config, cwd, filePath);
8720
8767
  if (!loaded) return null;
@@ -8769,14 +8816,14 @@ function readStoreGoalTemplate(templateId) {
8769
8816
  function recordField2(value) {
8770
8817
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
8771
8818
  }
8772
- function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
8819
+ function putGoalStateLegacy(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
8773
8820
  const previous = readStateText(config, cwd, goalStatePath(goalId));
8774
8821
  if (previous && !isManagedTodoRaw(previous.content)) {
8775
8822
  throw new Error(`Cannot overwrite regular todo list ${goalId} as managed goal`);
8776
8823
  }
8777
8824
  upsertStateText(config, cwd, goalStatePath(goalId), serializeTodoGoalState(goalId, state, previous?.content), message);
8778
8825
  }
8779
- function listGoalStateIds(config, cwd) {
8826
+ function listGoalStateIdsLegacy(config, cwd) {
8780
8827
  const ids = /* @__PURE__ */ new Set();
8781
8828
  const todoEntries = listStateDirectory(config, cwd, "todos");
8782
8829
  for (const entry of todoEntries) {
@@ -8787,11 +8834,46 @@ function listGoalStateIds(config, cwd) {
8787
8834
  }
8788
8835
  return [...ids].sort();
8789
8836
  }
8837
+ function backendTenant(config) {
8838
+ const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
8839
+ const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
8840
+ return owner && repo ? `${owner}/${repo}` : null;
8841
+ }
8842
+ function backendEnabled(config) {
8843
+ return Boolean(process.env.CONVEX_URL?.trim() && process.env.KODY_SERVICE_KEY?.trim() && backendTenant(config));
8844
+ }
8845
+ function backendRequired() {
8846
+ return process.env.GITHUB_ACTIONS === "true";
8847
+ }
8848
+ function decodeGoal(doc) {
8849
+ if (!doc || !doc.state || typeof doc.state !== "object" || Array.isArray(doc.state)) return null;
8850
+ const state = doc.state;
8851
+ if (typeof state.state !== "string" || !state.extra || typeof state.extra !== "object") return null;
8852
+ return resolveStoreBackedGoalState(state);
8853
+ }
8854
+ async function fetchGoalStateAsync(config, goalId, cwd) {
8855
+ const tenantId = backendTenant(config);
8856
+ if (backendEnabled(config) && tenantId) {
8857
+ return decodeGoal(await createStateBackendFromEnv().getGoal(tenantId, goalId));
8858
+ }
8859
+ if (backendRequired()) throw new Error("Convex backend is required for goal state in GitHub Actions");
8860
+ return fetchGoalStateLegacy(config, goalId, cwd);
8861
+ }
8862
+ function fetchGoalState(config, goalId, cwd) {
8863
+ return fetchGoalStateLegacy(config, goalId, cwd);
8864
+ }
8865
+ function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
8866
+ putGoalStateLegacy(config, goalId, state, message, cwd);
8867
+ }
8868
+ function listGoalStateIds(config, cwd) {
8869
+ return listGoalStateIdsLegacy(config, cwd);
8870
+ }
8790
8871
  var init_stateStore = __esm({
8791
8872
  "src/goal/stateStore.ts"() {
8792
8873
  "use strict";
8793
8874
  init_companyStore();
8794
8875
  init_stateRepo();
8876
+ init_state_backend();
8795
8877
  init_managedTodoState();
8796
8878
  }
8797
8879
  });
@@ -11290,9 +11372,9 @@ function createNeedsFixIssue(goalId, evidence, result, cwd) {
11290
11372
  if (!match) throw new Error(`gh issue create returned unexpected output: ${out}`);
11291
11373
  return Number(match[1]);
11292
11374
  }
11293
- function flushLogs(ctx) {
11375
+ async function flushLogs(ctx) {
11294
11376
  try {
11295
- flushGoalRunLogEvents(ctx.config, ctx.cwd, ctx.data);
11377
+ await flushGoalRunLogEventsAsync(ctx.config, ctx.cwd, ctx.data);
11296
11378
  } catch (err) {
11297
11379
  process.stderr.write(
11298
11380
  `[kody capability-report] goal log persist failed (${err instanceof Error ? err.message : String(err)})
@@ -11487,7 +11569,7 @@ var init_applyCapabilityReports = __esm({
11487
11569
  },
11488
11570
  decision: { kind: "reject-evidence", nextStep: "block", reason: "goal missing in state repo" }
11489
11571
  });
11490
- flushLogs(ctx);
11572
+ await flushLogs(ctx);
11491
11573
  process.stderr.write(`[kody capability-report] goal ${goalId} missing in state repo; report skipped
11492
11574
  `);
11493
11575
  continue;
@@ -11555,7 +11637,7 @@ var init_applyCapabilityReports = __esm({
11555
11637
  };
11556
11638
  }
11557
11639
  } finally {
11558
- flushLogs(ctx);
11640
+ await flushLogs(ctx);
11559
11641
  }
11560
11642
  }
11561
11643
  };
@@ -11854,9 +11936,9 @@ function refreshReportOrFail2(ctx, goalId, state) {
11854
11936
  if (ctx.output.exitCode === 0) ctx.output.exitCode = 99;
11855
11937
  }
11856
11938
  }
11857
- function flushLogs2(ctx) {
11939
+ async function flushLogs2(ctx) {
11858
11940
  try {
11859
- flushGoalRunLogEvents(ctx.config, ctx.cwd, ctx.data);
11941
+ await flushGoalRunLogEventsAsync(ctx.config, ctx.cwd, ctx.data);
11860
11942
  } catch (err) {
11861
11943
  process.stderr.write(
11862
11944
  `[goal-manager] goal log persist failed (${err instanceof Error ? err.message : String(err)})
@@ -11878,17 +11960,17 @@ var init_commitGoalState = __esm({
11878
11960
  commitGoalState = async (ctx) => {
11879
11961
  const goal = ctx.data.goal;
11880
11962
  if (!goal) {
11881
- flushLogs2(ctx);
11963
+ await flushLogs2(ctx);
11882
11964
  return;
11883
11965
  }
11884
11966
  if (ctx.data.goalPersistChanged !== true) {
11885
11967
  refreshReportOrFail2(ctx, goal.id, goal.raw);
11886
- flushLogs2(ctx);
11968
+ await flushLogs2(ctx);
11887
11969
  return;
11888
11970
  }
11889
11971
  const updated = ctx.data.goalPersistState;
11890
11972
  if (!updated) {
11891
- flushLogs2(ctx);
11973
+ await flushLogs2(ctx);
11892
11974
  return;
11893
11975
  }
11894
11976
  try {
@@ -11900,7 +11982,7 @@ var init_commitGoalState = __esm({
11900
11982
  `
11901
11983
  );
11902
11984
  } finally {
11903
- flushLogs2(ctx);
11985
+ await flushLogs2(ctx);
11904
11986
  }
11905
11987
  };
11906
11988
  }
@@ -14994,11 +15076,11 @@ function sleep(ms) {
14994
15076
  return new Promise((resolve10) => setTimeout(resolve10, ms));
14995
15077
  }
14996
15078
  async function fetchGoalStateWithRetry(config, goalId, cwd) {
14997
- let state = fetchGoalState(config, goalId, cwd);
15079
+ let state = await fetchGoalStateAsync(config, goalId, cwd);
14998
15080
  if (state) return state;
14999
15081
  for (const delay of retryDelaysMs()) {
15000
15082
  await sleep(delay);
15001
- state = fetchGoalState(config, goalId, cwd);
15083
+ state = await fetchGoalStateAsync(config, goalId, cwd);
15002
15084
  if (state) {
15003
15085
  process.stdout.write(`[goal-manager] loaded goal state for ${goalId} after retry
15004
15086
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.386",
3
+ "version": "0.4.388",
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",