@kody-ade/kody-engine 0.4.382 → 0.4.383

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 +189 -83
  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.382",
18
+ version: "0.4.383",
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",
@@ -3777,6 +3777,108 @@ var init_agents = __esm({
3777
3777
  }
3778
3778
  });
3779
3779
 
3780
+ // src/chat/convex-client.ts
3781
+ import { ConvexHttpClient } from "convex/browser";
3782
+ function isPlainObject2(value) {
3783
+ if (value === null || typeof value !== "object") return false;
3784
+ const proto = Object.getPrototypeOf(value);
3785
+ return proto === Object.prototype || proto === null;
3786
+ }
3787
+ function deepMapKeys(value, mapKey) {
3788
+ if (Array.isArray(value)) return value.map((item) => deepMapKeys(item, mapKey));
3789
+ if (isPlainObject2(value)) {
3790
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [mapKey(key), deepMapKeys(item, mapKey)]));
3791
+ }
3792
+ return value;
3793
+ }
3794
+ function deepEscapeKeys(value) {
3795
+ return deepMapKeys(value, (k) => NEEDS_ESCAPE.test(k) ? `${ESCAPE_CHAR}${k}` : k);
3796
+ }
3797
+ function deepUnescapeKeys(value) {
3798
+ return deepMapKeys(value, (k) => k.startsWith(ESCAPE_CHAR) ? k.slice(1) : k);
3799
+ }
3800
+ function injectServiceKey(args, serviceKey = process.env.KODY_SERVICE_KEY) {
3801
+ if (!serviceKey) return args;
3802
+ if (args === void 0) return { serviceKey };
3803
+ if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
3804
+ return { ...args, serviceKey };
3805
+ }
3806
+ function withEscapedKeys(client, serviceKey = process.env.KODY_SERVICE_KEY) {
3807
+ return new Proxy(client, {
3808
+ get(target, prop, receiver) {
3809
+ if (CALL_METHODS.includes(prop)) {
3810
+ const method = Reflect.get(target, prop, target);
3811
+ return async (fn, args) => {
3812
+ const authed = injectServiceKey(args, serviceKey);
3813
+ const result = await method.call(target, fn, authed === void 0 ? void 0 : deepEscapeKeys(authed));
3814
+ return deepUnescapeKeys(result);
3815
+ };
3816
+ }
3817
+ const value = Reflect.get(target, prop, receiver);
3818
+ return typeof value === "function" ? value.bind(target) : value;
3819
+ }
3820
+ });
3821
+ }
3822
+ function createConvexClientFromEnv(env = process.env) {
3823
+ const url = env.CONVEX_URL?.trim();
3824
+ if (!url) return null;
3825
+ return withEscapedKeys(new ConvexHttpClient(url), env.KODY_SERVICE_KEY);
3826
+ }
3827
+ var ESCAPE_CHAR, NEEDS_ESCAPE, CALL_METHODS;
3828
+ var init_convex_client = __esm({
3829
+ "src/chat/convex-client.ts"() {
3830
+ "use strict";
3831
+ ESCAPE_CHAR = "~";
3832
+ NEEDS_ESCAPE = /^[$_~]/;
3833
+ CALL_METHODS = ["query", "mutation", "action"];
3834
+ }
3835
+ });
3836
+
3837
+ // src/state-backend.ts
3838
+ import { anyApi } from "convex/server";
3839
+ function requireTenant(tenantId) {
3840
+ const value = tenantId.trim();
3841
+ if (!/^[^/\s]+\/[^/\s]+$/.test(value)) throw new Error("tenantId must be an owner/repository pair");
3842
+ return value;
3843
+ }
3844
+ function requireNonEmpty(value, name) {
3845
+ const normalized = value.trim();
3846
+ if (!normalized) throw new Error(`${name} must not be empty`);
3847
+ return normalized;
3848
+ }
3849
+ function createStateBackendFromEnv(env = process.env, client) {
3850
+ const url = env.CONVEX_URL?.trim();
3851
+ const serviceKey = env.KODY_SERVICE_KEY?.trim();
3852
+ if (!url || !serviceKey) throw new Error("CONVEX_URL and KODY_SERVICE_KEY are required");
3853
+ const transport = client ?? createConvexClientFromEnv(env);
3854
+ return {
3855
+ async get(tenantId, taskKey, kind) {
3856
+ const result = await transport.query(anyApi.taskState.get, {
3857
+ tenantId: requireTenant(tenantId),
3858
+ taskKey: requireNonEmpty(taskKey, "taskKey"),
3859
+ kind: requireNonEmpty(kind, "kind")
3860
+ });
3861
+ return result ?? null;
3862
+ },
3863
+ async save(tenantId, taskKey, kind, doc, expectedUpdatedAt) {
3864
+ await transport.mutation(anyApi.taskState.save, {
3865
+ tenantId: requireTenant(tenantId),
3866
+ taskKey: requireNonEmpty(taskKey, "taskKey"),
3867
+ kind: requireNonEmpty(kind, "kind"),
3868
+ doc,
3869
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3870
+ ...expectedUpdatedAt ? { expectedUpdatedAt } : {}
3871
+ });
3872
+ }
3873
+ };
3874
+ }
3875
+ var init_state_backend = __esm({
3876
+ "src/state-backend.ts"() {
3877
+ "use strict";
3878
+ init_convex_client();
3879
+ }
3880
+ });
3881
+
3780
3882
  // src/task-artifacts.ts
