@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.
- package/dist/bin/kody.js +189 -83
- 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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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 ??
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
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",
|