@kody-ade/kody-engine 0.4.430 → 0.4.432
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 +518 -131
- package/dist/capabilities/run/definition.json +42 -0
- package/dist/implementations/run/definition.json +13 -0
- package/dist/implementations/run/{profile.json → runtime.json} +1 -2
- package/dist/implementations/types.ts +8 -0
- package/dist/runtime-services/capability-scheduler/profile.json +61 -0
- package/dist/runtime-services/capability-tick/profile.json +86 -0
- package/dist/runtime-services/capability-tick/prompt.md +77 -0
- package/dist/runtime-services/capability-tick/prompts/locked.md +50 -0
- package/dist/runtime-services/capability-tick-scripted/profile.json +76 -0
- package/dist/runtime-services/dispatch-due-loops/profile.json +54 -0
- package/dist/runtime-services/goal-manager/profile.json +56 -0
- package/dist/runtime-services/goal-scheduler/__pycache__/managed_todo_state.cpython-314.pyc +0 -0
- package/dist/runtime-services/goal-scheduler/managed_todo_state.py +160 -0
- package/dist/runtime-services/goal-scheduler/profile.json +51 -0
- package/dist/runtime-services/goal-scheduler/scheduler.sh +872 -0
- package/dist/runtime-services/task-jobs/profile.json +51 -0
- package/package.json +3 -1
- package/dist/capabilities/run/profile.json +0 -6
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.432",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -40,6 +40,7 @@ var init_package = __esm({
|
|
|
40
40
|
posttest: "tsx scripts/check-coverage-floor.ts",
|
|
41
41
|
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
42
42
|
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
43
|
+
"test:runtime-services": 'node --test "tests/runtime-services/*.test.mjs"',
|
|
43
44
|
"test:all": "vitest run tests --no-coverage",
|
|
44
45
|
typecheck: "tsc --noEmit",
|
|
45
46
|
lint: "biome check",
|
|
@@ -47,13 +48,14 @@ var init_package = __esm({
|
|
|
47
48
|
format: "biome format --write",
|
|
48
49
|
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
49
50
|
"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",
|
|
50
|
-
prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
|
|
51
|
+
prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
51
52
|
},
|
|
52
53
|
dependencies: {
|
|
53
54
|
"@actions/cache": "^6.0.0",
|
|
54
55
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
55
56
|
"@kody-ade/agency-domain": "0.5.1",
|
|
56
57
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
58
|
+
ajv: "^8.18.0",
|
|
57
59
|
convex: "^1.17.0",
|
|
58
60
|
zod: "^4.0.0"
|
|
59
61
|
},
|
|
@@ -255,6 +257,7 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
255
257
|
...parsePerImplementationReasoningEffort(agent.perImplementationReasoningEffort),
|
|
256
258
|
...parseAgentReasoningEffort(agent.reasoningEffort)
|
|
257
259
|
},
|
|
260
|
+
execution: parseExecutionConfig(raw.execution),
|
|
258
261
|
issueContext: parseIssueContext(raw.issueContext),
|
|
259
262
|
testRequirements: parseTestRequirements(raw.testRequirements),
|
|
260
263
|
defaultImplementation: typeof raw.defaultImplementation === "string" && raw.defaultImplementation.length > 0 ? raw.defaultImplementation : "run",
|
|
@@ -267,6 +270,18 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
267
270
|
access: parseAccessConfig(raw.access)
|
|
268
271
|
};
|
|
269
272
|
}
|
|
273
|
+
function parseExecutionConfig(value) {
|
|
274
|
+
const execution = recordValue(value);
|
|
275
|
+
const bindings = recordValue(execution?.capabilityBindings);
|
|
276
|
+
if (!bindings) return void 0;
|
|
277
|
+
const capabilityBindings = {};
|
|
278
|
+
for (const [capabilityId, implementationId] of Object.entries(bindings)) {
|
|
279
|
+
if (/^[a-z][a-z0-9-]*$/.test(capabilityId) && typeof implementationId === "string" && /^[a-z][a-z0-9-]*$/.test(implementationId)) {
|
|
280
|
+
capabilityBindings[capabilityId] = implementationId;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return Object.keys(capabilityBindings).length > 0 ? { capabilityBindings } : void 0;
|
|
284
|
+
}
|
|
270
285
|
function parseAccessConfig(raw) {
|
|
271
286
|
if (raw === void 0 || raw === null) {
|
|
272
287
|
return { allowedAssociations: [...DEFAULT_ALLOWED_ASSOCIATIONS] };
|
|
@@ -747,7 +762,7 @@ function buildVerifyEnv(source = process.env) {
|
|
|
747
762
|
return env;
|
|
748
763
|
}
|
|
749
764
|
function runCommand(command, cwd) {
|
|
750
|
-
return new Promise((
|
|
765
|
+
return new Promise((resolve19) => {
|
|
751
766
|
const start = Date.now();
|
|
752
767
|
const child = spawn(command, {
|
|
753
768
|
cwd,
|
|
@@ -776,11 +791,11 @@ function runCommand(command, cwd) {
|
|
|
776
791
|
child.on("exit", (code) => {
|
|
777
792
|
clearTimeout(timer);
|
|
778
793
|
const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
|
|
779
|
-
|
|
794
|
+
resolve19({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
|
|
780
795
|
});
|
|
781
796
|
child.on("error", (err) => {
|
|
782
797
|
clearTimeout(timer);
|
|
783
|
-
|
|
798
|
+
resolve19({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
|
|
784
799
|
});
|
|
785
800
|
});
|
|
786
801
|
}
|
|
@@ -1631,10 +1646,71 @@ var init_issue = __esm({
|
|
|
1631
1646
|
}
|
|
1632
1647
|
});
|
|
1633
1648
|
|
|
1649
|
+
// src/agency/implementation-resolution.ts
|
|
1650
|
+
function resolveCapabilityImplementation(input) {
|
|
1651
|
+
const compatible = input.implementations.filter(
|
|
1652
|
+
(implementation) => implementation.capabilityRef.id === input.capabilityId && implementation.compatibleCapabilityRevision === input.capabilityRevision
|
|
1653
|
+
);
|
|
1654
|
+
if (input.explicitOverride) {
|
|
1655
|
+
if (!input.authorizeOverride?.(input.explicitOverride)) {
|
|
1656
|
+
throw new ImplementationResolutionError(`Implementation override "${input.explicitOverride}" is not authorized`);
|
|
1657
|
+
}
|
|
1658
|
+
return selectNamed(input.explicitOverride, input, compatible, "override");
|
|
1659
|
+
}
|
|
1660
|
+
if (input.repositoryBinding) {
|
|
1661
|
+
return selectNamed(input.repositoryBinding, input, compatible, "repository binding");
|
|
1662
|
+
}
|
|
1663
|
+
if (compatible.length === 1) return compatible[0];
|
|
1664
|
+
if (compatible.length === 0) {
|
|
1665
|
+
throw new ImplementationResolutionError(
|
|
1666
|
+
`No compatible Implementation is available for Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
throw new ImplementationResolutionError(
|
|
1670
|
+
`Capability "${input.capabilityId}" has ${compatible.length} compatible Implementations; configure a repository binding`
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
function selectNamed(id, input, compatible, source) {
|
|
1674
|
+
const known = input.implementations.find((implementation) => implementation.id === id);
|
|
1675
|
+
if (!known) {
|
|
1676
|
+
throw new ImplementationResolutionError(`Implementation ${source} "${id}" is not available`);
|
|
1677
|
+
}
|
|
1678
|
+
const selected = compatible.find((implementation) => implementation.id === id);
|
|
1679
|
+
if (!selected) {
|
|
1680
|
+
throw new ImplementationResolutionError(
|
|
1681
|
+
`Implementation ${source} "${id}" is not compatible with Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
return selected;
|
|
1685
|
+
}
|
|
1686
|
+
var ImplementationResolutionError;
|
|
1687
|
+
var init_implementation_resolution = __esm({
|
|
1688
|
+
"src/agency/implementation-resolution.ts"() {
|
|
1689
|
+
"use strict";
|
|
1690
|
+
ImplementationResolutionError = class extends Error {
|
|
1691
|
+
constructor(message) {
|
|
1692
|
+
super(message);
|
|
1693
|
+
this.name = "ImplementationResolutionError";
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
|
|
1634
1699
|
// src/capabilityFolders.ts
|
|
1635
1700
|
import * as fs4 from "fs";
|
|
1636
1701
|
import * as path5 from "path";
|
|
1637
1702
|
function capabilityOutputConditionPaths(config) {
|
|
1703
|
+
if (config.outputSchema) {
|
|
1704
|
+
const properties = isPlainObject(config.outputSchema.properties) ? config.outputSchema.properties : void 0;
|
|
1705
|
+
const factContract = isPlainObject(properties?.facts) ? properties.facts : void 0;
|
|
1706
|
+
const facts = isPlainObject(factContract?.properties) ? factContract.properties : void 0;
|
|
1707
|
+
return /* @__PURE__ */ new Set([
|
|
1708
|
+
...properties?.status ? ["result.status"] : [],
|
|
1709
|
+
...properties?.summary ? ["result.summary"] : [],
|
|
1710
|
+
...properties?.resultClass ? ["result.resultClass"] : [],
|
|
1711
|
+
...Object.keys(facts ?? {}).map((fact) => `result.facts.${fact}`)
|
|
1712
|
+
]);
|
|
1713
|
+
}
|
|
1638
1714
|
const result = config.output?.result;
|
|
1639
1715
|
if (!result) return /* @__PURE__ */ new Set();
|
|
1640
1716
|
return /* @__PURE__ */ new Set([
|
|
@@ -1655,16 +1731,19 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
1655
1731
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path5.join(absDir, e.name))).map((e) => e.name).sort();
|
|
1656
1732
|
}
|
|
1657
1733
|
function isCapabilityFolder(dir) {
|
|
1658
|
-
return fs4.existsSync(path5.join(dir, CAPABILITY_PROFILE_FILE)) && fs4.existsSync(path5.join(dir, CAPABILITY_BODY_FILE));
|
|
1734
|
+
return (fs4.existsSync(path5.join(dir, CAPABILITY_DEFINITION_FILE)) || fs4.existsSync(path5.join(dir, CAPABILITY_PROFILE_FILE))) && fs4.existsSync(path5.join(dir, CAPABILITY_BODY_FILE));
|
|
1659
1735
|
}
|
|
1660
1736
|
function readCapabilityFolder(root, slug) {
|
|
1661
1737
|
const dir = path5.join(root, slug);
|
|
1662
|
-
const
|
|
1738
|
+
const definitionPath = path5.join(dir, CAPABILITY_DEFINITION_FILE);
|
|
1739
|
+
const legacyProfilePath = path5.join(dir, CAPABILITY_PROFILE_FILE);
|
|
1740
|
+
const profilePath = fs4.existsSync(definitionPath) ? definitionPath : legacyProfilePath;
|
|
1663
1741
|
const bodyPath = path5.join(dir, CAPABILITY_BODY_FILE);
|
|
1664
1742
|
if (!fs4.existsSync(profilePath) || !fs4.statSync(profilePath).isFile()) return null;
|
|
1665
1743
|
if (!fs4.existsSync(bodyPath) || !fs4.statSync(bodyPath).isFile()) return null;
|
|
1666
1744
|
try {
|
|
1667
|
-
const
|
|
1745
|
+
const rawDefinition = JSON.parse(fs4.readFileSync(profilePath, "utf-8"));
|
|
1746
|
+
const rawProfile = rawDefinition;
|
|
1668
1747
|
const rawBody = fs4.readFileSync(bodyPath, "utf-8");
|
|
1669
1748
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
1670
1749
|
return {
|
|
@@ -1700,11 +1779,12 @@ function parseCapabilityConfig(raw) {
|
|
|
1700
1779
|
capabilityToolMode: parseCapabilityToolMode(raw.capabilityToolMode),
|
|
1701
1780
|
implementations,
|
|
1702
1781
|
role: stringField(raw.role),
|
|
1703
|
-
describe: stringField(raw.describe),
|
|
1782
|
+
describe: stringField(raw.describe) ?? stringField(raw.purpose),
|
|
1704
1783
|
stage: stringField(raw.stage),
|
|
1705
1784
|
readsFrom: stringList(raw.readsFrom ?? raw.reads_from),
|
|
1706
1785
|
writesTo: stringList(raw.writesTo ?? raw.writes_to),
|
|
1707
1786
|
output: parseCapabilityOutput(raw.output),
|
|
1787
|
+
outputSchema: isPlainObject(raw.outputSchema) ? raw.outputSchema : void 0,
|
|
1708
1788
|
workflow: parseCapabilityWorkflow(raw.workflow)
|
|
1709
1789
|
};
|
|
1710
1790
|
}
|
|
@@ -1873,11 +1953,12 @@ function isSafeSlug(value) {
|
|
|
1873
1953
|
function isSafeStepId(value) {
|
|
1874
1954
|
return /^[A-Za-z][A-Za-z0-9_-]*$/.test(value) && !value.includes("..");
|
|
1875
1955
|
}
|
|
1876
|
-
var CAPABILITY_PROFILE_FILE, CAPABILITY_BODY_FILE;
|
|
1956
|
+
var CAPABILITY_PROFILE_FILE, CAPABILITY_DEFINITION_FILE, CAPABILITY_BODY_FILE;
|
|
1877
1957
|
var init_capabilityFolders = __esm({
|
|
1878
1958
|
"src/capabilityFolders.ts"() {
|
|
1879
1959
|
"use strict";
|
|
1880
1960
|
CAPABILITY_PROFILE_FILE = "profile.json";
|
|
1961
|
+
CAPABILITY_DEFINITION_FILE = "definition.json";
|
|
1881
1962
|
CAPABILITY_BODY_FILE = "capability.md";
|
|
1882
1963
|
}
|
|
1883
1964
|
});
|
|
@@ -1903,6 +1984,9 @@ function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
|
|
|
1903
1984
|
function capabilitiesRoot(cwd = process.cwd()) {
|
|
1904
1985
|
return path6.join(definitionsRoot(cwd), "capabilities");
|
|
1905
1986
|
}
|
|
1987
|
+
function implementationsRoot(cwd = process.cwd()) {
|
|
1988
|
+
return path6.join(definitionsRoot(cwd), "implementations");
|
|
1989
|
+
}
|
|
1906
1990
|
function agentsRoot(cwd = process.cwd()) {
|
|
1907
1991
|
return path6.join(definitionsRoot(cwd), "agents");
|
|
1908
1992
|
}
|
|
@@ -1913,6 +1997,7 @@ var init_definition_paths = __esm({
|
|
|
1913
1997
|
});
|
|
1914
1998
|
|
|
1915
1999
|
// src/registry.ts
|
|
2000
|
+
import { createHash as createHash2 } from "crypto";
|
|
1916
2001
|
import * as fs6 from "fs";
|
|
1917
2002
|
import * as path7 from "path";
|
|
1918
2003
|
function getImplementationsRoot() {
|
|
@@ -1930,6 +2015,18 @@ function getImplementationsRoot() {
|
|
|
1930
2015
|
}
|
|
1931
2016
|
return candidates[0];
|
|
1932
2017
|
}
|
|
2018
|
+
function getRuntimeServicesRoot() {
|
|
2019
|
+
const here = path7.dirname(new URL(import.meta.url).pathname);
|
|
2020
|
+
const candidates = [
|
|
2021
|
+
path7.join(here, "runtime-services"),
|
|
2022
|
+
path7.join(here, "..", "runtime-services"),
|
|
2023
|
+
path7.join(here, "..", "src", "runtime-services")
|
|
2024
|
+
];
|
|
2025
|
+
for (const candidate of candidates) {
|
|
2026
|
+
if (fs6.existsSync(candidate) && fs6.statSync(candidate).isDirectory()) return candidate;
|
|
2027
|
+
}
|
|
2028
|
+
return candidates[0];
|
|
2029
|
+
}
|
|
1933
2030
|
function getProjectCapabilitiesRoot() {
|
|
1934
2031
|
return capabilitiesRoot();
|
|
1935
2032
|
}
|
|
@@ -1952,7 +2049,10 @@ function getImplementationRoots() {
|
|
|
1952
2049
|
return getImplementationRootsForCwd(process.cwd());
|
|
1953
2050
|
}
|
|
1954
2051
|
function getImplementationRootsForCwd(cwd) {
|
|
1955
|
-
return [
|
|
2052
|
+
return [implementationsRoot(cwd), getImplementationsRoot()];
|
|
2053
|
+
}
|
|
2054
|
+
function getRuntimeProfileRootsForCwd(cwd) {
|
|
2055
|
+
return [...getImplementationRootsForCwd(cwd), getRuntimeServicesRoot()];
|
|
1956
2056
|
}
|
|
1957
2057
|
function getCapabilityRoots(projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
1958
2058
|
return [projectCapabilitiesRoot, getBuiltinCapabilitiesRoot()];
|
|
@@ -1968,7 +2068,7 @@ function listImplementations(roots = getImplementationRoots()) {
|
|
|
1968
2068
|
for (const ent of entries) {
|
|
1969
2069
|
if (!ent.isDirectory()) continue;
|
|
1970
2070
|
if (seen.has(ent.name)) continue;
|
|
1971
|
-
const profilePath =
|
|
2071
|
+
const profilePath = implementationRuntimePath(root, ent.name);
|
|
1972
2072
|
if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, requireImplementationProfile)) {
|
|
1973
2073
|
out.push({ name: ent.name, profilePath });
|
|
1974
2074
|
seen.add(ent.name);
|
|
@@ -1977,15 +2077,18 @@ function listImplementations(roots = getImplementationRoots()) {
|
|
|
1977
2077
|
}
|
|
1978
2078
|
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
1979
2079
|
}
|
|
1980
|
-
function
|
|
2080
|
+
function listRuntimeProfilesForCwd(cwd) {
|
|
2081
|
+
return listImplementations(getRuntimeProfileRootsForCwd(cwd));
|
|
2082
|
+
}
|
|
2083
|
+
function resolveImplementation(name, roots = getRuntimeProfileRootsForCwd(process.cwd())) {
|
|
1981
2084
|
return resolveImplementationCandidates(name, roots)[0] ?? null;
|
|
1982
2085
|
}
|
|
1983
|
-
function resolveImplementationCandidates(name, roots =
|
|
2086
|
+
function resolveImplementationCandidates(name, roots = getRuntimeProfileRootsForCwd(process.cwd())) {
|
|
1984
2087
|
if (!isSafeName(name)) return [];
|
|
1985
2088
|
const rootList = typeof roots === "string" ? [roots] : roots;
|
|
1986
2089
|
const out = [];
|
|
1987
2090
|
for (const root of rootList) {
|
|
1988
|
-
const profilePath =
|
|
2091
|
+
const profilePath = implementationRuntimePath(root, name);
|
|
1989
2092
|
if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, isCapabilityRoot(root))) {
|
|
1990
2093
|
out.push(profilePath);
|
|
1991
2094
|
}
|
|
@@ -2023,9 +2126,43 @@ function resolveCapabilityFolder(slug, projectCapabilitiesRoot = getProjectCapab
|
|
|
2023
2126
|
function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2024
2127
|
const resolved = resolveCapabilityAction(action, projectCapabilitiesRoot);
|
|
2025
2128
|
if (!resolved) return null;
|
|
2129
|
+
const capability = resolveCapabilityFolder(resolved.capability, projectCapabilitiesRoot);
|
|
2130
|
+
if (capability && path7.basename(capability.profilePath) === "definition.json") {
|
|
2131
|
+
const schema = capability.rawProfile.inputSchema;
|
|
2132
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return [];
|
|
2133
|
+
const properties = schema.properties;
|
|
2134
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) return [];
|
|
2135
|
+
const required2 = new Set(
|
|
2136
|
+
Array.isArray(schema.required) ? schema.required.filter((value) => typeof value === "string") : []
|
|
2137
|
+
);
|
|
2138
|
+
return Object.entries(properties).map(([name, value]) => {
|
|
2139
|
+
const property = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2140
|
+
const type = property.type === "integer" ? "int" : property.type === "boolean" ? "bool" : Array.isArray(property.enum) ? "enum" : "string";
|
|
2141
|
+
return {
|
|
2142
|
+
name,
|
|
2143
|
+
flag: `--${name}`,
|
|
2144
|
+
type,
|
|
2145
|
+
required: required2.has(name),
|
|
2146
|
+
...type === "enum" && Array.isArray(property.enum) ? { values: property.enum.filter((item) => typeof item === "string") } : {},
|
|
2147
|
+
describe: typeof property.description === "string" ? property.description : name
|
|
2148
|
+
};
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2026
2151
|
return getProfileInputs(resolved.implementation);
|
|
2027
2152
|
}
|
|
2028
2153
|
function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
2154
|
+
if (path7.basename(capability.profilePath) === "definition.json") {
|
|
2155
|
+
const implementations = readExternalImplementations(cwd);
|
|
2156
|
+
const definition = JSON.parse(fs6.readFileSync(capability.profilePath, "utf-8"));
|
|
2157
|
+
const capabilityRevision = createHash2("sha256").update(canonical(definition)).digest("hex");
|
|
2158
|
+
const selected = resolveCapabilityImplementation({
|
|
2159
|
+
capabilityId: capability.slug,
|
|
2160
|
+
capabilityRevision,
|
|
2161
|
+
implementations,
|
|
2162
|
+
repositoryBinding: repositoryImplementationBinding(capability.slug, cwd)
|
|
2163
|
+
});
|
|
2164
|
+
return { implementation: selected.id, cliArgs: {} };
|
|
2165
|
+
}
|
|
2029
2166
|
const firstWorkflowStep = capability.config.workflow?.steps[0];
|
|
2030
2167
|
if (firstWorkflowStep) {
|
|
2031
2168
|
const implementation2 = firstWorkflowStep.implementation ?? firstWorkflowStep.capability;
|
|
@@ -2035,11 +2172,42 @@ function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
|
2035
2172
|
const cliArgs = implementationDeclaresInput(implementation, "capability", cwd) ? { capability: capability.slug } : {};
|
|
2036
2173
|
return { implementation, cliArgs };
|
|
2037
2174
|
}
|
|
2175
|
+
function repositoryImplementationBinding(capabilityId, cwd) {
|
|
2176
|
+
try {
|
|
2177
|
+
return loadConfig(cwd).execution?.capabilityBindings[capabilityId];
|
|
2178
|
+
} catch {
|
|
2179
|
+
return void 0;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
function readExternalImplementations(cwd) {
|
|
2183
|
+
const root = implementationsRoot(cwd);
|
|
2184
|
+
if (!fs6.existsSync(root)) return [];
|
|
2185
|
+
const definitions = [];
|
|
2186
|
+
for (const entry of fs6.readdirSync(root, { withFileTypes: true })) {
|
|
2187
|
+
if (!entry.isDirectory() || !isSafeName(entry.name)) continue;
|
|
2188
|
+
const definitionPath = path7.join(root, entry.name, "definition.json");
|
|
2189
|
+
if (!fs6.existsSync(definitionPath)) continue;
|
|
2190
|
+
try {
|
|
2191
|
+
const definition = JSON.parse(fs6.readFileSync(definitionPath, "utf-8"));
|
|
2192
|
+
definitions.push(definition);
|
|
2193
|
+
} catch {
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
return definitions;
|
|
2197
|
+
}
|
|
2198
|
+
function canonical(value) {
|
|
2199
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
2200
|
+
if (value && typeof value === "object") {
|
|
2201
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
2202
|
+
}
|
|
2203
|
+
return JSON.stringify(value);
|
|
2204
|
+
}
|
|
2038
2205
|
function implementationDeclaresInput(implementation, inputName, cwd = process.cwd()) {
|
|
2039
|
-
const profilePath = resolveImplementation(implementation,
|
|
2206
|
+
const profilePath = resolveImplementation(implementation, getRuntimeProfileRootsForCwd(cwd));
|
|
2040
2207
|
if (!profilePath) return false;
|
|
2041
2208
|
try {
|
|
2042
|
-
const
|
|
2209
|
+
const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
2210
|
+
const raw = document.config ?? document;
|
|
2043
2211
|
if (!Array.isArray(raw.inputs)) return false;
|
|
2044
2212
|
return raw.inputs.some((entry) => {
|
|
2045
2213
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
|
|
@@ -2059,6 +2227,10 @@ function isCapabilityRoot(root) {
|
|
|
2059
2227
|
const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
|
|
2060
2228
|
return knownRoots.some((candidate) => candidate && path7.normalize(candidate) === normalized);
|
|
2061
2229
|
}
|
|
2230
|
+
function implementationRuntimePath(root, name) {
|
|
2231
|
+
const runtimePath = path7.join(root, name, "runtime.json");
|
|
2232
|
+
return fs6.existsSync(runtimePath) ? runtimePath : path7.join(root, name, CAPABILITY_PROFILE_FILE);
|
|
2233
|
+
}
|
|
2062
2234
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2063
2235
|
if (!requireImplementationProfile) return true;
|
|
2064
2236
|
try {
|
|
@@ -2126,8 +2298,10 @@ function getProfileInputs(name, roots = getImplementationRoots()) {
|
|
|
2126
2298
|
const profilePath = resolveImplementation(name, roots);
|
|
2127
2299
|
if (!profilePath) return null;
|
|
2128
2300
|
try {
|
|
2129
|
-
const
|
|
2130
|
-
if (!
|
|
2301
|
+
const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
2302
|
+
if (!document || typeof document !== "object") return [];
|
|
2303
|
+
const raw = "config" in document && document.config && typeof document.config === "object" ? document.config : document;
|
|
2304
|
+
if (!Array.isArray(raw.inputs)) return [];
|
|
2131
2305
|
return raw.inputs;
|
|
2132
2306
|
} catch {
|
|
2133
2307
|
return null;
|
|
@@ -2162,7 +2336,9 @@ var PUBLIC_IMPLEMENTATION_ROLES;
|
|
|
2162
2336
|
var init_registry = __esm({
|
|
2163
2337
|
"src/registry.ts"() {
|
|
2164
2338
|
"use strict";
|
|
2339
|
+
init_implementation_resolution();
|
|
2165
2340
|
init_capabilityFolders();
|
|
2341
|
+
init_config();
|
|
2166
2342
|
init_definition_paths();
|
|
2167
2343
|
PUBLIC_IMPLEMENTATION_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
2168
2344
|
}
|
|
@@ -3256,7 +3432,7 @@ var init_repoWorkspace = __esm({
|
|
|
3256
3432
|
defaultCloneRepo = (repo, token, dir) => {
|
|
3257
3433
|
fs7.mkdirSync(path8.dirname(dir), { recursive: true });
|
|
3258
3434
|
const clone = buildCloneProcess(repo, token);
|
|
3259
|
-
return new Promise((
|
|
3435
|
+
return new Promise((resolve19, reject) => {
|
|
3260
3436
|
const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
|
|
3261
3437
|
env: clone.env,
|
|
3262
3438
|
stdio: "inherit"
|
|
@@ -3276,7 +3452,7 @@ var init_repoWorkspace = __esm({
|
|
|
3276
3452
|
}
|
|
3277
3453
|
} catch {
|
|
3278
3454
|
}
|
|
3279
|
-
|
|
3455
|
+
resolve19();
|
|
3280
3456
|
});
|
|
3281
3457
|
child.on("error", reject);
|
|
3282
3458
|
});
|
|
@@ -3590,10 +3766,10 @@ async function runAgent(opts) {
|
|
|
3590
3766
|
let timer;
|
|
3591
3767
|
let next;
|
|
3592
3768
|
if (turnTimeoutMs > 0) {
|
|
3593
|
-
const timeoutPromise = new Promise((
|
|
3769
|
+
const timeoutPromise = new Promise((resolve19) => {
|
|
3594
3770
|
timer = setTimeout(() => {
|
|
3595
3771
|
timedOut = true;
|
|
3596
|
-
|
|
3772
|
+
resolve19({ done: true, value: void 0 });
|
|
3597
3773
|
}, turnTimeoutMs);
|
|
3598
3774
|
});
|
|
3599
3775
|
next = await Promise.race([nextPromise, timeoutPromise]);
|
|
@@ -3609,7 +3785,7 @@ async function runAgent(opts) {
|
|
|
3609
3785
|
try {
|
|
3610
3786
|
await Promise.race([
|
|
3611
3787
|
iterator.return(void 0).catch(() => void 0),
|
|
3612
|
-
new Promise((
|
|
3788
|
+
new Promise((resolve19) => setTimeout(resolve19, 1e4).unref())
|
|
3613
3789
|
]);
|
|
3614
3790
|
} catch {
|
|
3615
3791
|
}
|
|
@@ -4166,6 +4342,40 @@ var init_agencyBoundaryEval = __esm({
|
|
|
4166
4342
|
}
|
|
4167
4343
|
});
|
|
4168
4344
|
|
|
4345
|
+
// src/agency/capability-contract-validation.ts
|
|
4346
|
+
import Ajv from "ajv";
|
|
4347
|
+
function validateCapabilityContractValue(boundary, schema, value) {
|
|
4348
|
+
const validate = validator.compile(schema);
|
|
4349
|
+
if (!validate(value)) {
|
|
4350
|
+
throw new CapabilityContractValidationError(boundary, validate.errors ?? []);
|
|
4351
|
+
}
|
|
4352
|
+
}
|
|
4353
|
+
var validator, CapabilityContractValidationError;
|
|
4354
|
+
var init_capability_contract_validation = __esm({
|
|
4355
|
+
"src/agency/capability-contract-validation.ts"() {
|
|
4356
|
+
"use strict";
|
|
4357
|
+
validator = new Ajv({
|
|
4358
|
+
allErrors: true,
|
|
4359
|
+
strict: true,
|
|
4360
|
+
validateFormats: false
|
|
4361
|
+
});
|
|
4362
|
+
CapabilityContractValidationError = class extends Error {
|
|
4363
|
+
constructor(boundary, errors) {
|
|
4364
|
+
super(
|
|
4365
|
+
`Capability ${boundary} does not match its canonical contract: ${validator.errorsText([...errors], {
|
|
4366
|
+
separator: "; "
|
|
4367
|
+
})}`
|
|
4368
|
+
);
|
|
4369
|
+
this.boundary = boundary;
|
|
4370
|
+
this.errors = errors;
|
|
4371
|
+
this.name = "CapabilityContractValidationError";
|
|
4372
|
+
}
|
|
4373
|
+
boundary;
|
|
4374
|
+
errors;
|
|
4375
|
+
};
|
|
4376
|
+
}
|
|
4377
|
+
});
|
|
4378
|
+
|
|
4169
4379
|
// src/capabilityReport.ts
|
|
4170
4380
|
function parseCapabilityReportsFromText(text2) {
|
|
4171
4381
|
const reports = [];
|
|
@@ -4603,10 +4813,12 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
4603
4813
|
const resolvePart = (bucket, entry) => {
|
|
4604
4814
|
const local = path17.join(profile.dir, bucket, entry);
|
|
4605
4815
|
if (fs18.existsSync(local)) return local;
|
|
4816
|
+
const shared = path17.resolve(profile.dir, "..", "..", "shared", bucket, entry);
|
|
4817
|
+
if (fs18.existsSync(shared)) return shared;
|
|
4606
4818
|
const central = path17.join(catalog, bucket, entry);
|
|
4607
4819
|
if (fs18.existsSync(central)) return central;
|
|
4608
4820
|
throw new Error(
|
|
4609
|
-
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/) or catalog (${catalog}/${bucket}/)`
|
|
4821
|
+
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path17.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
|
|
4610
4822
|
);
|
|
4611
4823
|
};
|
|
4612
4824
|
if (cc.skills.length > 0) {
|
|
@@ -4670,9 +4882,13 @@ function splitFrontmatter(raw) {
|
|
|
4670
4882
|
function resolveAgentFile2(profileDir, name) {
|
|
4671
4883
|
const local = path18.join(profileDir, "agents", `${name}.md`);
|
|
4672
4884
|
if (fs19.existsSync(local)) return local;
|
|
4885
|
+
const shared = path18.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
|
|
4886
|
+
if (fs19.existsSync(shared)) return shared;
|
|
4673
4887
|
const central = path18.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
|
|
4674
4888
|
if (fs19.existsSync(central)) return central;
|
|
4675
|
-
throw new Error(
|
|
4889
|
+
throw new Error(
|
|
4890
|
+
`loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
|
|
4891
|
+
);
|
|
4676
4892
|
}
|
|
4677
4893
|
function captureSubagentTemplates(profile) {
|
|
4678
4894
|
const names = profile.claudeCode.subagents;
|
|
@@ -4715,6 +4931,7 @@ var init_subagents = __esm({
|
|
|
4715
4931
|
});
|
|
4716
4932
|
|
|
4717
4933
|
// src/profile.ts
|
|
4934
|
+
import { createHash as createHash3 } from "crypto";
|
|
4718
4935
|
import * as fs20 from "fs";
|
|
4719
4936
|
import * as path19 from "path";
|
|
4720
4937
|
function loadProfile(profilePath) {
|
|
@@ -4730,7 +4947,8 @@ function loadProfile(profilePath) {
|
|
|
4730
4947
|
if (!raw || typeof raw !== "object") {
|
|
4731
4948
|
throw new ProfileError(profilePath, "profile must be a JSON object");
|
|
4732
4949
|
}
|
|
4733
|
-
const
|
|
4950
|
+
const document = raw;
|
|
4951
|
+
const r = compileRuntimeDocument(profilePath, document);
|
|
4734
4952
|
const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
|
|
4735
4953
|
if (unknownKeys.length > 0) {
|
|
4736
4954
|
process.stderr.write(
|
|
@@ -4877,6 +5095,67 @@ function loadProfile(profilePath) {
|
|
|
4877
5095
|
profile.subagentTemplates = captureSubagentTemplates(profile);
|
|
4878
5096
|
return profile;
|
|
4879
5097
|
}
|
|
5098
|
+
function compileRuntimeDocument(runtimePath, document) {
|
|
5099
|
+
if (path19.basename(runtimePath) !== "runtime.json") return document;
|
|
5100
|
+
if (document.adapter !== "kody-engine-profile") {
|
|
5101
|
+
throw new ProfileError(runtimePath, "unsupported runtime adapter document");
|
|
5102
|
+
}
|
|
5103
|
+
const implementationDir = path19.dirname(runtimePath);
|
|
5104
|
+
const implementation = readJsonObject(path19.join(implementationDir, "definition.json"), "Implementation definition");
|
|
5105
|
+
const definitionsRoot2 = path19.dirname(path19.dirname(implementationDir));
|
|
5106
|
+
const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
|
|
5107
|
+
if (typeof capabilityId !== "string" || !capabilityId) {
|
|
5108
|
+
throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
|
|
5109
|
+
}
|
|
5110
|
+
const capability = readJsonObject(
|
|
5111
|
+
path19.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
|
|
5112
|
+
"Capability definition"
|
|
5113
|
+
);
|
|
5114
|
+
const {
|
|
5115
|
+
adapter: _adapter,
|
|
5116
|
+
inputBindings: _inputBindings,
|
|
5117
|
+
outputBindings: _outputBindings,
|
|
5118
|
+
requirements: _requirements,
|
|
5119
|
+
config: nestedConfig,
|
|
5120
|
+
...inlineConfig
|
|
5121
|
+
} = document;
|
|
5122
|
+
const config = nestedConfig && typeof nestedConfig === "object" && !Array.isArray(nestedConfig) ? nestedConfig : inlineConfig;
|
|
5123
|
+
const agentRef = implementation.agentRef && typeof implementation.agentRef === "object" && !Array.isArray(implementation.agentRef) ? implementation.agentRef.id : void 0;
|
|
5124
|
+
return {
|
|
5125
|
+
...config,
|
|
5126
|
+
name: implementation.id,
|
|
5127
|
+
action: capability.action,
|
|
5128
|
+
describe: capability.purpose,
|
|
5129
|
+
inputs: config.inputs ?? [],
|
|
5130
|
+
agent: agentRef,
|
|
5131
|
+
canonicalContract: {
|
|
5132
|
+
capabilityId,
|
|
5133
|
+
capabilityRevision: createHash3("sha256").update(canonical2(capability)).digest("hex"),
|
|
5134
|
+
implementationId: String(implementation.id),
|
|
5135
|
+
implementationRevision: createHash3("sha256").update(canonical2(implementation)).digest("hex"),
|
|
5136
|
+
inputSchema: capability.inputSchema,
|
|
5137
|
+
outputSchema: capability.outputSchema
|
|
5138
|
+
}
|
|
5139
|
+
};
|
|
5140
|
+
}
|
|
5141
|
+
function canonical2(value) {
|
|
5142
|
+
if (Array.isArray(value)) return `[${value.map(canonical2).join(",")}]`;
|
|
5143
|
+
if (value && typeof value === "object") {
|
|
5144
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical2(item)}`).join(",")}}`;
|
|
5145
|
+
}
|
|
5146
|
+
return JSON.stringify(value);
|
|
5147
|
+
}
|
|
5148
|
+
function readJsonObject(filePath, label) {
|
|
5149
|
+
try {
|
|
5150
|
+
const value = JSON.parse(fs20.readFileSync(filePath, "utf-8"));
|
|
5151
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5152
|
+
throw new Error("must be an object");
|
|
5153
|
+
}
|
|
5154
|
+
return value;
|
|
5155
|
+
} catch (error) {
|
|
5156
|
+
throw new ProfileError(filePath, `${label} is invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
4880
5159
|
function parseCapabilityToolMode2(profilePath, raw) {
|
|
4881
5160
|
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
4882
5161
|
if (raw === "lock" || raw === "append") return raw;
|
|
@@ -5256,6 +5535,7 @@ var init_profile = __esm({
|
|
|
5256
5535
|
VALID_CONTAINER_CHILD_TARGETS = /* @__PURE__ */ new Set(["issue", "pr"]);
|
|
5257
5536
|
VALID_PHASES = /* @__PURE__ */ new Set(["research", "planning", "implementing", "reviewing", "shipped", "failed", "idle"]);
|
|
5258
5537
|
KNOWN_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
5538
|
+
"canonicalContract",
|
|
5259
5539
|
"name",
|
|
5260
5540
|
"action",
|
|
5261
5541
|
"implementation",
|
|
@@ -6779,11 +7059,11 @@ async function nextAvailableLitellmUrl(url) {
|
|
|
6779
7059
|
throw new Error(`no free LiteLLM port found after ${startPort}`);
|
|
6780
7060
|
}
|
|
6781
7061
|
function canListen(port, host) {
|
|
6782
|
-
return new Promise((
|
|
7062
|
+
return new Promise((resolve19) => {
|
|
6783
7063
|
const server = net.createServer();
|
|
6784
|
-
server.once("error", () =>
|
|
7064
|
+
server.once("error", () => resolve19(false));
|
|
6785
7065
|
server.once("listening", () => {
|
|
6786
|
-
server.close(() =>
|
|
7066
|
+
server.close(() => resolve19(true));
|
|
6787
7067
|
});
|
|
6788
7068
|
server.listen(port, host);
|
|
6789
7069
|
});
|
|
@@ -6899,6 +7179,9 @@ function runIndexRowFromJobContext(input) {
|
|
|
6899
7179
|
capability: stringValue(input.data.jobCapability) ?? void 0,
|
|
6900
7180
|
workflow: workflow ?? void 0,
|
|
6901
7181
|
implementation: stringValue(input.data.selectedImplementation) ?? input.profileName,
|
|
7182
|
+
parentRunId: stringValue(input.data.parentRunId) ?? void 0,
|
|
7183
|
+
capabilityRevision: stringValue(input.data.capabilityRevision) ?? void 0,
|
|
7184
|
+
implementationRevision: stringValue(input.data.implementationRevision) ?? void 0,
|
|
6902
7185
|
agent: stringValue(input.data.jobAgent) ?? input.profile.agent ?? void 0,
|
|
6903
7186
|
model: stringValue(input.data.jobModel) ?? void 0,
|
|
6904
7187
|
modelProvider: stringValue(input.data.jobModelProvider) ?? void 0,
|
|
@@ -6963,7 +7246,7 @@ function statusFromExitCode(exitCode) {
|
|
|
6963
7246
|
return exitCode === 0 ? "success" : "failed";
|
|
6964
7247
|
}
|
|
6965
7248
|
function isRunSubjectType(value) {
|
|
6966
|
-
return value === "goal" || value === "loop" || value === "workflow";
|
|
7249
|
+
return value === "goal" || value === "loop" || value === "workflow" || value === "capability";
|
|
6967
7250
|
}
|
|
6968
7251
|
function stagedRunIndexRows(data) {
|
|
6969
7252
|
const value = data[STAGED_RUN_INDEX_ROWS_KEY];
|
|
@@ -8472,9 +8755,9 @@ function goalInstanceTime(state) {
|
|
|
8472
8755
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
8473
8756
|
}
|
|
8474
8757
|
function loadGoalTemplate(cwd, targetId) {
|
|
8475
|
-
return
|
|
8758
|
+
return readJsonObject2(path24.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
|
|
8476
8759
|
}
|
|
8477
|
-
function
|
|
8760
|
+
function readJsonObject2(filePath) {
|
|
8478
8761
|
if (!fs27.existsSync(filePath)) return null;
|
|
8479
8762
|
const parsed = JSON.parse(fs27.readFileSync(filePath, "utf8"));
|
|
8480
8763
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -9504,6 +9787,7 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9504
9787
|
capability2,
|
|
9505
9788
|
slug,
|
|
9506
9789
|
backend,
|
|
9790
|
+
opts.cwd,
|
|
9507
9791
|
opts.previousScheduleState?.capabilities[slug]
|
|
9508
9792
|
);
|
|
9509
9793
|
statuses[slug] = status;
|
|
@@ -9558,21 +9842,19 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9558
9842
|
}
|
|
9559
9843
|
};
|
|
9560
9844
|
}
|
|
9561
|
-
async function describeCapabilitySchedule(capability, slug, backend, previous) {
|
|
9845
|
+
async function describeCapabilitySchedule(capability, slug, backend, cwd, previous) {
|
|
9562
9846
|
if (!capability) return { slug, state: "blocked", reason: "capability folder missing" };
|
|
9563
|
-
|
|
9564
|
-
if (config.disabled === true) {
|
|
9847
|
+
if (capability.config.disabled === true) {
|
|
9565
9848
|
return { slug, title: capability.title, state: "disabled", reason: "disabled" };
|
|
9566
9849
|
}
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
}
|
|
9570
|
-
if (config.implementations && config.implementations.length > 1) {
|
|
9850
|
+
try {
|
|
9851
|
+
resolveCapabilityExecution(capability, cwd);
|
|
9852
|
+
} catch (error) {
|
|
9571
9853
|
return {
|
|
9572
9854
|
slug,
|
|
9573
9855
|
title: capability.title,
|
|
9574
9856
|
state: "blocked",
|
|
9575
|
-
reason:
|
|
9857
|
+
reason: error instanceof Error ? error.message : "Implementation unavailable"
|
|
9576
9858
|
};
|
|
9577
9859
|
}
|
|
9578
9860
|
let lastFiredAt = validIso(previous?.lastFiredAt) ? previous?.lastFiredAt : void 0;
|
|
@@ -13242,7 +13524,7 @@ var init_triggerDispatcher = __esm({
|
|
|
13242
13524
|
});
|
|
13243
13525
|
|
|
13244
13526
|
// src/goal/policyResolver.ts
|
|
13245
|
-
import { createHash as
|
|
13527
|
+
import { createHash as createHash4 } from "crypto";
|
|
13246
13528
|
function resolveDispatchPolicy(input) {
|
|
13247
13529
|
const operation = input.catalog.operations.get(input.owner.definition.operationId);
|
|
13248
13530
|
if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
|
|
@@ -13260,7 +13542,7 @@ function resolveDispatchPolicy(input) {
|
|
|
13260
13542
|
const snapshotValue = { policy, constraints };
|
|
13261
13543
|
return {
|
|
13262
13544
|
snapshot: {
|
|
13263
|
-
hash:
|
|
13545
|
+
hash: createHash4("sha256").update(stableJson(snapshotValue)).digest("hex"),
|
|
13264
13546
|
...snapshotValue
|
|
13265
13547
|
},
|
|
13266
13548
|
operation,
|
|
@@ -13602,10 +13884,10 @@ async function runAttempt(run, job, timeoutSeconds) {
|
|
|
13602
13884
|
exitCode: 99,
|
|
13603
13885
|
reason: error instanceof Error ? error.message : String(error)
|
|
13604
13886
|
})),
|
|
13605
|
-
new Promise((
|
|
13887
|
+
new Promise((resolve19) => {
|
|
13606
13888
|
timer = setTimeout(() => {
|
|
13607
13889
|
abortController.abort();
|
|
13608
|
-
|
|
13890
|
+
resolve19({ exitCode: 124, reason: `target timed out after ${formatSeconds(timeoutSeconds)}s` });
|
|
13609
13891
|
}, timeoutSeconds * 1e3);
|
|
13610
13892
|
})
|
|
13611
13893
|
]);
|
|
@@ -13645,7 +13927,7 @@ function formatSeconds(seconds) {
|
|
|
13645
13927
|
}
|
|
13646
13928
|
async function wait(milliseconds) {
|
|
13647
13929
|
if (milliseconds <= 0) return;
|
|
13648
|
-
await new Promise((
|
|
13930
|
+
await new Promise((resolve19) => setTimeout(resolve19, milliseconds));
|
|
13649
13931
|
}
|
|
13650
13932
|
function repositoryTenant(config) {
|
|
13651
13933
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
@@ -14825,7 +15107,7 @@ function performInit(cwd, force) {
|
|
|
14825
15107
|
fs36.writeFileSync(workflowPath, loadKodyWorkflowTemplate());
|
|
14826
15108
|
wrote.push(".github/workflows/kody.yml");
|
|
14827
15109
|
}
|
|
14828
|
-
for (const exe of
|
|
15110
|
+
for (const exe of listRuntimeProfilesForCwd(cwd)) {
|
|
14829
15111
|
let profile;
|
|
14830
15112
|
try {
|
|
14831
15113
|
profile = loadProfile(exe.profilePath);
|
|
@@ -15233,7 +15515,7 @@ function retryDelaysMs() {
|
|
|
15233
15515
|
}
|
|
15234
15516
|
function sleep(ms) {
|
|
15235
15517
|
if (ms <= 0) return Promise.resolve();
|
|
15236
|
-
return new Promise((
|
|
15518
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
15237
15519
|
}
|
|
15238
15520
|
async function fetchGoalStateWithRetry(config, goalId, cwd) {
|
|
15239
15521
|
let state = await fetchGoalStateAsync(config, goalId, cwd);
|
|
@@ -15531,9 +15813,9 @@ var init_kodyVariables = __esm({
|
|
|
15531
15813
|
});
|
|
15532
15814
|
|
|
15533
15815
|
// src/backendVault.ts
|
|
15534
|
-
import { createDecipheriv, createHash as
|
|
15816
|
+
import { createDecipheriv, createHash as createHash5 } from "crypto";
|
|
15535
15817
|
function cacheKey(owner, repo, masterKey) {
|
|
15536
|
-
const keyHash =
|
|
15818
|
+
const keyHash = createHash5("sha256").update(masterKey).digest("hex").slice(0, 16);
|
|
15537
15819
|
return `${owner}/${repo}:${keyHash}`.toLowerCase();
|
|
15538
15820
|
}
|
|
15539
15821
|
function decryptVault(payload, masterKey) {
|
|
@@ -16182,7 +16464,7 @@ var init_notifyTerminal = __esm({
|
|
|
16182
16464
|
});
|
|
16183
16465
|
|
|
16184
16466
|
// src/scripts/openAgencyModelReviewPr.ts
|
|
16185
|
-
import { createHash as
|
|
16467
|
+
import { createHash as createHash6 } from "crypto";
|
|
16186
16468
|
function parseAgencyModelProposal(raw) {
|
|
16187
16469
|
const text2 = raw.trim();
|
|
16188
16470
|
const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
|
|
@@ -16234,7 +16516,7 @@ function normalizeBundleFiles(bundle) {
|
|
|
16234
16516
|
});
|
|
16235
16517
|
}
|
|
16236
16518
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
16237
|
-
const digest =
|
|
16519
|
+
const digest = createHash6("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
|
|
16238
16520
|
return `issue-${issueNumber}-${digest}`;
|
|
16239
16521
|
}
|
|
16240
16522
|
function isDryRun(ctx) {
|
|
@@ -18306,9 +18588,9 @@ var init_runFlow = __esm({
|
|
|
18306
18588
|
});
|
|
18307
18589
|
|
|
18308
18590
|
// src/scripts/previewBuildHelpers.ts
|
|
18309
|
-
import { createDecipheriv as createDecipheriv2, createHash as
|
|
18591
|
+
import { createDecipheriv as createDecipheriv2, createHash as createHash7, hkdfSync as hkdfSync2 } from "crypto";
|
|
18310
18592
|
function shortHash(s) {
|
|
18311
|
-
return
|
|
18593
|
+
return createHash7("sha256").update(s).digest("hex").slice(0, 6);
|
|
18312
18594
|
}
|
|
18313
18595
|
function previewAppName(repo, pr) {
|
|
18314
18596
|
const [owner, name] = repo.split("/");
|
|
@@ -18341,7 +18623,7 @@ function formatPreviewComment(args) {
|
|
|
18341
18623
|
].join("\n");
|
|
18342
18624
|
}
|
|
18343
18625
|
function defaultImageTag(repo, ref) {
|
|
18344
|
-
return
|
|
18626
|
+
return createHash7("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
18345
18627
|
}
|
|
18346
18628
|
var init_previewBuildHelpers = __esm({
|
|
18347
18629
|
"src/scripts/previewBuildHelpers.ts"() {
|
|
@@ -18352,7 +18634,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
18352
18634
|
// src/scripts/previewBuildRun.ts
|
|
18353
18635
|
import { spawn as spawn5 } from "child_process";
|
|
18354
18636
|
async function runCmd(cmd, args, opts = {}) {
|
|
18355
|
-
await new Promise((
|
|
18637
|
+
await new Promise((resolve19, reject) => {
|
|
18356
18638
|
const child = spawn5(cmd, args, {
|
|
18357
18639
|
cwd: opts.cwd,
|
|
18358
18640
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -18364,7 +18646,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
18364
18646
|
}
|
|
18365
18647
|
child.on("error", reject);
|
|
18366
18648
|
child.on("close", (code) => {
|
|
18367
|
-
if (code === 0)
|
|
18649
|
+
if (code === 0) resolve19();
|
|
18368
18650
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
18369
18651
|
});
|
|
18370
18652
|
});
|
|
@@ -19628,7 +19910,7 @@ function stripAnsi2(s) {
|
|
|
19628
19910
|
return s.replace(ANSI_RE2, "");
|
|
19629
19911
|
}
|
|
19630
19912
|
function runCommand2(command, cwd) {
|
|
19631
|
-
return new Promise((
|
|
19913
|
+
return new Promise((resolve19) => {
|
|
19632
19914
|
const child = spawn6(command, {
|
|
19633
19915
|
cwd,
|
|
19634
19916
|
shell: true,
|
|
@@ -19655,11 +19937,11 @@ function runCommand2(command, cwd) {
|
|
|
19655
19937
|
}, TEST_TIMEOUT_MS);
|
|
19656
19938
|
child.on("exit", (code) => {
|
|
19657
19939
|
clearTimeout(timer);
|
|
19658
|
-
|
|
19940
|
+
resolve19({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
19659
19941
|
});
|
|
19660
19942
|
child.on("error", (err) => {
|
|
19661
19943
|
clearTimeout(timer);
|
|
19662
|
-
|
|
19944
|
+
resolve19({ exitCode: -1, output: err.message });
|
|
19663
19945
|
});
|
|
19664
19946
|
});
|
|
19665
19947
|
}
|
|
@@ -20065,21 +20347,21 @@ function lineStream(stream) {
|
|
|
20065
20347
|
tryDeliver();
|
|
20066
20348
|
});
|
|
20067
20349
|
return {
|
|
20068
|
-
next: (timeoutMs) => new Promise((
|
|
20350
|
+
next: (timeoutMs) => new Promise((resolve19) => {
|
|
20069
20351
|
if (queue.length > 0) {
|
|
20070
|
-
|
|
20352
|
+
resolve19(queue.shift());
|
|
20071
20353
|
return;
|
|
20072
20354
|
}
|
|
20073
20355
|
if (ended) {
|
|
20074
|
-
|
|
20356
|
+
resolve19(null);
|
|
20075
20357
|
return;
|
|
20076
20358
|
}
|
|
20077
|
-
waiter =
|
|
20359
|
+
waiter = resolve19;
|
|
20078
20360
|
const t = setTimeout(
|
|
20079
20361
|
() => {
|
|
20080
|
-
if (waiter ===
|
|
20362
|
+
if (waiter === resolve19) {
|
|
20081
20363
|
waiter = null;
|
|
20082
|
-
|
|
20364
|
+
resolve19(null);
|
|
20083
20365
|
}
|
|
20084
20366
|
},
|
|
20085
20367
|
Math.max(0, timeoutMs)
|
|
@@ -20747,6 +21029,9 @@ async function runImplementation(profileName, input) {
|
|
|
20747
21029
|
let args;
|
|
20748
21030
|
try {
|
|
20749
21031
|
args = validateInputs(profile.inputs, input.cliArgs);
|
|
21032
|
+
if (profile.canonicalContract) {
|
|
21033
|
+
validateCapabilityContractValue("input", profile.canonicalContract.inputSchema, args);
|
|
21034
|
+
}
|
|
20750
21035
|
} catch (err) {
|
|
20751
21036
|
return finishAndEnd({ exitCode: 64, reason: err instanceof Error ? err.message : String(err) });
|
|
20752
21037
|
}
|
|
@@ -20807,6 +21092,12 @@ async function runImplementation(profileName, input) {
|
|
|
20807
21092
|
ctx.data.jobModelProvider = model.provider;
|
|
20808
21093
|
ctx.data.jobModelName = model.model;
|
|
20809
21094
|
if (reasoningEffort) ctx.data.jobReasoningEffort = reasoningEffort;
|
|
21095
|
+
if (profile.canonicalContract) {
|
|
21096
|
+
ctx.data.jobCapability = profile.canonicalContract.capabilityId;
|
|
21097
|
+
ctx.data.selectedImplementation = profile.canonicalContract.implementationId;
|
|
21098
|
+
ctx.data.capabilityRevision = profile.canonicalContract.capabilityRevision;
|
|
21099
|
+
ctx.data.implementationRevision = profile.canonicalContract.implementationRevision;
|
|
21100
|
+
}
|
|
20810
21101
|
const runIndexStartedAt = new Date(stageStartedAt).toISOString();
|
|
20811
21102
|
if (!input.skipConfig) {
|
|
20812
21103
|
await upsertRunIndexRowBestEffortAsync(
|
|
@@ -21116,6 +21407,25 @@ async function runImplementation(profileName, input) {
|
|
|
21116
21407
|
outcome: postOutcome
|
|
21117
21408
|
});
|
|
21118
21409
|
}
|
|
21410
|
+
const capabilityResults = Array.isArray(ctx.data.capabilityResults) ? ctx.data.capabilityResults : void 0;
|
|
21411
|
+
if (profile.canonicalContract) {
|
|
21412
|
+
try {
|
|
21413
|
+
validateCapabilityContractValue(
|
|
21414
|
+
"output",
|
|
21415
|
+
profile.canonicalContract.outputSchema,
|
|
21416
|
+
capabilityResults?.at(-1) ?? {
|
|
21417
|
+
exitCode: ctx.output.exitCode ?? 0,
|
|
21418
|
+
reason: ctx.output.reason,
|
|
21419
|
+
prUrl: ctx.output.prUrl
|
|
21420
|
+
}
|
|
21421
|
+
);
|
|
21422
|
+
} catch (error) {
|
|
21423
|
+
return finishAndEnd({
|
|
21424
|
+
exitCode: 99,
|
|
21425
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
21426
|
+
});
|
|
21427
|
+
}
|
|
21428
|
+
}
|
|
21119
21429
|
return finishAndEnd({
|
|
21120
21430
|
exitCode: ctx.output.exitCode ?? 0,
|
|
21121
21431
|
prUrl: ctx.output.prUrl,
|
|
@@ -21124,7 +21434,7 @@ async function runImplementation(profileName, input) {
|
|
|
21124
21434
|
nextJob: ctx.output.nextJob,
|
|
21125
21435
|
afterNextJob: ctx.output.afterNextJob,
|
|
21126
21436
|
taskState: ctx.data.taskState,
|
|
21127
|
-
capabilityResults
|
|
21437
|
+
capabilityResults
|
|
21128
21438
|
});
|
|
21129
21439
|
} catch (err) {
|
|
21130
21440
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -21311,7 +21621,7 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
21311
21621
|
}
|
|
21312
21622
|
}
|
|
21313
21623
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
21314
|
-
const found = resolveImplementation(profileName,
|
|
21624
|
+
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
21315
21625
|
if (found) return found;
|
|
21316
21626
|
const here = path45.dirname(new URL(import.meta.url).pathname);
|
|
21317
21627
|
const candidates = [
|
|
@@ -21328,10 +21638,7 @@ function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
|
21328
21638
|
return candidates[0];
|
|
21329
21639
|
}
|
|
21330
21640
|
function loadRunnableProfile(profileName, cwd) {
|
|
21331
|
-
const candidates = resolveImplementationCandidates(
|
|
21332
|
-
profileName,
|
|
21333
|
-
getImplementationRootsForCwd(cwd)
|
|
21334
|
-
);
|
|
21641
|
+
const candidates = resolveImplementationCandidates(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
21335
21642
|
const skipped = [];
|
|
21336
21643
|
for (const profilePath2 of candidates) {
|
|
21337
21644
|
const profile2 = loadProfile(profilePath2);
|
|
@@ -21484,14 +21791,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
21484
21791
|
let killTimer;
|
|
21485
21792
|
let escalateTimer;
|
|
21486
21793
|
const result = await new Promise(
|
|
21487
|
-
(
|
|
21794
|
+
(resolve19) => {
|
|
21488
21795
|
let settled = false;
|
|
21489
21796
|
const settle = (code, signal, spawnErr) => {
|
|
21490
21797
|
if (settled) return;
|
|
21491
21798
|
settled = true;
|
|
21492
21799
|
if (killTimer) clearTimeout(killTimer);
|
|
21493
21800
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
21494
|
-
|
|
21801
|
+
resolve19({ code, signal, spawnErr });
|
|
21495
21802
|
};
|
|
21496
21803
|
child.on("error", (err) => settle(null, null, err));
|
|
21497
21804
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -21583,6 +21890,7 @@ var MUTATING_POSTFLIGHTS, SHELL_MARKER_RE, TASK_ARTIFACT_WRITE_TOOLS, MAX_CHAIN_
|
|
|
21583
21890
|
var init_executor = __esm({
|
|
21584
21891
|
"src/executor.ts"() {
|
|
21585
21892
|
"use strict";
|
|
21893
|
+
init_capability_contract_validation();
|
|
21586
21894
|
init_agent();
|
|
21587
21895
|
init_agents();
|
|
21588
21896
|
init_capabilityReport();
|
|
@@ -21786,7 +22094,52 @@ async function runJob(job, base) {
|
|
|
21786
22094
|
...valid.workflowState ?? persistedState ? { workflowState: valid.workflowState ?? persistedState ?? void 0 } : {}
|
|
21787
22095
|
};
|
|
21788
22096
|
const checkpoint = valid.workflowRunId && workflowIdentity && base.config ? (state) => writeWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId, state) : void 0;
|
|
21789
|
-
const
|
|
22097
|
+
const parentRunId = `workflow:${workflowIdentity}:${valid.workflowRunId ?? newJobId(valid.flavor)}`;
|
|
22098
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22099
|
+
const parentRow = {
|
|
22100
|
+
version: 1,
|
|
22101
|
+
id: parentRunId,
|
|
22102
|
+
subjectType: "workflow",
|
|
22103
|
+
subjectId: workflowIdentity,
|
|
22104
|
+
subjectLabel: workflowCapability.title,
|
|
22105
|
+
status: "running",
|
|
22106
|
+
title: workflowCapability.title,
|
|
22107
|
+
startedAt,
|
|
22108
|
+
updatedAt: startedAt,
|
|
22109
|
+
workflow: workflowIdentity,
|
|
22110
|
+
kodyRunId: valid.workflowRunId,
|
|
22111
|
+
sourceType: "job"
|
|
22112
|
+
};
|
|
22113
|
+
const persistRun = Boolean(base.config && !base.skipConfig && hasStateBackendConfig());
|
|
22114
|
+
if (base.config && persistRun) {
|
|
22115
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, parentRow);
|
|
22116
|
+
}
|
|
22117
|
+
const workflowBase = {
|
|
22118
|
+
...base,
|
|
22119
|
+
preloadedData: { ...base.preloadedData ?? {}, parentRunId }
|
|
22120
|
+
};
|
|
22121
|
+
let result;
|
|
22122
|
+
try {
|
|
22123
|
+
result = await runCapabilityWorkflow(workflowJob, workflow, workflowCapability, workflowBase, checkpoint);
|
|
22124
|
+
} catch (error) {
|
|
22125
|
+
if (base.config && persistRun) {
|
|
22126
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, {
|
|
22127
|
+
...parentRow,
|
|
22128
|
+
status: "failed",
|
|
22129
|
+
summary: error instanceof Error ? error.message : String(error),
|
|
22130
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22131
|
+
});
|
|
22132
|
+
}
|
|
22133
|
+
throw error;
|
|
22134
|
+
}
|
|
22135
|
+
if (base.config && persistRun) {
|
|
22136
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, {
|
|
22137
|
+
...parentRow,
|
|
22138
|
+
status: result.exitCode === 0 ? "success" : "failed",
|
|
22139
|
+
summary: result.reason,
|
|
22140
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22141
|
+
});
|
|
22142
|
+
}
|
|
21790
22143
|
if (valid.workflowRunId && workflowIdentity && base.config && result.workflowState) {
|
|
21791
22144
|
await writeWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId, result.workflowState);
|
|
21792
22145
|
}
|
|
@@ -21926,6 +22279,9 @@ async function runLinearCapabilityWorkflow(parent, workflow, capability, base) {
|
|
|
21926
22279
|
...base,
|
|
21927
22280
|
preloadedData: {
|
|
21928
22281
|
...chainData,
|
|
22282
|
+
runSubjectType: "capability",
|
|
22283
|
+
runSubjectId: step.capability,
|
|
22284
|
+
runSubjectLabel: label,
|
|
21929
22285
|
workflowStep: label,
|
|
21930
22286
|
workflowStepIndex: index + 1,
|
|
21931
22287
|
workflowStepReason: step.reason,
|
|
@@ -22070,6 +22426,9 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22070
22426
|
...base,
|
|
22071
22427
|
preloadedData: {
|
|
22072
22428
|
...chainData,
|
|
22429
|
+
runSubjectType: "capability",
|
|
22430
|
+
runSubjectId: step.capability,
|
|
22431
|
+
runSubjectLabel: step.id,
|
|
22073
22432
|
workflowStep: step.id,
|
|
22074
22433
|
workflowStepIndex: index + 1,
|
|
22075
22434
|
workflowStepReason: step.reason,
|
|
@@ -22323,7 +22682,7 @@ function hydratedCapabilitiesRoot(cwd) {
|
|
|
22323
22682
|
return path46.join(cwd, ".kody-engine", "definitions", "capabilities");
|
|
22324
22683
|
}
|
|
22325
22684
|
function loadWorkflowContext(slug, base) {
|
|
22326
|
-
if (!slug || !
|
|
22685
|
+
if (!slug || !isWorkflowDefinitionId(slug)) return null;
|
|
22327
22686
|
const workflow = readWorkflowDefinition(base.config, base.cwd, slug);
|
|
22328
22687
|
return workflow ? workflowDefinitionToCapabilityFolder(slug, workflow) : null;
|
|
22329
22688
|
}
|
|
@@ -22359,6 +22718,8 @@ var init_job = __esm({
|
|
|
22359
22718
|
init_capabilityFolders();
|
|
22360
22719
|
init_executor();
|
|
22361
22720
|
init_registry();
|
|
22721
|
+
init_runIndex();
|
|
22722
|
+
init_state_backend();
|
|
22362
22723
|
init_workflowDefinitions();
|
|
22363
22724
|
init_workflowRunState();
|
|
22364
22725
|
init_workflowValidation();
|
|
@@ -22637,9 +22998,9 @@ var CodexAppServerClient = class {
|
|
|
22637
22998
|
await this.request("thread/resume", { threadId });
|
|
22638
22999
|
}
|
|
22639
23000
|
async runTurn(args) {
|
|
22640
|
-
await new Promise((
|
|
23001
|
+
await new Promise((resolve19, reject) => {
|
|
22641
23002
|
this.process.turnWaiters.set(args.threadId, {
|
|
22642
|
-
resolve:
|
|
23003
|
+
resolve: resolve19,
|
|
22643
23004
|
reject,
|
|
22644
23005
|
onNotification: args.onNotification,
|
|
22645
23006
|
queue: Promise.resolve()
|
|
@@ -22656,8 +23017,8 @@ var CodexAppServerClient = class {
|
|
|
22656
23017
|
}
|
|
22657
23018
|
request(method, params) {
|
|
22658
23019
|
const id = this.process.nextId++;
|
|
22659
|
-
return new Promise((
|
|
22660
|
-
this.process.pending.set(id, { resolve:
|
|
23020
|
+
return new Promise((resolve19, reject) => {
|
|
23021
|
+
this.process.pending.set(id, { resolve: resolve19, reject });
|
|
22661
23022
|
this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
|
|
22662
23023
|
`);
|
|
22663
23024
|
});
|
|
@@ -23941,7 +24302,7 @@ function dispatchScheduledWatches(opts) {
|
|
|
23941
24302
|
const envWindow = Number(process.env.KODY_SCHEDULE_WINDOW_SEC);
|
|
23942
24303
|
const windowSec = opts?.windowSec ?? (Number.isFinite(envWindow) && envWindow > 0 ? envWindow : 300);
|
|
23943
24304
|
const out = [];
|
|
23944
|
-
for (const exe of
|
|
24305
|
+
for (const exe of listRuntimeProfilesForCwd(opts?.cwd ?? process.cwd())) {
|
|
23945
24306
|
let raw;
|
|
23946
24307
|
try {
|
|
23947
24308
|
raw = fs16.readFileSync(exe.profilePath, "utf-8");
|
|
@@ -24535,8 +24896,14 @@ async function runCi(argv) {
|
|
|
24535
24896
|
if (noTarget && capabilityInput) {
|
|
24536
24897
|
forceRunAction = capabilityInput;
|
|
24537
24898
|
if (messageInput) {
|
|
24538
|
-
const route = resolveCapabilityAction(
|
|
24539
|
-
|
|
24899
|
+
const route = resolveCapabilityAction(
|
|
24900
|
+
capabilityInput,
|
|
24901
|
+
capabilitiesRoot(cwd)
|
|
24902
|
+
);
|
|
24903
|
+
const textInputs = route?.implementation ? (getProfileInputs(
|
|
24904
|
+
route.implementation,
|
|
24905
|
+
getRuntimeProfileRootsForCwd(cwd)
|
|
24906
|
+
) ?? []).filter(
|
|
24540
24907
|
(input) => input.type === "string"
|
|
24541
24908
|
) : [];
|
|
24542
24909
|
if (textInputs.length === 1) {
|
|
@@ -24569,7 +24936,7 @@ async function runCi(argv) {
|
|
|
24569
24936
|
workflow: forceRunAction,
|
|
24570
24937
|
cliArgs: {}
|
|
24571
24938
|
};
|
|
24572
|
-
const scheduledWatchRoute = manualGoalManager || capabilityRoute || workflowRoute ? void 0 : dispatchScheduledWatches({ force: true }).find(
|
|
24939
|
+
const scheduledWatchRoute = manualGoalManager || capabilityRoute || workflowRoute ? void 0 : dispatchScheduledWatches({ force: true, cwd }).find(
|
|
24573
24940
|
(match) => match.action === forceRunAction || match.capability === forceRunAction || match.implementation === forceRunAction
|
|
24574
24941
|
);
|
|
24575
24942
|
const route = manualGoalManager ? {
|
|
@@ -24822,7 +25189,10 @@ ${CI_HELP}`);
|
|
|
24822
25189
|
}
|
|
24823
25190
|
}
|
|
24824
25191
|
async function runScheduledFanOut(cwd, args, opts) {
|
|
24825
|
-
const matches = dispatchScheduledWatches({
|
|
25192
|
+
const matches = dispatchScheduledWatches({
|
|
25193
|
+
force: opts.force,
|
|
25194
|
+
cwd
|
|
25195
|
+
});
|
|
24826
25196
|
if (matches.length === 0) {
|
|
24827
25197
|
process.stdout.write(
|
|
24828
25198
|
`\u2192 kody: scheduled wake \u2014 no watches matched ${opts.force ? "(force mode, no watches discovered)" : "(window)"}, exiting cleanly
|
|
@@ -25109,17 +25479,17 @@ function authOk(req, expected) {
|
|
|
25109
25479
|
return false;
|
|
25110
25480
|
}
|
|
25111
25481
|
function readJsonBody(req) {
|
|
25112
|
-
return new Promise((
|
|
25482
|
+
return new Promise((resolve19, reject) => {
|
|
25113
25483
|
const chunks = [];
|
|
25114
25484
|
req.on("data", (c) => chunks.push(c));
|
|
25115
25485
|
req.on("end", () => {
|
|
25116
25486
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
25117
25487
|
if (!raw.trim()) {
|
|
25118
|
-
|
|
25488
|
+
resolve19({});
|
|
25119
25489
|
return;
|
|
25120
25490
|
}
|
|
25121
25491
|
try {
|
|
25122
|
-
|
|
25492
|
+
resolve19(JSON.parse(raw));
|
|
25123
25493
|
} catch (err) {
|
|
25124
25494
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
25125
25495
|
}
|
|
@@ -25459,11 +25829,11 @@ async function brainServe(opts) {
|
|
|
25459
25829
|
litellmUrl,
|
|
25460
25830
|
driver
|
|
25461
25831
|
});
|
|
25462
|
-
await new Promise((
|
|
25832
|
+
await new Promise((resolve19) => {
|
|
25463
25833
|
server.listen(port, "0.0.0.0", () => {
|
|
25464
25834
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
25465
25835
|
`);
|
|
25466
|
-
|
|
25836
|
+
resolve19();
|
|
25467
25837
|
});
|
|
25468
25838
|
});
|
|
25469
25839
|
const shutdown = (signal) => {
|
|
@@ -25718,14 +26088,14 @@ async function startBrainProxy(opts) {
|
|
|
25718
26088
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
25719
26089
|
const port = opts.port ?? 0;
|
|
25720
26090
|
const host = opts.host ?? "127.0.0.1";
|
|
25721
|
-
await new Promise((
|
|
26091
|
+
await new Promise((resolve19) => httpServer.listen(port, host, () => resolve19()));
|
|
25722
26092
|
const addr = httpServer.address();
|
|
25723
26093
|
return {
|
|
25724
26094
|
httpServer,
|
|
25725
26095
|
port: addr.port,
|
|
25726
26096
|
url: `http://${host}:${addr.port}`,
|
|
25727
|
-
stop: () => new Promise((
|
|
25728
|
-
httpServer.close(() =>
|
|
26097
|
+
stop: () => new Promise((resolve19) => {
|
|
26098
|
+
httpServer.close(() => resolve19());
|
|
25729
26099
|
}),
|
|
25730
26100
|
handler
|
|
25731
26101
|
};
|
|
@@ -25875,23 +26245,23 @@ function buildMcpHttpServer(opts) {
|
|
|
25875
26245
|
httpServer,
|
|
25876
26246
|
routes,
|
|
25877
26247
|
port,
|
|
25878
|
-
stop: () => new Promise((
|
|
26248
|
+
stop: () => new Promise((resolve19) => {
|
|
25879
26249
|
let pending = transports.size;
|
|
25880
26250
|
if (pending === 0) {
|
|
25881
|
-
httpServer.close(() =>
|
|
26251
|
+
httpServer.close(() => resolve19());
|
|
25882
26252
|
return;
|
|
25883
26253
|
}
|
|
25884
26254
|
for (const transport of transports.values()) {
|
|
25885
26255
|
void transport.close().finally(() => {
|
|
25886
26256
|
pending--;
|
|
25887
|
-
if (pending === 0) httpServer.close(() =>
|
|
26257
|
+
if (pending === 0) httpServer.close(() => resolve19());
|
|
25888
26258
|
});
|
|
25889
26259
|
}
|
|
25890
26260
|
})
|
|
25891
26261
|
};
|
|
25892
26262
|
}
|
|
25893
26263
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
25894
|
-
return new Promise((
|
|
26264
|
+
return new Promise((resolve19, reject) => {
|
|
25895
26265
|
server.httpServer.once("error", reject);
|
|
25896
26266
|
server.httpServer.listen(server.port, host, () => {
|
|
25897
26267
|
server.httpServer.off("error", reject);
|
|
@@ -25899,7 +26269,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
25899
26269
|
if (addr && typeof addr === "object") {
|
|
25900
26270
|
server.port = addr.port;
|
|
25901
26271
|
}
|
|
25902
|
-
|
|
26272
|
+
resolve19();
|
|
25903
26273
|
});
|
|
25904
26274
|
});
|
|
25905
26275
|
}
|
|
@@ -26049,7 +26419,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
26049
26419
|
}
|
|
26050
26420
|
}
|
|
26051
26421
|
function sleep3(ms) {
|
|
26052
|
-
return new Promise((
|
|
26422
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
26053
26423
|
}
|
|
26054
26424
|
function currentBranch(cwd) {
|
|
26055
26425
|
try {
|
|
@@ -26384,10 +26754,10 @@ init_definition_paths();
|
|
|
26384
26754
|
|
|
26385
26755
|
// src/definition-hydration.ts
|
|
26386
26756
|
init_state_backend();
|
|
26387
|
-
import { createHash as
|
|
26757
|
+
import { createHash as createHash8 } from "crypto";
|
|
26388
26758
|
import * as fs50 from "fs";
|
|
26389
26759
|
import * as path51 from "path";
|
|
26390
|
-
var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,
|
|
26760
|
+
var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
26391
26761
|
function assertSafeDefinitionPath(filePath) {
|
|
26392
26762
|
const segments = filePath.split("/");
|
|
26393
26763
|
if (!filePath || filePath.startsWith("/") || filePath.includes("\\") || filePath.includes("\0") || segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
@@ -26405,7 +26775,7 @@ function normalizeDefinitionBundle(bundle) {
|
|
|
26405
26775
|
return { schemaVersion: 1, files };
|
|
26406
26776
|
}
|
|
26407
26777
|
function definitionVersion(bundle) {
|
|
26408
|
-
return `sha256:${
|
|
26778
|
+
return `sha256:${createHash8("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
|
|
26409
26779
|
}
|
|
26410
26780
|
function verifyDefinition(definition) {
|
|
26411
26781
|
if (!SLUG_RE2.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
|
|
@@ -26415,6 +26785,13 @@ function verifyDefinition(definition) {
|
|
|
26415
26785
|
}
|
|
26416
26786
|
return bundle;
|
|
26417
26787
|
}
|
|
26788
|
+
function writeBundle(root, bundle) {
|
|
26789
|
+
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
26790
|
+
const target = path51.join(root, filePath);
|
|
26791
|
+
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
26792
|
+
fs50.writeFileSync(target, contents, "utf8");
|
|
26793
|
+
}
|
|
26794
|
+
}
|
|
26418
26795
|
function writeDefinition(root, kind, definition) {
|
|
26419
26796
|
const bundle = verifyDefinition(definition);
|
|
26420
26797
|
if (kind === "agent") {
|
|
@@ -26424,20 +26801,18 @@ function writeDefinition(root, kind, definition) {
|
|
|
26424
26801
|
return;
|
|
26425
26802
|
}
|
|
26426
26803
|
if (kind === "goal") {
|
|
26427
|
-
|
|
26428
|
-
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
26429
|
-
const target = path51.join(goalRoot, filePath);
|
|
26430
|
-
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
26431
|
-
fs50.writeFileSync(target, contents, "utf8");
|
|
26432
|
-
}
|
|
26804
|
+
writeBundle(path51.join(root, "goals", definition.slug), bundle);
|
|
26433
26805
|
return;
|
|
26434
26806
|
}
|
|
26435
|
-
|
|
26436
|
-
|
|
26437
|
-
|
|
26438
|
-
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
26439
|
-
fs50.writeFileSync(target, contents, "utf8");
|
|
26807
|
+
if (kind === "implementation") {
|
|
26808
|
+
writeBundle(path51.join(root, "implementations", definition.slug), bundle);
|
|
26809
|
+
return;
|
|
26440
26810
|
}
|
|
26811
|
+
if (kind === "asset") {
|
|
26812
|
+
writeBundle(path51.join(root, "shared"), bundle);
|
|
26813
|
+
return;
|
|
26814
|
+
}
|
|
26815
|
+
writeBundle(path51.join(root, "capabilities", definition.slug), bundle);
|
|
26441
26816
|
}
|
|
26442
26817
|
async function hydrateDefinitions(options) {
|
|
26443
26818
|
const root = path51.join(options.cwd, ".kody-engine", "definitions");
|
|
@@ -26446,11 +26821,15 @@ async function hydrateDefinitions(options) {
|
|
|
26446
26821
|
fs50.mkdirSync(path51.join(staging, "agents"), { recursive: true });
|
|
26447
26822
|
fs50.mkdirSync(path51.join(staging, "capabilities"), { recursive: true });
|
|
26448
26823
|
fs50.mkdirSync(path51.join(staging, "goals"), { recursive: true });
|
|
26824
|
+
fs50.mkdirSync(path51.join(staging, "implementations"), { recursive: true });
|
|
26825
|
+
fs50.mkdirSync(path51.join(staging, "shared"), { recursive: true });
|
|
26449
26826
|
try {
|
|
26450
|
-
const [capabilities, agents, goals] = await Promise.all([
|
|
26827
|
+
const [capabilities, agents, goals, implementations, assets] = await Promise.all([
|
|
26451
26828
|
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
26452
26829
|
options.backend.listDefinitions(options.tenantId, "agent"),
|
|
26453
|
-
options.backend.listDefinitions(options.tenantId, "goal")
|
|
26830
|
+
options.backend.listDefinitions(options.tenantId, "goal"),
|
|
26831
|
+
options.backend.listDefinitions(options.tenantId, "implementation"),
|
|
26832
|
+
options.backend.listDefinitions(options.tenantId, "asset")
|
|
26454
26833
|
]);
|
|
26455
26834
|
const versions = {};
|
|
26456
26835
|
for (const definition of capabilities) {
|
|
@@ -26465,6 +26844,14 @@ async function hydrateDefinitions(options) {
|
|
|
26465
26844
|
writeDefinition(staging, "goal", definition);
|
|
26466
26845
|
versions[`goal:${definition.slug}`] = definition.version;
|
|
26467
26846
|
}
|
|
26847
|
+
for (const definition of implementations) {
|
|
26848
|
+
writeDefinition(staging, "implementation", definition);
|
|
26849
|
+
versions[`implementation:${definition.slug}`] = definition.version;
|
|
26850
|
+
}
|
|
26851
|
+
for (const definition of assets) {
|
|
26852
|
+
writeDefinition(staging, "asset", definition);
|
|
26853
|
+
versions[`asset:${definition.slug}`] = definition.version;
|
|
26854
|
+
}
|
|
26468
26855
|
const manifest = {
|
|
26469
26856
|
schemaVersion: 1,
|
|
26470
26857
|
tenantId: options.tenantId,
|
|
@@ -27095,14 +27482,14 @@ function sendJson2(res, status, body) {
|
|
|
27095
27482
|
res.end(JSON.stringify(body));
|
|
27096
27483
|
}
|
|
27097
27484
|
function readJsonBody2(req) {
|
|
27098
|
-
return new Promise((
|
|
27485
|
+
return new Promise((resolve19, reject) => {
|
|
27099
27486
|
const chunks = [];
|
|
27100
27487
|
req.on("data", (c) => chunks.push(c));
|
|
27101
27488
|
req.on("end", () => {
|
|
27102
27489
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
27103
|
-
if (!raw.trim()) return
|
|
27490
|
+
if (!raw.trim()) return resolve19({});
|
|
27104
27491
|
try {
|
|
27105
|
-
|
|
27492
|
+
resolve19(JSON.parse(raw));
|
|
27106
27493
|
} catch (err) {
|
|
27107
27494
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
27108
27495
|
}
|
|
@@ -27313,10 +27700,10 @@ async function poolServe() {
|
|
|
27313
27700
|
}
|
|
27314
27701
|
});
|
|
27315
27702
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
27316
|
-
await new Promise((
|
|
27703
|
+
await new Promise((resolve19) => {
|
|
27317
27704
|
server.listen(apiPort, apiHost, () => {
|
|
27318
27705
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
27319
|
-
|
|
27706
|
+
resolve19();
|
|
27320
27707
|
});
|
|
27321
27708
|
});
|
|
27322
27709
|
if (loopTickEnabled) void runLoopTick();
|
|
@@ -27356,17 +27743,17 @@ function authOk2(req, expected) {
|
|
|
27356
27743
|
return false;
|
|
27357
27744
|
}
|
|
27358
27745
|
function readJsonBody3(req) {
|
|
27359
|
-
return new Promise((
|
|
27746
|
+
return new Promise((resolve19, reject) => {
|
|
27360
27747
|
const chunks = [];
|
|
27361
27748
|
req.on("data", (c) => chunks.push(c));
|
|
27362
27749
|
req.on("end", () => {
|
|
27363
27750
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
27364
27751
|
if (!raw.trim()) {
|
|
27365
|
-
|
|
27752
|
+
resolve19({});
|
|
27366
27753
|
return;
|
|
27367
27754
|
}
|
|
27368
27755
|
try {
|
|
27369
|
-
|
|
27756
|
+
resolve19(JSON.parse(raw));
|
|
27370
27757
|
} catch (err) {
|
|
27371
27758
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
27372
27759
|
}
|
|
@@ -27500,13 +27887,13 @@ async function defaultRunJob(job) {
|
|
|
27500
27887
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
27501
27888
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
27502
27889
|
};
|
|
27503
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
27890
|
+
const run = (cmd, args, cwd) => new Promise((resolve19) => {
|
|
27504
27891
|
const child = spawn9(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
27505
|
-
child.on("exit", (code) =>
|
|
27892
|
+
child.on("exit", (code) => resolve19(code ?? 0));
|
|
27506
27893
|
child.on("error", (err) => {
|
|
27507
27894
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
27508
27895
|
`);
|
|
27509
|
-
|
|
27896
|
+
resolve19(1);
|
|
27510
27897
|
});
|
|
27511
27898
|
});
|
|
27512
27899
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -27582,11 +27969,11 @@ async function runnerServe() {
|
|
|
27582
27969
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
27583
27970
|
const server = buildServer2({ apiKey });
|
|
27584
27971
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
27585
|
-
await new Promise((
|
|
27972
|
+
await new Promise((resolve19) => {
|
|
27586
27973
|
server.listen(port, host, () => {
|
|
27587
27974
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
27588
27975
|
`);
|
|
27589
|
-
|
|
27976
|
+
resolve19();
|
|
27590
27977
|
});
|
|
27591
27978
|
});
|
|
27592
27979
|
const shutdown = (signal) => {
|
|
@@ -27655,14 +28042,14 @@ async function serve(opts) {
|
|
|
27655
28042
|
`);
|
|
27656
28043
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
27657
28044
|
const child = spawn10("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
27658
|
-
const exitCode = await new Promise((
|
|
27659
|
-
child.on("exit", (code) =>
|
|
28045
|
+
const exitCode = await new Promise((resolve19) => {
|
|
28046
|
+
child.on("exit", (code) => resolve19(code ?? 0));
|
|
27660
28047
|
child.on("error", (err) => {
|
|
27661
28048
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
27662
28049
|
`);
|
|
27663
28050
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
27664
28051
|
`);
|
|
27665
|
-
|
|
28052
|
+
resolve19(1);
|
|
27666
28053
|
});
|
|
27667
28054
|
});
|
|
27668
28055
|
killProxy();
|