@kody-ade/kody-engine 0.4.152 → 0.4.154
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 +224 -166
- package/package.json +1 -1
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.154",
|
|
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",
|
|
@@ -1117,7 +1117,7 @@ var package_default = {
|
|
|
1117
1117
|
};
|
|
1118
1118
|
|
|
1119
1119
|
// src/chat-cli.ts
|
|
1120
|
-
import { execFileSync as
|
|
1120
|
+
import { execFileSync as execFileSync31 } from "child_process";
|
|
1121
1121
|
import * as fs42 from "fs";
|
|
1122
1122
|
import * as path38 from "path";
|
|
1123
1123
|
|
|
@@ -1376,7 +1376,7 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
1376
1376
|
throw new Error(`kody.config.json is invalid JSON: ${msg}`);
|
|
1377
1377
|
}
|
|
1378
1378
|
const quality = raw.quality ?? {};
|
|
1379
|
-
const
|
|
1379
|
+
const git5 = raw.git ?? {};
|
|
1380
1380
|
const github = raw.github ?? {};
|
|
1381
1381
|
const agent = raw.agent ?? {};
|
|
1382
1382
|
if (!agent.model || typeof agent.model !== "string") {
|
|
@@ -1393,7 +1393,7 @@ function loadConfig(projectDir = process.cwd()) {
|
|
|
1393
1393
|
testUnit: typeof quality.testUnit === "string" ? quality.testUnit : ""
|
|
1394
1394
|
},
|
|
1395
1395
|
git: {
|
|
1396
|
-
defaultBranch: typeof
|
|
1396
|
+
defaultBranch: typeof git5.defaultBranch === "string" ? git5.defaultBranch : "main"
|
|
1397
1397
|
},
|
|
1398
1398
|
github: {
|
|
1399
1399
|
owner: String(github.owner),
|
|
@@ -1952,6 +1952,14 @@ async function runAgent(opts) {
|
|
|
1952
1952
|
`[kody agent] transient connection error (attempt ${attempt + 1}/${MAX_CONNECTION_RETRIES + 1}); retrying in ${Math.round(delayMs / 1e3)}s: ${errorMessage}
|
|
1953
1953
|
`
|
|
1954
1954
|
);
|
|
1955
|
+
if (opts.ensureBackend) {
|
|
1956
|
+
try {
|
|
1957
|
+
await opts.ensureBackend();
|
|
1958
|
+
} catch (e) {
|
|
1959
|
+
process.stderr.write(`[kody agent] backend recovery failed: ${e instanceof Error ? e.message : String(e)}
|
|
1960
|
+
`);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1955
1963
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
1956
1964
|
}
|
|
1957
1965
|
const submittedState = getSubmitted?.();
|
|
@@ -2747,7 +2755,7 @@ async function emit2(sink, type, sessionId, suffix, payload) {
|
|
|
2747
2755
|
}
|
|
2748
2756
|
|
|
2749
2757
|
// src/kody-cli.ts
|
|
2750
|
-
import { execFileSync as
|
|
2758
|
+
import { execFileSync as execFileSync30 } from "child_process";
|
|
2751
2759
|
import * as fs41 from "fs";
|
|
2752
2760
|
import * as path37 from "path";
|
|
2753
2761
|
|
|
@@ -3148,7 +3156,7 @@ function coerceBare(spec, value) {
|
|
|
3148
3156
|
}
|
|
3149
3157
|
|
|
3150
3158
|
// src/executor.ts
|
|
3151
|
-
import { execFileSync as
|
|
3159
|
+
import { execFileSync as execFileSync29, spawn as spawn9 } from "child_process";
|
|
3152
3160
|
import * as fs40 from "fs";
|
|
3153
3161
|
import * as path36 from "path";
|
|
3154
3162
|
|
|
@@ -3850,65 +3858,85 @@ function generateLitellmConfigYaml(model) {
|
|
|
3850
3858
|
""
|
|
3851
3859
|
].join("\n");
|
|
3852
3860
|
}
|
|
3853
|
-
|
|
3854
|
-
if (!needsLitellmProxy(model)) return null;
|
|
3855
|
-
if (await checkLitellmHealth(url)) {
|
|
3856
|
-
return { url, kill: () => {
|
|
3857
|
-
} };
|
|
3858
|
-
}
|
|
3859
|
-
let cmd = "litellm";
|
|
3861
|
+
function resolveLitellmCommand() {
|
|
3860
3862
|
try {
|
|
3861
3863
|
execFileSync4("which", ["litellm"], { timeout: 3e3, stdio: "pipe" });
|
|
3864
|
+
return "litellm";
|
|
3862
3865
|
} catch {
|
|
3863
3866
|
try {
|
|
3864
3867
|
execFileSync4("python3", ["-c", "import litellm"], { timeout: 1e4, stdio: "pipe" });
|
|
3865
|
-
|
|
3868
|
+
return "python3";
|
|
3866
3869
|
} catch {
|
|
3867
3870
|
throw new Error("litellm not installed \u2014 run: pip install 'litellm[proxy]'");
|
|
3868
3871
|
}
|
|
3869
3872
|
}
|
|
3870
|
-
|
|
3871
|
-
|
|
3873
|
+
}
|
|
3874
|
+
async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL) {
|
|
3875
|
+
if (!needsLitellmProxy(model)) return null;
|
|
3876
|
+
const cmd = resolveLitellmCommand();
|
|
3872
3877
|
const portMatch = url.match(/:(\d+)/);
|
|
3873
3878
|
const port = portMatch ? portMatch[1] : "4000";
|
|
3874
|
-
const
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
const
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
try {
|
|
3893
|
-
child.kill();
|
|
3894
|
-
} catch {
|
|
3895
|
-
}
|
|
3896
|
-
}
|
|
3897
|
-
};
|
|
3879
|
+
const childEnv = stripBlockingEnv({ ...process.env, ...readDotenvApiKeys(projectDir) });
|
|
3880
|
+
let child;
|
|
3881
|
+
let logPath;
|
|
3882
|
+
const spawnProxy = () => {
|
|
3883
|
+
const configPath = path13.join(os2.tmpdir(), `kody-litellm-${Date.now()}.yaml`);
|
|
3884
|
+
fs14.writeFileSync(configPath, generateLitellmConfigYaml(model));
|
|
3885
|
+
const args = cmd === "litellm" ? ["--config", configPath, "--port", port] : ["-m", "litellm", "--config", configPath, "--port", port];
|
|
3886
|
+
const nextLogPath = path13.join(os2.tmpdir(), `kody-litellm-${Date.now()}.log`);
|
|
3887
|
+
const outFd = fs14.openSync(nextLogPath, "w");
|
|
3888
|
+
child = spawn3(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
|
|
3889
|
+
fs14.closeSync(outFd);
|
|
3890
|
+
logPath = nextLogPath;
|
|
3891
|
+
};
|
|
3892
|
+
const waitForHealth = async () => {
|
|
3893
|
+
const deadline = Date.now() + resolveLitellmTimeoutMs();
|
|
3894
|
+
while (Date.now() < deadline) {
|
|
3895
|
+
await new Promise((r) => setTimeout(r, LITELLM_HEALTH_POLL_INTERVAL_MS));
|
|
3896
|
+
if (await checkLitellmHealth(url)) return true;
|
|
3898
3897
|
}
|
|
3898
|
+
return false;
|
|
3899
|
+
};
|
|
3900
|
+
const readLogTail = () => {
|
|
3901
|
+
if (!logPath) return "";
|
|
3902
|
+
try {
|
|
3903
|
+
return fs14.readFileSync(logPath, "utf-8").slice(-2e3);
|
|
3904
|
+
} catch {
|
|
3905
|
+
return "";
|
|
3906
|
+
}
|
|
3907
|
+
};
|
|
3908
|
+
const killChild = () => {
|
|
3909
|
+
try {
|
|
3910
|
+
child?.kill();
|
|
3911
|
+
} catch {
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
const ensureHealthy = async () => {
|
|
3915
|
+
if (await checkLitellmHealth(url)) return true;
|
|
3916
|
+
const tail = readLogTail();
|
|
3917
|
+
process.stderr.write(
|
|
3918
|
+
`[kody litellm] proxy unreachable mid-run; restarting.${tail ? ` Last log:
|
|
3919
|
+
${tail}
|
|
3920
|
+
` : "\n"}`
|
|
3921
|
+
);
|
|
3922
|
+
killChild();
|
|
3923
|
+
spawnProxy();
|
|
3924
|
+
return waitForHealth();
|
|
3925
|
+
};
|
|
3926
|
+
if (await checkLitellmHealth(url)) {
|
|
3927
|
+
return { url, kill: killChild, ensureHealthy };
|
|
3899
3928
|
}
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3929
|
+
spawnProxy();
|
|
3930
|
+
if (!await waitForHealth()) {
|
|
3931
|
+
const tail = readLogTail();
|
|
3932
|
+
killChild();
|
|
3933
|
+
const seconds = Math.round(resolveLitellmTimeoutMs() / 1e3);
|
|
3934
|
+
throw new Error(
|
|
3935
|
+
`LiteLLM proxy failed to start within ${seconds}s (KODY_LITELLM_TIMEOUT_SEC overrides). Log tail:
|
|
3936
|
+
${tail}`
|
|
3937
|
+
);
|
|
3908
3938
|
}
|
|
3909
|
-
|
|
3910
|
-
throw new Error(`LiteLLM proxy failed to start within ${seconds}s (KODY_LITELLM_TIMEOUT_SEC overrides). Log tail:
|
|
3911
|
-
${logTail}`);
|
|
3939
|
+
return { url, kill: killChild, ensureHealthy };
|
|
3912
3940
|
}
|
|
3913
3941
|
function readDotenvApiKeys(projectDir) {
|
|
3914
3942
|
const dotenvPath = path13.join(projectDir, ".env");
|
|
@@ -7501,6 +7529,7 @@ var dispatchNextTask = async (ctx) => {
|
|
|
7501
7529
|
|
|
7502
7530
|
// src/pr.ts
|
|
7503
7531
|
init_issue();
|
|
7532
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
7504
7533
|
function prMergeStatus(prNumber, cwd) {
|
|
7505
7534
|
try {
|
|
7506
7535
|
const out = gh(
|
|
@@ -7620,6 +7649,51 @@ function recoverSourceIssueNumber(existingBody, branch, prNumber) {
|
|
|
7620
7649
|
}
|
|
7621
7650
|
return null;
|
|
7622
7651
|
}
|
|
7652
|
+
var ALREADY_EXISTS_RE = /pull request .*already exists|already exists for/i;
|
|
7653
|
+
function isAlreadyExistsError(err) {
|
|
7654
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7655
|
+
return ALREADY_EXISTS_RE.test(msg);
|
|
7656
|
+
}
|
|
7657
|
+
function git2(args, cwd) {
|
|
7658
|
+
return execFileSync13("git", args, {
|
|
7659
|
+
encoding: "utf-8",
|
|
7660
|
+
timeout: 3e4,
|
|
7661
|
+
cwd,
|
|
7662
|
+
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
7663
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7664
|
+
}).trim();
|
|
7665
|
+
}
|
|
7666
|
+
function updateExistingPr(existing, body, draft, cwd) {
|
|
7667
|
+
const stripped = existing.url.replace(/^https:\/\/github\.com\//, "");
|
|
7668
|
+
const [owner, repo] = stripped.split("/");
|
|
7669
|
+
try {
|
|
7670
|
+
gh(["api", "--method", "PATCH", `repos/${owner}/${repo}/pulls/${existing.number}`, "-f", `body=${body}`], { cwd });
|
|
7671
|
+
} catch (err) {
|
|
7672
|
+
throw new Error(`gh api PATCH #${existing.number} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7673
|
+
}
|
|
7674
|
+
return { url: existing.url, number: existing.number, draft, action: "updated" };
|
|
7675
|
+
}
|
|
7676
|
+
function createPr(branch, base, title, body, draft, cwd) {
|
|
7677
|
+
const args = ["pr", "create", "--head", branch, "--base", base, "--title", title, "--body-file", "-"];
|
|
7678
|
+
if (draft) args.push("--draft");
|
|
7679
|
+
const url = gh(args, { input: body, cwd }).trim();
|
|
7680
|
+
const match = url.match(/\/pull\/(\d+)$/);
|
|
7681
|
+
const number = match ? parseInt(match[1], 10) : 0;
|
|
7682
|
+
return { url, number, draft, action: "created" };
|
|
7683
|
+
}
|
|
7684
|
+
function recoverFromExistingPr(branch, base, title, body, draft, cwd) {
|
|
7685
|
+
const raced = findExistingPr(branch, cwd);
|
|
7686
|
+
if (raced) return updateExistingPr(raced, body, draft, cwd);
|
|
7687
|
+
try {
|
|
7688
|
+
git2(["push", "origin", "--delete", branch], cwd);
|
|
7689
|
+
} catch {
|
|
7690
|
+
}
|
|
7691
|
+
const push = pushWithRetry({ cwd, branch, setUpstream: true });
|
|
7692
|
+
if (!push.ok) {
|
|
7693
|
+
throw new Error(`re-push after deleting orphaned branch '${branch}' failed: ${push.reason}`);
|
|
7694
|
+
}
|
|
7695
|
+
return createPr(branch, base, title, body, draft, cwd);
|
|
7696
|
+
}
|
|
7623
7697
|
function ensurePr(opts) {
|
|
7624
7698
|
const existing = findExistingPr(opts.branch, opts.cwd);
|
|
7625
7699
|
const effectiveIssueNumber = existing ? recoverSourceIssueNumber(existing.body, opts.branch, existing.number) ?? opts.issueNumber : opts.issueNumber;
|
|
@@ -7627,36 +7701,15 @@ function ensurePr(opts) {
|
|
|
7627
7701
|
const title = buildPrTitle(effectiveOpts.issueNumber, effectiveOpts.issueTitle, effectiveOpts.draft);
|
|
7628
7702
|
const body = buildPrBody(effectiveOpts);
|
|
7629
7703
|
if (existing) {
|
|
7630
|
-
|
|
7631
|
-
const [owner, repo] = stripped.split("/");
|
|
7632
|
-
try {
|
|
7633
|
-
gh(["api", "--method", "PATCH", `repos/${owner}/${repo}/pulls/${existing.number}`, "-f", `body=${body}`], {
|
|
7634
|
-
cwd: opts.cwd
|
|
7635
|
-
});
|
|
7636
|
-
} catch (err) {
|
|
7637
|
-
throw new Error(`gh api PATCH #${existing.number} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7638
|
-
}
|
|
7639
|
-
return { url: existing.url, number: existing.number, draft: opts.draft, action: "updated" };
|
|
7704
|
+
return updateExistingPr(existing, body, opts.draft, opts.cwd);
|
|
7640
7705
|
}
|
|
7641
7706
|
const base = opts.baseBranch && opts.baseBranch.length > 0 ? opts.baseBranch : opts.defaultBranch;
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
opts.branch,
|
|
7647
|
-
|
|
7648
|
-
base,
|
|
7649
|
-
"--title",
|
|
7650
|
-
title,
|
|
7651
|
-
"--body-file",
|
|
7652
|
-
"-"
|
|
7653
|
-
];
|
|
7654
|
-
if (opts.draft) args.push("--draft");
|
|
7655
|
-
const output = gh(args, { input: body, cwd: opts.cwd });
|
|
7656
|
-
const url = output.trim();
|
|
7657
|
-
const match = url.match(/\/pull\/(\d+)$/);
|
|
7658
|
-
const number = match ? parseInt(match[1], 10) : 0;
|
|
7659
|
-
return { url, number, draft: opts.draft, action: "created" };
|
|
7707
|
+
try {
|
|
7708
|
+
return createPr(opts.branch, base, title, body, opts.draft, opts.cwd);
|
|
7709
|
+
} catch (err) {
|
|
7710
|
+
if (!isAlreadyExistsError(err)) throw err;
|
|
7711
|
+
return recoverFromExistingPr(opts.branch, base, title, body, opts.draft, opts.cwd);
|
|
7712
|
+
}
|
|
7660
7713
|
}
|
|
7661
7714
|
|
|
7662
7715
|
// src/scripts/ensurePr.ts
|
|
@@ -7933,7 +7986,7 @@ var finalizeTerminal = async (ctx) => {
|
|
|
7933
7986
|
|
|
7934
7987
|
// src/scripts/finishFlow.ts
|
|
7935
7988
|
init_issue();
|
|
7936
|
-
import { execFileSync as
|
|
7989
|
+
import { execFileSync as execFileSync14 } from "child_process";
|
|
7937
7990
|
var TERMINAL_PHASE = {
|
|
7938
7991
|
"review-passed": { phase: "shipped", status: "succeeded" },
|
|
7939
7992
|
"fix-applied": { phase: "shipped", status: "succeeded" },
|
|
@@ -7973,7 +8026,7 @@ var finishFlow = async (ctx, profile, _agentResult, args) => {
|
|
|
7973
8026
|
**PR:** ${state.core.prUrl}` : "";
|
|
7974
8027
|
const body = `${icon} kody flow \`${flowName}\` finished \u2014 \`${reason}\`${prSuffix}`;
|
|
7975
8028
|
try {
|
|
7976
|
-
|
|
8029
|
+
execFileSync14("gh", ["issue", "comment", String(issueNumber), "--body", body], {
|
|
7977
8030
|
timeout: API_TIMEOUT_MS6,
|
|
7978
8031
|
cwd: ctx.cwd,
|
|
7979
8032
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -8003,9 +8056,9 @@ var finishFlow = async (ctx, profile, _agentResult, args) => {
|
|
|
8003
8056
|
};
|
|
8004
8057
|
|
|
8005
8058
|
// src/branch.ts
|
|
8006
|
-
import { execFileSync as
|
|
8007
|
-
function
|
|
8008
|
-
return
|
|
8059
|
+
import { execFileSync as execFileSync15 } from "child_process";
|
|
8060
|
+
function git3(args, cwd) {
|
|
8061
|
+
return execFileSync15("git", args, {
|
|
8009
8062
|
encoding: "utf-8",
|
|
8010
8063
|
timeout: 3e4,
|
|
8011
8064
|
cwd,
|
|
@@ -8018,15 +8071,15 @@ function deriveBranchName(issueNumber, title) {
|
|
|
8018
8071
|
return slug ? `${issueNumber}-${slug}` : `${issueNumber}-task`;
|
|
8019
8072
|
}
|
|
8020
8073
|
function getCurrentBranch(cwd) {
|
|
8021
|
-
return
|
|
8074
|
+
return git3(["branch", "--show-current"], cwd);
|
|
8022
8075
|
}
|
|
8023
8076
|
function resetWorkingTree(cwd) {
|
|
8024
8077
|
try {
|
|
8025
|
-
|
|
8078
|
+
execFileSync15("git", ["reset", "--hard", "HEAD"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
|
|
8026
8079
|
} catch {
|
|
8027
8080
|
}
|
|
8028
8081
|
try {
|
|
8029
|
-
|
|
8082
|
+
execFileSync15("git", ["clean", "-fd"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
|
|
8030
8083
|
} catch {
|
|
8031
8084
|
}
|
|
8032
8085
|
}
|
|
@@ -8038,14 +8091,14 @@ function checkoutPrBranch(prNumber, cwd) {
|
|
|
8038
8091
|
GH_TOKEN: process.env.GH_PAT?.trim() || process.env.GH_TOKEN || ""
|
|
8039
8092
|
};
|
|
8040
8093
|
try {
|
|
8041
|
-
|
|
8094
|
+
execFileSync15("git", ["reset", "--hard", "HEAD"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
|
|
8042
8095
|
} catch {
|
|
8043
8096
|
}
|
|
8044
8097
|
try {
|
|
8045
|
-
|
|
8098
|
+
execFileSync15("git", ["clean", "-fd"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
|
|
8046
8099
|
} catch {
|
|
8047
8100
|
}
|
|
8048
|
-
|
|
8101
|
+
execFileSync15("gh", ["pr", "checkout", String(prNumber)], {
|
|
8049
8102
|
cwd,
|
|
8050
8103
|
env,
|
|
8051
8104
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -8055,21 +8108,21 @@ function checkoutPrBranch(prNumber, cwd) {
|
|
|
8055
8108
|
}
|
|
8056
8109
|
function mergeBase(baseBranch, cwd) {
|
|
8057
8110
|
try {
|
|
8058
|
-
|
|
8111
|
+
git3(["fetch", "origin", baseBranch], cwd);
|
|
8059
8112
|
} catch {
|
|
8060
8113
|
return "error";
|
|
8061
8114
|
}
|
|
8062
8115
|
try {
|
|
8063
|
-
|
|
8116
|
+
git3(["merge", `origin/${baseBranch}`, "--no-edit", "--no-ff"], cwd);
|
|
8064
8117
|
return "clean";
|
|
8065
8118
|
} catch {
|
|
8066
8119
|
try {
|
|
8067
|
-
const unmerged =
|
|
8120
|
+
const unmerged = git3(["diff", "--name-only", "--diff-filter=U"], cwd);
|
|
8068
8121
|
if (unmerged.length > 0) return "conflict";
|
|
8069
8122
|
} catch {
|
|
8070
8123
|
}
|
|
8071
8124
|
try {
|
|
8072
|
-
|
|
8125
|
+
git3(["merge", "--abort"], cwd);
|
|
8073
8126
|
} catch {
|
|
8074
8127
|
}
|
|
8075
8128
|
return "error";
|
|
@@ -8083,26 +8136,26 @@ function ensureFeatureBranch(issueNumber, title, defaultBranch2, cwd, baseBranch
|
|
|
8083
8136
|
return { branch: branchName, created: false };
|
|
8084
8137
|
}
|
|
8085
8138
|
try {
|
|
8086
|
-
|
|
8139
|
+
git3(["fetch", "origin"], cwd);
|
|
8087
8140
|
} catch {
|
|
8088
8141
|
}
|
|
8089
8142
|
let originBranchExists = false;
|
|
8090
8143
|
try {
|
|
8091
|
-
|
|
8144
|
+
git3(["rev-parse", "--verify", "--quiet", `refs/remotes/origin/${branchName}`], cwd);
|
|
8092
8145
|
originBranchExists = true;
|
|
8093
8146
|
} catch {
|
|
8094
8147
|
}
|
|
8095
8148
|
if (originBranchExists && baseBranch && baseBranch !== defaultBranch2) {
|
|
8096
8149
|
let baseExists = false;
|
|
8097
8150
|
try {
|
|
8098
|
-
|
|
8151
|
+
git3(["rev-parse", "--verify", `origin/${baseBranch}`], cwd);
|
|
8099
8152
|
baseExists = true;
|
|
8100
8153
|
} catch {
|
|
8101
8154
|
}
|
|
8102
8155
|
if (baseExists) {
|
|
8103
8156
|
let descendsFromBase = false;
|
|
8104
8157
|
try {
|
|
8105
|
-
|
|
8158
|
+
git3(["merge-base", "--is-ancestor", `origin/${baseBranch}`, `origin/${branchName}`], cwd);
|
|
8106
8159
|
descendsFromBase = true;
|
|
8107
8160
|
} catch {
|
|
8108
8161
|
}
|
|
@@ -8112,15 +8165,15 @@ function ensureFeatureBranch(issueNumber, title, defaultBranch2, cwd, baseBranch
|
|
|
8112
8165
|
`
|
|
8113
8166
|
);
|
|
8114
8167
|
try {
|
|
8115
|
-
|
|
8168
|
+
git3(["push", "origin", "--delete", branchName], cwd);
|
|
8116
8169
|
} catch {
|
|
8117
8170
|
}
|
|
8118
8171
|
try {
|
|
8119
|
-
|
|
8172
|
+
git3(["update-ref", "-d", `refs/remotes/origin/${branchName}`], cwd);
|
|
8120
8173
|
} catch {
|
|
8121
8174
|
}
|
|
8122
8175
|
try {
|
|
8123
|
-
|
|
8176
|
+
git3(["branch", "-D", branchName], cwd);
|
|
8124
8177
|
} catch {
|
|
8125
8178
|
}
|
|
8126
8179
|
originBranchExists = false;
|
|
@@ -8128,17 +8181,17 @@ function ensureFeatureBranch(issueNumber, title, defaultBranch2, cwd, baseBranch
|
|
|
8128
8181
|
}
|
|
8129
8182
|
}
|
|
8130
8183
|
if (originBranchExists) {
|
|
8131
|
-
|
|
8184
|
+
git3(["checkout", branchName], cwd);
|
|
8132
8185
|
try {
|
|
8133
|
-
|
|
8186
|
+
git3(["pull", "origin", branchName], cwd);
|
|
8134
8187
|
} catch {
|
|
8135
8188
|
}
|
|
8136
8189
|
if (!baseBranch || baseBranch === defaultBranch2) {
|
|
8137
8190
|
try {
|
|
8138
|
-
|
|
8191
|
+
git3(["merge", "--no-edit", `origin/${defaultBranch2}`], cwd);
|
|
8139
8192
|
} catch {
|
|
8140
8193
|
try {
|
|
8141
|
-
|
|
8194
|
+
git3(["merge", "--abort"], cwd);
|
|
8142
8195
|
} catch {
|
|
8143
8196
|
}
|
|
8144
8197
|
throw new Error(
|
|
@@ -8149,29 +8202,29 @@ function ensureFeatureBranch(issueNumber, title, defaultBranch2, cwd, baseBranch
|
|
|
8149
8202
|
return { branch: branchName, created: false };
|
|
8150
8203
|
}
|
|
8151
8204
|
try {
|
|
8152
|
-
|
|
8153
|
-
|
|
8205
|
+
git3(["rev-parse", "--verify", "--quiet", `refs/heads/${branchName}`], cwd);
|
|
8206
|
+
git3(["checkout", branchName], cwd);
|
|
8154
8207
|
return { branch: branchName, created: false };
|
|
8155
8208
|
} catch {
|
|
8156
8209
|
}
|
|
8157
8210
|
let forkPoint = defaultBranch2;
|
|
8158
8211
|
if (baseBranch && baseBranch !== defaultBranch2) {
|
|
8159
8212
|
try {
|
|
8160
|
-
|
|
8213
|
+
git3(["rev-parse", "--verify", `origin/${baseBranch}`], cwd);
|
|
8161
8214
|
forkPoint = baseBranch;
|
|
8162
8215
|
} catch {
|
|
8163
8216
|
}
|
|
8164
8217
|
}
|
|
8165
8218
|
try {
|
|
8166
|
-
|
|
8219
|
+
git3(["checkout", "-b", branchName, `origin/${forkPoint}`], cwd);
|
|
8167
8220
|
} catch {
|
|
8168
|
-
|
|
8221
|
+
git3(["checkout", "-b", branchName], cwd);
|
|
8169
8222
|
}
|
|
8170
8223
|
return { branch: branchName, created: true };
|
|
8171
8224
|
}
|
|
8172
8225
|
|
|
8173
8226
|
// src/gha.ts
|
|
8174
|
-
import { execFileSync as
|
|
8227
|
+
import { execFileSync as execFileSync16 } from "child_process";
|
|
8175
8228
|
import * as fs29 from "fs";
|
|
8176
8229
|
function getRunUrl() {
|
|
8177
8230
|
const server = process.env.GITHUB_SERVER_URL;
|
|
@@ -8214,7 +8267,7 @@ function reactToTriggerComment(cwd) {
|
|
|
8214
8267
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
8215
8268
|
if (attempt > 0) sleepMs(attempt === 1 ? 500 : 1500);
|
|
8216
8269
|
try {
|
|
8217
|
-
|
|
8270
|
+
execFileSync16("gh", args, opts);
|
|
8218
8271
|
return;
|
|
8219
8272
|
} catch (err) {
|
|
8220
8273
|
lastErr = err;
|
|
@@ -8227,7 +8280,7 @@ function reactToTriggerComment(cwd) {
|
|
|
8227
8280
|
}
|
|
8228
8281
|
function sleepMs(ms) {
|
|
8229
8282
|
try {
|
|
8230
|
-
|
|
8283
|
+
execFileSync16("sleep", [(ms / 1e3).toString()], { stdio: "ignore", timeout: ms + 1e3 });
|
|
8231
8284
|
} catch {
|
|
8232
8285
|
}
|
|
8233
8286
|
}
|
|
@@ -8236,7 +8289,7 @@ function sleepMs(ms) {
|
|
|
8236
8289
|
init_issue();
|
|
8237
8290
|
|
|
8238
8291
|
// src/workflow.ts
|
|
8239
|
-
import { execFileSync as
|
|
8292
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
8240
8293
|
var GH_TIMEOUT_MS = 3e4;
|
|
8241
8294
|
function ghToken3() {
|
|
8242
8295
|
return process.env.GH_PAT?.trim() || process.env.GH_TOKEN;
|
|
@@ -8244,7 +8297,7 @@ function ghToken3() {
|
|
|
8244
8297
|
function gh3(args, cwd) {
|
|
8245
8298
|
const token = ghToken3();
|
|
8246
8299
|
const env = token ? { ...process.env, GH_TOKEN: token } : { ...process.env };
|
|
8247
|
-
return
|
|
8300
|
+
return execFileSync17("gh", args, {
|
|
8248
8301
|
encoding: "utf-8",
|
|
8249
8302
|
timeout: GH_TIMEOUT_MS,
|
|
8250
8303
|
cwd,
|
|
@@ -8479,7 +8532,7 @@ var handleAbandonedGoal = async (ctx) => {
|
|
|
8479
8532
|
};
|
|
8480
8533
|
|
|
8481
8534
|
// src/scripts/initFlow.ts
|
|
8482
|
-
import { execFileSync as
|
|
8535
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
8483
8536
|
import * as fs30 from "fs";
|
|
8484
8537
|
import * as path28 from "path";
|
|
8485
8538
|
function detectPackageManager(cwd) {
|
|
@@ -8505,7 +8558,7 @@ function schemaUrlFromPkg() {
|
|
|
8505
8558
|
function detectOwnerRepo(cwd) {
|
|
8506
8559
|
let url;
|
|
8507
8560
|
try {
|
|
8508
|
-
url =
|
|
8561
|
+
url = execFileSync18("git", ["remote", "get-url", "origin"], {
|
|
8509
8562
|
cwd,
|
|
8510
8563
|
encoding: "utf-8",
|
|
8511
8564
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -8590,7 +8643,7 @@ jobs:
|
|
|
8590
8643
|
`;
|
|
8591
8644
|
function defaultBranchFromGit(cwd) {
|
|
8592
8645
|
try {
|
|
8593
|
-
const ref =
|
|
8646
|
+
const ref = execFileSync18("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
|
|
8594
8647
|
cwd,
|
|
8595
8648
|
encoding: "utf-8",
|
|
8596
8649
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -8598,7 +8651,7 @@ function defaultBranchFromGit(cwd) {
|
|
|
8598
8651
|
return ref.replace("refs/remotes/origin/", "");
|
|
8599
8652
|
} catch {
|
|
8600
8653
|
try {
|
|
8601
|
-
return
|
|
8654
|
+
return execFileSync18("git", ["branch", "--show-current"], {
|
|
8602
8655
|
cwd,
|
|
8603
8656
|
encoding: "utf-8",
|
|
8604
8657
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -9288,7 +9341,7 @@ var mergeFlow = async (ctx) => {
|
|
|
9288
9341
|
};
|
|
9289
9342
|
|
|
9290
9343
|
// src/scripts/mergeReleasePr.ts
|
|
9291
|
-
import { execFileSync as
|
|
9344
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
9292
9345
|
var API_TIMEOUT_MS7 = 6e4;
|
|
9293
9346
|
var mergeReleasePr = async (ctx) => {
|
|
9294
9347
|
const state = ctx.data.taskState;
|
|
@@ -9307,7 +9360,7 @@ var mergeReleasePr = async (ctx) => {
|
|
|
9307
9360
|
process.stderr.write(`[kody mergeReleasePr] merging PR #${prNumber} (${prUrl})
|
|
9308
9361
|
`);
|
|
9309
9362
|
try {
|
|
9310
|
-
const out =
|
|
9363
|
+
const out = execFileSync19("gh", ["pr", "merge", String(prNumber), "--merge"], {
|
|
9311
9364
|
timeout: API_TIMEOUT_MS7,
|
|
9312
9365
|
cwd: ctx.cwd,
|
|
9313
9366
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -10789,7 +10842,7 @@ ${body}`;
|
|
|
10789
10842
|
}
|
|
10790
10843
|
|
|
10791
10844
|
// src/scripts/recordClassification.ts
|
|
10792
|
-
import { execFileSync as
|
|
10845
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
10793
10846
|
var API_TIMEOUT_MS8 = 3e4;
|
|
10794
10847
|
var VALID_CLASSES3 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
|
|
10795
10848
|
var recordClassification = async (ctx) => {
|
|
@@ -10837,7 +10890,7 @@ function parseClassification(prSummary) {
|
|
|
10837
10890
|
}
|
|
10838
10891
|
function tryAuditComment(issueNumber, body, cwd) {
|
|
10839
10892
|
try {
|
|
10840
|
-
|
|
10893
|
+
execFileSync20("gh", ["issue", "comment", String(issueNumber), "--body", body], {
|
|
10841
10894
|
cwd,
|
|
10842
10895
|
timeout: API_TIMEOUT_MS8,
|
|
10843
10896
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -10951,7 +11004,7 @@ var resolveArtifacts = async (ctx, profile) => {
|
|
|
10951
11004
|
};
|
|
10952
11005
|
|
|
10953
11006
|
// src/scripts/resolveFlow.ts
|
|
10954
|
-
import { execFileSync as
|
|
11007
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
10955
11008
|
init_issue();
|
|
10956
11009
|
var CONFLICT_DIFF_MAX_BYTES = 4e4;
|
|
10957
11010
|
var resolveFlow = async (ctx) => {
|
|
@@ -11045,7 +11098,7 @@ function buildPreferBlock(prefer, baseBranch) {
|
|
|
11045
11098
|
}
|
|
11046
11099
|
function getConflictedFiles(cwd) {
|
|
11047
11100
|
try {
|
|
11048
|
-
const out =
|
|
11101
|
+
const out = execFileSync21("git", ["diff", "--name-only", "--diff-filter=U"], {
|
|
11049
11102
|
encoding: "utf-8",
|
|
11050
11103
|
cwd,
|
|
11051
11104
|
env: { ...process.env, HUSKY: "0" }
|
|
@@ -11060,7 +11113,7 @@ function getConflictMarkersPreview(files, cwd, maxBytes = CONFLICT_DIFF_MAX_BYTE
|
|
|
11060
11113
|
let total = 0;
|
|
11061
11114
|
for (const f of files) {
|
|
11062
11115
|
try {
|
|
11063
|
-
const content =
|
|
11116
|
+
const content = execFileSync21("cat", [f], { encoding: "utf-8", cwd }).toString();
|
|
11064
11117
|
const snippet = `### ${f}
|
|
11065
11118
|
|
|
11066
11119
|
\`\`\`
|
|
@@ -11084,12 +11137,12 @@ function tryPostPr3(prNumber, body, cwd) {
|
|
|
11084
11137
|
function pushEmptyCommit(branch, cwd) {
|
|
11085
11138
|
const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
|
|
11086
11139
|
try {
|
|
11087
|
-
|
|
11140
|
+
execFileSync21(
|
|
11088
11141
|
"git",
|
|
11089
11142
|
["commit", "--allow-empty", "-m", "chore: kody resolve refresh \u2014 empty commit to recompute mergeable status"],
|
|
11090
11143
|
{ cwd, env, stdio: ["ignore", "pipe", "pipe"] }
|
|
11091
11144
|
);
|
|
11092
|
-
|
|
11145
|
+
execFileSync21("git", ["push", "-u", "origin", branch], {
|
|
11093
11146
|
cwd,
|
|
11094
11147
|
env,
|
|
11095
11148
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -11220,10 +11273,10 @@ var resolvePreviewUrl = async (ctx) => {
|
|
|
11220
11273
|
};
|
|
11221
11274
|
|
|
11222
11275
|
// src/scripts/resolveQaUrl.ts
|
|
11223
|
-
import { execFileSync as
|
|
11276
|
+
import { execFileSync as execFileSync22 } from "child_process";
|
|
11224
11277
|
function ghQuery(args, cwd) {
|
|
11225
11278
|
try {
|
|
11226
|
-
const out =
|
|
11279
|
+
const out = execFileSync22("gh", args, {
|
|
11227
11280
|
cwd,
|
|
11228
11281
|
stdio: ["ignore", "pipe", "pipe"],
|
|
11229
11282
|
encoding: "utf-8",
|
|
@@ -11293,7 +11346,7 @@ var resolveQaUrl = async (ctx) => {
|
|
|
11293
11346
|
};
|
|
11294
11347
|
|
|
11295
11348
|
// src/scripts/revertFlow.ts
|
|
11296
|
-
import { execFileSync as
|
|
11349
|
+
import { execFileSync as execFileSync23 } from "child_process";
|
|
11297
11350
|
init_issue();
|
|
11298
11351
|
var SHA_RE = /^[0-9a-f]{4,40}$/i;
|
|
11299
11352
|
var revertFlow = async (ctx) => {
|
|
@@ -11332,7 +11385,7 @@ var revertFlow = async (ctx) => {
|
|
|
11332
11385
|
for (const s of requested) {
|
|
11333
11386
|
let full;
|
|
11334
11387
|
try {
|
|
11335
|
-
full =
|
|
11388
|
+
full = git4(["rev-parse", "--verify", `${s}^{commit}`], ctx.cwd);
|
|
11336
11389
|
} catch {
|
|
11337
11390
|
unreachable.push(s);
|
|
11338
11391
|
continue;
|
|
@@ -11343,7 +11396,7 @@ var revertFlow = async (ctx) => {
|
|
|
11343
11396
|
}
|
|
11344
11397
|
let subject = "";
|
|
11345
11398
|
try {
|
|
11346
|
-
subject =
|
|
11399
|
+
subject = git4(["log", "-1", "--format=%s", full], ctx.cwd);
|
|
11347
11400
|
} catch {
|
|
11348
11401
|
}
|
|
11349
11402
|
resolved.push({ input: s, full, subject });
|
|
@@ -11375,8 +11428,8 @@ function buildCommitMessage(resolved) {
|
|
|
11375
11428
|
function buildPrSummary(resolved) {
|
|
11376
11429
|
return resolved.map((r) => `- Reverted \`${r.full.slice(0, 7)}\`${r.subject ? ` \u2014 ${r.subject}` : ""}`).join("\n");
|
|
11377
11430
|
}
|
|
11378
|
-
function
|
|
11379
|
-
return
|
|
11431
|
+
function git4(args, cwd) {
|
|
11432
|
+
return execFileSync23("git", args, {
|
|
11380
11433
|
encoding: "utf-8",
|
|
11381
11434
|
timeout: 3e4,
|
|
11382
11435
|
cwd,
|
|
@@ -11386,7 +11439,7 @@ function git3(args, cwd) {
|
|
|
11386
11439
|
}
|
|
11387
11440
|
function isAncestorOfHead(sha, cwd) {
|
|
11388
11441
|
try {
|
|
11389
|
-
|
|
11442
|
+
execFileSync23("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
|
|
11390
11443
|
cwd,
|
|
11391
11444
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
11392
11445
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -12032,11 +12085,11 @@ var skipAgent = async (ctx) => {
|
|
|
12032
12085
|
};
|
|
12033
12086
|
|
|
12034
12087
|
// src/scripts/stageMergeConflicts.ts
|
|
12035
|
-
import { execFileSync as
|
|
12088
|
+
import { execFileSync as execFileSync24 } from "child_process";
|
|
12036
12089
|
var stageMergeConflicts = async (ctx) => {
|
|
12037
12090
|
if (ctx.data.agentDone === false) return;
|
|
12038
12091
|
try {
|
|
12039
|
-
|
|
12092
|
+
execFileSync24("git", ["add", "-A"], {
|
|
12040
12093
|
cwd: ctx.cwd,
|
|
12041
12094
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
12042
12095
|
stdio: "pipe"
|
|
@@ -12047,7 +12100,7 @@ var stageMergeConflicts = async (ctx) => {
|
|
|
12047
12100
|
|
|
12048
12101
|
// src/scripts/startFlow.ts
|
|
12049
12102
|
init_issue();
|
|
12050
|
-
import { execFileSync as
|
|
12103
|
+
import { execFileSync as execFileSync25 } from "child_process";
|
|
12051
12104
|
var API_TIMEOUT_MS9 = 3e4;
|
|
12052
12105
|
var startFlow = async (ctx, profile, _agentResult, args) => {
|
|
12053
12106
|
const entry = args?.entry;
|
|
@@ -12081,7 +12134,7 @@ function postKodyComment(target, issueNumber, state, next, cwd) {
|
|
|
12081
12134
|
const sub = target === "pr" && state?.core.prUrl ? "pr" : "issue";
|
|
12082
12135
|
const body = `@kody ${next}`;
|
|
12083
12136
|
try {
|
|
12084
|
-
|
|
12137
|
+
execFileSync25("gh", [sub, "comment", String(targetNumber), "--body", body], {
|
|
12085
12138
|
timeout: API_TIMEOUT_MS9,
|
|
12086
12139
|
cwd,
|
|
12087
12140
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -12095,7 +12148,7 @@ function postKodyComment(target, issueNumber, state, next, cwd) {
|
|
|
12095
12148
|
}
|
|
12096
12149
|
|
|
12097
12150
|
// src/scripts/syncFlow.ts
|
|
12098
|
-
import { execFileSync as
|
|
12151
|
+
import { execFileSync as execFileSync26 } from "child_process";
|
|
12099
12152
|
init_issue();
|
|
12100
12153
|
var DONE2 = {
|
|
12101
12154
|
label: "kody:done",
|
|
@@ -12173,7 +12226,7 @@ function bail2(ctx, prNumber, reason) {
|
|
|
12173
12226
|
}
|
|
12174
12227
|
function revParseHead(cwd) {
|
|
12175
12228
|
try {
|
|
12176
|
-
return
|
|
12229
|
+
return execFileSync26("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
12177
12230
|
} catch {
|
|
12178
12231
|
return "";
|
|
12179
12232
|
}
|
|
@@ -12430,7 +12483,7 @@ var verifyWithRetry = async (ctx) => {
|
|
|
12430
12483
|
|
|
12431
12484
|
// src/scripts/waitForCi.ts
|
|
12432
12485
|
init_issue();
|
|
12433
|
-
import { execFileSync as
|
|
12486
|
+
import { execFileSync as execFileSync27 } from "child_process";
|
|
12434
12487
|
var API_TIMEOUT_MS10 = 3e4;
|
|
12435
12488
|
var waitForCi = async (ctx, _profile, _agentResult, args) => {
|
|
12436
12489
|
const timeoutMinutes = numArg(args, "timeoutMinutes", 30);
|
|
@@ -12508,7 +12561,7 @@ var waitForCi = async (ctx, _profile, _agentResult, args) => {
|
|
|
12508
12561
|
};
|
|
12509
12562
|
function fetchChecks(prNumber, cwd) {
|
|
12510
12563
|
try {
|
|
12511
|
-
const raw =
|
|
12564
|
+
const raw = execFileSync27("gh", ["pr", "checks", String(prNumber), "--json", "bucket,state,name,workflow,link"], {
|
|
12512
12565
|
encoding: "utf-8",
|
|
12513
12566
|
timeout: API_TIMEOUT_MS10,
|
|
12514
12567
|
cwd,
|
|
@@ -12984,7 +13037,7 @@ var allScriptNames = /* @__PURE__ */ new Set([
|
|
|
12984
13037
|
]);
|
|
12985
13038
|
|
|
12986
13039
|
// src/tools.ts
|
|
12987
|
-
import { execFileSync as
|
|
13040
|
+
import { execFileSync as execFileSync28 } from "child_process";
|
|
12988
13041
|
function verifyCliTools(tools, cwd) {
|
|
12989
13042
|
const out = [];
|
|
12990
13043
|
for (const t of tools) out.push(verifyOne(t, cwd));
|
|
@@ -13021,7 +13074,7 @@ function verifyOne(tool4, cwd) {
|
|
|
13021
13074
|
}
|
|
13022
13075
|
function runShell(cmd, cwd, timeoutMs = 3e4) {
|
|
13023
13076
|
try {
|
|
13024
|
-
const stdout =
|
|
13077
|
+
const stdout = execFileSync28("sh", ["-c", cmd], {
|
|
13025
13078
|
cwd,
|
|
13026
13079
|
stdio: ["ignore", "pipe", "pipe"],
|
|
13027
13080
|
timeout: timeoutMs,
|
|
@@ -13106,7 +13159,10 @@ async function runExecutable(profileName, input) {
|
|
|
13106
13159
|
try {
|
|
13107
13160
|
model = parseProviderModel(modelSpec);
|
|
13108
13161
|
} catch (err) {
|
|
13109
|
-
return finishAndEnd({
|
|
13162
|
+
return finishAndEnd({
|
|
13163
|
+
exitCode: 99,
|
|
13164
|
+
reason: `agent.model invalid: ${err instanceof Error ? err.message : String(err)}`
|
|
13165
|
+
});
|
|
13110
13166
|
}
|
|
13111
13167
|
let litellm = null;
|
|
13112
13168
|
try {
|
|
@@ -13150,11 +13206,15 @@ async function runExecutable(profileName, input) {
|
|
|
13150
13206
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
13151
13207
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
13152
13208
|
const agents = loadSubagents(profile);
|
|
13209
|
+
const lm = litellm;
|
|
13153
13210
|
return runAgent({
|
|
13154
13211
|
prompt,
|
|
13155
13212
|
model,
|
|
13156
13213
|
cwd: input.cwd,
|
|
13157
|
-
litellmUrl:
|
|
13214
|
+
litellmUrl: lm?.url ?? null,
|
|
13215
|
+
// On a connection drop mid-run, restart the (possibly crashed) proxy
|
|
13216
|
+
// before the agent retries. No-op for direct-Anthropic runs (lm null).
|
|
13217
|
+
ensureBackend: lm ? () => lm.ensureHealthy().then(() => void 0) : void 0,
|
|
13158
13218
|
verbose: input.verbose,
|
|
13159
13219
|
quiet: input.quiet,
|
|
13160
13220
|
ndjsonDir,
|
|
@@ -13224,7 +13284,10 @@ async function runExecutable(profileName, input) {
|
|
|
13224
13284
|
} else if (!ctx.skipAgent) {
|
|
13225
13285
|
const prompt = ctx.data.prompt;
|
|
13226
13286
|
if (!prompt) {
|
|
13227
|
-
return finishAndEnd({
|
|
13287
|
+
return finishAndEnd({
|
|
13288
|
+
exitCode: 99,
|
|
13289
|
+
reason: "composePrompt did not produce a prompt (ctx.data.prompt missing)"
|
|
13290
|
+
});
|
|
13228
13291
|
}
|
|
13229
13292
|
emitEvent(input.cwd, { executable: profileName, kind: "agent_start" });
|
|
13230
13293
|
agentResult = await invokeAgent(prompt);
|
|
@@ -13285,10 +13348,7 @@ async function runExecutable(profileName, input) {
|
|
|
13285
13348
|
const runId = resolveRunId2();
|
|
13286
13349
|
const dir = pathMod.join(input.cwd, ".kody", "runs", runId, "crashes");
|
|
13287
13350
|
fsMod.mkdirSync(dir, { recursive: true });
|
|
13288
|
-
const file = pathMod.join(
|
|
13289
|
-
dir,
|
|
13290
|
-
`${label.replace(/[^a-zA-Z0-9_-]/g, "_")}-${Date.now()}.json`
|
|
13291
|
-
);
|
|
13351
|
+
const file = pathMod.join(dir, `${label.replace(/[^a-zA-Z0-9_-]/g, "_")}-${Date.now()}.json`);
|
|
13292
13352
|
fsMod.writeFileSync(
|
|
13293
13353
|
file,
|
|
13294
13354
|
JSON.stringify(
|
|
@@ -13328,10 +13388,8 @@ async function runExecutable(profileName, input) {
|
|
|
13328
13388
|
try {
|
|
13329
13389
|
const missing2 = verifyTaskArtifacts(taskArtifacts.absDir);
|
|
13330
13390
|
if (missing2.length > 0) {
|
|
13331
|
-
process.stderr.write(
|
|
13332
|
-
|
|
13333
|
-
`
|
|
13334
|
-
);
|
|
13391
|
+
process.stderr.write(`[task-artifacts] task ${taskArtifacts.taskId} missing: ${missing2.join(", ")}
|
|
13392
|
+
`);
|
|
13335
13393
|
}
|
|
13336
13394
|
} catch {
|
|
13337
13395
|
}
|
|
@@ -13805,7 +13863,7 @@ async function runContainerLoop(profile, ctx, input) {
|
|
|
13805
13863
|
}
|
|
13806
13864
|
function resetWorkingTree2(cwd) {
|
|
13807
13865
|
try {
|
|
13808
|
-
|
|
13866
|
+
execFileSync29("git", ["reset", "--hard", "HEAD"], {
|
|
13809
13867
|
cwd,
|
|
13810
13868
|
stdio: ["ignore", "pipe", "pipe"],
|
|
13811
13869
|
timeout: 3e4
|
|
@@ -13991,7 +14049,7 @@ function detectPackageManager2(cwd) {
|
|
|
13991
14049
|
}
|
|
13992
14050
|
function shellOut(cmd, args, cwd, stream = true) {
|
|
13993
14051
|
try {
|
|
13994
|
-
|
|
14052
|
+
execFileSync30(cmd, args, {
|
|
13995
14053
|
cwd,
|
|
13996
14054
|
stdio: stream ? "inherit" : "pipe",
|
|
13997
14055
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" }
|
|
@@ -14004,7 +14062,7 @@ function shellOut(cmd, args, cwd, stream = true) {
|
|
|
14004
14062
|
}
|
|
14005
14063
|
function isOnPath(bin) {
|
|
14006
14064
|
try {
|
|
14007
|
-
|
|
14065
|
+
execFileSync30("which", [bin], { stdio: "pipe" });
|
|
14008
14066
|
return true;
|
|
14009
14067
|
} catch {
|
|
14010
14068
|
return false;
|
|
@@ -14045,7 +14103,7 @@ function installLitellmIfNeeded(cwd) {
|
|
|
14045
14103
|
} catch {
|
|
14046
14104
|
}
|
|
14047
14105
|
try {
|
|
14048
|
-
|
|
14106
|
+
execFileSync30("python3", ["-c", "import litellm"], { stdio: "pipe" });
|
|
14049
14107
|
process.stdout.write("\u2192 kody: litellm already installed\n");
|
|
14050
14108
|
return 0;
|
|
14051
14109
|
} catch {
|
|
@@ -14055,16 +14113,16 @@ function installLitellmIfNeeded(cwd) {
|
|
|
14055
14113
|
}
|
|
14056
14114
|
function configureGitIdentity(cwd) {
|
|
14057
14115
|
try {
|
|
14058
|
-
const name =
|
|
14116
|
+
const name = execFileSync30("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
|
|
14059
14117
|
if (name) return;
|
|
14060
14118
|
} catch {
|
|
14061
14119
|
}
|
|
14062
14120
|
try {
|
|
14063
|
-
|
|
14121
|
+
execFileSync30("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
|
|
14064
14122
|
} catch {
|
|
14065
14123
|
}
|
|
14066
14124
|
try {
|
|
14067
|
-
|
|
14125
|
+
execFileSync30("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
|
|
14068
14126
|
cwd,
|
|
14069
14127
|
stdio: "pipe"
|
|
14070
14128
|
});
|
|
@@ -14384,8 +14442,8 @@ function commitChatFiles(cwd, sessionId, verbose) {
|
|
|
14384
14442
|
if (paths.length === 0) return;
|
|
14385
14443
|
const opts = { cwd, stdio: verbose ? "inherit" : "pipe" };
|
|
14386
14444
|
try {
|
|
14387
|
-
|
|
14388
|
-
|
|
14445
|
+
execFileSync31("git", ["add", "-f", ...paths], opts);
|
|
14446
|
+
execFileSync31("git", ["commit", "--quiet", "-m", `chat: reply for ${sessionId}`], opts);
|
|
14389
14447
|
} catch (err) {
|
|
14390
14448
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14391
14449
|
process.stderr.write(`[kody:chat] commit skipped: ${msg}
|
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.154",
|
|
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",
|