@kody-ade/kody-engine 0.4.155 → 0.4.157
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
|
@@ -1061,7 +1061,7 @@ var init_loadPriorArt = __esm({
|
|
|
1061
1061
|
// package.json
|
|
1062
1062
|
var package_default = {
|
|
1063
1063
|
name: "@kody-ade/kody-engine",
|
|
1064
|
-
version: "0.4.
|
|
1064
|
+
version: "0.4.157",
|
|
1065
1065
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
1066
1066
|
license: "MIT",
|
|
1067
1067
|
type: "module",
|
|
@@ -2935,7 +2935,7 @@ function autoDispatch(opts) {
|
|
|
2935
2935
|
const authorLogin = String(event.comment?.user?.login ?? "");
|
|
2936
2936
|
const authorType = String(event.comment?.user?.type ?? "");
|
|
2937
2937
|
if (!rawBody.toLowerCase().includes("@kody")) return null;
|
|
2938
|
-
|
|
2938
|
+
const isBotAuthor = authorLogin === "kody-bot" || authorType === "Bot";
|
|
2939
2939
|
if (!associationAllowed(event, opts?.config)) return null;
|
|
2940
2940
|
const body = rawBody.toLowerCase();
|
|
2941
2941
|
const targetNum = Number(event.issue?.number ?? 0);
|
|
@@ -2962,6 +2962,13 @@ function autoDispatch(opts) {
|
|
|
2962
2962
|
if (!executable && !firstToken) {
|
|
2963
2963
|
executable = isPr ? opts?.config?.defaultPrExecutable ?? "fix" : opts?.config?.defaultExecutable ?? null;
|
|
2964
2964
|
}
|
|
2965
|
+
if (isBotAuthor && !consumedFirstToken) {
|
|
2966
|
+
process.stderr.write(
|
|
2967
|
+
`[kody] dispatch: ignoring bot comment without an explicit command (author=${authorLogin || authorType}, firstToken=${firstToken ?? "<none>"})
|
|
2968
|
+
`
|
|
2969
|
+
);
|
|
2970
|
+
return null;
|
|
2971
|
+
}
|
|
2965
2972
|
if (!executable) {
|
|
2966
2973
|
const profileMissing = aliased ? getProfileInputs(aliased) === null : true;
|
|
2967
2974
|
process.stderr.write(
|
|
@@ -4562,40 +4569,73 @@ function writeTaskState(target, number, state, cwd) {
|
|
|
4562
4569
|
|
|
4563
4570
|
// src/scripts/advanceFlow.ts
|
|
4564
4571
|
var API_TIMEOUT_MS3 = 3e4;
|
|
4572
|
+
var FLOW_HOP_CAP = 25;
|
|
4573
|
+
function ghComment(issueNumber, body, cwd, label) {
|
|
4574
|
+
try {
|
|
4575
|
+
execFileSync8("gh", ["issue", "comment", String(issueNumber), "--body", body], {
|
|
4576
|
+
timeout: API_TIMEOUT_MS3,
|
|
4577
|
+
cwd,
|
|
4578
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4579
|
+
});
|
|
4580
|
+
} catch (err) {
|
|
4581
|
+
process.stderr.write(
|
|
4582
|
+
`[kody advanceFlow] ${label} on issue #${issueNumber} failed: ${err instanceof Error ? err.message : String(err)}
|
|
4583
|
+
`
|
|
4584
|
+
);
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4565
4587
|
var advanceFlow = async (ctx, profile) => {
|
|
4566
4588
|
const state = ctx.data.taskState;
|
|
4567
4589
|
const flow = state?.flow;
|
|
4568
4590
|
if (!flow?.issueNumber) return;
|
|
4591
|
+
const curState = state;
|
|
4592
|
+
let issueState;
|
|
4593
|
+
try {
|
|
4594
|
+
issueState = readTaskState("issue", flow.issueNumber, ctx.cwd);
|
|
4595
|
+
} catch {
|
|
4596
|
+
issueState = curState;
|
|
4597
|
+
}
|
|
4569
4598
|
const targetType = ctx.data.commentTargetType;
|
|
4570
4599
|
const action = ctx.data.action;
|
|
4600
|
+
let nextIssueState = issueState;
|
|
4571
4601
|
if (targetType === "pr" && action) {
|
|
4602
|
+
nextIssueState = reduce(issueState, profile.name, action, profile.phase);
|
|
4603
|
+
if (state?.core.prUrl && !nextIssueState.core.prUrl) nextIssueState.core.prUrl = state.core.prUrl;
|
|
4604
|
+
}
|
|
4605
|
+
const prevHops = issueState.flow?.hops ?? flow.hops ?? 0;
|
|
4606
|
+
const hops = prevHops + 1;
|
|
4607
|
+
if (hops > FLOW_HOP_CAP) {
|
|
4608
|
+
nextIssueState.flow = void 0;
|
|
4572
4609
|
try {
|
|
4573
|
-
|
|
4574
|
-
issueState.flow = flow;
|
|
4575
|
-
const next = reduce(issueState, profile.name, action, profile.phase);
|
|
4576
|
-
if (state?.core.prUrl && !next.core.prUrl) next.core.prUrl = state.core.prUrl;
|
|
4577
|
-
next.flow = flow;
|
|
4578
|
-
writeTaskState("issue", flow.issueNumber, next, ctx.cwd);
|
|
4610
|
+
writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd);
|
|
4579
4611
|
} catch (err) {
|
|
4580
4612
|
process.stderr.write(
|
|
4581
|
-
`[kody advanceFlow] failed to
|
|
4613
|
+
`[kody advanceFlow] failed to clear looping flow on issue #${flow.issueNumber}: ${err instanceof Error ? err.message : String(err)}
|
|
4582
4614
|
`
|
|
4583
4615
|
);
|
|
4584
4616
|
}
|
|
4617
|
+
ghComment(
|
|
4618
|
+
flow.issueNumber,
|
|
4619
|
+
`\u26A0\uFE0F kody: flow \`${flow.name}\` stopped after ${FLOW_HOP_CAP} steps without completing (loop guard). Re-trigger manually if this was intended.`,
|
|
4620
|
+
ctx.cwd,
|
|
4621
|
+
"loop-guard notice"
|
|
4622
|
+
);
|
|
4623
|
+
process.stderr.write(
|
|
4624
|
+
`[kody advanceFlow] flow '${flow.name}' on issue #${flow.issueNumber} hit hop cap ${FLOW_HOP_CAP}; stopping
|
|
4625
|
+
`
|
|
4626
|
+
);
|
|
4627
|
+
return;
|
|
4585
4628
|
}
|
|
4586
|
-
|
|
4629
|
+
nextIssueState.flow = { ...flow, hops };
|
|
4587
4630
|
try {
|
|
4588
|
-
|
|
4589
|
-
timeout: API_TIMEOUT_MS3,
|
|
4590
|
-
cwd: ctx.cwd,
|
|
4591
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
4592
|
-
});
|
|
4631
|
+
writeTaskState("issue", flow.issueNumber, nextIssueState, ctx.cwd);
|
|
4593
4632
|
} catch (err) {
|
|
4594
4633
|
process.stderr.write(
|
|
4595
|
-
`[kody advanceFlow] failed to
|
|
4634
|
+
`[kody advanceFlow] failed to persist hop count on issue #${flow.issueNumber}: ${err instanceof Error ? err.message : String(err)}
|
|
4596
4635
|
`
|
|
4597
4636
|
);
|
|
4598
4637
|
}
|
|
4638
|
+
ghComment(flow.issueNumber, `@kody ${flow.name}`, ctx.cwd, "re-trigger orchestrator");
|
|
4599
4639
|
};
|
|
4600
4640
|
|
|
4601
4641
|
// src/scripts/brainServe.ts
|
|
@@ -12124,7 +12164,8 @@ var startFlow = async (ctx, profile, _agentResult, args) => {
|
|
|
12124
12164
|
name: flowName,
|
|
12125
12165
|
step: entry,
|
|
12126
12166
|
issueNumber,
|
|
12127
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12167
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12168
|
+
hops: 0
|
|
12128
12169
|
};
|
|
12129
12170
|
}
|
|
12130
12171
|
postKodyComment(target, issueNumber, state, entry, ctx.cwd);
|
|
@@ -82,6 +82,18 @@ open_deploy_pr() {
|
|
|
82
82
|
local body
|
|
83
83
|
body=$(build_pr_body "$new_version" "$changelog_section" "$default_branch" "$release_branch" "$issue_arg")
|
|
84
84
|
|
|
85
|
+
# GitHub rejects a PR body over 65536 chars (GraphQL createPullRequest).
|
|
86
|
+
# A large accumulated CHANGELOG section can blow past it, so clamp: drop the
|
|
87
|
+
# changelog to a budget and rebuild, then hard-truncate as a final guard.
|
|
88
|
+
local body_max=65000
|
|
89
|
+
if (( ${#body} > body_max )); then
|
|
90
|
+
echo "[deploy] PR body ${#body} chars > ${body_max} — truncating changelog" >&2
|
|
91
|
+
local budget=$(( body_max - 2000 ))
|
|
92
|
+
changelog_section="${changelog_section:0:budget}"$'\n\n_…changelog truncated; see CHANGELOG.md on the branch._'
|
|
93
|
+
body=$(build_pr_body "$new_version" "$changelog_section" "$default_branch" "$release_branch" "$issue_arg")
|
|
94
|
+
(( ${#body} > body_max )) && body="${body:0:body_max}"
|
|
95
|
+
fi
|
|
96
|
+
|
|
85
97
|
# Idempotency: reuse an open PR for this branch pair if one exists.
|
|
86
98
|
local existing pr_url
|
|
87
99
|
existing=$(gh pr list --head "$default_branch" --base "$release_branch" --state open --json url --limit 1 2>/dev/null \
|
|
@@ -135,8 +135,22 @@ if [[ "$publish_status" == "failed" ]]; then
|
|
|
135
135
|
fi
|
|
136
136
|
|
|
137
137
|
# ── 5. Deploy PR (default → release branch) ───────────────────────────────
|
|
138
|
+
# Distinguish three outcomes: rc!=0 is a real failure (do NOT mask as no-op);
|
|
139
|
+
# rc==0 + empty URL is a genuine single-branch no-op; rc==0 + URL is success.
|
|
138
140
|
current_step="deploy"
|
|
139
|
-
|
|
141
|
+
set +e
|
|
142
|
+
deploy_pr_url=$(open_deploy_pr "$new_version" "$issue")
|
|
143
|
+
deploy_rc=$?
|
|
144
|
+
set -e
|
|
145
|
+
release_branch="${KODY_CFG_RELEASE_RELEASEBRANCH:-}"
|
|
146
|
+
if [[ "$deploy_rc" -ne 0 ]]; then
|
|
147
|
+
echo "[release] deploy step failed (rc=${deploy_rc}) — published v${new_version} but the ${default_branch}→${release_branch} promotion PR was not opened" >&2
|
|
148
|
+
echo "KODY_REASON=release v${new_version}: published, but the ${default_branch}→${release_branch} deploy PR failed"
|
|
149
|
+
echo "RELEASE_TAG=${tag}"
|
|
150
|
+
[[ -n "$release_url" ]] && echo "RELEASE_URL=${release_url}"
|
|
151
|
+
echo "RELEASE_FAILED=true"
|
|
152
|
+
exit 1
|
|
153
|
+
fi
|
|
140
154
|
if [[ -z "$deploy_pr_url" ]]; then
|
|
141
155
|
echo " (deploy: no-op — single-branch repo)"
|
|
142
156
|
else
|
|
@@ -142,6 +142,18 @@ if [[ "$issue_arg" =~ ^[0-9]+$ && "$issue_arg" != "0" ]]; then
|
|
|
142
142
|
fi
|
|
143
143
|
body=$(build_pr_body "$tracking_line")
|
|
144
144
|
|
|
145
|
+
# GitHub rejects a PR body over 65536 chars (GraphQL createPullRequest). A
|
|
146
|
+
# large accumulated CHANGELOG section can blow past it, so clamp: drop the
|
|
147
|
+
# changelog to a budget and rebuild, then hard-truncate as a final guard.
|
|
148
|
+
body_max=65000
|
|
149
|
+
if (( ${#body} > body_max )); then
|
|
150
|
+
echo "[kody release-deploy] PR body ${#body} chars > ${body_max} — truncating changelog" >&2
|
|
151
|
+
budget=$(( body_max - 2000 ))
|
|
152
|
+
changelog_section="${changelog_section:0:budget}"$'\n\n_…changelog truncated; see CHANGELOG.md on the branch._'
|
|
153
|
+
body=$(build_pr_body "$tracking_line")
|
|
154
|
+
(( ${#body} > body_max )) && body="${body:0:body_max}"
|
|
155
|
+
fi
|
|
156
|
+
|
|
145
157
|
if [[ -n "$existing" ]]; then
|
|
146
158
|
echo " reusing existing deploy PR: ${existing}"
|
|
147
159
|
pr_url="$existing"
|
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.157",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|