@kody-ade/kody-engine 0.4.289 → 0.4.291
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/README.md +3 -7
- package/dist/bin/kody.js +135 -144
- package/dist/executables/agent-factory/prompt.md +5 -4
- package/dist/executables/types.ts +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,10 +78,6 @@ See [SECURITY.md](SECURITY.md) to report a vulnerability.
|
|
|
78
78
|
│ src/executor.ts — runs capability implementations │
|
|
79
79
|
│ .kody/capabilities/<slug>/ │
|
|
80
80
|
│ profile.json · capability.md · optional skills/scripts │
|
|
81
|
-
│ .kody/capabilities/<slug>/ │
|
|
82
|
-
│ legacy fallback: profile.json · capability.md │
|
|
83
|
-
│ .kody/executables/<name>/ │
|
|
84
|
-
│ legacy fallback: profile.json · prompt.md · *.sh │
|
|
85
81
|
│ src/scripts/*.ts — cross-cutting catalog │
|
|
86
82
|
└─────────────────────────────────────────────┘
|
|
87
83
|
```
|
|
@@ -91,10 +87,10 @@ Every top-level command is an auto-discovered capability action. The router has
|
|
|
91
87
|
after `@kody` through `config.aliases`, then falls back to the legacy-named
|
|
92
88
|
`config.defaultExecutable` / `config.defaultPrExecutable` fields as default
|
|
93
89
|
capability actions. Drop a new `.kody/capabilities/<slug>/` directory with
|
|
94
|
-
`profile.json` + `capability.md
|
|
95
|
-
|
|
90
|
+
`profile.json` + `capability.md`. Project/store `.kody/executables/` folders
|
|
91
|
+
are obsolete and are not resolver sources.
|
|
96
92
|
|
|
97
|
-
|
|
93
|
+
Capability implementation profiles are private implementation units and contain
|
|
98
94
|
**only** three kinds of files: `profile.json` (declaration), `prompt.md` (agent
|
|
99
95
|
instructions), and `.sh` scripts (mechanical side-effect work). Cross-cutting
|
|
100
96
|
TypeScript lives in [src/scripts/](src/scripts/); it can't import from
|
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.291",
|
|
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",
|
|
@@ -1266,7 +1266,7 @@ var init_events = __esm({
|
|
|
1266
1266
|
// src/verify.ts
|
|
1267
1267
|
import { spawn } from "child_process";
|
|
1268
1268
|
function runCommand(command, cwd) {
|
|
1269
|
-
return new Promise((
|
|
1269
|
+
return new Promise((resolve10) => {
|
|
1270
1270
|
const start = Date.now();
|
|
1271
1271
|
const child = spawn(command, {
|
|
1272
1272
|
cwd,
|
|
@@ -1295,11 +1295,11 @@ function runCommand(command, cwd) {
|
|
|
1295
1295
|
child.on("exit", (code) => {
|
|
1296
1296
|
clearTimeout(timer);
|
|
1297
1297
|
const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
|
|
1298
|
-
|
|
1298
|
+
resolve10({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
|
|
1299
1299
|
});
|
|
1300
1300
|
child.on("error", (err) => {
|
|
1301
1301
|
clearTimeout(timer);
|
|
1302
|
-
|
|
1302
|
+
resolve10({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
|
|
1303
1303
|
});
|
|
1304
1304
|
});
|
|
1305
1305
|
}
|
|
@@ -1907,6 +1907,8 @@ function parseCapabilityConfig(raw) {
|
|
|
1907
1907
|
executable: stringField(raw.executable),
|
|
1908
1908
|
tickScript: stringField(raw.tickScript),
|
|
1909
1909
|
disabled: typeof raw.disabled === "boolean" ? raw.disabled : void 0,
|
|
1910
|
+
internal: typeof raw.internal === "boolean" ? raw.internal : void 0,
|
|
1911
|
+
public: typeof raw.public === "boolean" ? raw.public : void 0,
|
|
1910
1912
|
agent: stringField(raw.agent),
|
|
1911
1913
|
mentions: stringList(raw.mentions).map((m) => m.replace(/^@/, "")),
|
|
1912
1914
|
tools,
|
|
@@ -2022,7 +2024,6 @@ function getCompanyStoreAssetRoot(kind) {
|
|
|
2022
2024
|
if (!root) return null;
|
|
2023
2025
|
const folderByKind = {
|
|
2024
2026
|
capabilities: "capabilities",
|
|
2025
|
-
executables: "executables",
|
|
2026
2027
|
goals: "goals",
|
|
2027
2028
|
agents: "agents",
|
|
2028
2029
|
workflows: "workflows"
|
|
@@ -2128,15 +2129,9 @@ function getExecutablesRoot() {
|
|
|
2128
2129
|
}
|
|
2129
2130
|
return candidates[0];
|
|
2130
2131
|
}
|
|
2131
|
-
function getProjectExecutablesRoot() {
|
|
2132
|
-
return path8.join(process.cwd(), ".kody", "executables");
|
|
2133
|
-
}
|
|
2134
2132
|
function getProjectCapabilitiesRoot() {
|
|
2135
2133
|
return path8.join(process.cwd(), ".kody", "capabilities");
|
|
2136
2134
|
}
|
|
2137
|
-
function getCompanyStoreExecutablesRoot() {
|
|
2138
|
-
return getCompanyStoreAssetRoot("executables");
|
|
2139
|
-
}
|
|
2140
2135
|
function getCompanyStoreCapabilitiesRoot() {
|
|
2141
2136
|
return getCompanyStoreAssetRoot("capabilities");
|
|
2142
2137
|
}
|
|
@@ -2157,14 +2152,10 @@ function getBuiltinCapabilitiesRoot() {
|
|
|
2157
2152
|
}
|
|
2158
2153
|
function getExecutableRoots() {
|
|
2159
2154
|
const projectCapabilitiesRoot = getProjectCapabilitiesRoot();
|
|
2160
|
-
const projectExecutablesRoot = getProjectExecutablesRoot();
|
|
2161
2155
|
const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
|
|
2162
|
-
const storeExecutablesRoot = getCompanyStoreExecutablesRoot();
|
|
2163
2156
|
return [
|
|
2164
2157
|
projectCapabilitiesRoot,
|
|
2165
|
-
projectExecutablesRoot,
|
|
2166
2158
|
...storeCapabilitiesRoot ? [storeCapabilitiesRoot] : [],
|
|
2167
|
-
...storeExecutablesRoot ? [storeExecutablesRoot] : [],
|
|
2168
2159
|
getExecutablesRoot()
|
|
2169
2160
|
];
|
|
2170
2161
|
}
|
|
@@ -2216,21 +2207,12 @@ function listCapabilityActions(projectCapabilitiesRoot = getProjectCapabilitiesR
|
|
|
2216
2207
|
seen.add(action.action);
|
|
2217
2208
|
out.push(action);
|
|
2218
2209
|
};
|
|
2219
|
-
const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
|
|
2220
|
-
const projectExecutableRoots = [getProjectExecutablesRoot()];
|
|
2221
|
-
const storeExecutableRoot = getCompanyStoreExecutablesRoot();
|
|
2222
|
-
const storeExecutableRoots = storeExecutableRoot ? [storeExecutableRoot] : [];
|
|
2223
2210
|
for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder"))
|
|
2224
2211
|
add(action);
|
|
2225
|
-
|
|
2226
|
-
for (const action of listExecutableCapabilityActions(root, "project-executable")) add(action);
|
|
2227
|
-
}
|
|
2212
|
+
const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
|
|
2228
2213
|
if (storeCapabilitiesRoot) {
|
|
2229
2214
|
for (const action of listFolderCapabilityActions(storeCapabilitiesRoot, "company-store")) add(action);
|
|
2230
2215
|
}
|
|
2231
|
-
for (const root of storeExecutableRoots) {
|
|
2232
|
-
for (const action of listExecutableCapabilityActions(root, "company-store-executable")) add(action);
|
|
2233
|
-
}
|
|
2234
2216
|
for (const action of listBuiltinCapabilityActions(getBuiltinCapabilitiesRoot())) add(action);
|
|
2235
2217
|
return out.sort((a, b) => a.action.localeCompare(b.action));
|
|
2236
2218
|
}
|
|
@@ -2294,34 +2276,6 @@ function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
|
2294
2276
|
return false;
|
|
2295
2277
|
}
|
|
2296
2278
|
}
|
|
2297
|
-
function listExecutableCapabilityActions(root, source) {
|
|
2298
|
-
if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
|
|
2299
|
-
const out = [];
|
|
2300
|
-
for (const ent of fs6.readdirSync(root, { withFileTypes: true })) {
|
|
2301
|
-
if (!ent.isDirectory() || !isSafeName(ent.name)) continue;
|
|
2302
|
-
const profilePath = path8.join(root, ent.name, CAPABILITY_PROFILE_FILE);
|
|
2303
|
-
if (!fs6.existsSync(profilePath) || !fs6.statSync(profilePath).isFile()) continue;
|
|
2304
|
-
try {
|
|
2305
|
-
const raw = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
2306
|
-
const action = typeof raw.action === "string" && raw.action.trim() ? raw.action.trim() : "";
|
|
2307
|
-
if (!action) continue;
|
|
2308
|
-
if (!PUBLIC_EXECUTABLE_ROLES.has(String(raw.role))) continue;
|
|
2309
|
-
if (typeof raw.kind !== "string" || !raw.kind.trim()) continue;
|
|
2310
|
-
if (!Array.isArray(raw.inputs)) continue;
|
|
2311
|
-
out.push({
|
|
2312
|
-
action,
|
|
2313
|
-
capability: ent.name,
|
|
2314
|
-
executable: ent.name,
|
|
2315
|
-
cliArgs: {},
|
|
2316
|
-
source,
|
|
2317
|
-
describe: typeof raw.describe === "string" ? raw.describe : void 0,
|
|
2318
|
-
profilePath
|
|
2319
|
-
});
|
|
2320
|
-
} catch {
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
return out.sort((a, b) => a.action.localeCompare(b.action));
|
|
2324
|
-
}
|
|
2325
2279
|
function listFolderCapabilityActions(root, source) {
|
|
2326
2280
|
if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
|
|
2327
2281
|
const out = [];
|
|
@@ -2329,6 +2283,7 @@ function listFolderCapabilityActions(root, source) {
|
|
|
2329
2283
|
if (!isSafeName(slug2)) continue;
|
|
2330
2284
|
const capability = readCapabilityFolder(root, slug2);
|
|
2331
2285
|
if (!capability) continue;
|
|
2286
|
+
if (capability.config.internal === true || capability.config.public === false) continue;
|
|
2332
2287
|
const action = capability.config.action ?? slug2;
|
|
2333
2288
|
const { executable, cliArgs } = resolveCapabilityExecution(capability);
|
|
2334
2289
|
out.push({
|
|
@@ -2978,7 +2933,7 @@ var init_repoWorkspace = __esm({
|
|
|
2978
2933
|
defaultCloneRepo = (repo, token, dir) => {
|
|
2979
2934
|
fs7.mkdirSync(path9.dirname(dir), { recursive: true });
|
|
2980
2935
|
const authUrl = token ? `https://x-access-token:${token}@github.com/${repo}.git` : `https://github.com/${repo}.git`;
|
|
2981
|
-
return new Promise((
|
|
2936
|
+
return new Promise((resolve10, reject) => {
|
|
2982
2937
|
const child = spawn2("git", ["clone", "--depth=1", authUrl, dir], {
|
|
2983
2938
|
stdio: "inherit"
|
|
2984
2939
|
});
|
|
@@ -2994,7 +2949,7 @@ var init_repoWorkspace = __esm({
|
|
|
2994
2949
|
spawnSync("git", ["-C", dir, "config", "user.email", email]);
|
|
2995
2950
|
} catch {
|
|
2996
2951
|
}
|
|
2997
|
-
|
|
2952
|
+
resolve10();
|
|
2998
2953
|
});
|
|
2999
2954
|
child.on("error", reject);
|
|
3000
2955
|
});
|
|
@@ -3205,18 +3160,18 @@ async function runAgent(opts) {
|
|
|
3205
3160
|
}
|
|
3206
3161
|
if (opts.enableCapabilityTool) {
|
|
3207
3162
|
const { buildCapabilityMcpServer: buildCapabilityMcpServer2 } = await Promise.resolve().then(() => (init_capabilityMcp(), capabilityMcp_exports));
|
|
3208
|
-
if (!opts.
|
|
3163
|
+
if (!opts.capabilityRepoSlug) {
|
|
3209
3164
|
throw new Error(
|
|
3210
|
-
"enableCapabilityTool requires
|
|
3165
|
+
"enableCapabilityTool requires capabilityRepoSlug (owner/name) \u2014 set kody.config.json github.{owner,repo} or GITHUB_REPOSITORY env var"
|
|
3211
3166
|
);
|
|
3212
3167
|
}
|
|
3213
|
-
const
|
|
3214
|
-
repoSlug: opts.
|
|
3168
|
+
const capabilityHandle = buildCapabilityMcpServer2({
|
|
3169
|
+
repoSlug: opts.capabilityRepoSlug,
|
|
3215
3170
|
state: opts.capabilityState,
|
|
3216
3171
|
operatorMention: opts.capabilityOperatorMention ?? "",
|
|
3217
3172
|
...opts.capabilitySlug ? { capabilitySlug: opts.capabilitySlug } : {}
|
|
3218
3173
|
});
|
|
3219
|
-
mcpEntries.push(["kody-capability",
|
|
3174
|
+
mcpEntries.push(["kody-capability", capabilityHandle.server]);
|
|
3220
3175
|
}
|
|
3221
3176
|
if (opts.enableDashboardCmsTool) {
|
|
3222
3177
|
const { buildDashboardCmsMcpServer: buildDashboardCmsMcpServer2, DASHBOARD_CMS_MCP_TOOL_NAMES: DASHBOARD_CMS_MCP_TOOL_NAMES2 } = await Promise.resolve().then(() => (init_dashboardCmsMcp(), dashboardCmsMcp_exports));
|
|
@@ -3302,10 +3257,10 @@ async function runAgent(opts) {
|
|
|
3302
3257
|
let timer;
|
|
3303
3258
|
let next;
|
|
3304
3259
|
if (turnTimeoutMs > 0) {
|
|
3305
|
-
const timeoutPromise = new Promise((
|
|
3260
|
+
const timeoutPromise = new Promise((resolve10) => {
|
|
3306
3261
|
timer = setTimeout(() => {
|
|
3307
3262
|
timedOut = true;
|
|
3308
|
-
|
|
3263
|
+
resolve10({ done: true, value: void 0 });
|
|
3309
3264
|
}, turnTimeoutMs);
|
|
3310
3265
|
});
|
|
3311
3266
|
next = await Promise.race([nextPromise, timeoutPromise]);
|
|
@@ -4255,18 +4210,29 @@ function loadProfile(profilePath) {
|
|
|
4255
4210
|
if (!refPath) {
|
|
4256
4211
|
throw new ProfileError(profilePath, `capability references unknown executable '${execRef}'`);
|
|
4257
4212
|
}
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4213
|
+
if (path19.resolve(refPath) === path19.resolve(profilePath)) {
|
|
4214
|
+
} else {
|
|
4215
|
+
const base = loadProfile(refPath);
|
|
4216
|
+
return {
|
|
4217
|
+
...base,
|
|
4218
|
+
name: requireString(profilePath, r, "name"),
|
|
4219
|
+
action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
|
|
4220
|
+
implementation: execRef,
|
|
4221
|
+
executable: execRef,
|
|
4222
|
+
internal: typeof r.internal === "boolean" ? r.internal : base.internal,
|
|
4223
|
+
public: typeof r.public === "boolean" ? r.public : base.public,
|
|
4224
|
+
capabilityKind: parseCapabilityKind(r.capabilityKind) ?? base.capabilityKind,
|
|
4225
|
+
slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : base.slug,
|
|
4226
|
+
title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : base.title,
|
|
4227
|
+
skills: parseStringArray2(r.skills) ?? base.skills,
|
|
4228
|
+
prompt: typeof r.prompt === "string" && r.prompt.trim() ? r.prompt.trim() : base.prompt,
|
|
4229
|
+
chatTools: parseStringArray2(r.chatTools) ?? base.chatTools,
|
|
4230
|
+
describe: typeof r.describe === "string" ? r.describe : base.describe,
|
|
4231
|
+
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
|
|
4232
|
+
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
|
|
4233
|
+
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
|
|
4234
|
+
};
|
|
4235
|
+
}
|
|
4270
4236
|
}
|
|
4271
4237
|
const kind = r.kind === "scheduled" ? "scheduled" : "oneshot";
|
|
4272
4238
|
if (kind === "scheduled" && typeof r.schedule !== "string") {
|
|
@@ -4306,6 +4272,14 @@ function loadProfile(profilePath) {
|
|
|
4306
4272
|
action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
|
|
4307
4273
|
implementation: void 0,
|
|
4308
4274
|
executable: void 0,
|
|
4275
|
+
internal: typeof r.internal === "boolean" ? r.internal : void 0,
|
|
4276
|
+
public: typeof r.public === "boolean" ? r.public : void 0,
|
|
4277
|
+
capabilityKind: parseCapabilityKind(r.capabilityKind),
|
|
4278
|
+
slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : void 0,
|
|
4279
|
+
title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : void 0,
|
|
4280
|
+
skills: parseStringArray2(r.skills),
|
|
4281
|
+
prompt: typeof r.prompt === "string" && r.prompt.trim() ? r.prompt.trim() : void 0,
|
|
4282
|
+
chatTools: parseStringArray2(r.chatTools),
|
|
4309
4283
|
describe: typeof r.describe === "string" ? r.describe : "",
|
|
4310
4284
|
// Optional agent to run as. Empty/blank string → undefined (no agent).
|
|
4311
4285
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : void 0,
|
|
@@ -4406,6 +4380,9 @@ function parseStringArray2(raw) {
|
|
|
4406
4380
|
const values = raw.map((t) => String(t).trim()).filter(Boolean);
|
|
4407
4381
|
return values.length > 0 ? values : void 0;
|
|
4408
4382
|
}
|
|
4383
|
+
function parseCapabilityKind(raw) {
|
|
4384
|
+
return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
|
|
4385
|
+
}
|
|
4409
4386
|
function parseInputs(p, raw) {
|
|
4410
4387
|
if (!Array.isArray(raw)) throw new ProfileError(p, `"inputs" must be an array`);
|
|
4411
4388
|
const out = [];
|
|
@@ -4670,6 +4647,14 @@ var init_profile = __esm({
|
|
|
4670
4647
|
"implementations",
|
|
4671
4648
|
"executable",
|
|
4672
4649
|
"executables",
|
|
4650
|
+
"internal",
|
|
4651
|
+
"public",
|
|
4652
|
+
"capabilityKind",
|
|
4653
|
+
"slug",
|
|
4654
|
+
"title",
|
|
4655
|
+
"skills",
|
|
4656
|
+
"prompt",
|
|
4657
|
+
"chatTools",
|
|
4673
4658
|
"agent",
|
|
4674
4659
|
"every",
|
|
4675
4660
|
"capabilityTools",
|
|
@@ -8145,7 +8130,7 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
8145
8130
|
}
|
|
8146
8131
|
};
|
|
8147
8132
|
}
|
|
8148
|
-
const dispatch2 =
|
|
8133
|
+
const dispatch2 = capabilityDispatch(capability);
|
|
8149
8134
|
statuses[due.slug] = markCapabilitySelected(statuses[due.slug], now);
|
|
8150
8135
|
return {
|
|
8151
8136
|
kind: "dispatch",
|
|
@@ -8205,7 +8190,7 @@ async function describeCapabilitySchedule(capability, slug2, backend, previous)
|
|
|
8205
8190
|
lastFiredAt
|
|
8206
8191
|
};
|
|
8207
8192
|
}
|
|
8208
|
-
function
|
|
8193
|
+
function capabilityDispatch(capability) {
|
|
8209
8194
|
const { executable, cliArgs } = resolveCapabilityExecution(capability);
|
|
8210
8195
|
return { capability: capability.slug, executable, cliArgs };
|
|
8211
8196
|
}
|
|
@@ -9739,7 +9724,7 @@ var init_applyCapabilityReports = __esm({
|
|
|
9739
9724
|
init_stateStore();
|
|
9740
9725
|
applyCapabilityReports = async (ctx, _profile, agentResult) => {
|
|
9741
9726
|
const reports = collectReports(ctx.data.capabilityReports, agentResult);
|
|
9742
|
-
const results = collectResults(ctx.data.dutyResults, agentResult);
|
|
9727
|
+
const results = collectResults(ctx.data.capabilityResults ?? ctx.data.dutyResults, agentResult);
|
|
9743
9728
|
const resultGoalId = typeof ctx.args.goal === "string" && ctx.args.goal.length > 0 ? ctx.args.goal : null;
|
|
9744
9729
|
const explicitEvidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
|
|
9745
9730
|
const evidenceItems = collectGoalCapabilityEvidence(reports, results, resultGoalId, explicitEvidence);
|
|
@@ -10258,7 +10243,7 @@ function formatCapabilityReference(data, profileName) {
|
|
|
10258
10243
|
if (capabilitySchedule) {
|
|
10259
10244
|
lines.push(`- Cadence: \`${capabilitySchedule}\``);
|
|
10260
10245
|
}
|
|
10261
|
-
const capabilityBody = pickToken(data, "
|
|
10246
|
+
const capabilityBody = pickToken(data, "capabilityIntent", "jobIntent", "dutyIntent");
|
|
10262
10247
|
if (capabilityBody) {
|
|
10263
10248
|
lines.push("", "## Capability body", "", capabilityBody);
|
|
10264
10249
|
}
|
|
@@ -12961,7 +12946,7 @@ function retryDelaysMs() {
|
|
|
12961
12946
|
}
|
|
12962
12947
|
function sleep(ms) {
|
|
12963
12948
|
if (ms <= 0) return Promise.resolve();
|
|
12964
|
-
return new Promise((
|
|
12949
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
12965
12950
|
}
|
|
12966
12951
|
async function fetchGoalStateWithRetry(config, goalId, cwd) {
|
|
12967
12952
|
let state = fetchGoalState(config, goalId, cwd);
|
|
@@ -13798,6 +13783,11 @@ function normalizeBundleFiles(ctx, bundle) {
|
|
|
13798
13783
|
if (!relativePath) {
|
|
13799
13784
|
throw new Error(`openAgentFactoryStatePr: files[${index}].path must point to a state repo file`);
|
|
13800
13785
|
}
|
|
13786
|
+
if (relativePath === "executables" || relativePath.startsWith("executables/")) {
|
|
13787
|
+
throw new Error(
|
|
13788
|
+
`openAgentFactoryStatePr: files[${index}].path uses obsolete executables storage; use capabilities/<slug>/ instead`
|
|
13789
|
+
);
|
|
13790
|
+
}
|
|
13801
13791
|
if (seen.has(relativePath)) {
|
|
13802
13792
|
throw new Error(`openAgentFactoryStatePr: duplicate generated file path: ${relativePath}`);
|
|
13803
13793
|
}
|
|
@@ -15637,7 +15627,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
15637
15627
|
// src/scripts/previewBuildRun.ts
|
|
15638
15628
|
import { spawn as spawn4 } from "child_process";
|
|
15639
15629
|
async function runCmd(cmd, args, opts = {}) {
|
|
15640
|
-
await new Promise((
|
|
15630
|
+
await new Promise((resolve10, reject) => {
|
|
15641
15631
|
const child = spawn4(cmd, args, {
|
|
15642
15632
|
cwd: opts.cwd,
|
|
15643
15633
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -15649,7 +15639,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
15649
15639
|
}
|
|
15650
15640
|
child.on("error", reject);
|
|
15651
15641
|
child.on("close", (code) => {
|
|
15652
|
-
if (code === 0)
|
|
15642
|
+
if (code === 0) resolve10();
|
|
15653
15643
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
15654
15644
|
});
|
|
15655
15645
|
});
|
|
@@ -16773,7 +16763,7 @@ function stripAnsi2(s) {
|
|
|
16773
16763
|
return s.replace(ANSI_RE2, "");
|
|
16774
16764
|
}
|
|
16775
16765
|
function runCommand2(command, cwd) {
|
|
16776
|
-
return new Promise((
|
|
16766
|
+
return new Promise((resolve10) => {
|
|
16777
16767
|
const child = spawn5(command, {
|
|
16778
16768
|
cwd,
|
|
16779
16769
|
shell: true,
|
|
@@ -16800,11 +16790,11 @@ function runCommand2(command, cwd) {
|
|
|
16800
16790
|
}, TEST_TIMEOUT_MS);
|
|
16801
16791
|
child.on("exit", (code) => {
|
|
16802
16792
|
clearTimeout(timer);
|
|
16803
|
-
|
|
16793
|
+
resolve10({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
16804
16794
|
});
|
|
16805
16795
|
child.on("error", (err) => {
|
|
16806
16796
|
clearTimeout(timer);
|
|
16807
|
-
|
|
16797
|
+
resolve10({ exitCode: -1, output: err.message });
|
|
16808
16798
|
});
|
|
16809
16799
|
});
|
|
16810
16800
|
}
|
|
@@ -17209,21 +17199,21 @@ function lineStream(stream) {
|
|
|
17209
17199
|
tryDeliver();
|
|
17210
17200
|
});
|
|
17211
17201
|
return {
|
|
17212
|
-
next: (timeoutMs) => new Promise((
|
|
17202
|
+
next: (timeoutMs) => new Promise((resolve10) => {
|
|
17213
17203
|
if (queue.length > 0) {
|
|
17214
|
-
|
|
17204
|
+
resolve10(queue.shift());
|
|
17215
17205
|
return;
|
|
17216
17206
|
}
|
|
17217
17207
|
if (ended) {
|
|
17218
|
-
|
|
17208
|
+
resolve10(null);
|
|
17219
17209
|
return;
|
|
17220
17210
|
}
|
|
17221
|
-
waiter =
|
|
17211
|
+
waiter = resolve10;
|
|
17222
17212
|
const t = setTimeout(
|
|
17223
17213
|
() => {
|
|
17224
|
-
if (waiter ===
|
|
17214
|
+
if (waiter === resolve10) {
|
|
17225
17215
|
waiter = null;
|
|
17226
|
-
|
|
17216
|
+
resolve10(null);
|
|
17227
17217
|
}
|
|
17228
17218
|
},
|
|
17229
17219
|
Math.max(0, timeoutMs)
|
|
@@ -17712,7 +17702,6 @@ var init_stateWorkspace = __esm({
|
|
|
17712
17702
|
"use strict";
|
|
17713
17703
|
init_stateRepo();
|
|
17714
17704
|
DIR_MAPPINGS = [
|
|
17715
|
-
{ stateDir: "executables", localDir: path41.join(".kody", "executables") },
|
|
17716
17705
|
{ stateDir: "capabilities", localDir: path41.join(".kody", "capabilities") },
|
|
17717
17706
|
{ stateDir: "agents", localDir: path41.join(".kody", "agents") },
|
|
17718
17707
|
{ stateDir: "context", localDir: path41.join(".kody", "context") },
|
|
@@ -17817,10 +17806,11 @@ function collectShellSideChannels(ctx, stdout) {
|
|
|
17817
17806
|
const prior = Array.isArray(ctx.data.capabilityReports) ? ctx.data.capabilityReports : [];
|
|
17818
17807
|
ctx.data.capabilityReports = [...prior, ...capabilityReports];
|
|
17819
17808
|
}
|
|
17820
|
-
const
|
|
17821
|
-
if (
|
|
17822
|
-
const prior = Array.isArray(ctx.data.dutyResults) ? ctx.data.dutyResults : [];
|
|
17823
|
-
ctx.data.
|
|
17809
|
+
const capabilityResults = parseCapabilityResultsFromText(stdout);
|
|
17810
|
+
if (capabilityResults.length > 0) {
|
|
17811
|
+
const prior = Array.isArray(ctx.data.capabilityResults) ? ctx.data.capabilityResults : Array.isArray(ctx.data.dutyResults) ? ctx.data.dutyResults : [];
|
|
17812
|
+
ctx.data.capabilityResults = [...prior, ...capabilityResults];
|
|
17813
|
+
ctx.data.dutyResults = ctx.data.capabilityResults;
|
|
17824
17814
|
}
|
|
17825
17815
|
}
|
|
17826
17816
|
function operatorRequestBlock(why) {
|
|
@@ -18036,7 +18026,7 @@ async function runExecutable(profileName, input) {
|
|
|
18036
18026
|
// owner/repo from kody.config.json; envelope falls back to GITHUB_REPOSITORY
|
|
18037
18027
|
// for tester repos that don't set config.github (the file isn't always
|
|
18038
18028
|
// checked in). Either way, capabilityMcp needs "owner/name" to hit the compare API.
|
|
18039
|
-
|
|
18029
|
+
capabilityRepoSlug: config.github?.owner && config.github?.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY?.trim() || void 0,
|
|
18040
18030
|
verifyToolMaxAttempts: profile.claudeCode.verifyAttempts ?? null,
|
|
18041
18031
|
verifyConfig: profile.claudeCode.enableVerifyTool ? config : void 0,
|
|
18042
18032
|
executableName: profileName,
|
|
@@ -18513,14 +18503,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
18513
18503
|
let killTimer;
|
|
18514
18504
|
let escalateTimer;
|
|
18515
18505
|
const result = await new Promise(
|
|
18516
|
-
(
|
|
18506
|
+
(resolve10) => {
|
|
18517
18507
|
let settled = false;
|
|
18518
18508
|
const settle = (code, signal, spawnErr) => {
|
|
18519
18509
|
if (settled) return;
|
|
18520
18510
|
settled = true;
|
|
18521
18511
|
if (killTimer) clearTimeout(killTimer);
|
|
18522
18512
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
18523
|
-
|
|
18513
|
+
resolve10({ code, signal, spawnErr });
|
|
18524
18514
|
};
|
|
18525
18515
|
child.on("error", (err) => settle(null, null, err));
|
|
18526
18516
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -18781,7 +18771,7 @@ async function runJob(job, base) {
|
|
|
18781
18771
|
}
|
|
18782
18772
|
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
18783
18773
|
const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
|
|
18784
|
-
const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
18774
|
+
const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
18785
18775
|
const profileName = valid.executable ?? capabilitySelectedExecutable;
|
|
18786
18776
|
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedExecutable, base)) {
|
|
18787
18777
|
const workflowCapability = capabilityContext ?? workflowContext;
|
|
@@ -18825,6 +18815,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
18825
18815
|
if (capabilityContext) {
|
|
18826
18816
|
preloadedData.capabilitySlug = capabilityContext.slug;
|
|
18827
18817
|
preloadedData.capabilityTitle = capabilityContext.title;
|
|
18818
|
+
preloadedData.capabilityIntent = capabilityContext.body;
|
|
18828
18819
|
preloadedData.dutyIntent = capabilityContext.body;
|
|
18829
18820
|
preloadedData.jobIntent = capabilityContext.body;
|
|
18830
18821
|
if (preloadedData.jobCapability === void 0) preloadedData.jobCapability = capabilityContext.slug;
|
|
@@ -19509,11 +19500,11 @@ function buildExecutableCatalog() {
|
|
|
19509
19500
|
if (entries.length === 0) return "";
|
|
19510
19501
|
const lines = [
|
|
19511
19502
|
"",
|
|
19512
|
-
"# Available
|
|
19503
|
+
"# Available capability implementations",
|
|
19513
19504
|
"These run inside the engine, NOT inside this chat. You cannot invoke them",
|
|
19514
|
-
"directly \u2014 to run one, tell the user to post `@kody <
|
|
19505
|
+
"directly \u2014 to run one, tell the user to post the matching `@kody <action>`",
|
|
19515
19506
|
"as a comment on the relevant issue or PR. The dispatcher binds the issue/PR",
|
|
19516
|
-
"number to the
|
|
19507
|
+
"number to the implementation inputs automatically.",
|
|
19517
19508
|
""
|
|
19518
19509
|
];
|
|
19519
19510
|
for (const e of entries) {
|
|
@@ -20729,12 +20720,12 @@ async function runCi(argv) {
|
|
|
20729
20720
|
const evt = JSON.parse(fs46.readFileSync(dispatchEventPath, "utf-8"));
|
|
20730
20721
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
20731
20722
|
const sessionInput = String(evt?.inputs?.sessionId ?? "");
|
|
20732
|
-
const
|
|
20723
|
+
const capabilityInput = String(evt?.inputs?.capability ?? evt?.inputs?.executable ?? "").trim();
|
|
20733
20724
|
const messageInput = String(evt?.inputs?.message ?? "").trim();
|
|
20734
20725
|
const noTarget = !sessionInput && !(Number.isFinite(issueInput) && issueInput > 0);
|
|
20735
|
-
if (noTarget &&
|
|
20736
|
-
forceRunAction =
|
|
20737
|
-
if (
|
|
20726
|
+
if (noTarget && capabilityInput) {
|
|
20727
|
+
forceRunAction = capabilityInput;
|
|
20728
|
+
if (capabilityInput === "goal-manager" && messageInput) {
|
|
20738
20729
|
forceRunCliArgs = { goal: messageInput };
|
|
20739
20730
|
}
|
|
20740
20731
|
} else {
|
|
@@ -20747,8 +20738,8 @@ async function runCi(argv) {
|
|
|
20747
20738
|
if (forceRunAction) {
|
|
20748
20739
|
const config = earlyConfig ?? loadConfig(cwd);
|
|
20749
20740
|
const manualGoalManager = forceRunAction === "goal-manager";
|
|
20750
|
-
const
|
|
20751
|
-
const scheduledWatchRoute = manualGoalManager ||
|
|
20741
|
+
const capabilityRoute = manualGoalManager ? null : resolveCapabilityAction(forceRunAction);
|
|
20742
|
+
const scheduledWatchRoute = manualGoalManager || capabilityRoute ? void 0 : dispatchScheduledWatches({ force: true }).find(
|
|
20752
20743
|
(match) => match.action === forceRunAction || match.executable === forceRunAction
|
|
20753
20744
|
);
|
|
20754
20745
|
const route = manualGoalManager ? {
|
|
@@ -20756,7 +20747,7 @@ async function runCi(argv) {
|
|
|
20756
20747
|
capability: "goal-manager",
|
|
20757
20748
|
executable: "goal-manager",
|
|
20758
20749
|
cliArgs: forceRunCliArgs
|
|
20759
|
-
} :
|
|
20750
|
+
} : capabilityRoute ?? scheduledWatchRoute;
|
|
20760
20751
|
if (!route) {
|
|
20761
20752
|
process.stderr.write(`[kody] manual one-shot action '${forceRunAction}' has no capability action
|
|
20762
20753
|
`);
|
|
@@ -21250,17 +21241,17 @@ function authOk(req, expected) {
|
|
|
21250
21241
|
return false;
|
|
21251
21242
|
}
|
|
21252
21243
|
function readJsonBody(req) {
|
|
21253
|
-
return new Promise((
|
|
21244
|
+
return new Promise((resolve10, reject) => {
|
|
21254
21245
|
const chunks = [];
|
|
21255
21246
|
req.on("data", (c) => chunks.push(c));
|
|
21256
21247
|
req.on("end", () => {
|
|
21257
21248
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
21258
21249
|
if (!raw.trim()) {
|
|
21259
|
-
|
|
21250
|
+
resolve10({});
|
|
21260
21251
|
return;
|
|
21261
21252
|
}
|
|
21262
21253
|
try {
|
|
21263
|
-
|
|
21254
|
+
resolve10(JSON.parse(raw));
|
|
21264
21255
|
} catch (err) {
|
|
21265
21256
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
21266
21257
|
}
|
|
@@ -21615,11 +21606,11 @@ async function brainServe(opts) {
|
|
|
21615
21606
|
model,
|
|
21616
21607
|
litellmUrl
|
|
21617
21608
|
});
|
|
21618
|
-
await new Promise((
|
|
21609
|
+
await new Promise((resolve10) => {
|
|
21619
21610
|
server.listen(port, "0.0.0.0", () => {
|
|
21620
21611
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
21621
21612
|
`);
|
|
21622
|
-
|
|
21613
|
+
resolve10();
|
|
21623
21614
|
});
|
|
21624
21615
|
});
|
|
21625
21616
|
const shutdown = (signal) => {
|
|
@@ -21872,14 +21863,14 @@ async function startBrainProxy(opts) {
|
|
|
21872
21863
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
21873
21864
|
const port = opts.port ?? 0;
|
|
21874
21865
|
const host = opts.host ?? "127.0.0.1";
|
|
21875
|
-
await new Promise((
|
|
21866
|
+
await new Promise((resolve10) => httpServer.listen(port, host, () => resolve10()));
|
|
21876
21867
|
const addr = httpServer.address();
|
|
21877
21868
|
return {
|
|
21878
21869
|
httpServer,
|
|
21879
21870
|
port: addr.port,
|
|
21880
21871
|
url: `http://${host}:${addr.port}`,
|
|
21881
|
-
stop: () => new Promise((
|
|
21882
|
-
httpServer.close(() =>
|
|
21872
|
+
stop: () => new Promise((resolve10) => {
|
|
21873
|
+
httpServer.close(() => resolve10());
|
|
21883
21874
|
}),
|
|
21884
21875
|
handler
|
|
21885
21876
|
};
|
|
@@ -22029,23 +22020,23 @@ function buildMcpHttpServer(opts) {
|
|
|
22029
22020
|
httpServer,
|
|
22030
22021
|
routes,
|
|
22031
22022
|
port,
|
|
22032
|
-
stop: () => new Promise((
|
|
22023
|
+
stop: () => new Promise((resolve10) => {
|
|
22033
22024
|
let pending = transports.size;
|
|
22034
22025
|
if (pending === 0) {
|
|
22035
|
-
httpServer.close(() =>
|
|
22026
|
+
httpServer.close(() => resolve10());
|
|
22036
22027
|
return;
|
|
22037
22028
|
}
|
|
22038
22029
|
for (const transport of transports.values()) {
|
|
22039
22030
|
void transport.close().finally(() => {
|
|
22040
22031
|
pending--;
|
|
22041
|
-
if (pending === 0) httpServer.close(() =>
|
|
22032
|
+
if (pending === 0) httpServer.close(() => resolve10());
|
|
22042
22033
|
});
|
|
22043
22034
|
}
|
|
22044
22035
|
})
|
|
22045
22036
|
};
|
|
22046
22037
|
}
|
|
22047
22038
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
22048
|
-
return new Promise((
|
|
22039
|
+
return new Promise((resolve10, reject) => {
|
|
22049
22040
|
server.httpServer.once("error", reject);
|
|
22050
22041
|
server.httpServer.listen(server.port, host, () => {
|
|
22051
22042
|
server.httpServer.off("error", reject);
|
|
@@ -22053,7 +22044,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
22053
22044
|
if (addr && typeof addr === "object") {
|
|
22054
22045
|
server.port = addr.port;
|
|
22055
22046
|
}
|
|
22056
|
-
|
|
22047
|
+
resolve10();
|
|
22057
22048
|
});
|
|
22058
22049
|
});
|
|
22059
22050
|
}
|
|
@@ -22194,7 +22185,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
22194
22185
|
}
|
|
22195
22186
|
}
|
|
22196
22187
|
function sleep3(ms) {
|
|
22197
|
-
return new Promise((
|
|
22188
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
22198
22189
|
}
|
|
22199
22190
|
function currentBranch(cwd) {
|
|
22200
22191
|
try {
|
|
@@ -23297,14 +23288,14 @@ function sendJson2(res, status, body) {
|
|
|
23297
23288
|
res.end(JSON.stringify(body));
|
|
23298
23289
|
}
|
|
23299
23290
|
function readJsonBody2(req) {
|
|
23300
|
-
return new Promise((
|
|
23291
|
+
return new Promise((resolve10, reject) => {
|
|
23301
23292
|
const chunks = [];
|
|
23302
23293
|
req.on("data", (c) => chunks.push(c));
|
|
23303
23294
|
req.on("end", () => {
|
|
23304
23295
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
23305
|
-
if (!raw.trim()) return
|
|
23296
|
+
if (!raw.trim()) return resolve10({});
|
|
23306
23297
|
try {
|
|
23307
|
-
|
|
23298
|
+
resolve10(JSON.parse(raw));
|
|
23308
23299
|
} catch (err) {
|
|
23309
23300
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
23310
23301
|
}
|
|
@@ -23427,9 +23418,9 @@ async function poolServe() {
|
|
|
23427
23418
|
const tick = setInterval(() => {
|
|
23428
23419
|
registry.resyncAll().catch((err) => log(`resync tick failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
23429
23420
|
}, refillMs);
|
|
23430
|
-
const
|
|
23431
|
-
const
|
|
23432
|
-
const
|
|
23421
|
+
const capabilityTickEnabled = (process.env.POOL_CAPABILITY_TICK ?? "1") !== "0";
|
|
23422
|
+
const capabilityTickMs = envInt2("POOL_CAPABILITY_TICK_MS", 15 * 6e4);
|
|
23423
|
+
const capabilityTick = capabilityTickEnabled ? setInterval(() => {
|
|
23433
23424
|
runCapabilityFallbackTick({
|
|
23434
23425
|
isDegraded: () => gitHubActionsDegraded(),
|
|
23435
23426
|
activeRepos: () => registry.activeRepos(),
|
|
@@ -23438,7 +23429,7 @@ async function poolServe() {
|
|
|
23438
23429
|
}).catch(
|
|
23439
23430
|
(err) => log(`capability fallback tick failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
23440
23431
|
);
|
|
23441
|
-
},
|
|
23432
|
+
}, capabilityTickMs) : null;
|
|
23442
23433
|
const server = createServer4(async (req, res) => {
|
|
23443
23434
|
try {
|
|
23444
23435
|
if (!req.method || !req.url) return sendJson2(res, 400, { error: "bad request" });
|
|
@@ -23486,16 +23477,16 @@ async function poolServe() {
|
|
|
23486
23477
|
}
|
|
23487
23478
|
});
|
|
23488
23479
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
23489
|
-
await new Promise((
|
|
23480
|
+
await new Promise((resolve10) => {
|
|
23490
23481
|
server.listen(apiPort, apiHost, () => {
|
|
23491
23482
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
23492
|
-
|
|
23483
|
+
resolve10();
|
|
23493
23484
|
});
|
|
23494
23485
|
});
|
|
23495
23486
|
const shutdown = (signal) => {
|
|
23496
23487
|
log(`${signal} \u2014 shutting down`);
|
|
23497
23488
|
clearInterval(tick);
|
|
23498
|
-
if (
|
|
23489
|
+
if (capabilityTick) clearInterval(capabilityTick);
|
|
23499
23490
|
server.close(() => process.exit(0));
|
|
23500
23491
|
};
|
|
23501
23492
|
process.once("SIGINT", () => shutdown("SIGINT"));
|
|
@@ -23528,17 +23519,17 @@ function authOk2(req, expected) {
|
|
|
23528
23519
|
return false;
|
|
23529
23520
|
}
|
|
23530
23521
|
function readJsonBody3(req) {
|
|
23531
|
-
return new Promise((
|
|
23522
|
+
return new Promise((resolve10, reject) => {
|
|
23532
23523
|
const chunks = [];
|
|
23533
23524
|
req.on("data", (c) => chunks.push(c));
|
|
23534
23525
|
req.on("end", () => {
|
|
23535
23526
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
23536
23527
|
if (!raw.trim()) {
|
|
23537
|
-
|
|
23528
|
+
resolve10({});
|
|
23538
23529
|
return;
|
|
23539
23530
|
}
|
|
23540
23531
|
try {
|
|
23541
|
-
|
|
23532
|
+
resolve10(JSON.parse(raw));
|
|
23542
23533
|
} catch (err) {
|
|
23543
23534
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
23544
23535
|
}
|
|
@@ -23672,13 +23663,13 @@ async function defaultRunJob(job) {
|
|
|
23672
23663
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
23673
23664
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
23674
23665
|
};
|
|
23675
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
23666
|
+
const run = (cmd, args, cwd) => new Promise((resolve10) => {
|
|
23676
23667
|
const child = spawn8(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
23677
|
-
child.on("exit", (code) =>
|
|
23668
|
+
child.on("exit", (code) => resolve10(code ?? 0));
|
|
23678
23669
|
child.on("error", (err) => {
|
|
23679
23670
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
23680
23671
|
`);
|
|
23681
|
-
|
|
23672
|
+
resolve10(1);
|
|
23682
23673
|
});
|
|
23683
23674
|
});
|
|
23684
23675
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -23754,11 +23745,11 @@ async function runnerServe() {
|
|
|
23754
23745
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
23755
23746
|
const server = buildServer2({ apiKey });
|
|
23756
23747
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
23757
|
-
await new Promise((
|
|
23748
|
+
await new Promise((resolve10) => {
|
|
23758
23749
|
server.listen(port, host, () => {
|
|
23759
23750
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
23760
23751
|
`);
|
|
23761
|
-
|
|
23752
|
+
resolve10();
|
|
23762
23753
|
});
|
|
23763
23754
|
});
|
|
23764
23755
|
const shutdown = (signal) => {
|
|
@@ -23827,14 +23818,14 @@ async function serve(opts) {
|
|
|
23827
23818
|
`);
|
|
23828
23819
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
23829
23820
|
const child = spawn9("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
23830
|
-
const exitCode = await new Promise((
|
|
23831
|
-
child.on("exit", (code) =>
|
|
23821
|
+
const exitCode = await new Promise((resolve10) => {
|
|
23822
|
+
child.on("exit", (code) => resolve10(code ?? 0));
|
|
23832
23823
|
child.on("error", (err) => {
|
|
23833
23824
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
23834
23825
|
`);
|
|
23835
23826
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
23836
23827
|
`);
|
|
23837
|
-
|
|
23828
|
+
resolve10(1);
|
|
23838
23829
|
});
|
|
23839
23830
|
});
|
|
23840
23831
|
killProxy();
|
|
@@ -18,7 +18,7 @@ You are Kody's agent factory. Convert the operator request into review-ready Kod
|
|
|
18
18
|
|
|
19
19
|
# Task
|
|
20
20
|
|
|
21
|
-
Design the smallest Kody model structure that satisfies the request. You may create or assemble simple
|
|
21
|
+
Design the smallest Kody model structure that satisfies the request. You may create or assemble simple capability implementation profiles, capabilities, loops, goals, and agents.
|
|
22
22
|
|
|
23
23
|
Use the current Kody vocabulary:
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ Use the current Kody vocabulary:
|
|
|
31
31
|
Use current storage names when producing files:
|
|
32
32
|
|
|
33
33
|
- capability: capability contract, public action ownership, kind, agent, cadence, and output contract
|
|
34
|
-
-
|
|
34
|
+
- implementation profile: capability implementation stored under `capabilities/<slug>/`
|
|
35
35
|
|
|
36
36
|
# Boundaries
|
|
37
37
|
|
|
@@ -40,7 +40,8 @@ Use current storage names when producing files:
|
|
|
40
40
|
- Do not activate generated definitions yourself.
|
|
41
41
|
- Do not create a consumer-repo PR.
|
|
42
42
|
- The deterministic postflight will open a review PR in the configured state repo under the configured state path.
|
|
43
|
-
- Put generated file paths relative to the configured state path, for example `
|
|
43
|
+
- Put generated file paths relative to the configured state path, for example `capabilities/...`, `agents/...`, `goals/...`, or `memory/...`.
|
|
44
|
+
- Do not create `executables/...` paths. External executables are obsolete; implementation profiles live in capability folders.
|
|
44
45
|
- Produce complete file contents. Do not describe patches.
|
|
45
46
|
- Prefer a small bundle over a broad framework. Include assumptions in the summary.
|
|
46
47
|
|
|
@@ -59,7 +60,7 @@ PR_SUMMARY:
|
|
|
59
60
|
"summary": "human explanation and assumptions",
|
|
60
61
|
"files": [
|
|
61
62
|
{
|
|
62
|
-
"path": "
|
|
63
|
+
"path": "capabilities/example/profile.json",
|
|
63
64
|
"content": "{\n \"name\": \"example\"\n}\n"
|
|
64
65
|
}
|
|
65
66
|
]
|
|
@@ -56,6 +56,18 @@ export interface Profile {
|
|
|
56
56
|
executable?: string
|
|
57
57
|
implementations?: string[]
|
|
58
58
|
executables?: string[]
|
|
59
|
+
/** Hide a capability implementation profile from public action discovery. */
|
|
60
|
+
internal?: boolean
|
|
61
|
+
/** Explicit public-action flag for capability profiles. */
|
|
62
|
+
public?: boolean
|
|
63
|
+
/** Public capability output class when the profile also serves as a capability contract. */
|
|
64
|
+
capabilityKind?: "observe" | "act" | "verify"
|
|
65
|
+
/** Optional dashboard-facing capability metadata. The executor does not act on these fields. */
|
|
66
|
+
slug?: string
|
|
67
|
+
title?: string
|
|
68
|
+
skills?: string[]
|
|
69
|
+
prompt?: string
|
|
70
|
+
chatTools?: string[]
|
|
59
71
|
/**
|
|
60
72
|
* Execution model — orthogonal to `role`.
|
|
61
73
|
* `oneshot` (default): single invocation on demand.
|
|
@@ -160,7 +172,7 @@ export interface Profile {
|
|
|
160
172
|
* preflight runs. composePrompt prefers these over a fresh disk read so the
|
|
161
173
|
* template survives working-tree churn from runFlow's branch setup — on the CI
|
|
162
174
|
* runner a branch checkout can drop the tracked-but-ignore-negated
|
|
163
|
-
* `.kody/
|
|
175
|
+
* `.kody/capabilities/<name>/` dir, and reading prompt.md afterwards fails with
|
|
164
176
|
* ENOENT even though profile.json (read here, earlier) loaded fine.
|
|
165
177
|
*/
|
|
166
178
|
promptTemplates?: Record<string, string>
|
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.291",
|
|
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",
|