@kody-ade/kody-engine 0.2.33 → 0.2.34
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/kody2.js +83 -56
- package/dist/executables/types.ts +0 -2
- package/package.json +14 -15
package/dist/bin/kody2.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@kody-ade/kody-engine",
|
|
6
|
-
version: "0.2.
|
|
6
|
+
version: "0.2.34",
|
|
7
7
|
description: "kody2 \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
8
8
|
license: "MIT",
|
|
9
9
|
type: "module",
|
|
@@ -393,9 +393,6 @@ async function runAgent(opts) {
|
|
|
393
393
|
if (typeof opts.maxTurns === "number" && opts.maxTurns > 0) {
|
|
394
394
|
queryOptions.maxTurns = opts.maxTurns;
|
|
395
395
|
}
|
|
396
|
-
if (typeof opts.maxThinkingTokens === "number" && opts.maxThinkingTokens > 0) {
|
|
397
|
-
queryOptions.maxThinkingTokens = opts.maxThinkingTokens;
|
|
398
|
-
}
|
|
399
396
|
if (typeof opts.systemPromptAppend === "string" && opts.systemPromptAppend.length > 0) {
|
|
400
397
|
queryOptions.systemPrompt = { type: "preset", preset: "claude_code", append: opts.systemPromptAppend };
|
|
401
398
|
}
|
|
@@ -856,7 +853,6 @@ function parseClaudeCode(p, raw) {
|
|
|
856
853
|
model: typeof r.model === "string" ? r.model : "inherit",
|
|
857
854
|
permissionMode,
|
|
858
855
|
maxTurns: typeof r.maxTurns === "number" ? r.maxTurns : null,
|
|
859
|
-
maxThinkingTokens: typeof r.maxThinkingTokens === "number" ? r.maxThinkingTokens : null,
|
|
860
856
|
systemPromptAppend: typeof r.systemPromptAppend === "string" ? r.systemPromptAppend : null,
|
|
861
857
|
tools,
|
|
862
858
|
hooks: Array.isArray(r.hooks) ? r.hooks : [],
|
|
@@ -3219,31 +3215,17 @@ ${truncate2(r.stderr, 2e3)}
|
|
|
3219
3215
|
|
|
3220
3216
|
// src/scripts/requireFeedbackActions.ts
|
|
3221
3217
|
var MIN_ITEMS = 1;
|
|
3222
|
-
var ACTIONABLE_HEADINGS = /^#{1,6}\s+(Concerns|Suggestions|Bugs)\b/i;
|
|
3223
|
-
var NEXT_HEADING = /^#{1,6}\s+/;
|
|
3224
3218
|
var requireFeedbackActions = async (ctx, profile) => {
|
|
3225
3219
|
if (!ctx.data.agentDone) return;
|
|
3226
3220
|
const actions = String(ctx.data.feedbackActions ?? "").trim();
|
|
3227
3221
|
const items = countActionItems(actions);
|
|
3222
|
+
ctx.data.feedbackAgentItemCount = items;
|
|
3228
3223
|
if (items < MIN_ITEMS) {
|
|
3229
3224
|
fail(
|
|
3230
3225
|
ctx,
|
|
3231
3226
|
profile,
|
|
3232
3227
|
actions.length === 0 ? "agent omitted required FEEDBACK_ACTIONS block \u2014 cannot verify that review feedback was addressed" : "agent FEEDBACK_ACTIONS block listed no items \u2014 cannot verify that review feedback was addressed"
|
|
3233
3228
|
);
|
|
3234
|
-
return;
|
|
3235
|
-
}
|
|
3236
|
-
const reviewBody = String(ctx.data.feedback ?? "");
|
|
3237
|
-
const expectedItems = countActionableReviewBullets(reviewBody);
|
|
3238
|
-
ctx.data.feedbackReviewItemCount = expectedItems;
|
|
3239
|
-
ctx.data.feedbackAgentItemCount = items;
|
|
3240
|
-
if (expectedItems > 0 && items < expectedItems) {
|
|
3241
|
-
fail(
|
|
3242
|
-
ctx,
|
|
3243
|
-
profile,
|
|
3244
|
-
`agent FEEDBACK_ACTIONS listed ${items} item(s) but the review has ${expectedItems} actionable bullet(s) under ### Concerns / ### Suggestions / ### Bugs \u2014 every review item must be accounted for`
|
|
3245
|
-
);
|
|
3246
|
-
return;
|
|
3247
3229
|
}
|
|
3248
3230
|
};
|
|
3249
3231
|
function fail(ctx, profile, reason) {
|
|
@@ -3265,25 +3247,6 @@ function countActionItems(block) {
|
|
|
3265
3247
|
}
|
|
3266
3248
|
return count;
|
|
3267
3249
|
}
|
|
3268
|
-
function countActionableReviewBullets(reviewBody) {
|
|
3269
|
-
if (!reviewBody.trim()) return 0;
|
|
3270
|
-
const lines = reviewBody.split("\n");
|
|
3271
|
-
let count = 0;
|
|
3272
|
-
let insideActionable = false;
|
|
3273
|
-
for (const raw of lines) {
|
|
3274
|
-
if (ACTIONABLE_HEADINGS.test(raw)) {
|
|
3275
|
-
insideActionable = true;
|
|
3276
|
-
continue;
|
|
3277
|
-
}
|
|
3278
|
-
if (insideActionable && NEXT_HEADING.test(raw)) {
|
|
3279
|
-
insideActionable = false;
|
|
3280
|
-
continue;
|
|
3281
|
-
}
|
|
3282
|
-
if (!insideActionable) continue;
|
|
3283
|
-
if (/^[-*]\s+\S/.test(raw)) count++;
|
|
3284
|
-
}
|
|
3285
|
-
return count;
|
|
3286
|
-
}
|
|
3287
3250
|
|
|
3288
3251
|
// src/scripts/requirePlanDeviations.ts
|
|
3289
3252
|
var requirePlanDeviations = async (ctx, profile) => {
|
|
@@ -3703,6 +3666,44 @@ function summarizeFeedbackActions(block) {
|
|
|
3703
3666
|
}
|
|
3704
3667
|
return summary;
|
|
3705
3668
|
}
|
|
3669
|
+
function extractReviewFileRefs(reviewBody) {
|
|
3670
|
+
if (!reviewBody) return [];
|
|
3671
|
+
const found = /* @__PURE__ */ new Set();
|
|
3672
|
+
const backtick = /`([^`\s]+\.[a-zA-Z]{1,5})(?::\d+(?:-\d+)?)?`/g;
|
|
3673
|
+
let m;
|
|
3674
|
+
while ((m = backtick.exec(reviewBody)) !== null) {
|
|
3675
|
+
const raw = m[1];
|
|
3676
|
+
if (isPlausibleSourcePath(raw)) found.add(raw);
|
|
3677
|
+
}
|
|
3678
|
+
const bare = /(?<![A-Za-z0-9/_.-])((?:[A-Za-z0-9_./-]+\/)+[A-Za-z0-9_.-]+\.[a-zA-Z]{1,5})(?::\d+(?:-\d+)?)?/g;
|
|
3679
|
+
while ((m = bare.exec(reviewBody)) !== null) {
|
|
3680
|
+
const raw = m[1];
|
|
3681
|
+
if (isPlausibleSourcePath(raw)) found.add(raw);
|
|
3682
|
+
}
|
|
3683
|
+
return Array.from(found);
|
|
3684
|
+
}
|
|
3685
|
+
function isPlausibleSourcePath(p) {
|
|
3686
|
+
if (p.startsWith("http://") || p.startsWith("https://")) return false;
|
|
3687
|
+
if (p.startsWith("//")) return false;
|
|
3688
|
+
if (p.startsWith("/")) return false;
|
|
3689
|
+
if (!p.includes("/")) return false;
|
|
3690
|
+
if (/\.(md|rst|txt|png|jpg|jpeg|gif|svg|pdf)$/i.test(p)) return false;
|
|
3691
|
+
const firstSeg = p.slice(0, p.indexOf("/"));
|
|
3692
|
+
if (firstSeg.includes(".")) return false;
|
|
3693
|
+
return true;
|
|
3694
|
+
}
|
|
3695
|
+
function declinedFileRefs(feedbackActions, refs) {
|
|
3696
|
+
if (!feedbackActions.trim() || refs.length === 0) return /* @__PURE__ */ new Set();
|
|
3697
|
+
const declined = /* @__PURE__ */ new Set();
|
|
3698
|
+
for (const raw of feedbackActions.split("\n")) {
|
|
3699
|
+
if (!/^\s*[-*]\s+/.test(raw)) continue;
|
|
3700
|
+
if (!/\bdeclined\s*:/i.test(raw)) continue;
|
|
3701
|
+
for (const ref of refs) {
|
|
3702
|
+
if (raw.includes(ref)) declined.add(ref);
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
return declined;
|
|
3706
|
+
}
|
|
3706
3707
|
function makeAction2(type, payload) {
|
|
3707
3708
|
return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
3708
3709
|
}
|
|
@@ -3715,24 +3716,32 @@ var verifyFixAlignment = async (ctx, profile) => {
|
|
|
3715
3716
|
ctx.data.feedbackActionsSummary = summary;
|
|
3716
3717
|
const committed = Boolean(ctx.data.commitResult?.committed);
|
|
3717
3718
|
if (summary.totalItems === 0) {
|
|
3718
|
-
ctx
|
|
3719
|
-
ctx.output.reason = "fix produced no FEEDBACK_ACTIONS items";
|
|
3720
|
-
ctx.data.agentDone = false;
|
|
3721
|
-
ctx.data.action = makeAction2("FIX_FAILED", {
|
|
3722
|
-
reason: ctx.output.reason,
|
|
3723
|
-
feedbackActionsSummary: summary
|
|
3724
|
-
});
|
|
3725
|
-
return;
|
|
3719
|
+
return failOnce(ctx, "FIX_FAILED", "fix produced no FEEDBACK_ACTIONS items", summary);
|
|
3726
3720
|
}
|
|
3727
3721
|
if (summary.fixedItems > 0 && !committed) {
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3722
|
+
return failOnce(
|
|
3723
|
+
ctx,
|
|
3724
|
+
"FIX_FAILED",
|
|
3725
|
+
`fix claimed ${summary.fixedItems} fixed item(s) but produced no commit`,
|
|
3726
|
+
summary
|
|
3727
|
+
);
|
|
3728
|
+
}
|
|
3729
|
+
const reviewBody = ctx.data.feedback ?? "";
|
|
3730
|
+
const refs = extractReviewFileRefs(reviewBody);
|
|
3731
|
+
const changedFiles = (ctx.data.changedFiles ?? []).map((f) => f.trim()).filter(Boolean);
|
|
3732
|
+
ctx.data.reviewFileRefs = refs;
|
|
3733
|
+
if (refs.length > 0 && committed) {
|
|
3734
|
+
const declined = declinedFileRefs(feedbackActions, refs);
|
|
3735
|
+
const missing = refs.filter((r) => !declined.has(r) && !changedFiles.some((f) => filesMatch(f, r)));
|
|
3736
|
+
if (missing.length > 0) {
|
|
3737
|
+
return failOnce(
|
|
3738
|
+
ctx,
|
|
3739
|
+
"FIX_FAILED",
|
|
3740
|
+
`fix did not touch review-named file(s): ${missing.join(", ")} \u2014 address them or mark declined with a reason`,
|
|
3741
|
+
summary,
|
|
3742
|
+
{ missingFiles: missing, declinedFiles: Array.from(declined), changedFiles }
|
|
3743
|
+
);
|
|
3744
|
+
}
|
|
3736
3745
|
}
|
|
3737
3746
|
if (summary.fixedItems === 0 && summary.declinedItems > 0 && !committed) {
|
|
3738
3747
|
ctx.data.action = makeAction2("FIX_DECLINED", {
|
|
@@ -3741,6 +3750,25 @@ var verifyFixAlignment = async (ctx, profile) => {
|
|
|
3741
3750
|
});
|
|
3742
3751
|
}
|
|
3743
3752
|
};
|
|
3753
|
+
function failOnce(ctx, type, reason, summary, extra) {
|
|
3754
|
+
ctx.output.exitCode = 1;
|
|
3755
|
+
ctx.output.reason = reason;
|
|
3756
|
+
ctx.data.agentDone = false;
|
|
3757
|
+
ctx.data.action = makeAction2(type, {
|
|
3758
|
+
reason,
|
|
3759
|
+
feedbackActionsSummary: summary,
|
|
3760
|
+
...extra ?? {}
|
|
3761
|
+
});
|
|
3762
|
+
}
|
|
3763
|
+
function filesMatch(changedPath, reviewRef) {
|
|
3764
|
+
if (changedPath === reviewRef) return true;
|
|
3765
|
+
if (changedPath.endsWith("/" + reviewRef)) return true;
|
|
3766
|
+
if (reviewRef.endsWith("/" + changedPath)) return true;
|
|
3767
|
+
const a = changedPath.split("/");
|
|
3768
|
+
const b = reviewRef.split("/");
|
|
3769
|
+
if (a[a.length - 1] !== b[b.length - 1]) return false;
|
|
3770
|
+
return a.length >= 2 && b.length >= 2 && a[a.length - 2] === b[b.length - 2];
|
|
3771
|
+
}
|
|
3744
3772
|
|
|
3745
3773
|
// src/scripts/watchStalePrsFlow.ts
|
|
3746
3774
|
function readWatchConfig(ctx) {
|
|
@@ -4000,7 +4028,6 @@ async function runExecutable(profileName, input) {
|
|
|
4000
4028
|
mcpServers: profile.claudeCode.mcpServers,
|
|
4001
4029
|
pluginPaths: pluginPaths.length > 0 ? pluginPaths : void 0,
|
|
4002
4030
|
maxTurns: profile.claudeCode.maxTurns,
|
|
4003
|
-
maxThinkingTokens: profile.claudeCode.maxThinkingTokens,
|
|
4004
4031
|
systemPromptAppend: profile.claudeCode.systemPromptAppend,
|
|
4005
4032
|
settingSources: profile.claudeCode.settingSources
|
|
4006
4033
|
});
|
|
@@ -87,8 +87,6 @@ export interface ClaudeCodeSpec {
|
|
|
87
87
|
permissionMode: "default" | "acceptEdits" | "plan" | "bypassPermissions"
|
|
88
88
|
/** null = unbounded. */
|
|
89
89
|
maxTurns: number | null
|
|
90
|
-
/** Extended-thinking token budget. null = SDK default. */
|
|
91
|
-
maxThinkingTokens: number | null
|
|
92
90
|
/** Text appended on top of Claude Code's baseline system prompt. */
|
|
93
91
|
systemPromptAppend: string | null
|
|
94
92
|
/** SDK built-in tools this executable is allowed to use (capability pack). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.34",
|
|
4
4
|
"description": "kody2 — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,18 +12,6 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"kody2": "tsx bin/kody2.ts",
|
|
17
|
-
"build": "tsup && node scripts/copy-assets.cjs",
|
|
18
|
-
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
19
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
20
|
-
"test:all": "vitest run tests --no-coverage",
|
|
21
|
-
"typecheck": "tsc --noEmit",
|
|
22
|
-
"lint": "biome check",
|
|
23
|
-
"lint:fix": "biome check --write",
|
|
24
|
-
"format": "biome format --write",
|
|
25
|
-
"prepublishOnly": "pnpm build"
|
|
26
|
-
},
|
|
27
15
|
"dependencies": {
|
|
28
16
|
"@anthropic-ai/claude-agent-sdk": "0.2.92"
|
|
29
17
|
},
|
|
@@ -43,5 +31,16 @@
|
|
|
43
31
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
44
32
|
},
|
|
45
33
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
46
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
47
|
-
|
|
34
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"kody2": "tsx bin/kody2.ts",
|
|
37
|
+
"build": "tsup && node scripts/copy-assets.cjs",
|
|
38
|
+
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
39
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
40
|
+
"test:all": "vitest run tests --no-coverage",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"lint": "biome check",
|
|
43
|
+
"lint:fix": "biome check --write",
|
|
44
|
+
"format": "biome format --write"
|
|
45
|
+
}
|
|
46
|
+
}
|