@kody-ade/kody-engine 0.4.395 → 0.4.396
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 +244 -217
- 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.396",
|
|
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",
|
|
@@ -2549,6 +2549,222 @@ var init_registry = __esm({
|
|
|
2549
2549
|
}
|
|
2550
2550
|
});
|
|
2551
2551
|
|
|
2552
|
+
// src/chat/convex-client.ts
|
|
2553
|
+
import { ConvexHttpClient } from "convex/browser";
|
|
2554
|
+
function isPlainObject2(value) {
|
|
2555
|
+
if (value === null || typeof value !== "object") return false;
|
|
2556
|
+
const proto = Object.getPrototypeOf(value);
|
|
2557
|
+
return proto === Object.prototype || proto === null;
|
|
2558
|
+
}
|
|
2559
|
+
function deepMapKeys(value, mapKey) {
|
|
2560
|
+
if (Array.isArray(value)) return value.map((item) => deepMapKeys(item, mapKey));
|
|
2561
|
+
if (isPlainObject2(value)) {
|
|
2562
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [mapKey(key), deepMapKeys(item, mapKey)]));
|
|
2563
|
+
}
|
|
2564
|
+
return value;
|
|
2565
|
+
}
|
|
2566
|
+
function deepEscapeKeys(value) {
|
|
2567
|
+
return deepMapKeys(value, (k) => NEEDS_ESCAPE.test(k) ? `${ESCAPE_CHAR}${k}` : k);
|
|
2568
|
+
}
|
|
2569
|
+
function deepUnescapeKeys(value) {
|
|
2570
|
+
return deepMapKeys(value, (k) => k.startsWith(ESCAPE_CHAR) ? k.slice(1) : k);
|
|
2571
|
+
}
|
|
2572
|
+
function injectServiceKey(args, serviceKey = process.env.KODY_SERVICE_KEY) {
|
|
2573
|
+
if (!serviceKey) return args;
|
|
2574
|
+
if (args === void 0) return { serviceKey };
|
|
2575
|
+
if (typeof args !== "object" || args === null || Array.isArray(args)) return args;
|
|
2576
|
+
return { ...args, serviceKey };
|
|
2577
|
+
}
|
|
2578
|
+
function withEscapedKeys(client, serviceKey = process.env.KODY_SERVICE_KEY) {
|
|
2579
|
+
return new Proxy(client, {
|
|
2580
|
+
get(target, prop, receiver) {
|
|
2581
|
+
if (CALL_METHODS.includes(prop)) {
|
|
2582
|
+
const method = Reflect.get(target, prop, target);
|
|
2583
|
+
return async (fn, args) => {
|
|
2584
|
+
const authed = injectServiceKey(args, serviceKey);
|
|
2585
|
+
const result = await method.call(target, fn, authed === void 0 ? void 0 : deepEscapeKeys(authed));
|
|
2586
|
+
return deepUnescapeKeys(result);
|
|
2587
|
+
};
|
|
2588
|
+
}
|
|
2589
|
+
const value = Reflect.get(target, prop, receiver);
|
|
2590
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
2591
|
+
}
|
|
2592
|
+
});
|
|
2593
|
+
}
|
|
2594
|
+
function createConvexClientFromEnv(env = process.env) {
|
|
2595
|
+
const url = env.CONVEX_URL?.trim();
|
|
2596
|
+
if (!url) return null;
|
|
2597
|
+
return withEscapedKeys(new ConvexHttpClient(url), env.KODY_SERVICE_KEY);
|
|
2598
|
+
}
|
|
2599
|
+
var ESCAPE_CHAR, NEEDS_ESCAPE, CALL_METHODS;
|
|
2600
|
+
var init_convex_client = __esm({
|
|
2601
|
+
"src/chat/convex-client.ts"() {
|
|
2602
|
+
"use strict";
|
|
2603
|
+
ESCAPE_CHAR = "~";
|
|
2604
|
+
NEEDS_ESCAPE = /^[$_~]/;
|
|
2605
|
+
CALL_METHODS = ["query", "mutation", "action"];
|
|
2606
|
+
}
|
|
2607
|
+
});
|
|
2608
|
+
|
|
2609
|
+
// src/state-backend.ts
|
|
2610
|
+
import { anyApi } from "convex/server";
|
|
2611
|
+
function requireTenant(tenantId) {
|
|
2612
|
+
const value = tenantId.trim();
|
|
2613
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(value)) throw new Error("tenantId must be an owner/repository pair");
|
|
2614
|
+
return value;
|
|
2615
|
+
}
|
|
2616
|
+
function requireNonEmpty(value, name) {
|
|
2617
|
+
const normalized = value.trim();
|
|
2618
|
+
if (!normalized) throw new Error(`${name} must not be empty`);
|
|
2619
|
+
return normalized;
|
|
2620
|
+
}
|
|
2621
|
+
function createStateBackendFromEnv(env = process.env, client) {
|
|
2622
|
+
const url = env.CONVEX_URL?.trim();
|
|
2623
|
+
const serviceKey = env.KODY_SERVICE_KEY?.trim();
|
|
2624
|
+
if (!url || !serviceKey) throw new Error("CONVEX_URL and KODY_SERVICE_KEY are required");
|
|
2625
|
+
const transport = client ?? createConvexClientFromEnv(env);
|
|
2626
|
+
return {
|
|
2627
|
+
async get(tenantId, taskKey, kind) {
|
|
2628
|
+
const result = await transport.query(anyApi.taskState.get, {
|
|
2629
|
+
tenantId: requireTenant(tenantId),
|
|
2630
|
+
taskKey: requireNonEmpty(taskKey, "taskKey"),
|
|
2631
|
+
kind: requireNonEmpty(kind, "kind")
|
|
2632
|
+
});
|
|
2633
|
+
return result ?? null;
|
|
2634
|
+
},
|
|
2635
|
+
async save(tenantId, taskKey, kind, doc, expectedUpdatedAt) {
|
|
2636
|
+
await transport.mutation(anyApi.taskState.save, {
|
|
2637
|
+
tenantId: requireTenant(tenantId),
|
|
2638
|
+
taskKey: requireNonEmpty(taskKey, "taskKey"),
|
|
2639
|
+
kind: requireNonEmpty(kind, "kind"),
|
|
2640
|
+
doc,
|
|
2641
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2642
|
+
...expectedUpdatedAt ? { expectedUpdatedAt } : {}
|
|
2643
|
+
});
|
|
2644
|
+
},
|
|
2645
|
+
async getRepoDoc(tenantId, kind) {
|
|
2646
|
+
const result = await transport.query(anyApi.repoDocs.get, {
|
|
2647
|
+
tenantId: requireTenant(tenantId),
|
|
2648
|
+
kind: requireNonEmpty(kind, "kind")
|
|
2649
|
+
});
|
|
2650
|
+
return result ?? null;
|
|
2651
|
+
},
|
|
2652
|
+
async listRepoDocs(tenantId, prefix) {
|
|
2653
|
+
const result = await transport.query(anyApi.repoDocs.listByPrefix, {
|
|
2654
|
+
tenantId: requireTenant(tenantId),
|
|
2655
|
+
prefix: requireNonEmpty(prefix, "prefix")
|
|
2656
|
+
});
|
|
2657
|
+
return Array.isArray(result) ? result : [];
|
|
2658
|
+
},
|
|
2659
|
+
async saveRepoDoc(tenantId, kind, doc, expectedUpdatedAt) {
|
|
2660
|
+
await transport.mutation(anyApi.repoDocs.save, {
|
|
2661
|
+
tenantId: requireTenant(tenantId),
|
|
2662
|
+
kind: requireNonEmpty(kind, "kind"),
|
|
2663
|
+
doc,
|
|
2664
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2665
|
+
...expectedUpdatedAt ? { expectedUpdatedAt } : {}
|
|
2666
|
+
});
|
|
2667
|
+
},
|
|
2668
|
+
async getGoal(tenantId, goalId) {
|
|
2669
|
+
const result = await transport.query(anyApi.goals.get, {
|
|
2670
|
+
tenantId: requireTenant(tenantId),
|
|
2671
|
+
goalId: requireNonEmpty(goalId, "goalId")
|
|
2672
|
+
});
|
|
2673
|
+
return result ?? null;
|
|
2674
|
+
},
|
|
2675
|
+
async listGoals(tenantId) {
|
|
2676
|
+
const result = await transport.query(anyApi.goals.list, { tenantId: requireTenant(tenantId) });
|
|
2677
|
+
return Array.isArray(result) ? result : [];
|
|
2678
|
+
},
|
|
2679
|
+
async saveGoal(tenantId, goalId, state, updatedAt, expectedUpdatedAt) {
|
|
2680
|
+
await transport.mutation(anyApi.goals.save, {
|
|
2681
|
+
tenantId: requireTenant(tenantId),
|
|
2682
|
+
goalId: requireNonEmpty(goalId, "goalId"),
|
|
2683
|
+
state,
|
|
2684
|
+
updatedAt,
|
|
2685
|
+
...expectedUpdatedAt ? { expectedUpdatedAt } : {}
|
|
2686
|
+
});
|
|
2687
|
+
},
|
|
2688
|
+
async appendDailyLog(tenantId, stream, date, entry) {
|
|
2689
|
+
await transport.mutation(anyApi.dailyLogs.append, {
|
|
2690
|
+
tenantId: requireTenant(tenantId),
|
|
2691
|
+
stream,
|
|
2692
|
+
date: requireNonEmpty(date, "date"),
|
|
2693
|
+
entry
|
|
2694
|
+
});
|
|
2695
|
+
},
|
|
2696
|
+
async saveAgencyRun(tenantId, runId, subjectType, subjectId, run, updatedAt) {
|
|
2697
|
+
await transport.mutation(anyApi.agencyRuns.save, {
|
|
2698
|
+
tenantId: requireTenant(tenantId),
|
|
2699
|
+
runId: requireNonEmpty(runId, "runId"),
|
|
2700
|
+
subjectType,
|
|
2701
|
+
subjectId: requireNonEmpty(subjectId, "subjectId"),
|
|
2702
|
+
run,
|
|
2703
|
+
updatedAt
|
|
2704
|
+
});
|
|
2705
|
+
},
|
|
2706
|
+
async appendRunEvent(tenantId, runId, goalId, event, time) {
|
|
2707
|
+
await transport.mutation(anyApi.runEvents.append, {
|
|
2708
|
+
tenantId: requireTenant(tenantId),
|
|
2709
|
+
runId: requireNonEmpty(runId, "runId"),
|
|
2710
|
+
...goalId ? { goalId: requireNonEmpty(goalId, "goalId") } : {},
|
|
2711
|
+
event,
|
|
2712
|
+
time: requireNonEmpty(time, "time")
|
|
2713
|
+
});
|
|
2714
|
+
},
|
|
2715
|
+
async getManifest(tenantId, kind) {
|
|
2716
|
+
const result = await transport.query(anyApi.manifests.get, {
|
|
2717
|
+
tenantId: requireTenant(tenantId),
|
|
2718
|
+
kind: requireNonEmpty(kind, "kind")
|
|
2719
|
+
});
|
|
2720
|
+
return result ?? null;
|
|
2721
|
+
},
|
|
2722
|
+
async saveReport(tenantId, slug, runId, title, body, meta, updatedAt) {
|
|
2723
|
+
await transport.mutation(anyApi.reports.save, {
|
|
2724
|
+
tenantId: requireTenant(tenantId),
|
|
2725
|
+
slug: requireNonEmpty(slug, "slug"),
|
|
2726
|
+
runId: requireNonEmpty(runId, "runId"),
|
|
2727
|
+
title,
|
|
2728
|
+
body,
|
|
2729
|
+
meta,
|
|
2730
|
+
updatedAt
|
|
2731
|
+
});
|
|
2732
|
+
},
|
|
2733
|
+
async listIntents(tenantId) {
|
|
2734
|
+
const result = await transport.query(anyApi.intents.list, { tenantId: requireTenant(tenantId) });
|
|
2735
|
+
return Array.isArray(result) ? result : [];
|
|
2736
|
+
},
|
|
2737
|
+
async getIntent(tenantId, intentId) {
|
|
2738
|
+
const result = await transport.query(anyApi.intents.get, {
|
|
2739
|
+
tenantId: requireTenant(tenantId),
|
|
2740
|
+
intentId: requireNonEmpty(intentId, "intentId")
|
|
2741
|
+
});
|
|
2742
|
+
return result ?? null;
|
|
2743
|
+
},
|
|
2744
|
+
async saveIntent(tenantId, intentId, intent, updatedAt) {
|
|
2745
|
+
await transport.mutation(anyApi.intents.save, {
|
|
2746
|
+
tenantId: requireTenant(tenantId),
|
|
2747
|
+
intentId: requireNonEmpty(intentId, "intentId"),
|
|
2748
|
+
intent,
|
|
2749
|
+
updatedAt
|
|
2750
|
+
});
|
|
2751
|
+
},
|
|
2752
|
+
async appendIntentDecision(tenantId, intentId, decision) {
|
|
2753
|
+
await transport.mutation(anyApi.intents.appendDecision, {
|
|
2754
|
+
tenantId: requireTenant(tenantId),
|
|
2755
|
+
intentId: requireNonEmpty(intentId, "intentId"),
|
|
2756
|
+
decision
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
var init_state_backend = __esm({
|
|
2762
|
+
"src/state-backend.ts"() {
|
|
2763
|
+
"use strict";
|
|
2764
|
+
init_convex_client();
|
|
2765
|
+
}
|
|
2766
|
+
});
|
|
2767
|
+
|
|
2552
2768
|
// src/trustPolicy.ts
|
|
2553
2769
|
function trustSubjectKey(subject) {
|
|
2554
2770
|
return `${subject.kind}:${subject.id}`;
|
|
@@ -2583,6 +2799,20 @@ function readTrustModeOverride(stateOrRepoSlug, repoSlugOrSubject, maybeSubject)
|
|
|
2583
2799
|
return null;
|
|
2584
2800
|
}
|
|
2585
2801
|
}
|
|
2802
|
+
async function readTrustModeOverrideAsync(repoSlug, subject, state) {
|
|
2803
|
+
if (!subject.id) return null;
|
|
2804
|
+
const backendConfigured = Boolean(
|
|
2805
|
+
process.env.CONVEX_URL?.trim() && process.env.KODY_SERVICE_KEY?.trim() && /^[^/\s]+\/[^/\s]+$/.test(repoSlug)
|
|
2806
|
+
);
|
|
2807
|
+
if (backendConfigured) {
|
|
2808
|
+
const stored = await createStateBackendFromEnv().getManifest(repoSlug, "capability-trust");
|
|
2809
|
+
return stored ? parseTrustModeOverride(JSON.stringify(stored.doc), subject) : null;
|
|
2810
|
+
}
|
|
2811
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
2812
|
+
throw new Error("Convex backend is required for trust policy in GitHub Actions");
|
|
2813
|
+
}
|
|
2814
|
+
return readTrustModeOverride(state, repoSlug, subject);
|
|
2815
|
+
}
|
|
2586
2816
|
function defaultStateForRepoSlug(repoSlug) {
|
|
2587
2817
|
const [owner, repo] = repoSlug.split("/");
|
|
2588
2818
|
return { repo: `${owner}/kody-state`, path: repo ?? repoSlug };
|
|
@@ -2592,6 +2822,7 @@ var init_trustPolicy = __esm({
|
|
|
2592
2822
|
"src/trustPolicy.ts"() {
|
|
2593
2823
|
"use strict";
|
|
2594
2824
|
init_stateRepo();
|
|
2825
|
+
init_state_backend();
|
|
2595
2826
|
TRUST_FILE_PATH = "state/trust.json";
|
|
2596
2827
|
}
|
|
2597
2828
|
});
|
|
@@ -3777,215 +4008,6 @@ var init_agents = __esm({
|
|
|
3777
4008
|
}
|
|
3778
4009
|
});
|
|
3779
4010
|
|
|
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
|
-
async getRepoDoc(tenantId, kind) {
|
|
3874
|
-
const result = await transport.query(anyApi.repoDocs.get, {
|
|
3875
|
-
tenantId: requireTenant(tenantId),
|
|
3876
|
-
kind: requireNonEmpty(kind, "kind")
|
|
3877
|
-
});
|
|
3878
|
-
return result ?? null;
|
|
3879
|
-
},
|
|
3880
|
-
async listRepoDocs(tenantId, prefix) {
|
|
3881
|
-
const result = await transport.query(anyApi.repoDocs.listByPrefix, {
|
|
3882
|
-
tenantId: requireTenant(tenantId),
|
|
3883
|
-
prefix: requireNonEmpty(prefix, "prefix")
|
|
3884
|
-
});
|
|
3885
|
-
return Array.isArray(result) ? result : [];
|
|
3886
|
-
},
|
|
3887
|
-
async saveRepoDoc(tenantId, kind, doc, expectedUpdatedAt) {
|
|
3888
|
-
await transport.mutation(anyApi.repoDocs.save, {
|
|
3889
|
-
tenantId: requireTenant(tenantId),
|
|
3890
|
-
kind: requireNonEmpty(kind, "kind"),
|
|
3891
|
-
doc,
|
|
3892
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3893
|
-
...expectedUpdatedAt ? { expectedUpdatedAt } : {}
|
|
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
|
-
});
|
|
3923
|
-
},
|
|
3924
|
-
async saveAgencyRun(tenantId, runId, subjectType, subjectId, run, updatedAt) {
|
|
3925
|
-
await transport.mutation(anyApi.agencyRuns.save, {
|
|
3926
|
-
tenantId: requireTenant(tenantId),
|
|
3927
|
-
runId: requireNonEmpty(runId, "runId"),
|
|
3928
|
-
subjectType,
|
|
3929
|
-
subjectId: requireNonEmpty(subjectId, "subjectId"),
|
|
3930
|
-
run,
|
|
3931
|
-
updatedAt
|
|
3932
|
-
});
|
|
3933
|
-
},
|
|
3934
|
-
async appendRunEvent(tenantId, runId, goalId, event, time) {
|
|
3935
|
-
await transport.mutation(anyApi.runEvents.append, {
|
|
3936
|
-
tenantId: requireTenant(tenantId),
|
|
3937
|
-
runId: requireNonEmpty(runId, "runId"),
|
|
3938
|
-
...goalId ? { goalId: requireNonEmpty(goalId, "goalId") } : {},
|
|
3939
|
-
event,
|
|
3940
|
-
time: requireNonEmpty(time, "time")
|
|
3941
|
-
});
|
|
3942
|
-
},
|
|
3943
|
-
async saveReport(tenantId, slug, runId, title, body, meta, updatedAt) {
|
|
3944
|
-
await transport.mutation(anyApi.reports.save, {
|
|
3945
|
-
tenantId: requireTenant(tenantId),
|
|
3946
|
-
slug: requireNonEmpty(slug, "slug"),
|
|
3947
|
-
runId: requireNonEmpty(runId, "runId"),
|
|
3948
|
-
title,
|
|
3949
|
-
body,
|
|
3950
|
-
meta,
|
|
3951
|
-
updatedAt
|
|
3952
|
-
});
|
|
3953
|
-
},
|
|
3954
|
-
async listIntents(tenantId) {
|
|
3955
|
-
const result = await transport.query(anyApi.intents.list, { tenantId: requireTenant(tenantId) });
|
|
3956
|
-
return Array.isArray(result) ? result : [];
|
|
3957
|
-
},
|
|
3958
|
-
async getIntent(tenantId, intentId) {
|
|
3959
|
-
const result = await transport.query(anyApi.intents.get, {
|
|
3960
|
-
tenantId: requireTenant(tenantId),
|
|
3961
|
-
intentId: requireNonEmpty(intentId, "intentId")
|
|
3962
|
-
});
|
|
3963
|
-
return result ?? null;
|
|
3964
|
-
},
|
|
3965
|
-
async saveIntent(tenantId, intentId, intent, updatedAt) {
|
|
3966
|
-
await transport.mutation(anyApi.intents.save, {
|
|
3967
|
-
tenantId: requireTenant(tenantId),
|
|
3968
|
-
intentId: requireNonEmpty(intentId, "intentId"),
|
|
3969
|
-
intent,
|
|
3970
|
-
updatedAt
|
|
3971
|
-
});
|
|
3972
|
-
},
|
|
3973
|
-
async appendIntentDecision(tenantId, intentId, decision) {
|
|
3974
|
-
await transport.mutation(anyApi.intents.appendDecision, {
|
|
3975
|
-
tenantId: requireTenant(tenantId),
|
|
3976
|
-
intentId: requireNonEmpty(intentId, "intentId"),
|
|
3977
|
-
decision
|
|
3978
|
-
});
|
|
3979
|
-
}
|
|
3980
|
-
};
|
|
3981
|
-
}
|
|
3982
|
-
var init_state_backend = __esm({
|
|
3983
|
-
"src/state-backend.ts"() {
|
|
3984
|
-
"use strict";
|
|
3985
|
-
init_convex_client();
|
|
3986
|
-
}
|
|
3987
|
-
});
|
|
3988
|
-
|
|
3989
4011
|
// src/task-artifacts.ts
|
|
3990
4012
|
import fs10 from "fs";
|
|
3991
4013
|
import path12 from "path";
|
|
@@ -8971,7 +8993,9 @@ function decodeGoal(doc) {
|
|
|
8971
8993
|
async function fetchGoalStateAsync(config, goalId, cwd) {
|
|
8972
8994
|
const tenantId = backendTenant(config);
|
|
8973
8995
|
if (backendEnabled(config) && tenantId) {
|
|
8974
|
-
|
|
8996
|
+
const fromBackend = decodeGoal(await createStateBackendFromEnv().getGoal(tenantId, goalId));
|
|
8997
|
+
if (fromBackend) return fromBackend;
|
|
8998
|
+
return fetchGoalStateLegacy(config, goalId, cwd);
|
|
8975
8999
|
}
|
|
8976
9000
|
if (backendRequired()) throw new Error("Convex backend is required for goal state in GitHub Actions");
|
|
8977
9001
|
return fetchGoalStateLegacy(config, goalId, cwd);
|
|
@@ -10356,12 +10380,12 @@ function scalarFacts(facts) {
|
|
|
10356
10380
|
async function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options = {}) {
|
|
10357
10381
|
if (ctx.data.jobForce === true) return null;
|
|
10358
10382
|
const selfKind = managedModelKind(goal);
|
|
10359
|
-
const selfMode = selfKind === "Goal" ? firstTrustOverride(ctx, subjectCandidates("goal", goalId, goalState)) : null;
|
|
10383
|
+
const selfMode = selfKind === "Goal" ? await firstTrustOverride(ctx, subjectCandidates("goal", goalId, goalState)) : null;
|
|
10360
10384
|
if (selfKind === "Goal" && (selfMode === "ask" || selfMode !== "auto" && goal.runWithoutApproval !== true)) {
|
|
10361
10385
|
return `Run without approval is off for ${managedModelKind(goal)} ${goalId}`;
|
|
10362
10386
|
}
|
|
10363
10387
|
if (dispatch2.workflow && selfKind === "Goal") {
|
|
10364
|
-
const workflowMode = firstTrustOverride(ctx, [{ kind: "workflow", id: dispatch2.workflow }]);
|
|
10388
|
+
const workflowMode = await firstTrustOverride(ctx, [{ kind: "workflow", id: dispatch2.workflow }]);
|
|
10365
10389
|
const workflow = workflowMode === "auto" ? null : readWorkflowDefinition(ctx.config, ctx.cwd, dispatch2.workflow);
|
|
10366
10390
|
if (workflowMode === "ask" || workflowMode !== "auto" && workflow && workflow.runWithoutApproval !== true) {
|
|
10367
10391
|
return `Run without approval is off for workflow ${dispatch2.workflow}`;
|
|
@@ -10372,7 +10396,7 @@ async function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, opti
|
|
|
10372
10396
|
const target = await fetchGoalStateAsync(ctx.config, targetGoal, ctx.cwd);
|
|
10373
10397
|
const targetManaged = target ? managedGoalFromState(expandManagedGoalState(target)) : null;
|
|
10374
10398
|
const targetIsGoal = targetManaged ? managedModelKind(targetManaged) === "Goal" : false;
|
|
10375
|
-
const targetMode = targetManaged && targetIsGoal ? firstTrustOverride(ctx, subjectCandidates("goal", targetGoal, target)) : null;
|
|
10399
|
+
const targetMode = targetManaged && targetIsGoal ? await firstTrustOverride(ctx, subjectCandidates("goal", targetGoal, target)) : null;
|
|
10376
10400
|
if (targetIsGoal && (targetMode === "ask" || targetMode !== "auto" && targetManaged && targetManaged.runWithoutApproval !== true)) {
|
|
10377
10401
|
return `Run without approval is off for goal ${targetGoal}`;
|
|
10378
10402
|
}
|
|
@@ -10416,11 +10440,14 @@ function subjectCandidates(kind, id, state) {
|
|
|
10416
10440
|
}
|
|
10417
10441
|
return [...ids].map((candidate) => ({ kind, id: candidate }));
|
|
10418
10442
|
}
|
|
10419
|
-
function firstTrustOverride(ctx, subjects) {
|
|
10420
|
-
|
|
10443
|
+
async function firstTrustOverride(ctx, subjects) {
|
|
10444
|
+
const backendConfigured = Boolean(
|
|
10445
|
+
process.env.CONVEX_URL?.trim() && process.env.KODY_SERVICE_KEY?.trim()
|
|
10446
|
+
);
|
|
10447
|
+
if (!ctx.config.state && !backendConfigured) return null;
|
|
10421
10448
|
const repoSlug = ctx.config.github?.owner && ctx.config.github?.repo ? `${ctx.config.github.owner}/${ctx.config.github.repo}` : "";
|
|
10422
10449
|
for (const subject of subjects) {
|
|
10423
|
-
const mode =
|
|
10450
|
+
const mode = await readTrustModeOverrideAsync(repoSlug, subject, ctx.config.state);
|
|
10424
10451
|
if (mode) return mode;
|
|
10425
10452
|
}
|
|
10426
10453
|
return null;
|
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.396",
|
|
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",
|