@kody-ade/kody-engine 0.4.304 → 0.4.306
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 +254 -183
- package/dist/executables/types.ts +11 -4
- package/package.json +25 -24
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.306",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -1914,6 +1914,7 @@ function parseCapabilityConfig(raw) {
|
|
|
1914
1914
|
mentions: stringList(raw.mentions).map((m) => m.replace(/^@/, "")),
|
|
1915
1915
|
tools,
|
|
1916
1916
|
capabilityTools: tools,
|
|
1917
|
+
capabilityToolMode: parseCapabilityToolMode(raw.capabilityToolMode),
|
|
1917
1918
|
implementations,
|
|
1918
1919
|
executables: stringList(raw.executables),
|
|
1919
1920
|
role: stringField(raw.role),
|
|
@@ -1924,6 +1925,11 @@ function parseCapabilityConfig(raw) {
|
|
|
1924
1925
|
workflow: parseWorkflow(raw.workflow)
|
|
1925
1926
|
};
|
|
1926
1927
|
}
|
|
1928
|
+
function parseCapabilityToolMode(raw) {
|
|
1929
|
+
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
1930
|
+
if (raw === "lock" || raw === "append") return raw;
|
|
1931
|
+
return void 0;
|
|
1932
|
+
}
|
|
1927
1933
|
function parseCapabilityBody(raw, slug2) {
|
|
1928
1934
|
const trimmed = raw.trim();
|
|
1929
1935
|
const firstLine2 = trimmed.split("\n", 1)[0] ?? "";
|
|
@@ -2414,7 +2420,8 @@ __export(capabilityMcp_exports, {
|
|
|
2414
2420
|
parseCapabilityTrustMode: () => parseCapabilityTrustMode,
|
|
2415
2421
|
readCapabilityTrustMode: () => readCapabilityTrustMode,
|
|
2416
2422
|
readCheckRuns: () => readCheckRuns,
|
|
2417
|
-
readThread: () => readThread
|
|
2423
|
+
readThread: () => readThread,
|
|
2424
|
+
startCapability: () => startCapability
|
|
2418
2425
|
});
|
|
2419
2426
|
import { createSdkMcpServer as createSdkMcpServer4, tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
|
|
2420
2427
|
import { z as z3 } from "zod";
|
|
@@ -2663,6 +2670,9 @@ function dispatchWorkflow(workflowFile, capability, issueNumber, repoSlug) {
|
|
|
2663
2670
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
2664
2671
|
}
|
|
2665
2672
|
}
|
|
2673
|
+
function startCapability(workflowFile, name, issue, repoSlug) {
|
|
2674
|
+
return dispatchWorkflow(workflowFile, name, issue, repoSlug);
|
|
2675
|
+
}
|
|
2666
2676
|
function expectedDispatchTarget(capability) {
|
|
2667
2677
|
const route = resolveCapabilityAction(capability);
|
|
2668
2678
|
if (!route) return null;
|
|
@@ -2835,9 +2845,31 @@ function capabilityToolDefinitions(opts) {
|
|
|
2835
2845
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
2836
2846
|
}
|
|
2837
2847
|
};
|
|
2848
|
+
const startCapabilityTool = {
|
|
2849
|
+
name: "start_capability",
|
|
2850
|
+
description: "Start a known Kody capability on an issue or PR through workflow_dispatch. Use this instead of shelling out to `gh workflow run` or posting bot-authored `@kody` command comments. E.g. start_capability({name:'qa-engineer', issue:<n>}). Returns {ok} or {ok:false,error}.",
|
|
2851
|
+
inputSchema: {
|
|
2852
|
+
name: z3.string().min(1).describe("Capability action to start (e.g. 'qa-engineer', 'run', 'sync')."),
|
|
2853
|
+
issue: z3.number().int().positive().optional().describe("Issue or PR number forwarded as issue_number."),
|
|
2854
|
+
issueNumber: z3.number().int().positive().optional().describe("Deprecated alias for issue.")
|
|
2855
|
+
},
|
|
2856
|
+
handler: async (args) => {
|
|
2857
|
+
const name = String(args.name ?? "");
|
|
2858
|
+
const issue = Number(args.issue ?? args.issueNumber);
|
|
2859
|
+
if (!Number.isFinite(issue) || issue <= 0) {
|
|
2860
|
+
return { content: [{ type: "text", text: "Start failed: `issue` is required and must be a positive number." }] };
|
|
2861
|
+
}
|
|
2862
|
+
if (isDispatchGated(name, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2863
|
+
return { content: [{ type: "text", text: trustRefusal(opts.capabilitySlug) }] };
|
|
2864
|
+
}
|
|
2865
|
+
const result = startCapability(workflowFile, name, issue, opts.repoSlug);
|
|
2866
|
+
const text = result.ok ? `Started capability \`${name}\` on #${issue} via workflow_dispatch.` : `Start failed for capability \`${name}\` on #${issue}: ${result.error}`;
|
|
2867
|
+
return { content: [{ type: "text", text }] };
|
|
2868
|
+
}
|
|
2869
|
+
};
|
|
2838
2870
|
const dispatchTool = {
|
|
2839
2871
|
name: "dispatch_workflow",
|
|
2840
|
-
description: "
|
|
2872
|
+
description: "Legacy alias for start_capability. Dispatches a kody.yml workflow_dispatch run for a capability action against an issue. Prefer start_capability({name:'run', issue:<n>}). Returns {ok} or {ok:false,error}.",
|
|
2841
2873
|
inputSchema: {
|
|
2842
2874
|
capability: z3.string().min(1).optional().describe("Capability action to run (e.g. 'run')."),
|
|
2843
2875
|
executable: z3.string().min(1).optional().describe("Deprecated alias for capability."),
|
|
@@ -2849,7 +2881,7 @@ function capabilityToolDefinitions(opts) {
|
|
|
2849
2881
|
if (isDispatchGated(capability, readCapabilityTrustMode(opts.state, opts.repoSlug, opts.capabilitySlug))) {
|
|
2850
2882
|
return { content: [{ type: "text", text: trustRefusal(opts.capabilitySlug) }] };
|
|
2851
2883
|
}
|
|
2852
|
-
const result =
|
|
2884
|
+
const result = startCapability(workflowFile, capability, issueNumber, opts.repoSlug);
|
|
2853
2885
|
const text = result.ok ? `Dispatched capability \`${capability}\` on #${issueNumber} via workflow_dispatch.` : `Dispatch failed for capability \`${capability}\` on #${issueNumber}: ${result.error}`;
|
|
2854
2886
|
return { content: [{ type: "text", text }] };
|
|
2855
2887
|
}
|
|
@@ -2869,6 +2901,7 @@ function capabilityToolDefinitions(opts) {
|
|
|
2869
2901
|
readThreadTool,
|
|
2870
2902
|
ensureIssueTool,
|
|
2871
2903
|
ensureCommentTool,
|
|
2904
|
+
startCapabilityTool,
|
|
2872
2905
|
dispatchTool,
|
|
2873
2906
|
...cmsTools
|
|
2874
2907
|
];
|
|
@@ -2918,6 +2951,7 @@ var init_capabilityMcp = __esm({
|
|
|
2918
2951
|
"read_thread",
|
|
2919
2952
|
"ensure_issue",
|
|
2920
2953
|
"ensure_comment",
|
|
2954
|
+
"start_capability",
|
|
2921
2955
|
"dispatch_workflow",
|
|
2922
2956
|
...DASHBOARD_CMS_MCP_TOOL_NAMES
|
|
2923
2957
|
];
|
|
@@ -4264,6 +4298,7 @@ function loadProfile(profilePath) {
|
|
|
4264
4298
|
describe: typeof r.describe === "string" ? r.describe : base.describe,
|
|
4265
4299
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
|
|
4266
4300
|
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
|
|
4301
|
+
capabilityToolMode: parseCapabilityToolMode2(profilePath, r.capabilityToolMode) ?? base.capabilityToolMode,
|
|
4267
4302
|
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
|
|
4268
4303
|
};
|
|
4269
4304
|
}
|
|
@@ -4319,6 +4354,7 @@ function loadProfile(profilePath) {
|
|
|
4319
4354
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : void 0,
|
|
4320
4355
|
// Locked-toolbox palette + mentions from folder-capability profile metadata.
|
|
4321
4356
|
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools),
|
|
4357
|
+
capabilityToolMode: parseCapabilityToolMode2(profilePath, r.capabilityToolMode),
|
|
4322
4358
|
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : void 0,
|
|
4323
4359
|
role,
|
|
4324
4360
|
kind,
|
|
@@ -4360,12 +4396,7 @@ function loadProfile(profilePath) {
|
|
|
4360
4396
|
const preNames = new Set(profile.scripts.preflight.map((e) => e.script).filter(Boolean));
|
|
4361
4397
|
const postNames = profile.scripts.postflight.map((e) => e.script).filter(Boolean);
|
|
4362
4398
|
const needsState = postNames.includes("writeJobStateFile") || postNames.includes("parseJobStateFromAgentResult");
|
|
4363
|
-
const STATE_LOADERS = [
|
|
4364
|
-
"loadCapabilityState",
|
|
4365
|
-
"loadJobFromFile",
|
|
4366
|
-
"runTickScript",
|
|
4367
|
-
"runScheduledExecutableTick"
|
|
4368
|
-
];
|
|
4399
|
+
const STATE_LOADERS = ["loadCapabilityState", "loadJobFromFile", "runTickScript", "runScheduledExecutableTick"];
|
|
4369
4400
|
if (needsState && !STATE_LOADERS.some((s) => preNames.has(s))) {
|
|
4370
4401
|
throw new ProfileError(
|
|
4371
4402
|
profilePath,
|
|
@@ -4375,6 +4406,11 @@ function loadProfile(profilePath) {
|
|
|
4375
4406
|
profile.subagentTemplates = captureSubagentTemplates(profile);
|
|
4376
4407
|
return profile;
|
|
4377
4408
|
}
|
|
4409
|
+
function parseCapabilityToolMode2(profilePath, raw) {
|
|
4410
|
+
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
4411
|
+
if (raw === "lock" || raw === "append") return raw;
|
|
4412
|
+
throw new ProfileError(profilePath, `"capabilityToolMode" must be "lock" or "append"`);
|
|
4413
|
+
}
|
|
4378
4414
|
function readPromptTemplates(dir) {
|
|
4379
4415
|
const out = {};
|
|
4380
4416
|
const read = (p) => {
|
|
@@ -4694,6 +4730,7 @@ var init_profile = __esm({
|
|
|
4694
4730
|
"capabilityTools",
|
|
4695
4731
|
"capabilityTools",
|
|
4696
4732
|
"tools",
|
|
4733
|
+
"capabilityToolMode",
|
|
4697
4734
|
"mentions",
|
|
4698
4735
|
"stage",
|
|
4699
4736
|
"readsFrom",
|
|
@@ -13074,10 +13111,16 @@ var init_loadCapabilityState = __esm({
|
|
|
13074
13111
|
`loadCapabilityState: capability '${slug2}' declared capabilityTools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
13075
13112
|
);
|
|
13076
13113
|
}
|
|
13114
|
+
const mode = profile.capabilityToolMode ?? "lock";
|
|
13077
13115
|
ctx.data.capabilityTools = declaredTools;
|
|
13116
|
+
ctx.data.capabilityToolMode = mode;
|
|
13078
13117
|
ctx.data.capabilityToolsList = declaredTools.map((name) => `- \`${name}\``).join("\n");
|
|
13079
13118
|
ctx.data.capabilityOperatorMention = mentions;
|
|
13080
13119
|
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
13120
|
+
if (mode === "append") {
|
|
13121
|
+
profile.claudeCode.tools = [.../* @__PURE__ */ new Set([...profile.claudeCode.tools ?? [], ...mcpToolNames])];
|
|
13122
|
+
return;
|
|
13123
|
+
}
|
|
13081
13124
|
profile.claudeCode.tools = [...mcpToolNames, "mcp__kody-submit__submit_state"];
|
|
13082
13125
|
profile.claudeCode.enableSubmitTool = true;
|
|
13083
13126
|
}
|
|
@@ -13289,8 +13332,8 @@ var CAPABILITY_TOOL_PALETTE2, loadJobFromFile;
|
|
|
13289
13332
|
var init_loadJobFromFile = __esm({
|
|
13290
13333
|
"src/scripts/loadJobFromFile.ts"() {
|
|
13291
13334
|
"use strict";
|
|
13292
|
-
init_capabilityMcp();
|
|
13293
13335
|
init_agents();
|
|
13336
|
+
init_capabilityMcp();
|
|
13294
13337
|
init_registry();
|
|
13295
13338
|
init_jobState();
|
|
13296
13339
|
CAPABILITY_TOOL_PALETTE2 = new Set(CAPABILITY_MCP_TOOL_NAMES);
|
|
@@ -13304,9 +13347,7 @@ var init_loadJobFromFile = __esm({
|
|
|
13304
13347
|
}
|
|
13305
13348
|
const capability = resolveCapabilityFolder(slug2, path33.join(ctx.cwd, jobsDir));
|
|
13306
13349
|
if (!capability) {
|
|
13307
|
-
throw new Error(
|
|
13308
|
-
`loadJobFromFile: capability folder not found or incomplete: ${path33.join(ctx.cwd, jobsDir, slug2)}`
|
|
13309
|
-
);
|
|
13350
|
+
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${path33.join(ctx.cwd, jobsDir, slug2)}`);
|
|
13310
13351
|
}
|
|
13311
13352
|
const { title, body, config } = capability;
|
|
13312
13353
|
const mentions = (config.mentions ?? []).map((login) => `@${login}`).join(" ");
|
|
@@ -13351,10 +13392,16 @@ var init_loadJobFromFile = __esm({
|
|
|
13351
13392
|
);
|
|
13352
13393
|
}
|
|
13353
13394
|
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
13354
|
-
|
|
13395
|
+
const mode = config.capabilityToolMode ?? "lock";
|
|
13396
|
+
if (mode === "append") {
|
|
13397
|
+
profile.claudeCode.tools = [.../* @__PURE__ */ new Set([...profile.claudeCode.tools ?? [], ...mcpToolNames])];
|
|
13398
|
+
} else {
|
|
13399
|
+
profile.claudeCode.tools = [...mcpToolNames, "mcp__kody-submit__submit_state"];
|
|
13400
|
+
ctx.data.promptTemplate = "prompts/locked.md";
|
|
13401
|
+
}
|
|
13355
13402
|
ctx.data.capabilityTools = declaredTools;
|
|
13403
|
+
ctx.data.capabilityToolMode = mode;
|
|
13356
13404
|
ctx.data.capabilityOperatorMention = mentions;
|
|
13357
|
-
ctx.data.promptTemplate = "prompts/locked.md";
|
|
13358
13405
|
ctx.data.capabilityToolsList = declaredTools.map((name) => `- \`${name}\``).join("\n");
|
|
13359
13406
|
}
|
|
13360
13407
|
};
|
|
@@ -15826,165 +15873,6 @@ var init_runFlow = __esm({
|
|
|
15826
15873
|
}
|
|
15827
15874
|
});
|
|
15828
15875
|
|
|
15829
|
-
// src/scripts/previewBuildHelpers.ts
|
|
15830
|
-
import { createDecipheriv, createHash as createHash3 } from "crypto";
|
|
15831
|
-
function shortHash(s) {
|
|
15832
|
-
return createHash3("sha256").update(s).digest("hex").slice(0, 6);
|
|
15833
|
-
}
|
|
15834
|
-
function previewAppName(repo, pr) {
|
|
15835
|
-
const [owner, name] = repo.split("/");
|
|
15836
|
-
if (!owner || !name) {
|
|
15837
|
-
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
15838
|
-
}
|
|
15839
|
-
return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
|
|
15840
|
-
}
|
|
15841
|
-
function basePreviewAppName(repo) {
|
|
15842
|
-
const [owner, name] = repo.split("/");
|
|
15843
|
-
if (!owner || !name) {
|
|
15844
|
-
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
15845
|
-
}
|
|
15846
|
-
return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
|
|
15847
|
-
}
|
|
15848
|
-
function decryptVaultPayload(payload, keyRaw) {
|
|
15849
|
-
const parts = payload.split(":");
|
|
15850
|
-
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
15851
|
-
throw new Error("invalid vault payload format");
|
|
15852
|
-
}
|
|
15853
|
-
const [, ivB64, ctB64, tagB64] = parts;
|
|
15854
|
-
const key = /^[0-9a-fA-F]{64}$/.test(keyRaw) ? Buffer.from(keyRaw, "hex") : Buffer.from(keyRaw, "base64");
|
|
15855
|
-
if (key.length !== 32) {
|
|
15856
|
-
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
15857
|
-
}
|
|
15858
|
-
const iv = Buffer.from(ivB64, "base64");
|
|
15859
|
-
const ct = Buffer.from(ctB64, "base64");
|
|
15860
|
-
const tag = Buffer.from(tagB64, "base64");
|
|
15861
|
-
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
15862
|
-
decipher.setAuthTag(tag);
|
|
15863
|
-
return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
|
|
15864
|
-
}
|
|
15865
|
-
function buildEnvFromVault(doc) {
|
|
15866
|
-
const buildEnv = {};
|
|
15867
|
-
for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
|
|
15868
|
-
if (!entry?.value) continue;
|
|
15869
|
-
if (NEVER_PASS_TO_BUILD.has(name)) continue;
|
|
15870
|
-
buildEnv[name] = entry.value;
|
|
15871
|
-
}
|
|
15872
|
-
const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
|
|
15873
|
-
const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
|
|
15874
|
-
return { buildEnv, buildMode };
|
|
15875
|
-
}
|
|
15876
|
-
function formatPreviewComment(args) {
|
|
15877
|
-
const url = `https://${args.appName}.fly.dev`;
|
|
15878
|
-
return [
|
|
15879
|
-
"<!-- kody-fly-preview -->",
|
|
15880
|
-
`\u2705 **Preview ready:** ${url}`,
|
|
15881
|
-
"",
|
|
15882
|
-
`<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
|
|
15883
|
-
].join("\n");
|
|
15884
|
-
}
|
|
15885
|
-
function defaultImageTag(repo, ref) {
|
|
15886
|
-
return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
15887
|
-
}
|
|
15888
|
-
var NEVER_PASS_TO_BUILD;
|
|
15889
|
-
var init_previewBuildHelpers = __esm({
|
|
15890
|
-
"src/scripts/previewBuildHelpers.ts"() {
|
|
15891
|
-
"use strict";
|
|
15892
|
-
NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
|
|
15893
|
-
"FLY_API_TOKEN",
|
|
15894
|
-
"FLY_ORG_SLUG",
|
|
15895
|
-
"FLY_DEFAULT_REGION",
|
|
15896
|
-
"KODY_MASTER_KEY",
|
|
15897
|
-
// Preview-config knob; consumed by the dispatcher before spawn.
|
|
15898
|
-
"KODY_PREVIEW_BUILD_MODE"
|
|
15899
|
-
]);
|
|
15900
|
-
}
|
|
15901
|
-
});
|
|
15902
|
-
|
|
15903
|
-
// src/scripts/previewBuildRun.ts
|
|
15904
|
-
import { spawn as spawn4 } from "child_process";
|
|
15905
|
-
async function runCmd(cmd, args, opts = {}) {
|
|
15906
|
-
await new Promise((resolve10, reject) => {
|
|
15907
|
-
const child = spawn4(cmd, args, {
|
|
15908
|
-
cwd: opts.cwd,
|
|
15909
|
-
env: { ...process.env, ...opts.env ?? {} },
|
|
15910
|
-
stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
|
|
15911
|
-
});
|
|
15912
|
-
if (opts.input && child.stdin) {
|
|
15913
|
-
child.stdin.write(opts.input);
|
|
15914
|
-
child.stdin.end();
|
|
15915
|
-
}
|
|
15916
|
-
child.on("error", reject);
|
|
15917
|
-
child.on("close", (code) => {
|
|
15918
|
-
if (code === 0) resolve10();
|
|
15919
|
-
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
15920
|
-
});
|
|
15921
|
-
});
|
|
15922
|
-
}
|
|
15923
|
-
var init_previewBuildRun = __esm({
|
|
15924
|
-
"src/scripts/previewBuildRun.ts"() {
|
|
15925
|
-
"use strict";
|
|
15926
|
-
}
|
|
15927
|
-
});
|
|
15928
|
-
|
|
15929
|
-
// src/scripts/previewBuildNamespace.ts
|
|
15930
|
-
async function fetchGithubOidcToken(audience) {
|
|
15931
|
-
const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
|
|
15932
|
-
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
|
|
15933
|
-
if (!url || !requestToken) return null;
|
|
15934
|
-
const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
15935
|
-
headers: { Authorization: `Bearer ${requestToken}` },
|
|
15936
|
-
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
15937
|
-
});
|
|
15938
|
-
if (!res.ok) {
|
|
15939
|
-
throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
|
|
15940
|
-
}
|
|
15941
|
-
const data = await res.json();
|
|
15942
|
-
if (!data.value) throw new Error("OIDC token response missing `value`");
|
|
15943
|
-
return data.value;
|
|
15944
|
-
}
|
|
15945
|
-
async function setupNamespaceBuilder(opts) {
|
|
15946
|
-
try {
|
|
15947
|
-
await runCmd("bash", ["-c", NSC_INSTALL]);
|
|
15948
|
-
const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
|
|
15949
|
-
if (!jwt) {
|
|
15950
|
-
console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
|
|
15951
|
-
return null;
|
|
15952
|
-
}
|
|
15953
|
-
await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
|
|
15954
|
-
await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
|
|
15955
|
-
console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
|
|
15956
|
-
return opts.builderName;
|
|
15957
|
-
} catch (err) {
|
|
15958
|
-
console.warn(
|
|
15959
|
-
"[preview-build] Namespace setup failed \u2014 falling back to local docker:",
|
|
15960
|
-
err instanceof Error ? err.message : String(err)
|
|
15961
|
-
);
|
|
15962
|
-
return null;
|
|
15963
|
-
}
|
|
15964
|
-
}
|
|
15965
|
-
var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS, NSC_INSTALL;
|
|
15966
|
-
var init_previewBuildNamespace = __esm({
|
|
15967
|
-
"src/scripts/previewBuildNamespace.ts"() {
|
|
15968
|
-
"use strict";
|
|
15969
|
-
init_previewBuildRun();
|
|
15970
|
-
NSC_OIDC_AUDIENCE = "https://namespace.so";
|
|
15971
|
-
REQ_TIMEOUT_MS = 15e3;
|
|
15972
|
-
NSC_INSTALL = `
|
|
15973
|
-
set -euo pipefail
|
|
15974
|
-
if [ ! -x /usr/local/bin/nsc ]; then
|
|
15975
|
-
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
|
|
15976
|
-
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
15977
|
-
curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
|
|
15978
|
-
mkdir -p /tmp/nsc-extract
|
|
15979
|
-
tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
|
|
15980
|
-
NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
|
|
15981
|
-
sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
|
|
15982
|
-
fi
|
|
15983
|
-
/usr/local/bin/nsc version
|
|
15984
|
-
`;
|
|
15985
|
-
}
|
|
15986
|
-
});
|
|
15987
|
-
|
|
15988
15876
|
// src/stateRepoGithub.ts
|
|
15989
15877
|
import * as fs39 from "fs";
|
|
15990
15878
|
import * as path37 from "path";
|
|
@@ -16004,7 +15892,7 @@ async function githubContentsFile(opts) {
|
|
|
16004
15892
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
16005
15893
|
"User-Agent": "kody-engine"
|
|
16006
15894
|
},
|
|
16007
|
-
signal: AbortSignal.timeout(
|
|
15895
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
16008
15896
|
});
|
|
16009
15897
|
if (res.status === 404) return null;
|
|
16010
15898
|
if (!res.ok) {
|
|
@@ -16103,7 +15991,7 @@ async function writeGithubStateTextWithConfig(opts) {
|
|
|
16103
15991
|
"User-Agent": "kody-engine"
|
|
16104
15992
|
},
|
|
16105
15993
|
body: JSON.stringify(payload),
|
|
16106
|
-
signal: AbortSignal.timeout(
|
|
15994
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
|
|
16107
15995
|
});
|
|
16108
15996
|
if (!res.ok) {
|
|
16109
15997
|
throw new Error(
|
|
@@ -16157,13 +16045,196 @@ async function persistJsonlFileToGithubState(opts) {
|
|
|
16157
16045
|
}
|
|
16158
16046
|
}
|
|
16159
16047
|
}
|
|
16160
|
-
var GITHUB_API,
|
|
16048
|
+
var GITHUB_API, REQ_TIMEOUT_MS;
|
|
16161
16049
|
var init_stateRepoGithub = __esm({
|
|
16162
16050
|
"src/stateRepoGithub.ts"() {
|
|
16163
16051
|
"use strict";
|
|
16164
16052
|
init_stateRepo();
|
|
16165
16053
|
GITHUB_API = "https://api.github.com";
|
|
16166
|
-
|
|
16054
|
+
REQ_TIMEOUT_MS = 3e4;
|
|
16055
|
+
}
|
|
16056
|
+
});
|
|
16057
|
+
|
|
16058
|
+
// src/scripts/previewBuildHelpers.ts
|
|
16059
|
+
import { createDecipheriv, createHash as createHash3, hkdfSync } from "crypto";
|
|
16060
|
+
function shortHash(s) {
|
|
16061
|
+
return createHash3("sha256").update(s).digest("hex").slice(0, 6);
|
|
16062
|
+
}
|
|
16063
|
+
function previewAppName(repo, pr) {
|
|
16064
|
+
const [owner, name] = repo.split("/");
|
|
16065
|
+
if (!owner || !name) {
|
|
16066
|
+
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
16067
|
+
}
|
|
16068
|
+
return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
|
|
16069
|
+
}
|
|
16070
|
+
function basePreviewAppName(repo) {
|
|
16071
|
+
const [owner, name] = repo.split("/");
|
|
16072
|
+
if (!owner || !name) {
|
|
16073
|
+
throw new Error(`invalid repo "${repo}", expected "owner/name"`);
|
|
16074
|
+
}
|
|
16075
|
+
return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
|
|
16076
|
+
}
|
|
16077
|
+
function decryptVaultPayload(payload, keyRaw) {
|
|
16078
|
+
const parts = payload.split(":");
|
|
16079
|
+
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
16080
|
+
throw new Error("invalid vault payload format");
|
|
16081
|
+
}
|
|
16082
|
+
const [, ivB64, ctB64, tagB64] = parts;
|
|
16083
|
+
const key = decodeMasterKey(keyRaw);
|
|
16084
|
+
if (key.length !== 32) {
|
|
16085
|
+
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
16086
|
+
}
|
|
16087
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
16088
|
+
const ct = Buffer.from(ctB64, "base64");
|
|
16089
|
+
const tag = Buffer.from(tagB64, "base64");
|
|
16090
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
16091
|
+
decipher.setAuthTag(tag);
|
|
16092
|
+
return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
|
|
16093
|
+
}
|
|
16094
|
+
function decodeMasterKey(keyRaw) {
|
|
16095
|
+
if (/^[0-9a-fA-F]{64}$/.test(keyRaw)) return Buffer.from(keyRaw, "hex");
|
|
16096
|
+
return Buffer.from(keyRaw.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
16097
|
+
}
|
|
16098
|
+
function derivePreviewVerifyKey(masterKeyRaw) {
|
|
16099
|
+
const masterKey = decodeMasterKey(masterKeyRaw);
|
|
16100
|
+
if (masterKey.length !== 32) {
|
|
16101
|
+
throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
|
|
16102
|
+
}
|
|
16103
|
+
return Buffer.from(hkdfSync("sha256", masterKey, Buffer.alloc(0), PREVIEW_KEY_INFO, 32)).toString("hex");
|
|
16104
|
+
}
|
|
16105
|
+
function previewRuntimeEnv(args) {
|
|
16106
|
+
return {
|
|
16107
|
+
...args.buildEnv,
|
|
16108
|
+
KODY_PREVIEW_VERIFY_KEY: derivePreviewVerifyKey(args.masterKey),
|
|
16109
|
+
KODY_REPO_CONTEXT: args.repo,
|
|
16110
|
+
KODY_PR: String(args.pr)
|
|
16111
|
+
};
|
|
16112
|
+
}
|
|
16113
|
+
function buildEnvFromVault(doc) {
|
|
16114
|
+
const buildEnv = {};
|
|
16115
|
+
for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
|
|
16116
|
+
if (!entry?.value) continue;
|
|
16117
|
+
if (NEVER_PASS_TO_BUILD.has(name)) continue;
|
|
16118
|
+
buildEnv[name] = entry.value;
|
|
16119
|
+
}
|
|
16120
|
+
const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
|
|
16121
|
+
const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
|
|
16122
|
+
return { buildEnv, buildMode };
|
|
16123
|
+
}
|
|
16124
|
+
function formatPreviewComment(args) {
|
|
16125
|
+
const url = `https://${args.appName}.fly.dev`;
|
|
16126
|
+
return [
|
|
16127
|
+
"<!-- kody-fly-preview -->",
|
|
16128
|
+
`\u2705 **Preview ready:** ${url}`,
|
|
16129
|
+
"",
|
|
16130
|
+
`<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
|
|
16131
|
+
].join("\n");
|
|
16132
|
+
}
|
|
16133
|
+
function defaultImageTag(repo, ref) {
|
|
16134
|
+
return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
16135
|
+
}
|
|
16136
|
+
var NEVER_PASS_TO_BUILD, PREVIEW_KEY_INFO;
|
|
16137
|
+
var init_previewBuildHelpers = __esm({
|
|
16138
|
+
"src/scripts/previewBuildHelpers.ts"() {
|
|
16139
|
+
"use strict";
|
|
16140
|
+
NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
|
|
16141
|
+
"FLY_API_TOKEN",
|
|
16142
|
+
"FLY_ORG_SLUG",
|
|
16143
|
+
"FLY_DEFAULT_REGION",
|
|
16144
|
+
"KODY_MASTER_KEY",
|
|
16145
|
+
// Preview-config knob; consumed by the dispatcher before spawn.
|
|
16146
|
+
"KODY_PREVIEW_BUILD_MODE",
|
|
16147
|
+
"KODY_PREVIEW_VERIFY_KEY",
|
|
16148
|
+
"KODY_REPO_CONTEXT",
|
|
16149
|
+
"KODY_PR",
|
|
16150
|
+
"KODY_BRANCH"
|
|
16151
|
+
]);
|
|
16152
|
+
PREVIEW_KEY_INFO = "kody-preview:v1";
|
|
16153
|
+
}
|
|
16154
|
+
});
|
|
16155
|
+
|
|
16156
|
+
// src/scripts/previewBuildRun.ts
|
|
16157
|
+
import { spawn as spawn4 } from "child_process";
|
|
16158
|
+
async function runCmd(cmd, args, opts = {}) {
|
|
16159
|
+
await new Promise((resolve10, reject) => {
|
|
16160
|
+
const child = spawn4(cmd, args, {
|
|
16161
|
+
cwd: opts.cwd,
|
|
16162
|
+
env: { ...process.env, ...opts.env ?? {} },
|
|
16163
|
+
stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
|
|
16164
|
+
});
|
|
16165
|
+
if (opts.input && child.stdin) {
|
|
16166
|
+
child.stdin.write(opts.input);
|
|
16167
|
+
child.stdin.end();
|
|
16168
|
+
}
|
|
16169
|
+
child.on("error", reject);
|
|
16170
|
+
child.on("close", (code) => {
|
|
16171
|
+
if (code === 0) resolve10();
|
|
16172
|
+
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
16173
|
+
});
|
|
16174
|
+
});
|
|
16175
|
+
}
|
|
16176
|
+
var init_previewBuildRun = __esm({
|
|
16177
|
+
"src/scripts/previewBuildRun.ts"() {
|
|
16178
|
+
"use strict";
|
|
16179
|
+
}
|
|
16180
|
+
});
|
|
16181
|
+
|
|
16182
|
+
// src/scripts/previewBuildNamespace.ts
|
|
16183
|
+
async function fetchGithubOidcToken(audience) {
|
|
16184
|
+
const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
|
|
16185
|
+
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
|
|
16186
|
+
if (!url || !requestToken) return null;
|
|
16187
|
+
const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
|
|
16188
|
+
headers: { Authorization: `Bearer ${requestToken}` },
|
|
16189
|
+
signal: AbortSignal.timeout(REQ_TIMEOUT_MS2)
|
|
16190
|
+
});
|
|
16191
|
+
if (!res.ok) {
|
|
16192
|
+
throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
|
|
16193
|
+
}
|
|
16194
|
+
const data = await res.json();
|
|
16195
|
+
if (!data.value) throw new Error("OIDC token response missing `value`");
|
|
16196
|
+
return data.value;
|
|
16197
|
+
}
|
|
16198
|
+
async function setupNamespaceBuilder(opts) {
|
|
16199
|
+
try {
|
|
16200
|
+
await runCmd("bash", ["-c", NSC_INSTALL]);
|
|
16201
|
+
const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
|
|
16202
|
+
if (!jwt) {
|
|
16203
|
+
console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
|
|
16204
|
+
return null;
|
|
16205
|
+
}
|
|
16206
|
+
await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
|
|
16207
|
+
await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
|
|
16208
|
+
console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
|
|
16209
|
+
return opts.builderName;
|
|
16210
|
+
} catch (err) {
|
|
16211
|
+
console.warn(
|
|
16212
|
+
"[preview-build] Namespace setup failed \u2014 falling back to local docker:",
|
|
16213
|
+
err instanceof Error ? err.message : String(err)
|
|
16214
|
+
);
|
|
16215
|
+
return null;
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS2, NSC_INSTALL;
|
|
16219
|
+
var init_previewBuildNamespace = __esm({
|
|
16220
|
+
"src/scripts/previewBuildNamespace.ts"() {
|
|
16221
|
+
"use strict";
|
|
16222
|
+
init_previewBuildRun();
|
|
16223
|
+
NSC_OIDC_AUDIENCE = "https://namespace.so";
|
|
16224
|
+
REQ_TIMEOUT_MS2 = 15e3;
|
|
16225
|
+
NSC_INSTALL = `
|
|
16226
|
+
set -euo pipefail
|
|
16227
|
+
if [ ! -x /usr/local/bin/nsc ]; then
|
|
16228
|
+
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
|
|
16229
|
+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
16230
|
+
curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
|
|
16231
|
+
mkdir -p /tmp/nsc-extract
|
|
16232
|
+
tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
|
|
16233
|
+
NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
|
|
16234
|
+
sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
|
|
16235
|
+
fi
|
|
16236
|
+
/usr/local/bin/nsc version
|
|
16237
|
+
`;
|
|
16167
16238
|
}
|
|
16168
16239
|
});
|
|
16169
16240
|
|
|
@@ -16375,10 +16446,10 @@ var FLY_MACHINES, FLY_GRAPHQL, REQ_TIMEOUT_MS3, runPreviewBuild;
|
|
|
16375
16446
|
var init_runPreviewBuild = __esm({
|
|
16376
16447
|
"src/scripts/runPreviewBuild.ts"() {
|
|
16377
16448
|
"use strict";
|
|
16449
|
+
init_stateRepoGithub();
|
|
16378
16450
|
init_previewBuildHelpers();
|
|
16379
16451
|
init_previewBuildNamespace();
|
|
16380
16452
|
init_previewBuildRun();
|
|
16381
|
-
init_stateRepoGithub();
|
|
16382
16453
|
FLY_MACHINES = "https://api.machines.dev/v1";
|
|
16383
16454
|
FLY_GRAPHQL = "https://api.fly.io/graphql";
|
|
16384
16455
|
REQ_TIMEOUT_MS3 = 3e4;
|
|
@@ -16503,7 +16574,7 @@ var init_runPreviewBuild = __esm({
|
|
|
16503
16574
|
appName,
|
|
16504
16575
|
region,
|
|
16505
16576
|
image: `registry.fly.io/${appName}:${tag}`,
|
|
16506
|
-
env: buildEnv
|
|
16577
|
+
env: previewRuntimeEnv({ buildEnv, masterKey, pr, repo })
|
|
16507
16578
|
},
|
|
16508
16579
|
flyToken
|
|
16509
16580
|
);
|
|
@@ -23060,7 +23131,7 @@ async function runCapabilityFallbackTick(deps) {
|
|
|
23060
23131
|
}
|
|
23061
23132
|
|
|
23062
23133
|
// src/pool/keys.ts
|
|
23063
|
-
import { hkdfSync } from "crypto";
|
|
23134
|
+
import { hkdfSync as hkdfSync2 } from "crypto";
|
|
23064
23135
|
var POOL_API_KEY_INFO = "kody-pool-api:v1";
|
|
23065
23136
|
var RUNNER_API_KEY_INFO = "kody-runner-api:v1";
|
|
23066
23137
|
function masterKeyBytes(raw) {
|
|
@@ -23072,7 +23143,7 @@ function masterKeyBytes(raw) {
|
|
|
23072
23143
|
return Buffer.from(v.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
23073
23144
|
}
|
|
23074
23145
|
function deriveKey(master, info, length = 32) {
|
|
23075
|
-
return Buffer.from(
|
|
23146
|
+
return Buffer.from(hkdfSync2("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
|
|
23076
23147
|
}
|
|
23077
23148
|
function derivePoolApiKey(master) {
|
|
23078
23149
|
return deriveKey(master, POOL_API_KEY_INFO);
|
|
@@ -76,13 +76,20 @@ export interface Profile {
|
|
|
76
76
|
*/
|
|
77
77
|
kind: "oneshot" | "scheduled"
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
79
|
+
* Capability MCP palette (unified successor to a markdown capability's `tools:`
|
|
80
80
|
* metadata). When non-empty, loadCapabilityState sets ctx.data.capabilityTools so the
|
|
81
|
-
* executor spins up the in-process kody-capability MCP server
|
|
82
|
-
*
|
|
83
|
-
*
|
|
81
|
+
* executor spins up the in-process kody-capability MCP server. By default this
|
|
82
|
+
* is locked mode: Bash/Read are revoked and only the declared MCP tools plus
|
|
83
|
+
* submit_state remain.
|
|
84
84
|
*/
|
|
85
85
|
capabilityTools?: string[]
|
|
86
|
+
/**
|
|
87
|
+
* `lock` (default) replaces the normal toolbox with capability MCP tools.
|
|
88
|
+
* `append` keeps the normal toolbox and adds the declared MCP tools. Use append
|
|
89
|
+
* only for coordinator capabilities that still own repo state edits but must use
|
|
90
|
+
* an engine primitive for a narrow side effect such as starting another capability.
|
|
91
|
+
*/
|
|
92
|
+
capabilityToolMode?: "lock" | "append"
|
|
86
93
|
/**
|
|
87
94
|
* GitHub logins (no leading `@`) this capability's output should mention. Rendered
|
|
88
95
|
* to `@a @b` and exposed to the prompt as {{mentions}} (and as the capability-MCP
|
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.306",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,6 +12,28 @@
|
|
|
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
|
+
"test:all": "vitest run tests --no-coverage",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "biome check",
|
|
31
|
+
"lint:fix": "biome check --write",
|
|
32
|
+
"format": "biome format --write",
|
|
33
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
34
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
35
|
+
"prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
|
|
36
|
+
},
|
|
15
37
|
"dependencies": {
|
|
16
38
|
"@actions/cache": "^6.0.0",
|
|
17
39
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -35,26 +57,5 @@
|
|
|
35
57
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
36
58
|
},
|
|
37
59
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
38
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
39
|
-
|
|
40
|
-
"kody:run": "tsx bin/kody.ts",
|
|
41
|
-
"serve": "tsx bin/kody.ts serve",
|
|
42
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
43
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
44
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
45
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
46
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
47
|
-
"pretest": "pnpm check:modularity",
|
|
48
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
49
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
50
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
51
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
52
|
-
"test:all": "vitest run tests --no-coverage",
|
|
53
|
-
"typecheck": "tsc --noEmit",
|
|
54
|
-
"lint": "biome check",
|
|
55
|
-
"lint:fix": "biome check --write",
|
|
56
|
-
"format": "biome format --write",
|
|
57
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
58
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
60
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
61
|
+
}
|