@kody-ade/kody-engine 0.4.406 → 0.4.408
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 +74 -17
- package/package.json +24 -25
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.408",
|
|
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",
|
|
@@ -1885,9 +1885,13 @@ var init_capabilityFolders = __esm({
|
|
|
1885
1885
|
import * as fs5 from "fs";
|
|
1886
1886
|
import * as path6 from "path";
|
|
1887
1887
|
function definitionsRoot(cwd = process.cwd()) {
|
|
1888
|
+
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
1889
|
+
const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
1890
|
+
if (override && overrideCwd && path6.resolve(cwd) === path6.resolve(overrideCwd)) {
|
|
1891
|
+
return path6.resolve(override);
|
|
1892
|
+
}
|
|
1888
1893
|
const hydrated = path6.join(cwd, ".kody-engine", "definitions");
|
|
1889
1894
|
if (fs5.existsSync(hydrated)) return hydrated;
|
|
1890
|
-
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
1891
1895
|
return override ? path6.resolve(override) : hydrated;
|
|
1892
1896
|
}
|
|
1893
1897
|
function capabilitiesRoot(cwd = process.cwd()) {
|
|
@@ -1939,8 +1943,10 @@ function getBuiltinCapabilitiesRoot() {
|
|
|
1939
1943
|
return candidates[0];
|
|
1940
1944
|
}
|
|
1941
1945
|
function getImplementationRoots() {
|
|
1942
|
-
|
|
1943
|
-
|
|
1946
|
+
return getImplementationRootsForCwd(process.cwd());
|
|
1947
|
+
}
|
|
1948
|
+
function getImplementationRootsForCwd(cwd) {
|
|
1949
|
+
return [capabilitiesRoot(cwd), getImplementationsRoot()];
|
|
1944
1950
|
}
|
|
1945
1951
|
function getCapabilityRoots(projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
|
|
1946
1952
|
return [projectCapabilitiesRoot, getBuiltinCapabilitiesRoot()];
|
|
@@ -2013,18 +2019,18 @@ function getCapabilityActionInputs(action, projectCapabilitiesRoot = getProjectC
|
|
|
2013
2019
|
if (!resolved) return null;
|
|
2014
2020
|
return getProfileInputs(resolved.implementation);
|
|
2015
2021
|
}
|
|
2016
|
-
function resolveCapabilityExecution(capability) {
|
|
2022
|
+
function resolveCapabilityExecution(capability, cwd = process.cwd()) {
|
|
2017
2023
|
const firstWorkflowStep = capability.config.workflow?.steps[0];
|
|
2018
2024
|
if (firstWorkflowStep) {
|
|
2019
2025
|
const implementation2 = firstWorkflowStep.implementation ?? firstWorkflowStep.capability;
|
|
2020
2026
|
return { implementation: implementation2, cliArgs: {} };
|
|
2021
2027
|
}
|
|
2022
2028
|
const implementation = capability.config.implementation ?? capability.config.implementations?.[0] ?? (capability.config.role ? capability.slug : void 0) ?? (capability.config.tickScript ? "capability-tick-scripted" : "capability-tick");
|
|
2023
|
-
const cliArgs = implementationDeclaresInput(implementation, "capability") ? { capability: capability.slug } : {};
|
|
2029
|
+
const cliArgs = implementationDeclaresInput(implementation, "capability", cwd) ? { capability: capability.slug } : {};
|
|
2024
2030
|
return { implementation, cliArgs };
|
|
2025
2031
|
}
|
|
2026
|
-
function implementationDeclaresInput(implementation, inputName) {
|
|
2027
|
-
const profilePath = resolveImplementation(implementation);
|
|
2032
|
+
function implementationDeclaresInput(implementation, inputName, cwd = process.cwd()) {
|
|
2033
|
+
const profilePath = resolveImplementation(implementation, getImplementationRootsForCwd(cwd));
|
|
2028
2034
|
if (!profilePath) return false;
|
|
2029
2035
|
try {
|
|
2030
2036
|
const raw = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
|
|
@@ -9285,7 +9291,7 @@ async function planGoalCapabilitySchedule(opts) {
|
|
|
9285
9291
|
}
|
|
9286
9292
|
};
|
|
9287
9293
|
}
|
|
9288
|
-
const dispatch2 = capabilityDispatch(capability);
|
|
9294
|
+
const dispatch2 = capabilityDispatch(capability, opts.cwd);
|
|
9289
9295
|
statuses[due.slug] = markCapabilitySelected(statuses[due.slug], now);
|
|
9290
9296
|
return {
|
|
9291
9297
|
kind: "dispatch",
|
|
@@ -9345,8 +9351,8 @@ async function describeCapabilitySchedule(capability, slug, backend, previous) {
|
|
|
9345
9351
|
lastFiredAt
|
|
9346
9352
|
};
|
|
9347
9353
|
}
|
|
9348
|
-
function capabilityDispatch(capability) {
|
|
9349
|
-
const { implementation, cliArgs } = resolveCapabilityExecution(capability);
|
|
9354
|
+
function capabilityDispatch(capability, cwd) {
|
|
9355
|
+
const { implementation, cliArgs } = resolveCapabilityExecution(capability, cwd);
|
|
9350
9356
|
return { capability: capability.slug, implementation, cliArgs };
|
|
9351
9357
|
}
|
|
9352
9358
|
function compareOldestLastFired(a, b) {
|
|
@@ -11426,12 +11432,54 @@ var init_composePrompt = __esm({
|
|
|
11426
11432
|
});
|
|
11427
11433
|
|
|
11428
11434
|
// src/scripts/postReviewResult.ts
|
|
11435
|
+
function words(value) {
|
|
11436
|
+
return value.trim().split(/\s+/).filter(Boolean);
|
|
11437
|
+
}
|
|
11438
|
+
function removeForbiddenReviewSections(body) {
|
|
11439
|
+
const kept = [];
|
|
11440
|
+
let skipping = false;
|
|
11441
|
+
for (const line of body.split("\n")) {
|
|
11442
|
+
const heading = line.match(/^\s*(?:#{1,6}\s+(.+?)|\*\*(.+?)\*\*)\s*$/);
|
|
11443
|
+
if (heading) {
|
|
11444
|
+
const title = (heading[1] ?? heading[2] ?? "").replace(/[*_`]/g, "").trim();
|
|
11445
|
+
skipping = FORBIDDEN_REVIEW_SECTION.test(title);
|
|
11446
|
+
}
|
|
11447
|
+
if (!skipping) kept.push(line);
|
|
11448
|
+
}
|
|
11449
|
+
return kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
11450
|
+
}
|
|
11451
|
+
function prepareReviewBody(rawBody) {
|
|
11452
|
+
let body = rawBody.trim();
|
|
11453
|
+
const verdict = body.match(/(^|\n)(\s*#{1,6}\s*Verdict\s*:?\s*(?:PASS|CONCERNS|FAIL)\b)/i);
|
|
11454
|
+
if (verdict?.index !== void 0) {
|
|
11455
|
+
body = body.slice(verdict.index + verdict[1].length).trim();
|
|
11456
|
+
}
|
|
11457
|
+
body = removeForbiddenReviewSections(body);
|
|
11458
|
+
const bodyWords = words(body);
|
|
11459
|
+
if (bodyWords.length <= MAX_REVIEW_WORDS) return body;
|
|
11460
|
+
const noteWords = words(REVIEW_TRUNCATION_NOTE);
|
|
11461
|
+
const retainedWordCount = MAX_REVIEW_WORDS - noteWords.length;
|
|
11462
|
+
const matches = [...body.matchAll(/\S+/g)];
|
|
11463
|
+
const retainedEnd = matches[retainedWordCount - 1].index + matches[retainedWordCount - 1][0].length;
|
|
11464
|
+
return `${body.slice(0, retainedEnd).trimEnd()}
|
|
11465
|
+
|
|
11466
|
+
${REVIEW_TRUNCATION_NOTE}`;
|
|
11467
|
+
}
|
|
11429
11468
|
function inferVerdictFromReviewText(body) {
|
|
11430
11469
|
const structuredVerdict = body.match(/"verdict"\s*:\s*"(pass|concerns|fail|partial)"/i);
|
|
11431
11470
|
if (structuredVerdict) {
|
|
11432
11471
|
const value = structuredVerdict[1].toUpperCase();
|
|
11433
11472
|
return value === "PARTIAL" ? "CONCERNS" : value;
|
|
11434
11473
|
}
|
|
11474
|
+
const status = body.match(
|
|
11475
|
+
/(^|\n)\s*(?:#{1,6}\s*)?(?:\*\*Status:\*\*|Status:)\s*(PASS|CONCERNS|FAIL|WARN|NONE|BLOCK|NEEDS_CONTEXT)\b/i
|
|
11476
|
+
);
|
|
11477
|
+
if (status) {
|
|
11478
|
+
const value = status[2].toUpperCase();
|
|
11479
|
+
if (value === "PASS" || value === "NONE") return "PASS";
|
|
11480
|
+
if (value === "CONCERNS" || value === "WARN") return "CONCERNS";
|
|
11481
|
+
return "FAIL";
|
|
11482
|
+
}
|
|
11435
11483
|
if (/\bpartial\b/i.test(body) && /\b(finding|gap|unverified|unverifiable|blocker|issue)s?\b/i.test(body)) {
|
|
11436
11484
|
return "CONCERNS";
|
|
11437
11485
|
}
|
|
@@ -11474,11 +11522,14 @@ function reviewAction(verdict, payload) {
|
|
|
11474
11522
|
function failedAction(reason) {
|
|
11475
11523
|
return { type: "REVIEW_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
11476
11524
|
}
|
|
11477
|
-
var postReviewResult;
|
|
11525
|
+
var MAX_REVIEW_WORDS, REVIEW_TRUNCATION_NOTE, FORBIDDEN_REVIEW_SECTION, postReviewResult;
|
|
11478
11526
|
var init_postReviewResult = __esm({
|
|
11479
11527
|
"src/scripts/postReviewResult.ts"() {
|
|
11480
11528
|
"use strict";
|
|
11481
11529
|
init_issue();
|
|
11530
|
+
MAX_REVIEW_WORDS = 600;
|
|
11531
|
+
REVIEW_TRUNCATION_NOTE = "> Review truncated to the highest-priority findings.";
|
|
11532
|
+
FORBIDDEN_REVIEW_SECTION = /^(?:clean\b|strengths?\b|suggest(?:ion|ed)s?\b|follow[- ]?ups?\b|verification\b|notes?\b|nits?\b|non[- ]issues?\b)/i;
|
|
11482
11533
|
postReviewResult = async (ctx, _profile, agentResult) => {
|
|
11483
11534
|
const prNumber = ctx.data.commentTargetNumber;
|
|
11484
11535
|
if (!prNumber) {
|
|
@@ -11498,7 +11549,7 @@ var init_postReviewResult = __esm({
|
|
|
11498
11549
|
ctx.data.action = failedAction(reason);
|
|
11499
11550
|
return;
|
|
11500
11551
|
}
|
|
11501
|
-
const reviewBody = agentResult.finalText
|
|
11552
|
+
const reviewBody = prepareReviewBody(agentResult.finalText);
|
|
11502
11553
|
if (!reviewBody) {
|
|
11503
11554
|
try {
|
|
11504
11555
|
postPrReviewComment(prNumber, `\u26A0\uFE0F kody review FAILED: agent produced no review body`, ctx.cwd);
|
|
@@ -19827,6 +19878,9 @@ function jobReferenceBlock(profileName, profile, data) {
|
|
|
19827
19878
|
];
|
|
19828
19879
|
return lines.join("\n");
|
|
19829
19880
|
}
|
|
19881
|
+
function shouldPromptForTaskArtifacts(tools) {
|
|
19882
|
+
return tools.some((tool6) => TASK_ARTIFACT_WRITE_TOOLS.has(tool6));
|
|
19883
|
+
}
|
|
19830
19884
|
async function runImplementation(profileName, input) {
|
|
19831
19885
|
const stageStartedAt = Date.now();
|
|
19832
19886
|
let finishRunIndex = null;
|
|
@@ -19977,6 +20031,7 @@ async function runImplementation(profileName, input) {
|
|
|
19977
20031
|
})
|
|
19978
20032
|
};
|
|
19979
20033
|
})() : null;
|
|
20034
|
+
const agentTaskArtifacts = taskArtifacts && shouldPromptForTaskArtifacts(profile.claudeCode.tools) ? taskArtifacts : null;
|
|
19980
20035
|
const ndjsonDir = agentRunDir(input.cwd);
|
|
19981
20036
|
const agentSlug = typeof profile.agent === "string" && profile.agent.length > 0 ? profile.agent : typeof ctx.data.jobAgent === "string" && ctx.data.jobAgent.length > 0 ? ctx.data.jobAgent : null;
|
|
19982
20037
|
const agentIdentityBlock = agentSlug ? frameAgentIdentity(agentSlug, loadAgentIdentity(input.cwd, agentSlug)) : null;
|
|
@@ -20009,7 +20064,7 @@ async function runImplementation(profileName, input) {
|
|
|
20009
20064
|
verbose: input.verbose,
|
|
20010
20065
|
quiet: input.quiet,
|
|
20011
20066
|
ndjsonDir,
|
|
20012
|
-
additionalDirectories:
|
|
20067
|
+
additionalDirectories: agentTaskArtifacts ? [agentTaskArtifacts.absDir] : void 0,
|
|
20013
20068
|
allowedToolsOverride: profile.claudeCode.tools,
|
|
20014
20069
|
permissionModeOverride: profile.claudeCode.permissionMode,
|
|
20015
20070
|
mcpServers: profile.claudeCode.mcpServers.length > 0 ? profile.claudeCode.mcpServers : void 0,
|
|
@@ -20027,7 +20082,7 @@ async function runImplementation(profileName, input) {
|
|
|
20027
20082
|
jobRefBlock,
|
|
20028
20083
|
jobWhyBlock,
|
|
20029
20084
|
profile.claudeCode.systemPromptAppend,
|
|
20030
|
-
|
|
20085
|
+
agentTaskArtifacts?.promptAddendum
|
|
20031
20086
|
].filter((s) => typeof s === "string" && s.length > 0).join("\n\n") || void 0,
|
|
20032
20087
|
cacheable: profile.claudeCode.cacheable,
|
|
20033
20088
|
enableVerifyTool: profile.claudeCode.enableVerifyTool,
|
|
@@ -20684,7 +20739,7 @@ function flattenConfig(obj, prefix = "") {
|
|
|
20684
20739
|
}
|
|
20685
20740
|
return out;
|
|
20686
20741
|
}
|
|
20687
|
-
var MUTATING_POSTFLIGHTS, SHELL_MARKER_RE, MAX_CHAIN_HOPS, DEFAULT_SHELL_TIMEOUT_MS, SIGKILL_GRACE_MS;
|
|
20742
|
+
var MUTATING_POSTFLIGHTS, SHELL_MARKER_RE, TASK_ARTIFACT_WRITE_TOOLS, MAX_CHAIN_HOPS, DEFAULT_SHELL_TIMEOUT_MS, SIGKILL_GRACE_MS;
|
|
20688
20743
|
var init_executor = __esm({
|
|
20689
20744
|
"src/executor.ts"() {
|
|
20690
20745
|
"use strict";
|
|
@@ -20717,6 +20772,7 @@ var init_executor = __esm({
|
|
|
20717
20772
|
"openAgencyModelReviewPr"
|
|
20718
20773
|
]);
|
|
20719
20774
|
SHELL_MARKER_RE = /^KODY_(SKIP_AGENT|PR_URL|REASON|CAPABILITY_REPORT|CAPABILITY_RESULT)=/m;
|
|
20775
|
+
TASK_ARTIFACT_WRITE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "NotebookEdit"]);
|
|
20720
20776
|
MAX_CHAIN_HOPS = 60;
|
|
20721
20777
|
DEFAULT_SHELL_TIMEOUT_MS = 3e5;
|
|
20722
20778
|
SIGKILL_GRACE_MS = 5e3;
|
|
@@ -24346,6 +24402,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
24346
24402
|
const storeRepoUrl = strField(body, "storeRepoUrl");
|
|
24347
24403
|
const storeRef = strField(body, "storeRef");
|
|
24348
24404
|
const runtime = strField(body, "runtime");
|
|
24405
|
+
const conversationId = strField(body, "conversationId") || chatId;
|
|
24349
24406
|
const allowCrossRepo = boolField(body, "allowCrossRepo");
|
|
24350
24407
|
const agentIdentity = agentIdentityField(body);
|
|
24351
24408
|
let turnDriver = opts.driver;
|
|
@@ -24387,7 +24444,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
24387
24444
|
const stateToken = repoToken || envGithubToken();
|
|
24388
24445
|
const sessionFile = sessionFilePath(agentCwd, chatId);
|
|
24389
24446
|
const sessionStore = opts.createStore({
|
|
24390
|
-
sessionId:
|
|
24447
|
+
sessionId: conversationId,
|
|
24391
24448
|
sessionFile,
|
|
24392
24449
|
...repo ? { tenantId: repo } : {}
|
|
24393
24450
|
});
|
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.408",
|
|
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,28 +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: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",
|
|
@@ -58,5 +36,26 @@
|
|
|
58
36
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
59
37
|
},
|
|
60
38
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
61
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
62
|
-
|
|
39
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
40
|
+
"scripts": {
|
|
41
|
+
"kody:run": "tsx bin/kody.ts",
|
|
42
|
+
"serve": "tsx bin/kody.ts serve",
|
|
43
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
44
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
45
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
46
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
47
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
48
|
+
"pretest": "pnpm check:modularity",
|
|
49
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
50
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
51
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
52
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
53
|
+
"test:all": "vitest run tests --no-coverage",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"lint": "biome check",
|
|
56
|
+
"lint:fix": "biome check --write",
|
|
57
|
+
"format": "biome format --write",
|
|
58
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
59
|
+
"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"
|
|
60
|
+
}
|
|
61
|
+
}
|