@kody-ade/kody-engine 0.4.429 → 0.4.431
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 +439 -55
- 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/package.json +26 -26
- 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.431",
|
|
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",
|
|
@@ -52,8 +52,9 @@ var init_package = __esm({
|
|
|
52
52
|
dependencies: {
|
|
53
53
|
"@actions/cache": "^6.0.0",
|
|
54
54
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
55
|
-
"@kody-ade/agency-domain": "0.5.
|
|
55
|
+
"@kody-ade/agency-domain": "0.5.1",
|
|
56
56
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
57
|
+
ajv: "^8.18.0",
|
|
57
58
|
convex: "^1.17.0",
|
|
58
59
|
zod: "^4.0.0"
|
|
59
60
|
},
|
|
@@ -255,6 +256,7 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
255
256
|
...parsePerImplementationReasoningEffort(agent.perImplementationReasoningEffort),
|
|
256
257
|
...parseAgentReasoningEffort(agent.reasoningEffort)
|
|
257
258
|
},
|
|
259
|
+
execution: parseExecutionConfig(raw.execution),
|
|
258
260
|
issueContext: parseIssueContext(raw.issueContext),
|
|
259
261
|
testRequirements: parseTestRequirements(raw.testRequirements),
|
|
260
262
|
defaultImplementation: typeof raw.defaultImplementation === "string" && raw.defaultImplementation.length > 0 ? raw.defaultImplementation : "run",
|
|
@@ -267,6 +269,18 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
267
269
|
access: parseAccessConfig(raw.access)
|
|
268
270
|
};
|
|
269
271
|
}
|
|
272
|
+
function parseExecutionConfig(value) {
|
|
273
|
+
const execution = recordValue(value);
|
|
274
|
+
const bindings = recordValue(execution?.capabilityBindings);
|
|
275
|
+
if (!bindings) return void 0;
|
|
276
|
+
const capabilityBindings = {};
|
|
277
|
+
for (const [capabilityId, implementationId] of Object.entries(bindings)) {
|
|
278
|
+
if (/^[a-z][a-z0-9-]*$/.test(capabilityId) && typeof implementationId === "string" && /^[a-z][a-z0-9-]*$/.test(implementationId)) {
|
|
279
|
+
capabilityBindings[capabilityId] = implementationId;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return Object.keys(capabilityBindings).length > 0 ? { capabilityBindings } : void 0;
|
|
283
|
+
}
|
|
270
284
|
function parseAccessConfig(raw) {
|
|
271
285
|
if (raw === void 0 || raw === null) {
|
|
272
286
|
return { allowedAssociations: [...DEFAULT_ALLOWED_ASSOCIATIONS] };
|
|
@@ -1631,10 +1645,71 @@ var init_issue = __esm({
|
|
|
1631
1645
|
}
|
|
1632
1646
|
});
|
|
1633
1647
|
|
|
1648
|
+
// src/agency/implementation-resolution.ts
|
|
1649
|
+
function resolveCapabilityImplementation(input) {
|
|
1650
|
+
const compatible = input.implementations.filter(
|
|
1651
|
+
(implementation) => implementation.capabilityRef.id === input.capabilityId && implementation.compatibleCapabilityRevision === input.capabilityRevision
|
|
1652
|
+
);
|
|
1653
|
+
if (input.explicitOverride) {
|
|
1654
|
+
if (!input.authorizeOverride?.(input.explicitOverride)) {
|
|
1655
|
+
throw new ImplementationResolutionError(`Implementation override "${input.explicitOverride}" is not authorized`);
|
|
1656
|
+
}
|
|
1657
|
+
return selectNamed(input.explicitOverride, input, compatible, "override");
|
|
1658
|
+
}
|
|
1659
|
+
if (input.repositoryBinding) {
|
|
1660
|
+
return selectNamed(input.repositoryBinding, input, compatible, "repository binding");
|
|
1661
|
+
}
|
|
1662
|
+
if (compatible.length === 1) return compatible[0];
|
|
1663
|
+
if (compatible.length === 0) {
|
|
1664
|
+
throw new ImplementationResolutionError(
|
|
1665
|
+
`No compatible Implementation is available for Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
throw new ImplementationResolutionError(
|
|
1669
|
+
`Capability "${input.capabilityId}" has ${compatible.length} compatible Implementations; configure a repository binding`
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
function selectNamed(id, input, compatible, source) {
|
|
1673
|
+
const known = input.implementations.find((implementation) => implementation.id === id);
|
|
1674
|
+
if (!known) {
|
|
1675
|
+
throw new ImplementationResolutionError(`Implementation ${source} "${id}" is not available`);
|
|
1676
|
+
}
|
|
1677
|
+
const selected = compatible.find((implementation) => implementation.id === id);
|
|
1678
|
+
if (!selected) {
|
|
1679
|
+
throw new ImplementationResolutionError(
|
|
1680
|
+
`Implementation ${source} "${id}" is not compatible with Capability "${input.capabilityId}" at revision "${input.capabilityRevision}"`
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
return selected;
|
|
1684
|
+
}
|
|
1685
|
+
var ImplementationResolutionError;
|
|
1686
|
+
var init_implementation_resolution = __esm({
|
|
1687
|
+
"src/agency/implementation-resolution.ts"() {
|
|
1688
|
+
"use strict";
|
|
1689
|
+
ImplementationResolutionError = class extends Error {
|
|
1690
|
+
constructor(message) {
|
|
1691
|
+
super(message);
|
|
1692
|
+
this.name = "ImplementationResolutionError";
|
|
1693
|
+
}
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1634
1698
|
// src/capabilityFolders.ts
|
|
1635
1699
|
import * as fs4 from "fs";
|
|
1636
1700
|
import * as path5 from "path";
|
|
1637
1701
|
function capabilityOutputConditionPaths(config) {
|
|
1702
|
+
if (config.outputSchema) {
|
|
1703
|
+
const properties = isPlainObject(config.outputSchema.properties) ? config.outputSchema.properties : void 0;
|
|
1704
|
+
const factContract = isPlainObject(properties?.facts) ? properties.facts : void 0;
|
|
1705
|
+
const facts = isPlainObject(factContract?.properties) ? factContract.properties : void 0;
|
|
1706
|
+
return /* @__PURE__ */ new Set([
|
|
1707
|
+
...properties?.status ? ["result.status"] : [],
|
|
1708
|
+
...properties?.summary ? ["result.summary"] : [],
|
|
1709
|
+
...properties?.resultClass ? ["result.resultClass"] : [],
|
|
1710
|
+
...Object.keys(facts ?? {}).map((fact) => `result.facts.${fact}`)
|
|
1711
|
+
]);
|
|
1712
|
+
}
|
|
1638
1713
|
const result = config.output?.result;
|
|
1639
1714
|
if (!result) return /* @__PURE__ */ new Set();
|
|
1640
1715
|
return /* @__PURE__ */ new Set([
|
|
@@ -1655,16 +1730,19 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
1655
1730
|
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
1731
|
}
|
|
1657
1732
|
function isCapabilityFolder(dir) {
|
|
1658
|
-
return fs4.existsSync(path5.join(dir, CAPABILITY_PROFILE_FILE)) && fs4.existsSync(path5.join(dir, CAPABILITY_BODY_FILE));
|
|
1733
|
+
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
1734
|
}
|
|
1660
1735
|
function readCapabilityFolder(root, slug) {
|
|
1661
1736
|
const dir = path5.join(root, slug);
|
|
1662
|
-
const
|
|
1737
|
+
const definitionPath = path5.join(dir, CAPABILITY_DEFINITION_FILE);
|
|
1738
|
+
const legacyProfilePath = path5.join(dir, CAPABILITY_PROFILE_FILE);
|
|
1739
|
+
const profilePath = fs4.existsSync(definitionPath) ? definitionPath : legacyProfilePath;
|
|
1663
1740
|
const bodyPath = path5.join(dir, CAPABILITY_BODY_FILE);
|
|
1664
1741
|
if (!fs4.existsSync(profilePath) || !fs4.statSync(profilePath).isFile()) return null;
|
|
1665
1742
|
if (!fs4.existsSync(bodyPath) || !fs4.statSync(bodyPath).isFile()) return null;
|
|
1666
1743
|
try {
|
|
1667
|
-
const
|
|
1744
|
+
const rawDefinition = JSON.parse(fs4.readFileSync(profilePath, "utf-8"));
|
|
1745
|
+
const rawProfile = rawDefinition;
|
|
1668
1746
|
const rawBody = fs4.readFileSync(bodyPath, "utf-8");
|
|
1669
1747
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
1670
1748
|
return {
|
|
@@ -1700,11 +1778,12 @@ function parseCapabilityConfig(raw) {
|
|
|
1700
1778
|
capabilityToolMode: parseCapabilityToolMode(raw.capabilityToolMode),
|
|
1701
1779
|
implementations,
|
|
1702
1780
|
role: stringField(raw.role),
|
|
1703
|
-
describe: stringField(raw.describe),
|
|
1781
|
+
describe: stringField(raw.describe) ?? stringField(raw.purpose),
|
|
1704
1782
|
stage: stringField(raw.stage),
|
|
1705
1783
|
readsFrom: stringList(raw.readsFrom ?? raw.reads_from),
|
|
1706
1784
|
writesTo: stringList(raw.writesTo ?? raw.writes_to),
|
|
1707
1785
|
output: parseCapabilityOutput(raw.output),
|
|
1786
|
+
outputSchema: isPlainObject(raw.outputSchema) ? raw.outputSchema : void 0,
|
|
1708
1787
|
workflow: parseCapabilityWorkflow(raw.workflow)
|
|
1709
1788
|
};
|
|
1710
1789
|
}
|
|
@@ -1873,11 +1952,12 @@ function isSafeSlug(value) {
|
|
|
1873
1952
|
function isSafeStepId(value) {
|
|
1874
1953
|
return /^[A-Za-z][A-Za-z0-9_-]*$/.test(value) && !value.includes("..");
|
|
1875
1954
|
}
|
|
1876
|
-
var CAPABILITY_PROFILE_FILE, CAPABILITY_BODY_FILE;
|
|
1955
|
+
var CAPABILITY_PROFILE_FILE, CAPABILITY_DEFINITION_FILE, CAPABILITY_BODY_FILE;
|
|
1877
1956
|
var init_capabilityFolders = __esm({
|
|
1878
1957
|
"src/capabilityFolders.ts"() {
|
|
1879
1958
|
"use strict";
|
|
1880
1959
|
CAPABILITY_PROFILE_FILE = "profile.json";
|
|
1960
|
+
CAPABILITY_DEFINITION_FILE = "definition.json";
|
|
1881
1961
|
CAPABILITY_BODY_FILE = "capability.md";
|
|
1882
1962
|
}
|
|
1883
1963
|
});
|
|
@@ -1903,6 +1983,9 @@ function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
|
|
|
1903
1983
|
function capabilitiesRoot(cwd = process.cwd()) {
|
|
1904
1984
|
return path6.join(definitionsRoot(cwd), "capabilities");
|
|
1905
1985
|
}
|
|
1986
|
+
function implementationsRoot(cwd = process.cwd()) {
|
|
1987
|
+
return path6.join(definitionsRoot(cwd), "implementations");
|
|
1988
|
+
}
|
|
1906
1989
|
function agentsRoot(cwd = process.cwd()) {
|
|
1907
1990
|
return path6.join(definitionsRoot(cwd), "agents");
|
|
1908
1991
|
}
|
|
@@ -1913,6 +1996,7 @@ var init_definition_paths = __esm({
|
|
|
1913
1996
|
});
|
|
1914
1997
|
|
|
1915
1998
|
// src/registry.ts
|
|
1999
|
+
import { createHash as createHash2 } from "crypto";
|
|
1916
2000
|
import * as fs6 from "fs";
|
|
1917
2001
|
import * as path7 from "path";
|
|
1918
2002
|
function getImplementationsRoot() {
|
|
@@ -1952,7 +2036,7 @@ function getImplementationRoots() {
|
|
|
1952
2036
|
return getImplementationRootsForCwd(process.cwd());
|
|
1953
2037
|
}
|
|
1954
2038
|
function getImplementationRootsForCwd(cwd) {
|
|
1955
|
-
return [
|
|
2039
|
+
return [implementationsRoot(cwd), getImplementationsRoot()];
|
|
1956
2040
|
}
|
|
1957
2041
|
function getCapabilityRoots(projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
1958
2042
|
return [projectCapabilitiesRoot, getBuiltinCapabilitiesRoot()];
|
|
@@ -1968,7 +2052,7 @@ function listImplementations(roots = getImplementationRoots()) {
|
|
|
1968
2052
|
for (const ent of entries) {
|
|
1969
2053
|
if (!ent.isDirectory()) continue;
|
|
1970
2054
|
if (seen.has(ent.name)) continue;
|
|
1971
|
-
const profilePath =
|
|
2055
|
+
const profilePath = implementationRuntimePath(root, ent.name);
|
|
1972
2056
|
if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, requireImplementationProfile)) {
|
|
1973
2057
|
out.push({ name: ent.name, profilePath });
|
|
1974
2058
|
seen.add(ent.name);
|
|
@@ -1985,7 +2069,7 @@ function resolveImplementationCandidates(name, roots = getImplementationRoots())
|
|
|
1985
2069
|
const rootList = typeof roots === "string" ? [roots] : roots;
|
|
1986
2070
|
const out = [];
|
|
1987
2071
|
for (const root of rootList) {
|
|
1988
|
-
const profilePath =
|
|
2072
|
+
const profilePath = implementationRuntimePath(root, name);
|
|
1989
2073
|
if (fs6.existsSync(profilePath) && fs6.statSync(profilePath).isFile() && isImplementationProfile(profilePath, isCapabilityRoot(root))) {
|
|
1990
2074
|
out.push(profilePath);
|
|
1991
2075
|
}
|
|
@@ -2023,9 +2107,43 @@ function resolveCapabilityFolder(slug, projectCapabilitiesRoot = getProjectCapab
|
|
|
2023
2107
|
function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2024
2108
|
const resolved = resolveCapabilityAction(action, projectCapabilitiesRoot);
|
|
2025
2109
|
if (!resolved) return null;
|
|
2110
|
+
const capability = resolveCapabilityFolder(resolved.capability, projectCapabilitiesRoot);
|
|
2111
|
+
if (capability && path7.basename(capability.profilePath) === "definition.json") {
|
|
2112
|
+
const schema = capability.rawProfile.inputSchema;
|
|
2113
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return [];
|
|
2114
|
+
const properties = schema.properties;
|
|
2115
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) return [];
|
|
2116
|
+
const required2 = new Set(
|
|
2117
|
+
Array.isArray(schema.required) ? schema.required.filter((value) => typeof value === "string") : []
|
|
2118
|
+
);
|
|
2119
|
+
return Object.entries(properties).map(([name, value]) => {
|
|
2120
|
+
const property = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2121
|
+
const type = property.type === "integer" ? "int" : property.type === "boolean" ? "bool" : Array.isArray(property.enum) ? "enum" : "string";
|
|
2122
|
+
return {
|
|
2123
|
+
name,
|
|
2124
|
+
flag: `--${name}`,
|
|
2125
|
+
type,
|
|
2126
|
+
required: required2.has(name),
|
|
2127
|
+
...type === "enum" && Array.isArray(property.enum) ? { values: property.enum.filter((item) => typeof item === "string") } : {},
|
|
2128
|
+
describe: typeof property.description === "string" ? property.description : name
|
|
2129
|
+
};
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2026
2132
|
return getProfileInputs(resolved.implementation);
|
|
2027
2133
|
}
|
|
2028
2134
|
function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
2135
|
+
if (path7.basename(capability.profilePath) === "definition.json") {
|
|
2136
|
+
const implementations = readExternalImplementations(cwd);
|
|
2137
|
+
const definition = JSON.parse(fs6.readFileSync(capability.profilePath, "utf-8"));
|
|
2138
|
+
const capabilityRevision = createHash2("sha256").update(canonical(definition)).digest("hex");
|
|
2139
|
+
const selected = resolveCapabilityImplementation({
|
|
2140
|
+
capabilityId: capability.slug,
|
|
2141
|
+
capabilityRevision,
|
|
2142
|
+
implementations,
|
|
2143
|
+
repositoryBinding: repositoryImplementationBinding(capability.slug, cwd)
|
|
2144
|
+
});
|
|
2145
|
+
return { implementation: selected.id, cliArgs: {} };
|
|
2146
|
+
}
|
|
2029
2147
|
const firstWorkflowStep = capability.config.workflow?.steps[0];
|
|
2030
2148
|
if (firstWorkflowStep) {
|
|
2031
2149
|
const implementation2 = firstWorkflowStep.implementation ?? firstWorkflowStep.capability;
|
|
@@ -2035,11 +2153,42 @@ function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
|
2035
2153
|
const cliArgs = implementationDeclaresInput(implementation, "capability", cwd) ? { capability: capability.slug } : {};
|
|
2036
2154
|
return { implementation, cliArgs };
|
|
2037
2155
|
}
|
|
2156
|
+
function repositoryImplementationBinding(capabilityId, cwd) {
|
|
2157
|
+
try {
|
|
2158
|
+
return loadConfig(cwd).execution?.capabilityBindings[capabilityId];
|
|
2159
|
+
} catch {
|
|
2160
|
+
return void 0;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
function readExternalImplementations(cwd) {
|
|
2164
|
+
const root = implementationsRoot(cwd);
|
|
2165
|
+
if (!fs6.existsSync(root)) return [];
|
|
2166
|
+
const definitions = [];
|
|
2167
|
+
for (const entry of fs6.readdirSync(root, { withFileTypes: true })) {
|
|
2168
|
+
if (!entry.isDirectory() || !isSafeName(entry.name)) continue;
|
|
2169
|
+
const definitionPath = path7.join(root, entry.name, "definition.json");
|
|
2170
|
+
if (!fs6.existsSync(definitionPath)) continue;
|
|
2171
|
+
try {
|
|
2172
|
+
const definition = JSON.parse(fs6.readFileSync(definitionPath, "utf-8"));
|
|
2173
|
+
definitions.push(definition);
|
|
2174
|
+
} catch {
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
return definitions;
|
|
2178
|
+
}
|
|
2179
|
+
function canonical(value) {
|
|
2180
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
2181
|
+
if (value && typeof value === "object") {
|
|
2182
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
2183
|
+
}
|
|
2184
|
+
return JSON.stringify(value);
|
|
2185
|
+
}
|
|
2038
2186
|
function implementationDeclaresInput(implementation, inputName, cwd = process.cwd()) {
|
|
2039
2187
|
const profilePath = resolveImplementation(implementation, getImplementationRootsForCwd(cwd));
|
|
2040
2188
|
if (!profilePath) return false;
|
|
2041
2189
|
try {
|
|
2042
|
-
const
|
|
2190
|
+
const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
2191
|
+
const raw = document.config ?? document;
|
|
2043
2192
|
if (!Array.isArray(raw.inputs)) return false;
|
|
2044
2193
|
return raw.inputs.some((entry) => {
|
|
2045
2194
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
|
|
@@ -2059,6 +2208,10 @@ function isCapabilityRoot(root) {
|
|
|
2059
2208
|
const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
|
|
2060
2209
|
return knownRoots.some((candidate) => candidate && path7.normalize(candidate) === normalized);
|
|
2061
2210
|
}
|
|
2211
|
+
function implementationRuntimePath(root, name) {
|
|
2212
|
+
const runtimePath = path7.join(root, name, "runtime.json");
|
|
2213
|
+
return fs6.existsSync(runtimePath) ? runtimePath : path7.join(root, name, CAPABILITY_PROFILE_FILE);
|
|
2214
|
+
}
|
|
2062
2215
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2063
2216
|
if (!requireImplementationProfile) return true;
|
|
2064
2217
|
try {
|
|
@@ -2126,8 +2279,10 @@ function getProfileInputs(name, roots = getImplementationRoots()) {
|
|
|
2126
2279
|
const profilePath = resolveImplementation(name, roots);
|
|
2127
2280
|
if (!profilePath) return null;
|
|
2128
2281
|
try {
|
|
2129
|
-
const
|
|
2130
|
-
if (!
|
|
2282
|
+
const document = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
2283
|
+
if (!document || typeof document !== "object") return [];
|
|
2284
|
+
const raw = "config" in document && document.config && typeof document.config === "object" ? document.config : document;
|
|
2285
|
+
if (!Array.isArray(raw.inputs)) return [];
|
|
2131
2286
|
return raw.inputs;
|
|
2132
2287
|
} catch {
|
|
2133
2288
|
return null;
|
|
@@ -2162,7 +2317,9 @@ var PUBLIC_IMPLEMENTATION_ROLES;
|
|
|
2162
2317
|
var init_registry = __esm({
|
|
2163
2318
|
"src/registry.ts"() {
|
|
2164
2319
|
"use strict";
|
|
2320
|
+
init_implementation_resolution();
|
|
2165
2321
|
init_capabilityFolders();
|
|
2322
|
+
init_config();
|
|
2166
2323
|
init_definition_paths();
|
|
2167
2324
|
PUBLIC_IMPLEMENTATION_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
2168
2325
|
}
|
|
@@ -2455,9 +2612,10 @@ function createStateBackendFromEnv(env = process.env, client) {
|
|
|
2455
2612
|
});
|
|
2456
2613
|
return Array.isArray(result) ? result : [];
|
|
2457
2614
|
},
|
|
2458
|
-
async getAgencyState(tenantId2, definitionId2) {
|
|
2615
|
+
async getAgencyState(tenantId2, kind, definitionId2) {
|
|
2459
2616
|
const result = await transport.query(anyApi.agencyModel.getState, {
|
|
2460
2617
|
tenantId: requireTenant(tenantId2),
|
|
2618
|
+
kind,
|
|
2461
2619
|
definitionId: requireNonEmpty(definitionId2, "definitionId")
|
|
2462
2620
|
});
|
|
2463
2621
|
return result ?? null;
|
|
@@ -4165,6 +4323,40 @@ var init_agencyBoundaryEval = __esm({
|
|
|
4165
4323
|
}
|
|
4166
4324
|
});
|
|
4167
4325
|
|
|
4326
|
+
// src/agency/capability-contract-validation.ts
|
|
4327
|
+
import Ajv from "ajv";
|
|
4328
|
+
function validateCapabilityContractValue(boundary, schema, value) {
|
|
4329
|
+
const validate = validator.compile(schema);
|
|
4330
|
+
if (!validate(value)) {
|
|
4331
|
+
throw new CapabilityContractValidationError(boundary, validate.errors ?? []);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
var validator, CapabilityContractValidationError;
|
|
4335
|
+
var init_capability_contract_validation = __esm({
|
|
4336
|
+
"src/agency/capability-contract-validation.ts"() {
|
|
4337
|
+
"use strict";
|
|
4338
|
+
validator = new Ajv({
|
|
4339
|
+
allErrors: true,
|
|
4340
|
+
strict: true,
|
|
4341
|
+
validateFormats: false
|
|
4342
|
+
});
|
|
4343
|
+
CapabilityContractValidationError = class extends Error {
|
|
4344
|
+
constructor(boundary, errors) {
|
|
4345
|
+
super(
|
|
4346
|
+
`Capability ${boundary} does not match its canonical contract: ${validator.errorsText([...errors], {
|
|
4347
|
+
separator: "; "
|
|
4348
|
+
})}`
|
|
4349
|
+
);
|
|
4350
|
+
this.boundary = boundary;
|
|
4351
|
+
this.errors = errors;
|
|
4352
|
+
this.name = "CapabilityContractValidationError";
|
|
4353
|
+
}
|
|
4354
|
+
boundary;
|
|
4355
|
+
errors;
|
|
4356
|
+
};
|
|
4357
|
+
}
|
|
4358
|
+
});
|
|
4359
|
+
|
|
4168
4360
|
// src/capabilityReport.ts
|
|
4169
4361
|
function parseCapabilityReportsFromText(text2) {
|
|
4170
4362
|
const reports = [];
|
|
@@ -4714,6 +4906,7 @@ var init_subagents = __esm({
|
|
|
4714
4906
|
});
|
|
4715
4907
|
|
|
4716
4908
|
// src/profile.ts
|
|
4909
|
+
import { createHash as createHash3 } from "crypto";
|
|
4717
4910
|
import * as fs20 from "fs";
|
|
4718
4911
|
import * as path19 from "path";
|
|
4719
4912
|
function loadProfile(profilePath) {
|
|
@@ -4729,7 +4922,8 @@ function loadProfile(profilePath) {
|
|
|
4729
4922
|
if (!raw || typeof raw !== "object") {
|
|
4730
4923
|
throw new ProfileError(profilePath, "profile must be a JSON object");
|
|
4731
4924
|
}
|
|
4732
|
-
const
|
|
4925
|
+
const document = raw;
|
|
4926
|
+
const r = compileRuntimeDocument(profilePath, document);
|
|
4733
4927
|
const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
|
|
4734
4928
|
if (unknownKeys.length > 0) {
|
|
4735
4929
|
process.stderr.write(
|
|
@@ -4876,6 +5070,67 @@ function loadProfile(profilePath) {
|
|
|
4876
5070
|
profile.subagentTemplates = captureSubagentTemplates(profile);
|
|
4877
5071
|
return profile;
|
|
4878
5072
|
}
|
|
5073
|
+
function compileRuntimeDocument(runtimePath, document) {
|
|
5074
|
+
if (path19.basename(runtimePath) !== "runtime.json") return document;
|
|
5075
|
+
if (document.adapter !== "kody-engine-profile") {
|
|
5076
|
+
throw new ProfileError(runtimePath, "unsupported runtime adapter document");
|
|
5077
|
+
}
|
|
5078
|
+
const implementationDir = path19.dirname(runtimePath);
|
|
5079
|
+
const implementation = readJsonObject(path19.join(implementationDir, "definition.json"), "Implementation definition");
|
|
5080
|
+
const definitionsRoot2 = path19.dirname(path19.dirname(implementationDir));
|
|
5081
|
+
const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
|
|
5082
|
+
if (typeof capabilityId !== "string" || !capabilityId) {
|
|
5083
|
+
throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
|
|
5084
|
+
}
|
|
5085
|
+
const capability = readJsonObject(
|
|
5086
|
+
path19.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
|
|
5087
|
+
"Capability definition"
|
|
5088
|
+
);
|
|
5089
|
+
const {
|
|
5090
|
+
adapter: _adapter,
|
|
5091
|
+
inputBindings: _inputBindings,
|
|
5092
|
+
outputBindings: _outputBindings,
|
|
5093
|
+
requirements: _requirements,
|
|
5094
|
+
config: nestedConfig,
|
|
5095
|
+
...inlineConfig
|
|
5096
|
+
} = document;
|
|
5097
|
+
const config = nestedConfig && typeof nestedConfig === "object" && !Array.isArray(nestedConfig) ? nestedConfig : inlineConfig;
|
|
5098
|
+
const agentRef = implementation.agentRef && typeof implementation.agentRef === "object" && !Array.isArray(implementation.agentRef) ? implementation.agentRef.id : void 0;
|
|
5099
|
+
return {
|
|
5100
|
+
...config,
|
|
5101
|
+
name: implementation.id,
|
|
5102
|
+
action: capability.action,
|
|
5103
|
+
describe: capability.purpose,
|
|
5104
|
+
inputs: config.inputs ?? [],
|
|
5105
|
+
agent: agentRef,
|
|
5106
|
+
canonicalContract: {
|
|
5107
|
+
capabilityId,
|
|
5108
|
+
capabilityRevision: createHash3("sha256").update(canonical2(capability)).digest("hex"),
|
|
5109
|
+
implementationId: String(implementation.id),
|
|
5110
|
+
implementationRevision: createHash3("sha256").update(canonical2(implementation)).digest("hex"),
|
|
5111
|
+
inputSchema: capability.inputSchema,
|
|
5112
|
+
outputSchema: capability.outputSchema
|
|
5113
|
+
}
|
|
5114
|
+
};
|
|
5115
|
+
}
|
|
5116
|
+
function canonical2(value) {
|
|
5117
|
+
if (Array.isArray(value)) return `[${value.map(canonical2).join(",")}]`;
|
|
5118
|
+
if (value && typeof value === "object") {
|
|
5119
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonical2(item)}`).join(",")}}`;
|
|
5120
|
+
}
|
|
5121
|
+
return JSON.stringify(value);
|
|
5122
|
+
}
|
|
5123
|
+
function readJsonObject(filePath, label) {
|
|
5124
|
+
try {
|
|
5125
|
+
const value = JSON.parse(fs20.readFileSync(filePath, "utf-8"));
|
|
5126
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5127
|
+
throw new Error("must be an object");
|
|
5128
|
+
}
|
|
5129
|
+
return value;
|
|
5130
|
+
} catch (error) {
|
|
5131
|
+
throw new ProfileError(filePath, `${label} is invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
4879
5134
|
function parseCapabilityToolMode2(profilePath, raw) {
|
|
4880
5135
|
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
4881
5136
|
if (raw === "lock" || raw === "append") return raw;
|
|
@@ -5255,6 +5510,7 @@ var init_profile = __esm({
|
|
|
5255
5510
|
VALID_CONTAINER_CHILD_TARGETS = /* @__PURE__ */ new Set(["issue", "pr"]);
|
|
5256
5511
|
VALID_PHASES = /* @__PURE__ */ new Set(["research", "planning", "implementing", "reviewing", "shipped", "failed", "idle"]);
|
|
5257
5512
|
KNOWN_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
5513
|
+
"canonicalContract",
|
|
5258
5514
|
"name",
|
|
5259
5515
|
"action",
|
|
5260
5516
|
"implementation",
|
|
@@ -6898,6 +7154,9 @@ function runIndexRowFromJobContext(input) {
|
|
|
6898
7154
|
capability: stringValue(input.data.jobCapability) ?? void 0,
|
|
6899
7155
|
workflow: workflow ?? void 0,
|
|
6900
7156
|
implementation: stringValue(input.data.selectedImplementation) ?? input.profileName,
|
|
7157
|
+
parentRunId: stringValue(input.data.parentRunId) ?? void 0,
|
|
7158
|
+
capabilityRevision: stringValue(input.data.capabilityRevision) ?? void 0,
|
|
7159
|
+
implementationRevision: stringValue(input.data.implementationRevision) ?? void 0,
|
|
6901
7160
|
agent: stringValue(input.data.jobAgent) ?? input.profile.agent ?? void 0,
|
|
6902
7161
|
model: stringValue(input.data.jobModel) ?? void 0,
|
|
6903
7162
|
modelProvider: stringValue(input.data.jobModelProvider) ?? void 0,
|
|
@@ -6962,7 +7221,7 @@ function statusFromExitCode(exitCode) {
|
|
|
6962
7221
|
return exitCode === 0 ? "success" : "failed";
|
|
6963
7222
|
}
|
|
6964
7223
|
function isRunSubjectType(value) {
|
|
6965
|
-
return value === "goal" || value === "loop" || value === "workflow";
|
|
7224
|
+
return value === "goal" || value === "loop" || value === "workflow" || value === "capability";
|
|
6966
7225
|
}
|
|
6967
7226
|
function stagedRunIndexRows(data) {
|
|
6968
7227
|
const value = data[STAGED_RUN_INDEX_ROWS_KEY];
|
|
@@ -8471,9 +8730,9 @@ function goalInstanceTime(state) {
|
|
|
8471
8730
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
8472
8731
|
}
|
|
8473
8732
|
function loadGoalTemplate(cwd, targetId) {
|
|
8474
|
-
return
|
|
8733
|
+
return readJsonObject2(path24.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
|
|
8475
8734
|
}
|
|
8476
|
-
function
|
|
8735
|
+
function readJsonObject2(filePath) {
|
|
8477
8736
|
if (!fs27.existsSync(filePath)) return null;
|
|
8478
8737
|
const parsed = JSON.parse(fs27.readFileSync(filePath, "utf8"));
|
|
8479
8738
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -9503,6 +9762,7 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9503
9762
|
capability2,
|
|
9504
9763
|
slug,
|
|
9505
9764
|
backend,
|
|
9765
|
+
opts.cwd,
|
|
9506
9766
|
opts.previousScheduleState?.capabilities[slug]
|
|
9507
9767
|
);
|
|
9508
9768
|
statuses[slug] = status;
|
|
@@ -9557,21 +9817,19 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9557
9817
|
}
|
|
9558
9818
|
};
|
|
9559
9819
|
}
|
|
9560
|
-
async function describeCapabilitySchedule(capability, slug, backend, previous) {
|
|
9820
|
+
async function describeCapabilitySchedule(capability, slug, backend, cwd, previous) {
|
|
9561
9821
|
if (!capability) return { slug, state: "blocked", reason: "capability folder missing" };
|
|
9562
|
-
|
|
9563
|
-
if (config.disabled === true) {
|
|
9822
|
+
if (capability.config.disabled === true) {
|
|
9564
9823
|
return { slug, title: capability.title, state: "disabled", reason: "disabled" };
|
|
9565
9824
|
}
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
}
|
|
9569
|
-
if (config.implementations && config.implementations.length > 1) {
|
|
9825
|
+
try {
|
|
9826
|
+
resolveCapabilityExecution(capability, cwd);
|
|
9827
|
+
} catch (error) {
|
|
9570
9828
|
return {
|
|
9571
9829
|
slug,
|
|
9572
9830
|
title: capability.title,
|
|
9573
9831
|
state: "blocked",
|
|
9574
|
-
reason:
|
|
9832
|
+
reason: error instanceof Error ? error.message : "Implementation unavailable"
|
|
9575
9833
|
};
|
|
9576
9834
|
}
|
|
9577
9835
|
let lastFiredAt = validIso(previous?.lastFiredAt) ? previous?.lastFiredAt : void 0;
|
|
@@ -13028,11 +13286,13 @@ import {
|
|
|
13028
13286
|
createWorkflowDefinition,
|
|
13029
13287
|
relationshipIssues
|
|
13030
13288
|
} from "@kody-ade/agency-domain";
|
|
13031
|
-
function goalProgressFromOutputs(definition, outputs) {
|
|
13289
|
+
function goalProgressFromOutputs(definition, revision, outputs) {
|
|
13032
13290
|
const required2 = definition.objective.requiredEvidence;
|
|
13033
13291
|
if (required2.length === 0) return 1;
|
|
13034
13292
|
const satisfied = new Set(
|
|
13035
|
-
outputs.filter(
|
|
13293
|
+
outputs.filter(
|
|
13294
|
+
(output) => output.kind === "evidence" && output.value === true && output.parentRef?.kind === "goal" && output.parentRef.id === definition.id && output.parentRef.revision === revision
|
|
13295
|
+
).map((output) => output.key)
|
|
13036
13296
|
);
|
|
13037
13297
|
return required2.filter((key) => satisfied.has(key)).length / required2.length;
|
|
13038
13298
|
}
|
|
@@ -13123,7 +13383,11 @@ var init_agencyModelRepository = __esm({
|
|
|
13123
13383
|
definition: record2.definition,
|
|
13124
13384
|
revision: record2.revision,
|
|
13125
13385
|
state: parseState(
|
|
13126
|
-
await this.backend.getAgencyState(
|
|
13386
|
+
await this.backend.getAgencyState(
|
|
13387
|
+
this.tenantId,
|
|
13388
|
+
record2.kind,
|
|
13389
|
+
record2.definition.id
|
|
13390
|
+
),
|
|
13127
13391
|
record2.definition,
|
|
13128
13392
|
record2.kind
|
|
13129
13393
|
)
|
|
@@ -13169,7 +13433,11 @@ var init_agencyModelRepository = __esm({
|
|
|
13169
13433
|
const state = createGoalState({
|
|
13170
13434
|
definitionId: record2.definition.id,
|
|
13171
13435
|
lifecycle: previous?.lifecycle ?? "draft",
|
|
13172
|
-
progress: goalProgressFromOutputs(
|
|
13436
|
+
progress: goalProgressFromOutputs(
|
|
13437
|
+
record2.definition,
|
|
13438
|
+
record2.revision,
|
|
13439
|
+
await this.listOutputs()
|
|
13440
|
+
),
|
|
13173
13441
|
blockers: previous?.blockers ?? [],
|
|
13174
13442
|
updatedAt
|
|
13175
13443
|
});
|
|
@@ -13187,8 +13455,7 @@ function decideTrigger(input) {
|
|
|
13187
13455
|
return { kind: "skip", reason: `loop is ${input.state.lifecycle}` };
|
|
13188
13456
|
}
|
|
13189
13457
|
const trigger = input.definition.trigger;
|
|
13190
|
-
if (
|
|
13191
|
-
if (!input.manualRequestId?.trim()) return { kind: "skip", reason: "manual trigger was not requested" };
|
|
13458
|
+
if (input.manualRequestId?.trim()) {
|
|
13192
13459
|
return {
|
|
13193
13460
|
kind: "fire",
|
|
13194
13461
|
reason: "manual trigger was requested",
|
|
@@ -13196,6 +13463,9 @@ function decideTrigger(input) {
|
|
|
13196
13463
|
idempotencyKey: `${input.definition.id}:manual:${input.manualRequestId.trim()}`
|
|
13197
13464
|
};
|
|
13198
13465
|
}
|
|
13466
|
+
if (trigger.type === "manual") {
|
|
13467
|
+
return { kind: "skip", reason: "manual trigger was not requested" };
|
|
13468
|
+
}
|
|
13199
13469
|
if (trigger.type !== "schedule") {
|
|
13200
13470
|
return { kind: "skip", reason: `${trigger.type} trigger is not enabled yet` };
|
|
13201
13471
|
}
|
|
@@ -13229,7 +13499,7 @@ var init_triggerDispatcher = __esm({
|
|
|
13229
13499
|
});
|
|
13230
13500
|
|
|
13231
13501
|
// src/goal/policyResolver.ts
|
|
13232
|
-
import { createHash as
|
|
13502
|
+
import { createHash as createHash4 } from "crypto";
|
|
13233
13503
|
function resolveDispatchPolicy(input) {
|
|
13234
13504
|
const operation = input.catalog.operations.get(input.owner.definition.operationId);
|
|
13235
13505
|
if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
|
|
@@ -13247,7 +13517,7 @@ function resolveDispatchPolicy(input) {
|
|
|
13247
13517
|
const snapshotValue = { policy, constraints };
|
|
13248
13518
|
return {
|
|
13249
13519
|
snapshot: {
|
|
13250
|
-
hash:
|
|
13520
|
+
hash: createHash4("sha256").update(stableJson(snapshotValue)).digest("hex"),
|
|
13251
13521
|
...snapshotValue
|
|
13252
13522
|
},
|
|
13253
13523
|
operation,
|
|
@@ -13331,7 +13601,15 @@ async function dispatchAgencyLoopsWith(input) {
|
|
|
13331
13601
|
);
|
|
13332
13602
|
const results = [];
|
|
13333
13603
|
for (const record2 of loops) {
|
|
13334
|
-
|
|
13604
|
+
if (input.manualRequest && record2.definition.id !== input.manualRequest.loopId) {
|
|
13605
|
+
continue;
|
|
13606
|
+
}
|
|
13607
|
+
const decision = decideTrigger({
|
|
13608
|
+
definition: record2.definition,
|
|
13609
|
+
state: record2.state,
|
|
13610
|
+
now: input.now,
|
|
13611
|
+
...input.manualRequest ? { manualRequestId: input.manualRequest.requestId } : {}
|
|
13612
|
+
});
|
|
13335
13613
|
const now = input.now.toISOString();
|
|
13336
13614
|
if (decision.kind === "skip") {
|
|
13337
13615
|
const key = `${record2.definition.id}:skip:${now}`;
|
|
@@ -13493,14 +13771,25 @@ async function dispatchAgencyLoopsWith(input) {
|
|
|
13493
13771
|
const goalRecord = record2.definition.targetRef.kind === "goal" ? records.find(
|
|
13494
13772
|
(candidate) => "executionRef" in candidate.definition && candidate.definition.id === record2.definition.targetRef.id
|
|
13495
13773
|
) : void 0;
|
|
13496
|
-
if (succeeded &&
|
|
13774
|
+
if (succeeded && finalRunId) {
|
|
13497
13775
|
await appendCapabilityOutputs(
|
|
13498
13776
|
repository,
|
|
13499
13777
|
finalRunId,
|
|
13500
13778
|
target.reference,
|
|
13779
|
+
goalRecord ? {
|
|
13780
|
+
kind: "goal",
|
|
13781
|
+
id: goalRecord.definition.id,
|
|
13782
|
+
revision: goalRecord.revision
|
|
13783
|
+
} : {
|
|
13784
|
+
kind: "loop",
|
|
13785
|
+
id: record2.definition.id,
|
|
13786
|
+
revision: record2.revision
|
|
13787
|
+
},
|
|
13501
13788
|
finalCapabilityResults,
|
|
13502
13789
|
finishedAt
|
|
13503
13790
|
);
|
|
13791
|
+
}
|
|
13792
|
+
if (succeeded && goalRecord) {
|
|
13504
13793
|
await repository.refreshGoalProgress(goalRecord, finishedAt);
|
|
13505
13794
|
}
|
|
13506
13795
|
await input.backend.finishAgencyDispatch(
|
|
@@ -13581,7 +13870,7 @@ async function runAttempt(run, job, timeoutSeconds) {
|
|
|
13581
13870
|
if (timer) clearTimeout(timer);
|
|
13582
13871
|
}
|
|
13583
13872
|
}
|
|
13584
|
-
async function appendCapabilityOutputs(repository, runId, producer, results, createdAt) {
|
|
13873
|
+
async function appendCapabilityOutputs(repository, runId, producer, parentRef, results, createdAt) {
|
|
13585
13874
|
for (const result of results) {
|
|
13586
13875
|
const outputs = [
|
|
13587
13876
|
...Object.entries(result.facts).map(([key, value]) => ({ kind: "fact", key, value })),
|
|
@@ -13601,6 +13890,7 @@ async function appendCapabilityOutputs(repository, runId, producer, results, cre
|
|
|
13601
13890
|
...output,
|
|
13602
13891
|
runId,
|
|
13603
13892
|
producer: { kind: producer.kind, id: producer.id },
|
|
13893
|
+
parentRef,
|
|
13604
13894
|
contract: "capability-result/v1",
|
|
13605
13895
|
createdAt
|
|
13606
13896
|
});
|
|
@@ -13632,10 +13922,17 @@ var init_dispatchAgencyLoops = __esm({
|
|
|
13632
13922
|
const tenantId2 = repositoryTenant(ctx.config);
|
|
13633
13923
|
if (!tenantId2) throw new Error("Repository identity is required for Agency Loop dispatch");
|
|
13634
13924
|
const backend = createStateBackendFromEnv();
|
|
13925
|
+
const requestedLoopId = typeof ctx.args.loop === "string" ? ctx.args.loop.trim() : "";
|
|
13635
13926
|
const results = await dispatchAgencyLoopsWith({
|
|
13636
13927
|
tenantId: tenantId2,
|
|
13637
13928
|
backend,
|
|
13638
13929
|
now: /* @__PURE__ */ new Date(),
|
|
13930
|
+
...requestedLoopId ? {
|
|
13931
|
+
manualRequest: {
|
|
13932
|
+
loopId: requestedLoopId,
|
|
13933
|
+
requestId: process.env.GITHUB_RUN_ID?.trim() || `local-${randomUUID()}`
|
|
13934
|
+
}
|
|
13935
|
+
} : {},
|
|
13639
13936
|
run: (job, abortController) => runJob(job, {
|
|
13640
13937
|
cwd: ctx.cwd,
|
|
13641
13938
|
config: ctx.config,
|
|
@@ -15491,9 +15788,9 @@ var init_kodyVariables = __esm({
|
|
|
15491
15788
|
});
|
|
15492
15789
|
|
|
15493
15790
|
// src/backendVault.ts
|
|
15494
|
-
import { createDecipheriv, createHash as
|
|
15791
|
+
import { createDecipheriv, createHash as createHash5 } from "crypto";
|
|
15495
15792
|
function cacheKey(owner, repo, masterKey) {
|
|
15496
|
-
const keyHash =
|
|
15793
|
+
const keyHash = createHash5("sha256").update(masterKey).digest("hex").slice(0, 16);
|
|
15497
15794
|
return `${owner}/${repo}:${keyHash}`.toLowerCase();
|
|
15498
15795
|
}
|
|
15499
15796
|
function decryptVault(payload, masterKey) {
|
|
@@ -16142,7 +16439,7 @@ var init_notifyTerminal = __esm({
|
|
|
16142
16439
|
});
|
|
16143
16440
|
|
|
16144
16441
|
// src/scripts/openAgencyModelReviewPr.ts
|
|
16145
|
-
import { createHash as
|
|
16442
|
+
import { createHash as createHash6 } from "crypto";
|
|
16146
16443
|
function parseAgencyModelProposal(raw) {
|
|
16147
16444
|
const text2 = raw.trim();
|
|
16148
16445
|
const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
|
|
@@ -16194,7 +16491,7 @@ function normalizeBundleFiles(bundle) {
|
|
|
16194
16491
|
});
|
|
16195
16492
|
}
|
|
16196
16493
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
16197
|
-
const digest =
|
|
16494
|
+
const digest = createHash6("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
|
|
16198
16495
|
return `issue-${issueNumber}-${digest}`;
|
|
16199
16496
|
}
|
|
16200
16497
|
function isDryRun(ctx) {
|
|
@@ -18266,9 +18563,9 @@ var init_runFlow = __esm({
|
|
|
18266
18563
|
});
|
|
18267
18564
|
|
|
18268
18565
|
// src/scripts/previewBuildHelpers.ts
|
|
18269
|
-
import { createDecipheriv as createDecipheriv2, createHash as
|
|
18566
|
+
import { createDecipheriv as createDecipheriv2, createHash as createHash7, hkdfSync as hkdfSync2 } from "crypto";
|
|
18270
18567
|
function shortHash(s) {
|
|
18271
|
-
return
|
|
18568
|
+
return createHash7("sha256").update(s).digest("hex").slice(0, 6);
|
|
18272
18569
|
}
|
|
18273
18570
|
function previewAppName(repo, pr) {
|
|
18274
18571
|
const [owner, name] = repo.split("/");
|
|
@@ -18301,7 +18598,7 @@ function formatPreviewComment(args) {
|
|
|
18301
18598
|
].join("\n");
|
|
18302
18599
|
}
|
|
18303
18600
|
function defaultImageTag(repo, ref) {
|
|
18304
|
-
return
|
|
18601
|
+
return createHash7("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
18305
18602
|
}
|
|
18306
18603
|
var init_previewBuildHelpers = __esm({
|
|
18307
18604
|
"src/scripts/previewBuildHelpers.ts"() {
|
|
@@ -20707,6 +21004,9 @@ async function runImplementation(profileName, input) {
|
|
|
20707
21004
|
let args;
|
|
20708
21005
|
try {
|
|
20709
21006
|
args = validateInputs(profile.inputs, input.cliArgs);
|
|
21007
|
+
if (profile.canonicalContract) {
|
|
21008
|
+
validateCapabilityContractValue("input", profile.canonicalContract.inputSchema, args);
|
|
21009
|
+
}
|
|
20710
21010
|
} catch (err) {
|
|
20711
21011
|
return finishAndEnd({ exitCode: 64, reason: err instanceof Error ? err.message : String(err) });
|
|
20712
21012
|
}
|
|
@@ -20767,6 +21067,12 @@ async function runImplementation(profileName, input) {
|
|
|
20767
21067
|
ctx.data.jobModelProvider = model.provider;
|
|
20768
21068
|
ctx.data.jobModelName = model.model;
|
|
20769
21069
|
if (reasoningEffort) ctx.data.jobReasoningEffort = reasoningEffort;
|
|
21070
|
+
if (profile.canonicalContract) {
|
|
21071
|
+
ctx.data.jobCapability = profile.canonicalContract.capabilityId;
|
|
21072
|
+
ctx.data.selectedImplementation = profile.canonicalContract.implementationId;
|
|
21073
|
+
ctx.data.capabilityRevision = profile.canonicalContract.capabilityRevision;
|
|
21074
|
+
ctx.data.implementationRevision = profile.canonicalContract.implementationRevision;
|
|
21075
|
+
}
|
|
20770
21076
|
const runIndexStartedAt = new Date(stageStartedAt).toISOString();
|
|
20771
21077
|
if (!input.skipConfig) {
|
|
20772
21078
|
await upsertRunIndexRowBestEffortAsync(
|
|
@@ -21076,6 +21382,25 @@ async function runImplementation(profileName, input) {
|
|
|
21076
21382
|
outcome: postOutcome
|
|
21077
21383
|
});
|
|
21078
21384
|
}
|
|
21385
|
+
const capabilityResults = Array.isArray(ctx.data.capabilityResults) ? ctx.data.capabilityResults : void 0;
|
|
21386
|
+
if (profile.canonicalContract) {
|
|
21387
|
+
try {
|
|
21388
|
+
validateCapabilityContractValue(
|
|
21389
|
+
"output",
|
|
21390
|
+
profile.canonicalContract.outputSchema,
|
|
21391
|
+
capabilityResults?.at(-1) ?? {
|
|
21392
|
+
exitCode: ctx.output.exitCode ?? 0,
|
|
21393
|
+
reason: ctx.output.reason,
|
|
21394
|
+
prUrl: ctx.output.prUrl
|
|
21395
|
+
}
|
|
21396
|
+
);
|
|
21397
|
+
} catch (error) {
|
|
21398
|
+
return finishAndEnd({
|
|
21399
|
+
exitCode: 99,
|
|
21400
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
21401
|
+
});
|
|
21402
|
+
}
|
|
21403
|
+
}
|
|
21079
21404
|
return finishAndEnd({
|
|
21080
21405
|
exitCode: ctx.output.exitCode ?? 0,
|
|
21081
21406
|
prUrl: ctx.output.prUrl,
|
|
@@ -21084,7 +21409,7 @@ async function runImplementation(profileName, input) {
|
|
|
21084
21409
|
nextJob: ctx.output.nextJob,
|
|
21085
21410
|
afterNextJob: ctx.output.afterNextJob,
|
|
21086
21411
|
taskState: ctx.data.taskState,
|
|
21087
|
-
capabilityResults
|
|
21412
|
+
capabilityResults
|
|
21088
21413
|
});
|
|
21089
21414
|
} catch (err) {
|
|
21090
21415
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -21288,10 +21613,7 @@ function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
|
21288
21613
|
return candidates[0];
|
|
21289
21614
|
}
|
|
21290
21615
|
function loadRunnableProfile(profileName, cwd) {
|
|
21291
|
-
const candidates = resolveImplementationCandidates(
|
|
21292
|
-
profileName,
|
|
21293
|
-
getImplementationRootsForCwd(cwd)
|
|
21294
|
-
);
|
|
21616
|
+
const candidates = resolveImplementationCandidates(profileName, getImplementationRootsForCwd(cwd));
|
|
21295
21617
|
const skipped = [];
|
|
21296
21618
|
for (const profilePath2 of candidates) {
|
|
21297
21619
|
const profile2 = loadProfile(profilePath2);
|
|
@@ -21543,6 +21865,7 @@ var MUTATING_POSTFLIGHTS, SHELL_MARKER_RE, TASK_ARTIFACT_WRITE_TOOLS, MAX_CHAIN_
|
|
|
21543
21865
|
var init_executor = __esm({
|
|
21544
21866
|
"src/executor.ts"() {
|
|
21545
21867
|
"use strict";
|
|
21868
|
+
init_capability_contract_validation();
|
|
21546
21869
|
init_agent();
|
|
21547
21870
|
init_agents();
|
|
21548
21871
|
init_capabilityReport();
|
|
@@ -21746,7 +22069,52 @@ async function runJob(job, base) {
|
|
|
21746
22069
|
...valid.workflowState ?? persistedState ? { workflowState: valid.workflowState ?? persistedState ?? void 0 } : {}
|
|
21747
22070
|
};
|
|
21748
22071
|
const checkpoint = valid.workflowRunId && workflowIdentity && base.config ? (state) => writeWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId, state) : void 0;
|
|
21749
|
-
const
|
|
22072
|
+
const parentRunId = `workflow:${workflowIdentity}:${valid.workflowRunId ?? newJobId(valid.flavor)}`;
|
|
22073
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22074
|
+
const parentRow = {
|
|
22075
|
+
version: 1,
|
|
22076
|
+
id: parentRunId,
|
|
22077
|
+
subjectType: "workflow",
|
|
22078
|
+
subjectId: workflowIdentity,
|
|
22079
|
+
subjectLabel: workflowCapability.title,
|
|
22080
|
+
status: "running",
|
|
22081
|
+
title: workflowCapability.title,
|
|
22082
|
+
startedAt,
|
|
22083
|
+
updatedAt: startedAt,
|
|
22084
|
+
workflow: workflowIdentity,
|
|
22085
|
+
kodyRunId: valid.workflowRunId,
|
|
22086
|
+
sourceType: "job"
|
|
22087
|
+
};
|
|
22088
|
+
const persistRun = Boolean(base.config && !base.skipConfig && hasStateBackendConfig());
|
|
22089
|
+
if (base.config && persistRun) {
|
|
22090
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, parentRow);
|
|
22091
|
+
}
|
|
22092
|
+
const workflowBase = {
|
|
22093
|
+
...base,
|
|
22094
|
+
preloadedData: { ...base.preloadedData ?? {}, parentRunId }
|
|
22095
|
+
};
|
|
22096
|
+
let result;
|
|
22097
|
+
try {
|
|
22098
|
+
result = await runCapabilityWorkflow(workflowJob, workflow, workflowCapability, workflowBase, checkpoint);
|
|
22099
|
+
} catch (error) {
|
|
22100
|
+
if (base.config && persistRun) {
|
|
22101
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, {
|
|
22102
|
+
...parentRow,
|
|
22103
|
+
status: "failed",
|
|
22104
|
+
summary: error instanceof Error ? error.message : String(error),
|
|
22105
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22106
|
+
});
|
|
22107
|
+
}
|
|
22108
|
+
throw error;
|
|
22109
|
+
}
|
|
22110
|
+
if (base.config && persistRun) {
|
|
22111
|
+
await upsertRunIndexRowBestEffortAsync(base.config, base.cwd, {
|
|
22112
|
+
...parentRow,
|
|
22113
|
+
status: result.exitCode === 0 ? "success" : "failed",
|
|
22114
|
+
summary: result.reason,
|
|
22115
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
22116
|
+
});
|
|
22117
|
+
}
|
|
21750
22118
|
if (valid.workflowRunId && workflowIdentity && base.config && result.workflowState) {
|
|
21751
22119
|
await writeWorkflowRunState(base.config, base.cwd, workflowIdentity, valid.workflowRunId, result.workflowState);
|
|
21752
22120
|
}
|
|
@@ -21886,6 +22254,9 @@ async function runLinearCapabilityWorkflow(parent, workflow, capability, base) {
|
|
|
21886
22254
|
...base,
|
|
21887
22255
|
preloadedData: {
|
|
21888
22256
|
...chainData,
|
|
22257
|
+
runSubjectType: "capability",
|
|
22258
|
+
runSubjectId: step.capability,
|
|
22259
|
+
runSubjectLabel: label,
|
|
21889
22260
|
workflowStep: label,
|
|
21890
22261
|
workflowStepIndex: index + 1,
|
|
21891
22262
|
workflowStepReason: step.reason,
|
|
@@ -22030,6 +22401,9 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22030
22401
|
...base,
|
|
22031
22402
|
preloadedData: {
|
|
22032
22403
|
...chainData,
|
|
22404
|
+
runSubjectType: "capability",
|
|
22405
|
+
runSubjectId: step.capability,
|
|
22406
|
+
runSubjectLabel: step.id,
|
|
22033
22407
|
workflowStep: step.id,
|
|
22034
22408
|
workflowStepIndex: index + 1,
|
|
22035
22409
|
workflowStepReason: step.reason,
|
|
@@ -22283,7 +22657,7 @@ function hydratedCapabilitiesRoot(cwd) {
|
|
|
22283
22657
|
return path46.join(cwd, ".kody-engine", "definitions", "capabilities");
|
|
22284
22658
|
}
|
|
22285
22659
|
function loadWorkflowContext(slug, base) {
|
|
22286
|
-
if (!slug || !
|
|
22660
|
+
if (!slug || !isWorkflowDefinitionId(slug)) return null;
|
|
22287
22661
|
const workflow = readWorkflowDefinition(base.config, base.cwd, slug);
|
|
22288
22662
|
return workflow ? workflowDefinitionToCapabilityFolder(slug, workflow) : null;
|
|
22289
22663
|
}
|
|
@@ -22319,6 +22693,8 @@ var init_job = __esm({
|
|
|
22319
22693
|
init_capabilityFolders();
|
|
22320
22694
|
init_executor();
|
|
22321
22695
|
init_registry();
|
|
22696
|
+
init_runIndex();
|
|
22697
|
+
init_state_backend();
|
|
22322
22698
|
init_workflowDefinitions();
|
|
22323
22699
|
init_workflowRunState();
|
|
22324
22700
|
init_workflowValidation();
|
|
@@ -24494,8 +24870,16 @@ async function runCi(argv) {
|
|
|
24494
24870
|
const noTarget = !sessionInput && !(Number.isFinite(issueInput) && issueInput > 0);
|
|
24495
24871
|
if (noTarget && capabilityInput) {
|
|
24496
24872
|
forceRunAction = capabilityInput;
|
|
24497
|
-
if (
|
|
24498
|
-
|
|
24873
|
+
if (messageInput) {
|
|
24874
|
+
const route = resolveCapabilityAction(capabilityInput);
|
|
24875
|
+
const textInputs = route?.implementation ? (getProfileInputs(route.implementation) ?? []).filter(
|
|
24876
|
+
(input) => input.type === "string"
|
|
24877
|
+
) : [];
|
|
24878
|
+
if (textInputs.length === 1) {
|
|
24879
|
+
forceRunCliArgs = { [textInputs[0].name]: messageInput };
|
|
24880
|
+
} else if (capabilityInput === "goal-manager") {
|
|
24881
|
+
forceRunCliArgs = { goal: messageInput };
|
|
24882
|
+
}
|
|
24499
24883
|
}
|
|
24500
24884
|
} else {
|
|
24501
24885
|
manualWorkflowDispatch = noTarget;
|
|
@@ -26336,7 +26720,7 @@ init_definition_paths();
|
|
|
26336
26720
|
|
|
26337
26721
|
// src/definition-hydration.ts
|
|
26338
26722
|
init_state_backend();
|
|
26339
|
-
import { createHash as
|
|
26723
|
+
import { createHash as createHash8 } from "crypto";
|
|
26340
26724
|
import * as fs50 from "fs";
|
|
26341
26725
|
import * as path51 from "path";
|
|
26342
26726
|
var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
@@ -26357,7 +26741,7 @@ function normalizeDefinitionBundle(bundle) {
|
|
|
26357
26741
|
return { schemaVersion: 1, files };
|
|
26358
26742
|
}
|
|
26359
26743
|
function definitionVersion(bundle) {
|
|
26360
|
-
return `sha256:${
|
|
26744
|
+
return `sha256:${createHash8("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
|
|
26361
26745
|
}
|
|
26362
26746
|
function verifyDefinition(definition) {
|
|
26363
26747
|
if (!SLUG_RE2.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "run",
|
|
3
|
+
"action": "run",
|
|
4
|
+
"purpose": "Implement one GitHub issue end-to-end.",
|
|
5
|
+
"inputSchema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"issue": {
|
|
9
|
+
"type": "integer",
|
|
10
|
+
"description": "GitHub issue number to implement."
|
|
11
|
+
},
|
|
12
|
+
"base": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Optional safe base branch override for manual branch targeting (see resolveBaseOverride in runFlow.ts)."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"required": [
|
|
18
|
+
"issue"
|
|
19
|
+
],
|
|
20
|
+
"additionalProperties": false
|
|
21
|
+
},
|
|
22
|
+
"outputSchema": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"properties": {
|
|
25
|
+
"reason": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"summary": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"data": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"additionalProperties": true
|
|
37
|
+
},
|
|
38
|
+
"effects": [],
|
|
39
|
+
"permissions": [],
|
|
40
|
+
"success": "The requested issue is implemented and the canonical result is returned.",
|
|
41
|
+
"failure": "The issue cannot be implemented safely or no valid canonical result is returned."
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "run",
|
|
3
|
+
"capabilityRef": {
|
|
4
|
+
"kind": "capability",
|
|
5
|
+
"id": "run"
|
|
6
|
+
},
|
|
7
|
+
"compatibleCapabilityRevision": "c50fdcd64daedbcde4428b2985a68a8a11ece518f00a0f5a0c0a2c9d38b5e9c1",
|
|
8
|
+
"type": "agent",
|
|
9
|
+
"agentRef": {
|
|
10
|
+
"kind": "agent",
|
|
11
|
+
"id": "kody"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -40,6 +40,14 @@ export interface AuthSpec {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface Profile {
|
|
43
|
+
canonicalContract?: {
|
|
44
|
+
capabilityId: string
|
|
45
|
+
capabilityRevision: string
|
|
46
|
+
implementationId: string
|
|
47
|
+
implementationRevision: string
|
|
48
|
+
inputSchema: Record<string, unknown>
|
|
49
|
+
outputSchema: Record<string, unknown>
|
|
50
|
+
}
|
|
43
51
|
name: string
|
|
44
52
|
/**
|
|
45
53
|
* Public action name owned by a capability. A user may type `@kody <action>`;
|
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.431",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,33 +12,12 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"kody:run": "tsx bin/kody.ts",
|
|
17
|
-
"serve": "tsx bin/kody.ts serve",
|
|
18
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
19
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
20
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
21
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
22
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
23
|
-
"pretest": "pnpm check:modularity",
|
|
24
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
25
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
26
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
27
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
28
|
-
"test:all": "vitest run tests --no-coverage",
|
|
29
|
-
"typecheck": "tsc --noEmit",
|
|
30
|
-
"lint": "biome check",
|
|
31
|
-
"lint:fix": "biome check --write",
|
|
32
|
-
"format": "biome format --write",
|
|
33
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
34
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
35
|
-
"prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
|
|
36
|
-
},
|
|
37
15
|
"dependencies": {
|
|
38
16
|
"@actions/cache": "^6.0.0",
|
|
39
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
40
|
-
"@kody-ade/agency-domain": "0.5.
|
|
18
|
+
"@kody-ade/agency-domain": "0.5.1",
|
|
41
19
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
20
|
+
"ajv": "^8.18.0",
|
|
42
21
|
"convex": "^1.17.0",
|
|
43
22
|
"zod": "^4.0.0"
|
|
44
23
|
},
|
|
@@ -59,5 +38,26 @@
|
|
|
59
38
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
60
39
|
},
|
|
61
40
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
62
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
63
|
-
|
|
41
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"kody:run": "tsx bin/kody.ts",
|
|
44
|
+
"serve": "tsx bin/kody.ts serve",
|
|
45
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
46
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
47
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
48
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
49
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
50
|
+
"pretest": "pnpm check:modularity",
|
|
51
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
52
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
53
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
54
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
55
|
+
"test:all": "vitest run tests --no-coverage",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"lint": "biome check",
|
|
58
|
+
"lint:fix": "biome check --write",
|
|
59
|
+
"format": "biome format --write",
|
|
60
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
61
|
+
"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"
|
|
62
|
+
}
|
|
63
|
+
}
|