@kody-ade/kody-engine 0.4.289 → 0.4.290
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 +104 -115
- 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.290",
|
|
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
|
});
|
|
@@ -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",
|
|
@@ -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") },
|
|
@@ -18513,14 +18502,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
18513
18502
|
let killTimer;
|
|
18514
18503
|
let escalateTimer;
|
|
18515
18504
|
const result = await new Promise(
|
|
18516
|
-
(
|
|
18505
|
+
(resolve10) => {
|
|
18517
18506
|
let settled = false;
|
|
18518
18507
|
const settle = (code, signal, spawnErr) => {
|
|
18519
18508
|
if (settled) return;
|
|
18520
18509
|
settled = true;
|
|
18521
18510
|
if (killTimer) clearTimeout(killTimer);
|
|
18522
18511
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
18523
|
-
|
|
18512
|
+
resolve10({ code, signal, spawnErr });
|
|
18524
18513
|
};
|
|
18525
18514
|
child.on("error", (err) => settle(null, null, err));
|
|
18526
18515
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -18781,7 +18770,7 @@ async function runJob(job, base) {
|
|
|
18781
18770
|
}
|
|
18782
18771
|
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
18783
18772
|
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);
|
|
18773
|
+
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
18774
|
const profileName = valid.executable ?? capabilitySelectedExecutable;
|
|
18786
18775
|
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedExecutable, base)) {
|
|
18787
18776
|
const workflowCapability = capabilityContext ?? workflowContext;
|
|
@@ -21250,17 +21239,17 @@ function authOk(req, expected) {
|
|
|
21250
21239
|
return false;
|
|
21251
21240
|
}
|
|
21252
21241
|
function readJsonBody(req) {
|
|
21253
|
-
return new Promise((
|
|
21242
|
+
return new Promise((resolve10, reject) => {
|
|
21254
21243
|
const chunks = [];
|
|
21255
21244
|
req.on("data", (c) => chunks.push(c));
|
|
21256
21245
|
req.on("end", () => {
|
|
21257
21246
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
21258
21247
|
if (!raw.trim()) {
|
|
21259
|
-
|
|
21248
|
+
resolve10({});
|
|
21260
21249
|
return;
|
|
21261
21250
|
}
|
|
21262
21251
|
try {
|
|
21263
|
-
|
|
21252
|
+
resolve10(JSON.parse(raw));
|
|
21264
21253
|
} catch (err) {
|
|
21265
21254
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
21266
21255
|
}
|
|
@@ -21615,11 +21604,11 @@ async function brainServe(opts) {
|
|
|
21615
21604
|
model,
|
|
21616
21605
|
litellmUrl
|
|
21617
21606
|
});
|
|
21618
|
-
await new Promise((
|
|
21607
|
+
await new Promise((resolve10) => {
|
|
21619
21608
|
server.listen(port, "0.0.0.0", () => {
|
|
21620
21609
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
21621
21610
|
`);
|
|
21622
|
-
|
|
21611
|
+
resolve10();
|
|
21623
21612
|
});
|
|
21624
21613
|
});
|
|
21625
21614
|
const shutdown = (signal) => {
|
|
@@ -21872,14 +21861,14 @@ async function startBrainProxy(opts) {
|
|
|
21872
21861
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
21873
21862
|
const port = opts.port ?? 0;
|
|
21874
21863
|
const host = opts.host ?? "127.0.0.1";
|
|
21875
|
-
await new Promise((
|
|
21864
|
+
await new Promise((resolve10) => httpServer.listen(port, host, () => resolve10()));
|
|
21876
21865
|
const addr = httpServer.address();
|
|
21877
21866
|
return {
|
|
21878
21867
|
httpServer,
|
|
21879
21868
|
port: addr.port,
|
|
21880
21869
|
url: `http://${host}:${addr.port}`,
|
|
21881
|
-
stop: () => new Promise((
|
|
21882
|
-
httpServer.close(() =>
|
|
21870
|
+
stop: () => new Promise((resolve10) => {
|
|
21871
|
+
httpServer.close(() => resolve10());
|
|
21883
21872
|
}),
|
|
21884
21873
|
handler
|
|
21885
21874
|
};
|
|
@@ -22029,23 +22018,23 @@ function buildMcpHttpServer(opts) {
|
|
|
22029
22018
|
httpServer,
|
|
22030
22019
|
routes,
|
|
22031
22020
|
port,
|
|
22032
|
-
stop: () => new Promise((
|
|
22021
|
+
stop: () => new Promise((resolve10) => {
|
|
22033
22022
|
let pending = transports.size;
|
|
22034
22023
|
if (pending === 0) {
|
|
22035
|
-
httpServer.close(() =>
|
|
22024
|
+
httpServer.close(() => resolve10());
|
|
22036
22025
|
return;
|
|
22037
22026
|
}
|
|
22038
22027
|
for (const transport of transports.values()) {
|
|
22039
22028
|
void transport.close().finally(() => {
|
|
22040
22029
|
pending--;
|
|
22041
|
-
if (pending === 0) httpServer.close(() =>
|
|
22030
|
+
if (pending === 0) httpServer.close(() => resolve10());
|
|
22042
22031
|
});
|
|
22043
22032
|
}
|
|
22044
22033
|
})
|
|
22045
22034
|
};
|
|
22046
22035
|
}
|
|
22047
22036
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
22048
|
-
return new Promise((
|
|
22037
|
+
return new Promise((resolve10, reject) => {
|
|
22049
22038
|
server.httpServer.once("error", reject);
|
|
22050
22039
|
server.httpServer.listen(server.port, host, () => {
|
|
22051
22040
|
server.httpServer.off("error", reject);
|
|
@@ -22053,7 +22042,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
22053
22042
|
if (addr && typeof addr === "object") {
|
|
22054
22043
|
server.port = addr.port;
|
|
22055
22044
|
}
|
|
22056
|
-
|
|
22045
|
+
resolve10();
|
|
22057
22046
|
});
|
|
22058
22047
|
});
|
|
22059
22048
|
}
|
|
@@ -22194,7 +22183,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
22194
22183
|
}
|
|
22195
22184
|
}
|
|
22196
22185
|
function sleep3(ms) {
|
|
22197
|
-
return new Promise((
|
|
22186
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
22198
22187
|
}
|
|
22199
22188
|
function currentBranch(cwd) {
|
|
22200
22189
|
try {
|
|
@@ -23297,14 +23286,14 @@ function sendJson2(res, status, body) {
|
|
|
23297
23286
|
res.end(JSON.stringify(body));
|
|
23298
23287
|
}
|
|
23299
23288
|
function readJsonBody2(req) {
|
|
23300
|
-
return new Promise((
|
|
23289
|
+
return new Promise((resolve10, reject) => {
|
|
23301
23290
|
const chunks = [];
|
|
23302
23291
|
req.on("data", (c) => chunks.push(c));
|
|
23303
23292
|
req.on("end", () => {
|
|
23304
23293
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
23305
|
-
if (!raw.trim()) return
|
|
23294
|
+
if (!raw.trim()) return resolve10({});
|
|
23306
23295
|
try {
|
|
23307
|
-
|
|
23296
|
+
resolve10(JSON.parse(raw));
|
|
23308
23297
|
} catch (err) {
|
|
23309
23298
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
23310
23299
|
}
|
|
@@ -23486,10 +23475,10 @@ async function poolServe() {
|
|
|
23486
23475
|
}
|
|
23487
23476
|
});
|
|
23488
23477
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
23489
|
-
await new Promise((
|
|
23478
|
+
await new Promise((resolve10) => {
|
|
23490
23479
|
server.listen(apiPort, apiHost, () => {
|
|
23491
23480
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
23492
|
-
|
|
23481
|
+
resolve10();
|
|
23493
23482
|
});
|
|
23494
23483
|
});
|
|
23495
23484
|
const shutdown = (signal) => {
|
|
@@ -23528,17 +23517,17 @@ function authOk2(req, expected) {
|
|
|
23528
23517
|
return false;
|
|
23529
23518
|
}
|
|
23530
23519
|
function readJsonBody3(req) {
|
|
23531
|
-
return new Promise((
|
|
23520
|
+
return new Promise((resolve10, reject) => {
|
|
23532
23521
|
const chunks = [];
|
|
23533
23522
|
req.on("data", (c) => chunks.push(c));
|
|
23534
23523
|
req.on("end", () => {
|
|
23535
23524
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
23536
23525
|
if (!raw.trim()) {
|
|
23537
|
-
|
|
23526
|
+
resolve10({});
|
|
23538
23527
|
return;
|
|
23539
23528
|
}
|
|
23540
23529
|
try {
|
|
23541
|
-
|
|
23530
|
+
resolve10(JSON.parse(raw));
|
|
23542
23531
|
} catch (err) {
|
|
23543
23532
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
23544
23533
|
}
|
|
@@ -23672,13 +23661,13 @@ async function defaultRunJob(job) {
|
|
|
23672
23661
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
23673
23662
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
23674
23663
|
};
|
|
23675
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
23664
|
+
const run = (cmd, args, cwd) => new Promise((resolve10) => {
|
|
23676
23665
|
const child = spawn8(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
23677
|
-
child.on("exit", (code) =>
|
|
23666
|
+
child.on("exit", (code) => resolve10(code ?? 0));
|
|
23678
23667
|
child.on("error", (err) => {
|
|
23679
23668
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
23680
23669
|
`);
|
|
23681
|
-
|
|
23670
|
+
resolve10(1);
|
|
23682
23671
|
});
|
|
23683
23672
|
});
|
|
23684
23673
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -23754,11 +23743,11 @@ async function runnerServe() {
|
|
|
23754
23743
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
23755
23744
|
const server = buildServer2({ apiKey });
|
|
23756
23745
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
23757
|
-
await new Promise((
|
|
23746
|
+
await new Promise((resolve10) => {
|
|
23758
23747
|
server.listen(port, host, () => {
|
|
23759
23748
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
23760
23749
|
`);
|
|
23761
|
-
|
|
23750
|
+
resolve10();
|
|
23762
23751
|
});
|
|
23763
23752
|
});
|
|
23764
23753
|
const shutdown = (signal) => {
|
|
@@ -23827,14 +23816,14 @@ async function serve(opts) {
|
|
|
23827
23816
|
`);
|
|
23828
23817
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
23829
23818
|
const child = spawn9("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
23830
|
-
const exitCode = await new Promise((
|
|
23831
|
-
child.on("exit", (code) =>
|
|
23819
|
+
const exitCode = await new Promise((resolve10) => {
|
|
23820
|
+
child.on("exit", (code) => resolve10(code ?? 0));
|
|
23832
23821
|
child.on("error", (err) => {
|
|
23833
23822
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
23834
23823
|
`);
|
|
23835
23824
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
23836
23825
|
`);
|
|
23837
|
-
|
|
23826
|
+
resolve10(1);
|
|
23838
23827
|
});
|
|
23839
23828
|
});
|
|
23840
23829
|
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.290",
|
|
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",
|