@kody-ade/kody-engine 0.4.305 → 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 +63 -16
- 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
|
};
|
|
@@ -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
|
+
}
|