@kody-ade/kody-engine 0.4.463 → 0.4.465
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
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.465",
|
|
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",
|
|
@@ -1688,6 +1688,9 @@ function readCapabilityFolder(root, slug) {
|
|
|
1688
1688
|
try {
|
|
1689
1689
|
const rawBody = fs4.readFileSync(bodyPath, "utf-8");
|
|
1690
1690
|
const contract = fs4.existsSync(contractPath) ? parseCapabilityContract(fs4.readFileSync(contractPath, "utf-8")) : void 0;
|
|
1691
|
+
if (contract?.execution === "script" && !isRegularFile(path5.join(dir, "tools", "run.sh"))) {
|
|
1692
|
+
throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
|
|
1693
|
+
}
|
|
1691
1694
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
1692
1695
|
return {
|
|
1693
1696
|
slug,
|
|
@@ -1701,12 +1704,17 @@ function readCapabilityFolder(root, slug) {
|
|
|
1701
1704
|
config: {
|
|
1702
1705
|
action: slug,
|
|
1703
1706
|
describe: title,
|
|
1707
|
+
...contract?.execution ? { execution: contract.execution } : {},
|
|
1704
1708
|
...contract ? {
|
|
1705
1709
|
inputSchema: contract.input,
|
|
1706
1710
|
outputSchema: contract.output
|
|
1707
1711
|
} : {}
|
|
1708
1712
|
},
|
|
1709
|
-
rawProfile: contract ? {
|
|
1713
|
+
rawProfile: contract ? {
|
|
1714
|
+
...contract.execution ? { execution: contract.execution } : {},
|
|
1715
|
+
input: contract.input,
|
|
1716
|
+
output: contract.output
|
|
1717
|
+
} : {},
|
|
1710
1718
|
...contract ? { contract } : {}
|
|
1711
1719
|
};
|
|
1712
1720
|
} catch {
|
|
@@ -1718,11 +1726,28 @@ function parseCapabilityContract(raw) {
|
|
|
1718
1726
|
if (!isPlainObject(parsed) || !isPlainObject(parsed.input) || !isPlainObject(parsed.output)) {
|
|
1719
1727
|
throw new Error("contract.json must contain input and output JSON schemas");
|
|
1720
1728
|
}
|
|
1721
|
-
|
|
1729
|
+
if (parsed.execution !== void 0 && parsed.execution !== "agent" && parsed.execution !== "script") {
|
|
1730
|
+
throw new Error('contract.json execution must be "agent" or "script"');
|
|
1731
|
+
}
|
|
1732
|
+
const unsupported = Object.keys(parsed).filter(
|
|
1733
|
+
(key) => key !== "execution" && key !== "input" && key !== "output"
|
|
1734
|
+
);
|
|
1722
1735
|
if (unsupported.length > 0) {
|
|
1723
1736
|
throw new Error(`contract.json contains unsupported fields: ${unsupported.join(", ")}`);
|
|
1724
1737
|
}
|
|
1725
|
-
return {
|
|
1738
|
+
return {
|
|
1739
|
+
...parsed.execution ? { execution: parsed.execution } : {},
|
|
1740
|
+
input: parsed.input,
|
|
1741
|
+
output: parsed.output
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
function isRegularFile(filePath) {
|
|
1745
|
+
try {
|
|
1746
|
+
const stat = fs4.lstatSync(filePath);
|
|
1747
|
+
return stat.isFile() && !stat.isSymbolicLink();
|
|
1748
|
+
} catch {
|
|
1749
|
+
return false;
|
|
1750
|
+
}
|
|
1726
1751
|
}
|
|
1727
1752
|
function schemaPropertyPaths(schema, prefix) {
|
|
1728
1753
|
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
@@ -11469,11 +11494,13 @@ var init_classifyByLabel = __esm({
|
|
|
11469
11494
|
});
|
|
11470
11495
|
|
|
11471
11496
|
// src/scripts/commitAndPush.ts
|
|
11497
|
+
import { createHash as createHash4 } from "crypto";
|
|
11472
11498
|
import * as fs31 from "fs";
|
|
11473
11499
|
import * as path29 from "path";
|
|
11474
|
-
function sentinelPathForStage(cwd, profileName) {
|
|
11500
|
+
function sentinelPathForStage(cwd, profileName, workflowExecutionKey) {
|
|
11475
11501
|
const runId = resolveRunId();
|
|
11476
|
-
|
|
11502
|
+
const executionSuffix = typeof workflowExecutionKey === "string" && workflowExecutionKey.length > 0 ? `-${createHash4("sha256").update(workflowExecutionKey).digest("hex").slice(0, 16)}` : "";
|
|
11503
|
+
return runtimeStatePath(cwd, "agent-runs", runId, `commit-${profileName}${executionSuffix}.lock`);
|
|
11477
11504
|
}
|
|
11478
11505
|
var DEFAULT_COMMIT_MESSAGE, commitAndPush2;
|
|
11479
11506
|
var init_commitAndPush = __esm({
|
|
@@ -11490,7 +11517,7 @@ var init_commitAndPush = __esm({
|
|
|
11490
11517
|
return;
|
|
11491
11518
|
}
|
|
11492
11519
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
11493
|
-
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
11520
|
+
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name, ctx.data.workflowExecutionKey) : null;
|
|
11494
11521
|
if (sentinel && fs31.existsSync(sentinel)) {
|
|
11495
11522
|
try {
|
|
11496
11523
|
const replay = JSON.parse(fs31.readFileSync(sentinel, "utf-8"));
|
|
@@ -13287,7 +13314,7 @@ var init_triggerDispatcher = __esm({
|
|
|
13287
13314
|
});
|
|
13288
13315
|
|
|
13289
13316
|
// src/goal/policyResolver.ts
|
|
13290
|
-
import { createHash as
|
|
13317
|
+
import { createHash as createHash5 } from "crypto";
|
|
13291
13318
|
function resolveDispatchPolicy(input) {
|
|
13292
13319
|
const operation = input.catalog.operations.get(input.owner.definition.operationId);
|
|
13293
13320
|
if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
|
|
@@ -13305,7 +13332,7 @@ function resolveDispatchPolicy(input) {
|
|
|
13305
13332
|
const snapshotValue = { policy, constraints };
|
|
13306
13333
|
return {
|
|
13307
13334
|
snapshot: {
|
|
13308
|
-
hash:
|
|
13335
|
+
hash: createHash5("sha256").update(stableJson(snapshotValue)).digest("hex"),
|
|
13309
13336
|
...snapshotValue
|
|
13310
13337
|
},
|
|
13311
13338
|
operation,
|
|
@@ -15919,9 +15946,9 @@ var init_kodyVariables = __esm({
|
|
|
15919
15946
|
});
|
|
15920
15947
|
|
|
15921
15948
|
// src/backendVault.ts
|
|
15922
|
-
import { createDecipheriv, createHash as
|
|
15949
|
+
import { createDecipheriv, createHash as createHash6 } from "crypto";
|
|
15923
15950
|
function cacheKey(owner, repo, masterKey) {
|
|
15924
|
-
const keyHash =
|
|
15951
|
+
const keyHash = createHash6("sha256").update(masterKey).digest("hex").slice(0, 16);
|
|
15925
15952
|
return `${owner}/${repo}:${keyHash}`.toLowerCase();
|
|
15926
15953
|
}
|
|
15927
15954
|
function decryptVault(payload, masterKey) {
|
|
@@ -16247,6 +16274,10 @@ var init_loadSimpleCapability = __esm({
|
|
|
16247
16274
|
}
|
|
16248
16275
|
ctx.data.jobCapability = slug;
|
|
16249
16276
|
ctx.data.capabilityInput = input;
|
|
16277
|
+
ctx.data.capabilityExecution = capability.contract?.execution ?? "agent";
|
|
16278
|
+
if (capability.contract?.execution === "script") {
|
|
16279
|
+
ctx.data.capabilityScriptPath = path40.join(capability.dir, "tools", "run.sh");
|
|
16280
|
+
}
|
|
16250
16281
|
if (capability.config.outputSchema) {
|
|
16251
16282
|
ctx.data.capabilityOutputSchema = capability.config.outputSchema;
|
|
16252
16283
|
}
|
|
@@ -16704,7 +16735,7 @@ var init_notifyTerminal = __esm({
|
|
|
16704
16735
|
});
|
|
16705
16736
|
|
|
16706
16737
|
// src/scripts/openAgencyModelReviewPr.ts
|
|
16707
|
-
import { createHash as
|
|
16738
|
+
import { createHash as createHash7 } from "crypto";
|
|
16708
16739
|
function parseAgencyModelProposal(raw) {
|
|
16709
16740
|
const text2 = raw.trim();
|
|
16710
16741
|
const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
|
|
@@ -16756,7 +16787,7 @@ function normalizeBundleFiles(bundle) {
|
|
|
16756
16787
|
});
|
|
16757
16788
|
}
|
|
16758
16789
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
16759
|
-
const digest =
|
|
16790
|
+
const digest = createHash7("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
|
|
16760
16791
|
return `issue-${issueNumber}-${digest}`;
|
|
16761
16792
|
}
|
|
16762
16793
|
function isDryRun(ctx) {
|
|
@@ -17272,7 +17303,7 @@ var init_parseSimpleCapabilityOutput = __esm({
|
|
|
17272
17303
|
"use strict";
|
|
17273
17304
|
init_capability_contract_validation();
|
|
17274
17305
|
parseSimpleCapabilityOutput = async (ctx, _profile, agentResult) => {
|
|
17275
|
-
const output = parseOutput(agentResult?.finalText);
|
|
17306
|
+
const output = Object.hasOwn(ctx.data, "capabilityScriptOutput") ? ctx.data.capabilityScriptOutput : parseOutput(agentResult?.finalText);
|
|
17276
17307
|
if (output === void 0) {
|
|
17277
17308
|
const reason2 = agentResult?.outcomeKind === "out_of_turns" ? "Capability execution limit reached" : "Capability execution ended before returning a result";
|
|
17278
17309
|
const blocked = {
|
|
@@ -19086,9 +19117,9 @@ var init_reviewFlow = __esm({
|
|
|
19086
19117
|
});
|
|
19087
19118
|
|
|
19088
19119
|
// src/scripts/previewBuildHelpers.ts
|
|
19089
|
-
import { createDecipheriv as createDecipheriv2, createHash as
|
|
19120
|
+
import { createDecipheriv as createDecipheriv2, createHash as createHash8, hkdfSync as hkdfSync2 } from "crypto";
|
|
19090
19121
|
function shortHash(s) {
|
|
19091
|
-
return
|
|
19122
|
+
return createHash8("sha256").update(s).digest("hex").slice(0, 6);
|
|
19092
19123
|
}
|
|
19093
19124
|
function previewAppName(repo, pr) {
|
|
19094
19125
|
const [owner, name] = repo.split("/");
|
|
@@ -19121,7 +19152,7 @@ function formatPreviewComment(args) {
|
|
|
19121
19152
|
].join("\n");
|
|
19122
19153
|
}
|
|
19123
19154
|
function defaultImageTag(repo, ref) {
|
|
19124
|
-
return
|
|
19155
|
+
return createHash8("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
|
|
19125
19156
|
}
|
|
19126
19157
|
var init_previewBuildHelpers = __esm({
|
|
19127
19158
|
"src/scripts/previewBuildHelpers.ts"() {
|
|
@@ -19766,6 +19797,74 @@ var init_runTickScript = __esm({
|
|
|
19766
19797
|
}
|
|
19767
19798
|
});
|
|
19768
19799
|
|
|
19800
|
+
// src/scripts/runSimpleCapabilityScript.ts
|
|
19801
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
19802
|
+
import * as fs48 from "fs";
|
|
19803
|
+
function isRegularFile2(filePath) {
|
|
19804
|
+
try {
|
|
19805
|
+
const stat = fs48.lstatSync(filePath);
|
|
19806
|
+
return stat.isFile() && !stat.isSymbolicLink();
|
|
19807
|
+
} catch {
|
|
19808
|
+
return false;
|
|
19809
|
+
}
|
|
19810
|
+
}
|
|
19811
|
+
function isStringRecord(value) {
|
|
19812
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
19813
|
+
}
|
|
19814
|
+
var SCRIPT_TIMEOUT_MS, SCRIPT_MAX_OUTPUT_BYTES, runSimpleCapabilityScript;
|
|
19815
|
+
var init_runSimpleCapabilityScript = __esm({
|
|
19816
|
+
"src/scripts/runSimpleCapabilityScript.ts"() {
|
|
19817
|
+
"use strict";
|
|
19818
|
+
init_tickShellRunner();
|
|
19819
|
+
SCRIPT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
19820
|
+
SCRIPT_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
19821
|
+
runSimpleCapabilityScript = async (ctx) => {
|
|
19822
|
+
ctx.skipAgent = true;
|
|
19823
|
+
const scriptPath = typeof ctx.data.capabilityScriptPath === "string" ? ctx.data.capabilityScriptPath : "";
|
|
19824
|
+
if (!scriptPath || !isRegularFile2(scriptPath)) {
|
|
19825
|
+
ctx.output.exitCode = 99;
|
|
19826
|
+
ctx.output.reason = 'Script-backed Capability requires a regular "tools/run.sh" entrypoint';
|
|
19827
|
+
return;
|
|
19828
|
+
}
|
|
19829
|
+
const capabilityEnvironment2 = isStringRecord(ctx.data.capabilityEnvironment) ? ctx.data.capabilityEnvironment : {};
|
|
19830
|
+
const result = spawnSync3("bash", [scriptPath], {
|
|
19831
|
+
cwd: ctx.cwd,
|
|
19832
|
+
env: {
|
|
19833
|
+
...buildTickChildEnv(process.env, false),
|
|
19834
|
+
...capabilityEnvironment2
|
|
19835
|
+
},
|
|
19836
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
19837
|
+
encoding: "utf-8",
|
|
19838
|
+
timeout: SCRIPT_TIMEOUT_MS,
|
|
19839
|
+
maxBuffer: SCRIPT_MAX_OUTPUT_BYTES
|
|
19840
|
+
});
|
|
19841
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
19842
|
+
if (result.error) {
|
|
19843
|
+
const timedOut = result.error.code === "ETIMEDOUT";
|
|
19844
|
+
ctx.output.exitCode = timedOut ? 124 : 99;
|
|
19845
|
+
ctx.output.reason = timedOut ? "Capability script timed out after 5 minutes" : `Capability script failed to start: ${result.error.message}`;
|
|
19846
|
+
return;
|
|
19847
|
+
}
|
|
19848
|
+
if (result.signal) {
|
|
19849
|
+
ctx.output.exitCode = 124;
|
|
19850
|
+
ctx.output.reason = `Capability script was killed by ${result.signal}`;
|
|
19851
|
+
return;
|
|
19852
|
+
}
|
|
19853
|
+
if (result.status !== 0) {
|
|
19854
|
+
ctx.output.exitCode = result.status ?? 99;
|
|
19855
|
+
ctx.output.reason = `Capability script exited ${result.status ?? 99}`;
|
|
19856
|
+
return;
|
|
19857
|
+
}
|
|
19858
|
+
try {
|
|
19859
|
+
ctx.data.capabilityScriptOutput = JSON.parse(result.stdout ?? "");
|
|
19860
|
+
} catch {
|
|
19861
|
+
ctx.output.exitCode = 64;
|
|
19862
|
+
ctx.output.reason = "Capability script must return exactly one valid JSON value on stdout";
|
|
19863
|
+
}
|
|
19864
|
+
};
|
|
19865
|
+
}
|
|
19866
|
+
});
|
|
19867
|
+
|
|
19769
19868
|
// src/scripts/saveManagedGoalState.ts
|
|
19770
19869
|
var saveManagedGoalState;
|
|
19771
19870
|
var init_saveManagedGoalState = __esm({
|
|
@@ -20781,7 +20880,7 @@ var init_warmupMcp = __esm({
|
|
|
20781
20880
|
});
|
|
20782
20881
|
|
|
20783
20882
|
// src/scripts/writeAgentRunSummary.ts
|
|
20784
|
-
import * as
|
|
20883
|
+
import * as fs49 from "fs";
|
|
20785
20884
|
var writeAgentRunSummary;
|
|
20786
20885
|
var init_writeAgentRunSummary = __esm({
|
|
20787
20886
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -20807,7 +20906,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
20807
20906
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
20808
20907
|
lines.push("");
|
|
20809
20908
|
try {
|
|
20810
|
-
|
|
20909
|
+
fs49.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
20811
20910
|
`);
|
|
20812
20911
|
} catch {
|
|
20813
20912
|
}
|
|
@@ -21010,6 +21109,7 @@ var init_scripts = __esm({
|
|
|
21010
21109
|
init_runPreviewBuild();
|
|
21011
21110
|
init_runScheduledImplementationTick();
|
|
21012
21111
|
init_runTickScript();
|
|
21112
|
+
init_runSimpleCapabilityScript();
|
|
21013
21113
|
init_saveManagedGoalState();
|
|
21014
21114
|
init_saveTaskState();
|
|
21015
21115
|
init_setCommentTarget();
|
|
@@ -21078,6 +21178,7 @@ var init_scripts = __esm({
|
|
|
21078
21178
|
runScheduledImplementationTick,
|
|
21079
21179
|
runScheduledExecutableTick: runScheduledImplementationTick,
|
|
21080
21180
|
runTickScript,
|
|
21181
|
+
runSimpleCapabilityScript,
|
|
21081
21182
|
runPreviewBuild,
|
|
21082
21183
|
advanceManagedGoal,
|
|
21083
21184
|
loadGoalState,
|
|
@@ -21143,7 +21244,7 @@ var init_scripts = __esm({
|
|
|
21143
21244
|
});
|
|
21144
21245
|
|
|
21145
21246
|
// src/stateWorkspace.ts
|
|
21146
|
-
import * as
|
|
21247
|
+
import * as fs50 from "fs";
|
|
21147
21248
|
import * as path47 from "path";
|
|
21148
21249
|
function tenantId(config) {
|
|
21149
21250
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
@@ -21152,8 +21253,8 @@ function tenantId(config) {
|
|
|
21152
21253
|
}
|
|
21153
21254
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
21154
21255
|
const target = path47.join(cwd, RUNTIME_ROOT, relativePath);
|
|
21155
|
-
|
|
21156
|
-
|
|
21256
|
+
fs50.mkdirSync(path47.dirname(target), { recursive: true });
|
|
21257
|
+
fs50.writeFileSync(target, content, "utf8");
|
|
21157
21258
|
}
|
|
21158
21259
|
function record(value) {
|
|
21159
21260
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -21222,7 +21323,7 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
21222
21323
|
if (hydratedWorkspaces.has(key)) return;
|
|
21223
21324
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
21224
21325
|
const root = path47.join(cwd, RUNTIME_ROOT);
|
|
21225
|
-
|
|
21326
|
+
fs50.rmSync(root, { recursive: true, force: true });
|
|
21226
21327
|
await Promise.all([
|
|
21227
21328
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
21228
21329
|
hydratePrefix(backend, tenant, cwd, "memory:"),
|
|
@@ -21309,7 +21410,7 @@ var init_tools = __esm({
|
|
|
21309
21410
|
|
|
21310
21411
|
// src/executor.ts
|
|
21311
21412
|
import { spawn as spawn8 } from "child_process";
|
|
21312
|
-
import * as
|
|
21413
|
+
import * as fs51 from "fs";
|
|
21313
21414
|
import * as os7 from "os";
|
|
21314
21415
|
import * as path48 from "path";
|
|
21315
21416
|
function isMutatingPostflight(scriptName) {
|
|
@@ -22027,7 +22128,7 @@ function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
|
22027
22128
|
// fallback
|
|
22028
22129
|
];
|
|
22029
22130
|
for (const c of candidates) {
|
|
22030
|
-
if (
|
|
22131
|
+
if (fs51.existsSync(c)) return c;
|
|
22031
22132
|
}
|
|
22032
22133
|
return candidates[0];
|
|
22033
22134
|
}
|
|
@@ -22143,7 +22244,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
22143
22244
|
async function runShellEntry(entry, ctx, profile) {
|
|
22144
22245
|
const shellName = entry.shell;
|
|
22145
22246
|
const shellPath = path48.join(profile.dir, shellName);
|
|
22146
|
-
if (!
|
|
22247
|
+
if (!fs51.existsSync(shellPath)) {
|
|
22147
22248
|
ctx.skipAgent = true;
|
|
22148
22249
|
ctx.output.exitCode = 99;
|
|
22149
22250
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -22222,9 +22323,9 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22222
22323
|
}
|
|
22223
22324
|
let sideChannelText = "";
|
|
22224
22325
|
try {
|
|
22225
|
-
if (
|
|
22226
|
-
sideChannelText =
|
|
22227
|
-
|
|
22326
|
+
if (fs51.existsSync(outputFile)) {
|
|
22327
|
+
sideChannelText = fs51.readFileSync(outputFile, "utf-8");
|
|
22328
|
+
fs51.rmSync(outputFile, { force: true });
|
|
22228
22329
|
}
|
|
22229
22330
|
} catch {
|
|
22230
22331
|
}
|
|
@@ -22717,6 +22818,7 @@ async function runLinearCapabilityWorkflow(parent, workflow, capability, base) {
|
|
|
22717
22818
|
runSubjectLabel: label,
|
|
22718
22819
|
workflowStep: label,
|
|
22719
22820
|
workflowStepIndex: index + 1,
|
|
22821
|
+
workflowExecutionKey: [capability.slug, label, index + 1].join(":"),
|
|
22720
22822
|
workflowStepReason: step.reason,
|
|
22721
22823
|
workflowContinueOn: step.continueOn ?? []
|
|
22722
22824
|
}
|
|
@@ -22853,6 +22955,12 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22853
22955
|
runSubjectLabel: step.id,
|
|
22854
22956
|
workflowStep: step.id,
|
|
22855
22957
|
workflowStepIndex: index + 1,
|
|
22958
|
+
workflowExecutionKey: graphWorkflowExecutionKey(
|
|
22959
|
+
base.preloadedData?.workflowExecutionKey,
|
|
22960
|
+
capability.slug,
|
|
22961
|
+
step.id,
|
|
22962
|
+
state.transitionCounts
|
|
22963
|
+
),
|
|
22856
22964
|
workflowStepReason: step.reason,
|
|
22857
22965
|
workflowContinueOn: step.continueOn ?? []
|
|
22858
22966
|
}
|
|
@@ -22919,6 +23027,15 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
|
|
|
22919
23027
|
await checkpoint?.(state);
|
|
22920
23028
|
return withWorkflowBoundaryEval(capability, { ...result, workflowState: state });
|
|
22921
23029
|
}
|
|
23030
|
+
function graphWorkflowExecutionKey(parentExecutionKey, workflowSlug, stepId, transitionCounts) {
|
|
23031
|
+
const transitionHistory = Object.entries(transitionCounts).filter(([, count]) => count > 0).sort(([left], [right]) => left.localeCompare(right)).map(([transition, count]) => `${transition}=${count}`).join(",");
|
|
23032
|
+
return [
|
|
23033
|
+
typeof parentExecutionKey === "string" && parentExecutionKey.length > 0 ? parentExecutionKey : void 0,
|
|
23034
|
+
workflowSlug,
|
|
23035
|
+
stepId,
|
|
23036
|
+
transitionHistory || "initial"
|
|
23037
|
+
].filter((part) => part !== void 0).join(":");
|
|
23038
|
+
}
|
|
22922
23039
|
function mergeWorkflowResults(state, results) {
|
|
22923
23040
|
for (const result of results ?? []) {
|
|
22924
23041
|
Object.assign(state.facts, result.facts);
|
|
@@ -24478,7 +24595,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
24478
24595
|
|
|
24479
24596
|
// src/kody-cli.ts
|
|
24480
24597
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
24481
|
-
import * as
|
|
24598
|
+
import * as fs52 from "fs";
|
|
24482
24599
|
import * as path49 from "path";
|
|
24483
24600
|
|
|
24484
24601
|
// src/app-auth.ts
|
|
@@ -25298,9 +25415,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
25298
25415
|
return void 0;
|
|
25299
25416
|
}
|
|
25300
25417
|
function detectPackageManager2(cwd) {
|
|
25301
|
-
if (
|
|
25302
|
-
if (
|
|
25303
|
-
if (
|
|
25418
|
+
if (fs52.existsSync(path49.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
25419
|
+
if (fs52.existsSync(path49.join(cwd, "yarn.lock"))) return "yarn";
|
|
25420
|
+
if (fs52.existsSync(path49.join(cwd, "bun.lockb"))) return "bun";
|
|
25304
25421
|
return "npm";
|
|
25305
25422
|
}
|
|
25306
25423
|
function shouldChainScheduledWatch(match) {
|
|
@@ -25404,8 +25521,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
25404
25521
|
const logPath = lastRunLogPath(cwd);
|
|
25405
25522
|
let tail = "";
|
|
25406
25523
|
try {
|
|
25407
|
-
if (
|
|
25408
|
-
const content =
|
|
25524
|
+
if (fs52.existsSync(logPath)) {
|
|
25525
|
+
const content = fs52.readFileSync(logPath, "utf-8");
|
|
25409
25526
|
tail = content.slice(-3e3);
|
|
25410
25527
|
}
|
|
25411
25528
|
} catch {
|
|
@@ -25493,9 +25610,9 @@ async function runCi(argv) {
|
|
|
25493
25610
|
forceRunCliArgs = { goal: envForceMessage };
|
|
25494
25611
|
}
|
|
25495
25612
|
}
|
|
25496
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
25613
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs52.existsSync(dispatchEventPath)) {
|
|
25497
25614
|
try {
|
|
25498
|
-
const evt = JSON.parse(
|
|
25615
|
+
const evt = JSON.parse(fs52.readFileSync(dispatchEventPath, "utf-8"));
|
|
25499
25616
|
const inputs = objectValue2(evt.inputs);
|
|
25500
25617
|
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
25501
25618
|
const sessionInput = String(inputs?.sessionId ?? "");
|
|
@@ -25903,7 +26020,7 @@ init_repoWorkspace();
|
|
|
25903
26020
|
|
|
25904
26021
|
// src/scripts/brainTurnLog.ts
|
|
25905
26022
|
init_runtimePaths();
|
|
25906
|
-
import * as
|
|
26023
|
+
import * as fs53 from "fs";
|
|
25907
26024
|
import * as path50 from "path";
|
|
25908
26025
|
import posixPath4 from "path/posix";
|
|
25909
26026
|
var live = /* @__PURE__ */ new Map();
|
|
@@ -25912,8 +26029,8 @@ function brainEventsFilePath(dir, chatId) {
|
|
|
25912
26029
|
}
|
|
25913
26030
|
function lastPersistedSeq(dir, chatId) {
|
|
25914
26031
|
const p = brainEventsFilePath(dir, chatId);
|
|
25915
|
-
if (!
|
|
25916
|
-
const lines =
|
|
26032
|
+
if (!fs53.existsSync(p)) return 0;
|
|
26033
|
+
const lines = fs53.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
25917
26034
|
if (lines.length === 0) return 0;
|
|
25918
26035
|
try {
|
|
25919
26036
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -25923,9 +26040,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
25923
26040
|
}
|
|
25924
26041
|
function readSince(dir, chatId, since) {
|
|
25925
26042
|
const p = brainEventsFilePath(dir, chatId);
|
|
25926
|
-
if (!
|
|
26043
|
+
if (!fs53.existsSync(p)) return [];
|
|
25927
26044
|
const out = [];
|
|
25928
|
-
for (const line of
|
|
26045
|
+
for (const line of fs53.readFileSync(p, "utf-8").split("\n")) {
|
|
25929
26046
|
if (!line) continue;
|
|
25930
26047
|
try {
|
|
25931
26048
|
const rec = JSON.parse(line);
|
|
@@ -25951,12 +26068,12 @@ function beginTurn(dir, chatId) {
|
|
|
25951
26068
|
};
|
|
25952
26069
|
live.set(chatId, state);
|
|
25953
26070
|
const p = brainEventsFilePath(dir, chatId);
|
|
25954
|
-
|
|
26071
|
+
fs53.mkdirSync(path50.dirname(p), { recursive: true });
|
|
25955
26072
|
return (event) => {
|
|
25956
26073
|
state.seq += 1;
|
|
25957
26074
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
25958
26075
|
try {
|
|
25959
|
-
|
|
26076
|
+
fs53.appendFileSync(p, `${JSON.stringify(rec)}
|
|
25960
26077
|
`);
|
|
25961
26078
|
} catch (err) {
|
|
25962
26079
|
process.stderr.write(
|
|
@@ -25995,7 +26112,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
25995
26112
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
25996
26113
|
};
|
|
25997
26114
|
try {
|
|
25998
|
-
|
|
26115
|
+
fs53.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
25999
26116
|
`);
|
|
26000
26117
|
} catch {
|
|
26001
26118
|
}
|
|
@@ -28228,7 +28345,7 @@ async function poolServe() {
|
|
|
28228
28345
|
|
|
28229
28346
|
// src/servers/runner-serve.ts
|
|
28230
28347
|
import { spawn as spawn9 } from "child_process";
|
|
28231
|
-
import * as
|
|
28348
|
+
import * as fs54 from "fs";
|
|
28232
28349
|
import { createServer as createServer6 } from "http";
|
|
28233
28350
|
var DEFAULT_PORT2 = 8080;
|
|
28234
28351
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -28363,8 +28480,8 @@ async function defaultRunJob(job) {
|
|
|
28363
28480
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
28364
28481
|
const branch = job.ref ?? "main";
|
|
28365
28482
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
28366
|
-
|
|
28367
|
-
|
|
28483
|
+
fs54.rmSync(workdir, { recursive: true, force: true });
|
|
28484
|
+
fs54.mkdirSync(workdir, { recursive: true });
|
|
28368
28485
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
28369
28486
|
const target = job.runRequest.target;
|
|
28370
28487
|
const interactive = target.type === "chat";
|
|
@@ -74,7 +74,11 @@
|
|
|
74
74
|
"scripts": {
|
|
75
75
|
"preflight": [
|
|
76
76
|
{ "script": "loadSimpleCapability" },
|
|
77
|
-
{ "script": "prepareCapabilityDelivery" }
|
|
77
|
+
{ "script": "prepareCapabilityDelivery" },
|
|
78
|
+
{
|
|
79
|
+
"script": "runSimpleCapabilityScript",
|
|
80
|
+
"runWhen": { "data.capabilityExecution": "script" }
|
|
81
|
+
}
|
|
78
82
|
],
|
|
79
83
|
"postflight": [
|
|
80
84
|
{ "script": "parseSimpleCapabilityOutput" }
|
|
@@ -36,7 +36,13 @@
|
|
|
36
36
|
},
|
|
37
37
|
"cliTools": [],
|
|
38
38
|
"scripts": {
|
|
39
|
-
"preflight": [
|
|
39
|
+
"preflight": [
|
|
40
|
+
{ "script": "loadSimpleCapability" },
|
|
41
|
+
{
|
|
42
|
+
"script": "runSimpleCapabilityScript",
|
|
43
|
+
"runWhen": { "data.capabilityExecution": "script" }
|
|
44
|
+
}
|
|
45
|
+
],
|
|
40
46
|
"postflight": [{ "script": "parseSimpleCapabilityOutput" }]
|
|
41
47
|
},
|
|
42
48
|
"inputArtifacts": [],
|
|
File without changes
|
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.465",
|
|
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,29 +12,6 @@
|
|
|
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:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
29
|
-
"test:all": "vitest run tests --no-coverage",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"lint": "biome check",
|
|
32
|
-
"lint:fix": "biome check --write",
|
|
33
|
-
"format": "biome format --write",
|
|
34
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
35
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
36
|
-
"prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
37
|
-
},
|
|
38
15
|
"dependencies": {
|
|
39
16
|
"@actions/cache": "^6.0.0",
|
|
40
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -61,5 +38,27 @@
|
|
|
61
38
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
62
39
|
},
|
|
63
40
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
64
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
65
|
-
|
|
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:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
56
|
+
"test:all": "vitest run tests --no-coverage",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"lint": "biome check",
|
|
59
|
+
"lint:fix": "biome check --write",
|
|
60
|
+
"format": "biome format --write",
|
|
61
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
62
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
63
|
+
}
|
|
64
|
+
}
|