@kody-ade/kody-engine 0.4.560 → 0.4.562
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 +99 -16
- package/package.json +1 -1
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.562",
|
|
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",
|
|
@@ -671,11 +671,22 @@ var init_format = __esm({
|
|
|
671
671
|
|
|
672
672
|
// src/agency/capability-contract-validation.ts
|
|
673
673
|
import Ajv from "ajv";
|
|
674
|
-
function
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
674
|
+
function createCapabilityContractValueValidator(compile) {
|
|
675
|
+
const compiled = /* @__PURE__ */ new WeakMap();
|
|
676
|
+
return (boundary, schema, value) => {
|
|
677
|
+
let validate = compiled.get(schema);
|
|
678
|
+
if (!validate) {
|
|
679
|
+
validate = compile(schema);
|
|
680
|
+
compiled.set(schema, validate);
|
|
681
|
+
}
|
|
682
|
+
if (!validate(value)) {
|
|
683
|
+
throw new CapabilityContractValidationError(boundary, validate.errors ?? []);
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
function validateCapabilityContractOutput(schema, value) {
|
|
688
|
+
if (value === void 0) throw new CapabilityContractMissingOutputError();
|
|
689
|
+
validateCapabilityContractValue("output", schema, value);
|
|
679
690
|
}
|
|
680
691
|
function capabilityContractInput(inputs, args, capabilityId, contractProperties = []) {
|
|
681
692
|
const isGenericRunnerInput = inputs.some((input) => input.name === "input") && Object.hasOwn(args, "input");
|
|
@@ -693,7 +704,7 @@ function capabilityContractInput(inputs, args, capabilityId, contractProperties
|
|
|
693
704
|
return value;
|
|
694
705
|
}
|
|
695
706
|
}
|
|
696
|
-
var validator, CapabilityContractValidationError;
|
|
707
|
+
var validator, CapabilityContractValidationError, CapabilityContractMissingOutputError, validateCapabilityContractValue;
|
|
697
708
|
var init_capability_contract_validation = __esm({
|
|
698
709
|
"src/agency/capability-contract-validation.ts"() {
|
|
699
710
|
"use strict";
|
|
@@ -717,6 +728,15 @@ var init_capability_contract_validation = __esm({
|
|
|
717
728
|
boundary;
|
|
718
729
|
errors;
|
|
719
730
|
};
|
|
731
|
+
CapabilityContractMissingOutputError = class extends Error {
|
|
732
|
+
constructor() {
|
|
733
|
+
super("Capability output is missing despite its declared contract");
|
|
734
|
+
this.name = "CapabilityContractMissingOutputError";
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
validateCapabilityContractValue = createCapabilityContractValueValidator(
|
|
738
|
+
(schema) => validator.compile(schema)
|
|
739
|
+
);
|
|
720
740
|
}
|
|
721
741
|
});
|
|
722
742
|
|
|
@@ -731,7 +751,7 @@ function outputContractError(contract) {
|
|
|
731
751
|
return `The required output file is missing or is not valid JSON: ${error instanceof Error ? error.message : String(error)}`;
|
|
732
752
|
}
|
|
733
753
|
try {
|
|
734
|
-
|
|
754
|
+
validateCapabilityContractOutput(contract.schema, value);
|
|
735
755
|
return null;
|
|
736
756
|
} catch (error) {
|
|
737
757
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -2012,20 +2032,52 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
2012
2032
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path8.join(absDir, e.name))).map((e) => e.name).sort();
|
|
2013
2033
|
}
|
|
2014
2034
|
function isCapabilityFolder(dir) {
|
|
2015
|
-
if (!fs7.existsSync(path8.join(dir, CAPABILITY_BODY_FILE))) return false;
|
|
2016
2035
|
const entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
2036
|
+
const legacyBody = path8.join(dir, CAPABILITY_BODY_FILE);
|
|
2037
|
+
if (fs7.existsSync(legacyBody)) {
|
|
2038
|
+
return entries.every(
|
|
2039
|
+
(entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
2042
|
+
const canonicalBody = path8.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
|
|
2043
|
+
const canonicalDefinition = path8.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
|
|
2044
|
+
if (!fs7.existsSync(canonicalBody) || !fs7.existsSync(canonicalDefinition)) return false;
|
|
2017
2045
|
return entries.every(
|
|
2018
|
-
(entry) => entry.name ===
|
|
2046
|
+
(entry) => entry.name === CANONICAL_CAPABILITY_BODY_FILE || entry.name === CANONICAL_CAPABILITY_DEFINITION_FILE
|
|
2019
2047
|
);
|
|
2020
2048
|
}
|
|
2021
2049
|
function readCapabilityFolder(root, slug) {
|
|
2022
2050
|
const dir = path8.join(root, slug);
|
|
2023
|
-
const
|
|
2051
|
+
const legacyBodyPath = path8.join(dir, CAPABILITY_BODY_FILE);
|
|
2052
|
+
const canonicalBodyPath = path8.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
|
|
2053
|
+
const bodyPath = fs7.existsSync(legacyBodyPath) ? legacyBodyPath : canonicalBodyPath;
|
|
2024
2054
|
const contractPath = path8.join(dir, CAPABILITY_CONTRACT_FILE);
|
|
2025
2055
|
if (!fs7.existsSync(bodyPath) || !fs7.statSync(bodyPath).isFile()) return null;
|
|
2026
2056
|
if (!isCapabilityFolder(dir)) return null;
|
|
2027
2057
|
try {
|
|
2028
2058
|
const rawBody = fs7.readFileSync(bodyPath, "utf-8");
|
|
2059
|
+
if (bodyPath === canonicalBodyPath) {
|
|
2060
|
+
const definitionPath = path8.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
|
|
2061
|
+
const definition = JSON.parse(fs7.readFileSync(definitionPath, "utf-8"));
|
|
2062
|
+
if (definition.id !== slug || typeof definition.action !== "string") return null;
|
|
2063
|
+
const { title: title2, body: body2 } = parseCapabilityBody(rawBody, slug);
|
|
2064
|
+
return {
|
|
2065
|
+
slug,
|
|
2066
|
+
dir,
|
|
2067
|
+
profilePath: definitionPath,
|
|
2068
|
+
bodyPath,
|
|
2069
|
+
title: title2,
|
|
2070
|
+
body: body2,
|
|
2071
|
+
rawBody,
|
|
2072
|
+
config: {
|
|
2073
|
+
action: definition.action,
|
|
2074
|
+
describe: typeof definition.purpose === "string" ? definition.purpose : title2,
|
|
2075
|
+
...isPlainObject(definition.inputSchema) ? { inputSchema: definition.inputSchema } : {},
|
|
2076
|
+
...isPlainObject(definition.outputSchema) ? { outputSchema: definition.outputSchema } : {}
|
|
2077
|
+
},
|
|
2078
|
+
rawProfile: definition
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2029
2081
|
const contract = fs7.existsSync(contractPath) ? parseCapabilityContract(fs7.readFileSync(contractPath, "utf-8")) : void 0;
|
|
2030
2082
|
if (contract?.execution === "script" && !isRegularFile(path8.join(dir, "tools", "run.sh"))) {
|
|
2031
2083
|
throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
|
|
@@ -2301,13 +2353,15 @@ function isSafeSlug(value) {
|
|
|
2301
2353
|
function isSafeStepId(value) {
|
|
2302
2354
|
return /^[A-Za-z][A-Za-z0-9_-]*$/.test(value) && !value.includes("..");
|
|
2303
2355
|
}
|
|
2304
|
-
var CAPABILITY_BODY_FILE, CAPABILITY_CONTRACT_FILE, CAPABILITY_PROFILE_FILE;
|
|
2356
|
+
var CAPABILITY_BODY_FILE, CAPABILITY_CONTRACT_FILE, CAPABILITY_PROFILE_FILE, CANONICAL_CAPABILITY_BODY_FILE, CANONICAL_CAPABILITY_DEFINITION_FILE;
|
|
2305
2357
|
var init_capabilityFolders = __esm({
|
|
2306
2358
|
"src/capabilityFolders.ts"() {
|
|
2307
2359
|
"use strict";
|
|
2308
2360
|
CAPABILITY_BODY_FILE = "instructions.md";
|
|
2309
2361
|
CAPABILITY_CONTRACT_FILE = "contract.json";
|
|
2310
2362
|
CAPABILITY_PROFILE_FILE = CAPABILITY_BODY_FILE;
|
|
2363
|
+
CANONICAL_CAPABILITY_BODY_FILE = "capability.md";
|
|
2364
|
+
CANONICAL_CAPABILITY_DEFINITION_FILE = "definition.json";
|
|
2311
2365
|
}
|
|
2312
2366
|
});
|
|
2313
2367
|
|
|
@@ -2498,6 +2552,7 @@ function resolveCapabilityFolder(slug, projectCapabilitiesRoot = getProjectCapab
|
|
|
2498
2552
|
function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
2499
2553
|
const resolved = resolveCapabilityAction(action, projectCapabilitiesRoot);
|
|
2500
2554
|
if (!resolved) return null;
|
|
2555
|
+
if (resolved.source === "builtin") return getProfileInputs(resolved.implementation);
|
|
2501
2556
|
const capability = resolveCapabilityFolder(resolved.capability, projectCapabilitiesRoot);
|
|
2502
2557
|
if (capability && !capability.config.workflow) {
|
|
2503
2558
|
return [
|
|
@@ -17251,7 +17306,7 @@ var init_parseSimpleCapabilityOutput = __esm({
|
|
|
17251
17306
|
const outputSchema = isObject2(ctx.data.capabilityOutputSchema) ? ctx.data.capabilityOutputSchema : void 0;
|
|
17252
17307
|
if (outputSchema) {
|
|
17253
17308
|
try {
|
|
17254
|
-
|
|
17309
|
+
validateCapabilityContractOutput(outputSchema, output);
|
|
17255
17310
|
} catch (error) {
|
|
17256
17311
|
const reason2 = error instanceof Error ? error.message : String(error);
|
|
17257
17312
|
ctx.output.exitCode = 64;
|
|
@@ -22221,8 +22276,7 @@ async function runImplementation(profileName, input) {
|
|
|
22221
22276
|
const capabilityResults = Array.isArray(ctx.data.capabilityResults) ? ctx.data.capabilityResults : void 0;
|
|
22222
22277
|
if (profile.canonicalContract) {
|
|
22223
22278
|
try {
|
|
22224
|
-
|
|
22225
|
-
"output",
|
|
22279
|
+
validateCapabilityContractOutput(
|
|
22226
22280
|
profile.canonicalContract.outputSchema,
|
|
22227
22281
|
capabilityResults?.at(-1) ?? {
|
|
22228
22282
|
exitCode: ctx.output.exitCode ?? 0,
|
|
@@ -23192,7 +23246,35 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
23192
23246
|
input.cliArgs = simpleCapabilityRuntimeArgs(simpleCapabilityRuntime, capabilityIdentity, capabilityInput);
|
|
23193
23247
|
}
|
|
23194
23248
|
const run = base.chain === false ? runImplementation : runImplementationChain;
|
|
23195
|
-
|
|
23249
|
+
const result = await run(profileName, input);
|
|
23250
|
+
return enforceCapabilityOutputContract(capabilityContext, result);
|
|
23251
|
+
}
|
|
23252
|
+
function enforceCapabilityOutputContract(capability, result) {
|
|
23253
|
+
const schema = capability?.config.outputSchema;
|
|
23254
|
+
if (result.exitCode !== 0 || !schema) {
|
|
23255
|
+
return result;
|
|
23256
|
+
}
|
|
23257
|
+
try {
|
|
23258
|
+
validateCapabilityContractOutput(schema, result.capabilityOutput);
|
|
23259
|
+
return result;
|
|
23260
|
+
} catch (error) {
|
|
23261
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
23262
|
+
const blocked = {
|
|
23263
|
+
version: 1,
|
|
23264
|
+
status: "blocked",
|
|
23265
|
+
summary: reason,
|
|
23266
|
+
facts: {},
|
|
23267
|
+
artifacts: [],
|
|
23268
|
+
missingEvidence: [],
|
|
23269
|
+
blockers: [reason]
|
|
23270
|
+
};
|
|
23271
|
+
return {
|
|
23272
|
+
...result,
|
|
23273
|
+
exitCode: 64,
|
|
23274
|
+
reason,
|
|
23275
|
+
capabilityResults: [blocked]
|
|
23276
|
+
};
|
|
23277
|
+
}
|
|
23196
23278
|
}
|
|
23197
23279
|
function shouldRunCapabilityWorkflow(job, workflow, capabilityIdentity, selectedImplementation, base) {
|
|
23198
23280
|
if (workflow.steps.length === 0) return false;
|
|
@@ -23909,6 +23991,7 @@ var DEFAULT_INSTANT_AGENT, localJobSeq, InvalidJobError;
|
|
|
23909
23991
|
var init_job = __esm({
|
|
23910
23992
|
"src/job.ts"() {
|
|
23911
23993
|
"use strict";
|
|
23994
|
+
init_capability_contract_validation();
|
|
23912
23995
|
init_agencyBoundaryEval();
|
|
23913
23996
|
init_capabilityFolders();
|
|
23914
23997
|
init_config();
|
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.562",
|
|
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",
|