3781
3883
  import fs10 from "fs";
3782
3884
  import path12 from "path";
@@ -3804,7 +3906,29 @@ function verifyTaskArtifacts(absDir) {
3804
3906
  function taskArtifactStatePath(taskId, file) {
3805
3907
  return posixPath.join("tasks", taskId, file);
3806
3908
  }
3807
- function persistTaskArtifactsToState(config, cwd, artifacts) {
3909
+ async function persistTaskArtifactsToState(config, cwd, artifacts) {
3910
+ const tenantId = config.github?.owner && config.github.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY?.trim();
3911
+ if (process.env.CONVEX_URL && process.env.KODY_SERVICE_KEY && tenantId) {
3912
+ const backend = createStateBackendFromEnv();
3913
+ for (const file of TASK_ARTIFACT_FILES) {
3914
+ const full = path12.join(artifacts.absDir, file);
3915
+ if (!fs10.existsSync(full)) continue;
3916
+ const stat = fs10.statSync(full);
3917
+ if (!stat.isFile() || stat.size === 0) continue;
3918
+ const content = fs10.readFileSync(full, "utf-8");
3919
+ const kind = file.replace(/\.(json|md)$/, "");
3920
+ let doc = content;
3921
+ if (file.endsWith(".json")) {
3922
+ try {
3923
+ doc = JSON.parse(content);
3924
+ } catch (err) {
3925
+ throw new Error(`task artifact ${file} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
3926
+ }
3927
+ }
3928
+ await backend.save(tenantId, artifacts.taskId, kind, doc);
3929
+ }
3930
+ return;
3931
+ }
3808
3932
  for (const file of TASK_ARTIFACT_FILES) {
3809
3933
  const full = path12.join(artifacts.absDir, file);
3810
3934
  if (!fs10.existsSync(full)) continue;
@@ -3883,6 +4007,7 @@ var init_task_artifacts = __esm({
3883
4007
  "src/task-artifacts.ts"() {
3884
4008
  "use strict";
3885
4009
  init_runtimePaths();
4010
+ init_state_backend();
3886
4011
  init_stateRepo();
3887
4012
  TASK_ARTIFACT_FILES = ["context.json", "memory-recs.json", "followups.json", "handoff-notes.md"];
3888
4013
  }
@@ -5498,7 +5623,7 @@ function renderStateComment(state) {
5498
5623
  lines.push("</details>");
5499
5624
  return lines.join("\n");
5500
5625
  }
5501
- function readTaskState(target, number, cwd, config) {
5626
+ function readTaskStateLegacy(target, number, cwd, config) {
5502
5627
  const stateConfig = taskStateConfig(cwd, config);
5503
5628
  const loaded = readStateText(stateConfig, cwd, taskStatePath(target, number));
5504
5629
  if (!loaded) return emptyState();
@@ -5512,13 +5637,34 @@ function readTaskState(target, number, cwd, config) {
5512
5637
  }
5513
5638
  return normalizeTaskState(parsed);
5514
5639
  }
5640
+ function backendScope(config) {
5641
+ const tenantId = config?.github?.owner && config.github.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY?.trim();
5642
+ if (!process.env.CONVEX_URL || !process.env.KODY_SERVICE_KEY || !tenantId) return null;
5643
+ return { tenantId };
5644
+ }
5645
+ async function readTaskState(target, number, cwd, config) {
5646
+ const scope = backendScope(config);
5647
+ if (!scope) return readTaskStateLegacy(target, number, cwd, config);
5648
+ const backend = createStateBackendFromEnv();
5649
+ const kind = "state";
5650
+ const taskKey = `${target === "issue" ? "issues" : "prs"}/${number}`;
5651
+ const record = await backend.get(scope.tenantId, taskKey, kind);
5652
+ if (!record) return emptyState();
5653
+ try {
5654
+ return normalizeTaskState(record.doc);
5655
+ } catch (err) {
5656
+ throw new CorruptStateError(
5657
+ `backend task state unparseable for ${taskKey}: ${err instanceof Error ? err.message : String(err)}`
5658
+ );
5659
+ }
5660
+ }
5515
5661
  function setArtifact(state, name, artifact) {
5516
5662
  return {
5517
5663
  ...state,
5518
5664
  artifacts: { ...state.artifacts ?? {}, [name]: artifact }
5519
5665
  };
5520
5666
  }
5521
- function writeTaskState(target, number, state, cwd, config) {
5667
+ function writeTaskStateLegacy(target, number, state, cwd, config) {
5522
5668
  const stateConfig = taskStateConfig(cwd, config);
5523
5669
  upsertStateText(
5524
5670
  stateConfig,
@@ -5529,11 +5675,21 @@ function writeTaskState(target, number, state, cwd, config) {
5529
5675
  `chore(tasks): update ${target} ${number} state`
5530
5676
  );
5531
5677
  }
5532
- var STATE_BEGIN, STATE_END, HISTORY_MAX_ENTRIES, JOB_RUNS_MAX_ENTRIES, CorruptStateError;
5678
+ async function writeTaskState(target, number, state, cwd, config) {
5679
+ const scope = backendScope(config);
5680
+ if (!scope) {
5681
+ writeTaskStateLegacy(target, number, state, cwd, config);
5682
+ return;
5683
+ }
5684
+ const backend = createStateBackendFromEnv();
5685
+ await backend.save(scope.tenantId, `${target === "issue" ? "issues" : "prs"}/${number}`, "state", state);
5686
+ }
5687
+ var STATE_BEGIN, STATE_END, HISTORY_MAX_ENTRIES, JOB_RUNS_MAX_ENTRIES, CorruptStateError, readTaskStateAsync;
5533
5688
  var init_state = __esm({
5534
5689
  "src/state.ts"() {
5535
5690
  "use strict";
5536
5691
  init_config();
5692
+ init_state_backend();
5537
5693
  init_stateRepo();
5538
5694
  STATE_BEGIN = "<!-- kody:state:v1:begin -->";
5539
5695
  STATE_END = "<!-- kody:state:v1:end -->";
@@ -5545,6 +5701,7 @@ var init_state = __esm({
5545
5701
  this.name = "CorruptStateError";
5546
5702
  }
5547
5703
  };
5704
+ readTaskStateAsync = readTaskState;
5548
5705
  }
5549
5706
  });
5550
5707
 
@@ -5979,7 +6136,7 @@ async function runContainerLoop(profile, ctx, input) {
5979
6136
  return;
5980
6137
  }
5981
6138
  const runChild = input.__runChild ?? ((name, opts) => runImplementation(name, opts));
5982
- const reader = input.__readTaskState ?? readTaskState;
6139
+ const reader = input.__readTaskState ?? readTaskStateAsync;
5983
6140
  const issueNumber = ctx.args.issue;
5984
6141
  let preloadedSnapshot;
5985
6142
  if (profile.preloadContext) {
@@ -6029,7 +6186,7 @@ async function runContainerLoop(profile, ctx, input) {
6029
6186
  process.stderr.write(`[kody container] resetBetweenChildren=false; preserving tracked tree
6030
6187
  `);
6031
6188
  }
6032
- const priorState = readContainerState(ctx, child, reader);
6189
+ const priorState = await readContainerState(ctx, child, reader);
6033
6190
  if (priorState.core?.prUrl) knownPrUrl = priorState.core.prUrl;
6034
6191
  const priorAction = priorState.implementations?.[child.implementation]?.lastAction;
6035
6192
  let actionType2;
@@ -6123,7 +6280,7 @@ async function runContainerLoop(profile, ctx, input) {
6123
6280
  else process.env.KODY_CONTAINER_PARENT = priorParent;
6124
6281
  }
6125
6282
  const priorAttempts = priorState.core?.attempts?.[child.implementation] ?? 0;
6126
- const next = readContainerState(ctx, child, reader);
6283
+ const next = await readContainerState(ctx, child, reader);
6127
6284
  if (next.core?.prUrl) knownPrUrl = next.core.prUrl;
6128
6285
  const nextAttempts = next.core?.attempts?.[child.implementation] ?? 0;
6129
6286
  const nextChildAction = next.implementations?.[child.implementation]?.lastAction;
@@ -6210,20 +6367,20 @@ function resetWorkingTree(cwd) {
6210
6367
  `);
6211
6368
  }
6212
6369
  }
6213
- function readContainerState(ctx, child, reader) {
6370
+ async function readContainerState(ctx, child, reader) {
6214
6371
  const issueNumber = ctx.args.issue;
6215
6372
  const cached2 = ctx.data.taskState;
6216
6373
  const prUrl = cached2?.core?.prUrl;
6217
6374
  const prNumber = prUrl ? parsePrNumber2(prUrl) : null;
6218
6375
  if (child.target === "pr" && prNumber) {
6219
6376
  try {
6220
- return reader("pr", prNumber, ctx.cwd);
6377
+ return await reader("pr", prNumber, ctx.cwd);
6221
6378
  } catch {
6222
6379
  }
6223
6380
  }
6224
6381
  if (issueNumber !== void 0) {
6225
6382
  try {
6226
- return reader("issue", issueNumber, ctx.cwd);
6383
+ return await reader("issue", issueNumber, ctx.cwd);
6227
6384
  } catch {
6228
6385
  }
6229
6386
  }
@@ -7381,7 +7538,7 @@ var init_saveTaskState = __esm({
7381
7538
  if (ctx.output.prUrl) next.core.prUrl = ctx.output.prUrl;
7382
7539
  if (typeof ctx.data.runUrl === "string") next.core.runUrl = ctx.data.runUrl;
7383
7540
  applyStandaloneFinalState(next, ctx, profile);
7384
- writeTaskState(target, number, next, ctx.cwd, ctx.config);
7541
+ await writeTaskState(target, number, next, ctx.cwd, ctx.config);
7385
7542
  ctx.data.taskState = next;
7386
7543
  ctx.data.taskStateRendered = renderStateComment(next);
7387
7544
  };
@@ -7419,7 +7576,7 @@ var init_advanceFlow = __esm({
7419
7576
  const curState = state;
7420
7577
  let issueState;
7421
7578
  try {
7422
- issueState = readTaskState("issue", flow.issueNumber, ctx.cwd, ctx.config);
7579
+ issueState = await readTaskState("issue", flow.issueNumber, ctx.cwd, ctx.config);
7423
7580
  } catch {
7424
7581
  issueState = curState;
7425
7582
  }
@@ -7435,7 +7592,7 @@ var init_advanceFlow = __esm({
7435
7592
  if (hops > FLOW_HOP_CAP) {
7436
7593
  nextIssueState.flow = void 0;
7437
7594
  try {
7438
- writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd, ctx.config);
7595
+ await writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd, ctx.config);
7439
7596
  } catch (err) {
7440
7597
  process.stderr.write(
7441
7598
  `[kody advanceFlow] failed to clear looping flow on issue #${flow.issueNumber}: ${err instanceof Error ? err.message : String(err)}
@@ -7456,7 +7613,7 @@ var init_advanceFlow = __esm({
7456
7613
  }
7457
7614
  nextIssueState.flow = { ...flow, hops };
7458
7615
  try {
7459
- writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd, ctx.config);
7616
+ await writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd, ctx.config);
7460
7617
  } catch (err) {
7461
7618
  process.stderr.write(
7462
7619
  `[kody advanceFlow] failed to persist hop count on issue #${flow.issueNumber}: ${err instanceof Error ? err.message : String(err)}
@@ -13168,7 +13325,7 @@ var init_dispatchClassified = __esm({
13168
13325
  const nextState = reduce(state, "classify", action, void 0, profile.agent, jobMetaFromData(ctx.data));
13169
13326
  ctx.data.taskState = nextState;
13170
13327
  ctx.data.taskStateRendered = renderStateComment(nextState);
13171
- writeTaskState("issue", issueNumber, nextState, ctx.cwd, ctx.config);
13328
+ await writeTaskState("issue", issueNumber, nextState, ctx.cwd, ctx.config);
13172
13329
  const cliArgs = { issue: issueNumber };
13173
13330
  if (base && getProfileInputs(classification)?.some((i) => i.name === "base")) {
13174
13331
  cliArgs.base = base;
@@ -13681,7 +13838,7 @@ var init_finalizeTerminal = __esm({
13681
13838
  if (prNumber && prNumber !== issueNumber) setKodyLabel(prNumber, spec, ctx.cwd);
13682
13839
  if (!state) {
13683
13840
  try {
13684
- state = readTaskState(target, targetNumber, ctx.cwd, ctx.config);
13841
+ state = await readTaskState(target, targetNumber, ctx.cwd, ctx.config);
13685
13842
  } catch {
13686
13843
  state = void 0;
13687
13844
  }
@@ -13700,7 +13857,7 @@ var init_finalizeTerminal = __esm({
13700
13857
  };
13701
13858
  ctx.data.taskState = next;
13702
13859
  try {
13703
- writeTaskState(target, targetNumber, next, ctx.cwd, ctx.config);
13860
+ await writeTaskState(target, targetNumber, next, ctx.cwd, ctx.config);
13704
13861
  } catch (err) {
13705
13862
  process.stderr.write(
13706
13863
  `[kody finalizeTerminal] failed to write terminal state on ${target} #${targetNumber}: ${err instanceof Error ? err.message : String(err)}
@@ -13778,7 +13935,7 @@ var init_finishFlow = __esm({
13778
13935
  const target = ctx.data.commentTargetType ?? "issue";
13779
13936
  const targetNumber = ctx.data.commentTargetNumber ?? issueNumber;
13780
13937
  try {
13781
- writeTaskState(target, targetNumber, state, ctx.cwd, ctx.config);
13938
+ await writeTaskState(target, targetNumber, state, ctx.cwd, ctx.config);
13782
13939
  } catch (err) {
13783
13940
  process.stderr.write(
13784
13941
  `[kody finishFlow] failed to update state mirror: ${err instanceof Error ? err.message : String(err)}
@@ -15582,7 +15739,7 @@ var init_loadTaskState = __esm({
15582
15739
  return;
15583
15740
  }
15584
15741
  try {
15585
- ctx.data.taskState = readTaskState(target, number, ctx.cwd, ctx.config);
15742
+ ctx.data.taskState = await readTaskState(target, number, ctx.cwd, ctx.config);
15586
15743
  } catch (err) {
15587
15744
  if (err instanceof CorruptStateError) {
15588
15745
  process.stderr.write(
@@ -15590,7 +15747,7 @@ var init_loadTaskState = __esm({
15590
15747
  `
15591
15748
  );
15592
15749
  try {
15593
- writeTaskState(target, number, emptyState(), ctx.cwd, ctx.config);
15750
+ await writeTaskState(target, number, emptyState(), ctx.cwd, ctx.config);
15594
15751
  } catch {
15595
15752
  }
15596
15753
  ctx.skipAgent = true;
@@ -15847,7 +16004,7 @@ var init_mirrorStateToPr = __esm({
15847
16004
  if (!prNumber) return;
15848
16005
  if (!state) {
15849
16006
  try {
15850
- state = readTaskState("issue", issueNumber, ctx.cwd, ctx.config);
16007
+ state = await readTaskState("issue", issueNumber, ctx.cwd, ctx.config);
15851
16008
  } catch {
15852
16009
  return;
15853
16010
  }
@@ -15857,7 +16014,7 @@ var init_mirrorStateToPr = __esm({
15857
16014
  ctx.data.taskState = state;
15858
16015
  }
15859
16016
  try {
15860
- writeTaskState("pr", prNumber, state, ctx.cwd, ctx.config);
16017
+ await writeTaskState("pr", prNumber, state, ctx.cwd, ctx.config);
15861
16018
  } catch (err) {
15862
16019
  process.stderr.write(
15863
16020
  `[kody mirrorStateToPr] failed to mirror state to PR #${prNumber}: ${err instanceof Error ? err.message : String(err)}
@@ -16620,7 +16777,7 @@ var init_persistFlowState = __esm({
16620
16777
  const issueNumber = ctx.args.issue ?? state.flow?.issueNumber;
16621
16778
  if (!issueNumber) return;
16622
16779
  try {
16623
- writeTaskState("issue", issueNumber, state, ctx.cwd, ctx.config);
16780
+ await writeTaskState("issue", issueNumber, state, ctx.cwd, ctx.config);
16624
16781
  } catch (err) {
16625
16782
  process.stderr.write(
16626
16783
  `[kody persistFlowState] failed to write state on issue #${issueNumber}: ${err instanceof Error ? err.message : String(err)}
@@ -16740,7 +16897,7 @@ var init_planTaskJobs = __esm({
16740
16897
  ctx.data.plannedTaskJobIds = planned.map((job) => job.id);
16741
16898
  const target = ctx.data.commentTargetType;
16742
16899
  const number = ctx.data.commentTargetNumber;
16743
- if (target && number) writeTaskState(target, number, next, ctx.cwd, ctx.config);
16900
+ if (target && number) await writeTaskState(target, number, next, ctx.cwd, ctx.config);
16744
16901
  };
16745
16902
  }
16746
16903
  });
@@ -21063,7 +21220,7 @@ async function runImplementation(profileName, input) {
21063
21220
  `);
21064
21221
  }
21065
21222
  if (!input.skipConfig && (config.state || config.github.owner && config.github.repo)) {
21066
- persistTaskArtifactsToState(config, input.cwd, taskArtifacts);
21223
+ await persistTaskArtifactsToState(config, input.cwd, taskArtifacts);
21067
21224
  }
21068
21225
  } catch (err) {
21069
21226
  process.stderr.write(
@@ -22535,59 +22692,8 @@ function makeRunId(sessionId, suffix) {
22535
22692
  }
22536
22693
 
22537
22694
  // src/chat/session-store.ts
22538
- import { anyApi } from "convex/server";
22539
-
22540
- // src/chat/convex-client.ts
22541
- import { ConvexHttpClient } from "convex/browser";
22542
- var ESCAPE_CHAR = "~";
22543
- var NEEDS_ESCAPE = /^[$_~]/;
22544
- function isPlainObject2(value) {
22545
- if (value === null || typeof value !== "object") return false;
22546
- const proto = Object.getPrototypeOf(value);
22547
- return proto === Object.prototype || proto === null;
22548
- }
22549
- function deepMapKeys(value, mapKey) {
22550
- if (Array.isArray(value)) return value.map((item) => deepMapKeys(item, mapKey));
22551
- if (isPlainObject2(value)) {
22552
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [mapKey(key), deepMapKeys(item, mapKey)]));
22553
- }
22554
- return value;
22555
- }
22556
- function deepEscapeKeys(value) {
22557
- return deepMapKeys(value, (k) => NEEDS_ESCAPE.test(k) ? `${ESCAPE_CHAR}${k}` : k);
22558
- }
22559
- function deepUnescapeKeys(value) {
22560
- return deepMapKeys(value, (k) => k.startsWith(ESCAPE_CHAR) ? k.slice(1) : k);
22561
- }
22562
- var CALL_METHODS = ["query", "mutation", "action"];
22563
- function injectServiceKey(args) {
22564
- const serviceKey = process.env.KODY_SERVICE_KEY;
22565
- if (!serviceKey) return args;
22566
- if (args === void 0) return { serviceKey };
22567
- if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
22568
- return { ...args, serviceKey };
22569
- }
22570
- function withEscapedKeys(client) {
22571
- return new Proxy(client, {
22572
- get(target, prop, receiver) {
22573
- if (CALL_METHODS.includes(prop)) {
22574
- const method = Reflect.get(target, prop, target);
22575
- return async (fn, args) => {
22576
- const authed = injectServiceKey(args);
22577
- const result = await method.call(target, fn, authed === void 0 ? void 0 : deepEscapeKeys(authed));
22578
- return deepUnescapeKeys(result);
22579
- };
22580
- }
22581
- const value = Reflect.get(target, prop, receiver);
22582
- return typeof value === "function" ? value.bind(target) : value;
22583
- }
22584
- });
22585
- }
22586
- function createConvexClientFromEnv(env = process.env) {
22587
- const url = env.CONVEX_URL?.trim();
22588
- if (!url) return null;
22589
- return withEscapedKeys(new ConvexHttpClient(url));
22590
- }
22695
+ init_convex_client();
22696
+ import { anyApi as anyApi2 } from "convex/server";
22591
22697
 
22592
22698
  // src/chat/session.ts
22593
22699
  import * as fs13 from "fs";
@@ -22710,7 +22816,7 @@ function createConvexStore(args) {
22710
22816
  if (!sessionUpserted) {
22711
22817
  try {
22712
22818
  const meta = readMeta(sessionFile) ?? { type: "meta", mode: "one-shot" };
22713
- await client.mutation(anyApi.chatSessions.upsert, {
22819
+ await client.mutation(anyApi2.chatSessions.upsert, {
22714
22820
  tenantId,
22715
22821
  sessionId,
22716
22822
  meta,
@@ -22721,12 +22827,12 @@ function createConvexStore(args) {
22721
22827
  logger.warn(`session ${sessionId}: chatSessions.upsert failed: ${err instanceof Error ? err.message : String(err)}`);
22722
22828
  }
22723
22829
  }
22724
- await client.mutation(anyApi.chatTurns.append, { tenantId, sessionId, turn });
22830
+ await client.mutation(anyApi2.chatTurns.append, { tenantId, sessionId, turn });
22725
22831
  };
22726
22832
  return {
22727
22833
  backend: "convex",
22728
22834
  readTurns: async () => {
22729
- const docs = await client.query(anyApi.chatTurns.list, { tenantId, sessionId });
22835
+ const docs = await client.query(anyApi2.chatTurns.list, { tenantId, sessionId });
22730
22836
  const convexTurns = [...docs].sort((a, b) => a.seq - b.seq).map((doc) => doc.turn).filter(isChatTurn);
22731
22837
  const localTurns = readSession(sessionFile);
22732
22838
  if (localTurns.length <= convexTurns.length) return convexTurns;
@@ -23045,7 +23151,7 @@ async function runChatTurn(opts) {
23045
23151
  `
23046
23152
  );
23047
23153
  }
23048
- if (opts.stateConfig) persistTaskArtifactsToState(opts.stateConfig, opts.cwd, taskArtifactsPaths);
23154
+ if (opts.stateConfig) await persistTaskArtifactsToState(opts.stateConfig, opts.cwd, taskArtifactsPaths);
23049
23155
  } catch (err) {
23050
23156
  process.stderr.write(
23051
23157
  `[task-artifacts] chat session ${taskArtifactsPaths.taskId} persist failed: ${err instanceof Error ? err.message : String(err)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.382",
3
+ "version": "0.4.383",
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",