@kody-ade/kody-engine-lite 0.1.80 → 0.1.81
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/cli.js +256 -53
- package/package.json +1 -1
- package/templates/kody.yml +3 -2
- package/dist/agent-runner.d.ts +0 -4
- package/dist/agent-runner.js +0 -122
- package/dist/ci/parse-inputs.d.ts +0 -6
- package/dist/ci/parse-inputs.js +0 -76
- package/dist/ci/parse-safety.d.ts +0 -6
- package/dist/ci/parse-safety.js +0 -22
- package/dist/cli/args.d.ts +0 -13
- package/dist/cli/args.js +0 -42
- package/dist/cli/litellm.d.ts +0 -2
- package/dist/cli/litellm.js +0 -85
- package/dist/cli/task-resolution.d.ts +0 -2
- package/dist/cli/task-resolution.js +0 -41
- package/dist/config.d.ts +0 -49
- package/dist/config.js +0 -72
- package/dist/context.d.ts +0 -4
- package/dist/context.js +0 -83
- package/dist/definitions.d.ts +0 -3
- package/dist/definitions.js +0 -59
- package/dist/entry.d.ts +0 -1
- package/dist/entry.js +0 -236
- package/dist/git-utils.d.ts +0 -13
- package/dist/git-utils.js +0 -174
- package/dist/github-api.d.ts +0 -14
- package/dist/github-api.js +0 -114
- package/dist/kody-utils.d.ts +0 -1
- package/dist/kody-utils.js +0 -9
- package/dist/learning/auto-learn.d.ts +0 -2
- package/dist/learning/auto-learn.js +0 -169
- package/dist/logger.d.ts +0 -14
- package/dist/logger.js +0 -51
- package/dist/memory.d.ts +0 -1
- package/dist/memory.js +0 -20
- package/dist/observer.d.ts +0 -9
- package/dist/observer.js +0 -80
- package/dist/pipeline/complexity.d.ts +0 -3
- package/dist/pipeline/complexity.js +0 -12
- package/dist/pipeline/executor-registry.d.ts +0 -3
- package/dist/pipeline/executor-registry.js +0 -20
- package/dist/pipeline/hooks.d.ts +0 -17
- package/dist/pipeline/hooks.js +0 -110
- package/dist/pipeline/questions.d.ts +0 -2
- package/dist/pipeline/questions.js +0 -44
- package/dist/pipeline/runner-selection.d.ts +0 -2
- package/dist/pipeline/runner-selection.js +0 -13
- package/dist/pipeline/state.d.ts +0 -4
- package/dist/pipeline/state.js +0 -37
- package/dist/pipeline.d.ts +0 -3
- package/dist/pipeline.js +0 -213
- package/dist/preflight.d.ts +0 -1
- package/dist/preflight.js +0 -69
- package/dist/retrospective.d.ts +0 -26
- package/dist/retrospective.js +0 -211
- package/dist/stages/agent.d.ts +0 -2
- package/dist/stages/agent.js +0 -94
- package/dist/stages/gate.d.ts +0 -2
- package/dist/stages/gate.js +0 -32
- package/dist/stages/review.d.ts +0 -2
- package/dist/stages/review.js +0 -32
- package/dist/stages/ship.d.ts +0 -3
- package/dist/stages/ship.js +0 -154
- package/dist/stages/verify.d.ts +0 -2
- package/dist/stages/verify.js +0 -94
- package/dist/types.d.ts +0 -61
- package/dist/types.js +0 -1
- package/dist/validators.d.ts +0 -8
- package/dist/validators.js +0 -42
- package/dist/verify-runner.d.ts +0 -11
- package/dist/verify-runner.js +0 -110
package/dist/bin/cli.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
2
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
4
|
var __esm = (fn, res) => function __init() {
|
|
4
5
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
6
|
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
6
11
|
|
|
7
12
|
// src/agent-runner.ts
|
|
8
13
|
import { spawn, execFileSync } from "child_process";
|
|
@@ -290,7 +295,7 @@ function getProjectConfig() {
|
|
|
290
295
|
}
|
|
291
296
|
return _config;
|
|
292
297
|
}
|
|
293
|
-
var DEFAULT_CONFIG, LITELLM_DEFAULT_PORT, LITELLM_DEFAULT_URL,
|
|
298
|
+
var DEFAULT_CONFIG, LITELLM_DEFAULT_PORT, LITELLM_DEFAULT_URL, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
|
|
294
299
|
var init_config = __esm({
|
|
295
300
|
"src/config.ts"() {
|
|
296
301
|
"use strict";
|
|
@@ -320,11 +325,6 @@ var init_config = __esm({
|
|
|
320
325
|
};
|
|
321
326
|
LITELLM_DEFAULT_PORT = 4e3;
|
|
322
327
|
LITELLM_DEFAULT_URL = `http://localhost:${LITELLM_DEFAULT_PORT}`;
|
|
323
|
-
TIER_TO_ANTHROPIC_IDS = {
|
|
324
|
-
cheap: ["claude-haiku-4-5-20251001", "claude-haiku-4-5", "haiku"],
|
|
325
|
-
mid: ["claude-sonnet-4-6-20250514", "claude-sonnet-4-6", "sonnet"],
|
|
326
|
-
strong: ["claude-opus-4-6-20250514", "claude-opus-4-6", "opus"]
|
|
327
|
-
};
|
|
328
328
|
VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
329
329
|
FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
330
330
|
_config = null;
|
|
@@ -444,6 +444,41 @@ function syncWithDefault(cwd) {
|
|
|
444
444
|
logger.warn(` Merge conflict with origin/${defaultBranch} \u2014 skipping sync`);
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
|
+
function mergeDefault(cwd) {
|
|
448
|
+
const defaultBranch = getDefaultBranch(cwd);
|
|
449
|
+
const current = getCurrentBranch(cwd);
|
|
450
|
+
if (current === defaultBranch) return "clean";
|
|
451
|
+
try {
|
|
452
|
+
git(["fetch", "origin", defaultBranch], { cwd, timeout: 3e4 });
|
|
453
|
+
} catch {
|
|
454
|
+
logger.warn(" Failed to fetch latest from origin");
|
|
455
|
+
return "error";
|
|
456
|
+
}
|
|
457
|
+
try {
|
|
458
|
+
git(["merge", `origin/${defaultBranch}`, "--no-edit"], { cwd, timeout: 3e4 });
|
|
459
|
+
logger.info(` Merged origin/${defaultBranch} cleanly`);
|
|
460
|
+
return "clean";
|
|
461
|
+
} catch {
|
|
462
|
+
try {
|
|
463
|
+
const unmerged = git(["diff", "--name-only", "--diff-filter=U"], { cwd });
|
|
464
|
+
if (unmerged.trim()) return "conflict";
|
|
465
|
+
} catch {
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
git(["merge", "--abort"], { cwd });
|
|
469
|
+
} catch {
|
|
470
|
+
}
|
|
471
|
+
return "error";
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function getConflictedFiles(cwd) {
|
|
475
|
+
try {
|
|
476
|
+
const output = git(["diff", "--name-only", "--diff-filter=U"], { cwd });
|
|
477
|
+
return output ? output.split("\n") : [];
|
|
478
|
+
} catch {
|
|
479
|
+
return [];
|
|
480
|
+
}
|
|
481
|
+
}
|
|
447
482
|
function commitAll(message, cwd) {
|
|
448
483
|
const status = git(["status", "--porcelain"], { cwd });
|
|
449
484
|
if (!status) {
|
|
@@ -1483,9 +1518,6 @@ ${prompt}` : prompt;
|
|
|
1483
1518
|
}
|
|
1484
1519
|
function resolveModel(modelTier, stageName) {
|
|
1485
1520
|
const config = getProjectConfig();
|
|
1486
|
-
if (config.agent.provider && config.agent.provider !== "anthropic") {
|
|
1487
|
-
return DEFAULT_MODEL_MAP[modelTier] ?? "sonnet";
|
|
1488
|
-
}
|
|
1489
1521
|
const mapped = config.agent.modelMap[modelTier];
|
|
1490
1522
|
if (mapped) return mapped;
|
|
1491
1523
|
return DEFAULT_MODEL_MAP[modelTier] ?? "sonnet";
|
|
@@ -2928,8 +2960,16 @@ If no pipeline flaw is detected, set "pipelineFlaw" to null.
|
|
|
2928
2960
|
import * as fs15 from "fs";
|
|
2929
2961
|
import * as path15 from "path";
|
|
2930
2962
|
function ensureFeatureBranchIfNeeded(ctx) {
|
|
2931
|
-
if (ctx.input.
|
|
2932
|
-
if (
|
|
2963
|
+
if (ctx.input.dryRun) return;
|
|
2964
|
+
if (ctx.input.prNumber) {
|
|
2965
|
+
try {
|
|
2966
|
+
syncWithDefault(ctx.projectDir);
|
|
2967
|
+
} catch (err) {
|
|
2968
|
+
logger.warn(` Failed to sync with default branch: ${err}`);
|
|
2969
|
+
}
|
|
2970
|
+
return;
|
|
2971
|
+
}
|
|
2972
|
+
if (!ctx.input.issueNumber) return;
|
|
2933
2973
|
try {
|
|
2934
2974
|
const taskMdPath = path15.join(ctx.taskDir, "task.md");
|
|
2935
2975
|
const title = fs15.existsSync(taskMdPath) ? fs15.readFileSync(taskMdPath, "utf-8").split("\n")[0].slice(0, 50) : ctx.taskId;
|
|
@@ -3354,12 +3394,13 @@ function parseArgs() {
|
|
|
3354
3394
|
kody fix --task-id <id> [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
|
|
3355
3395
|
kody fix-ci [--pr-number <n>] [--ci-run-id <id>] [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
|
|
3356
3396
|
kody review [--pr-number <n>] [--issue-number <n>] [--cwd <path>] [--local]
|
|
3397
|
+
kody resolve --pr-number <n> [--cwd <path>] [--local]
|
|
3357
3398
|
kody status --task-id <id> [--cwd <path>]
|
|
3358
3399
|
kody --help`);
|
|
3359
3400
|
process.exit(0);
|
|
3360
3401
|
}
|
|
3361
3402
|
const command2 = args2[0];
|
|
3362
|
-
if (!["run", "rerun", "fix", "fix-ci", "status", "review"].includes(command2)) {
|
|
3403
|
+
if (!["run", "rerun", "fix", "fix-ci", "status", "review", "resolve"].includes(command2)) {
|
|
3363
3404
|
console.error(`Unknown command: ${command2}`);
|
|
3364
3405
|
process.exit(1);
|
|
3365
3406
|
}
|
|
@@ -3437,15 +3478,14 @@ async function checkModelHealth(baseUrl, apiKey, model = "claude-haiku-4-5") {
|
|
|
3437
3478
|
function generateLitellmConfig(provider, modelMap) {
|
|
3438
3479
|
const apiKeyVar = providerApiKeyEnvVar(provider);
|
|
3439
3480
|
const entries = ["model_list:"];
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
if (
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
}
|
|
3481
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3482
|
+
for (const providerModel of Object.values(modelMap)) {
|
|
3483
|
+
if (seen.has(providerModel)) continue;
|
|
3484
|
+
seen.add(providerModel);
|
|
3485
|
+
entries.push(` - model_name: ${providerModel}`);
|
|
3486
|
+
entries.push(` litellm_params:`);
|
|
3487
|
+
entries.push(` model: ${provider}/${providerModel}`);
|
|
3488
|
+
entries.push(` api_key: os.environ/${apiKeyVar}`);
|
|
3449
3489
|
}
|
|
3450
3490
|
return entries.join("\n") + "\n";
|
|
3451
3491
|
}
|
|
@@ -3593,6 +3633,133 @@ var init_task_state = __esm({
|
|
|
3593
3633
|
}
|
|
3594
3634
|
});
|
|
3595
3635
|
|
|
3636
|
+
// src/resolve.ts
|
|
3637
|
+
var resolve_exports = {};
|
|
3638
|
+
__export(resolve_exports, {
|
|
3639
|
+
runResolve: () => runResolve
|
|
3640
|
+
});
|
|
3641
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
3642
|
+
function getConflictContext(cwd, files) {
|
|
3643
|
+
const parts = [];
|
|
3644
|
+
for (const file of files.slice(0, 10)) {
|
|
3645
|
+
try {
|
|
3646
|
+
const content = execFileSync11("git", ["diff", file], {
|
|
3647
|
+
cwd,
|
|
3648
|
+
encoding: "utf-8",
|
|
3649
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3650
|
+
}).trim();
|
|
3651
|
+
parts.push(`### ${file}
|
|
3652
|
+
\`\`\`diff
|
|
3653
|
+
${content.slice(0, 3e3)}
|
|
3654
|
+
\`\`\``);
|
|
3655
|
+
} catch {
|
|
3656
|
+
parts.push(`### ${file}
|
|
3657
|
+
(could not read diff)`);
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
return parts.join("\n\n");
|
|
3661
|
+
}
|
|
3662
|
+
async function runResolve(options) {
|
|
3663
|
+
const { prNumber, projectDir, runners, local } = options;
|
|
3664
|
+
const defaultBranch = getDefaultBranch(projectDir);
|
|
3665
|
+
logger.info(`Resolving PR #${prNumber} \u2014 merging ${defaultBranch}...`);
|
|
3666
|
+
const mergeResult = mergeDefault(projectDir);
|
|
3667
|
+
if (mergeResult === "error") {
|
|
3668
|
+
return { outcome: "failed", error: "Failed to merge default branch" };
|
|
3669
|
+
}
|
|
3670
|
+
if (mergeResult === "clean") {
|
|
3671
|
+
logger.info(" Clean merge \u2014 no conflicts");
|
|
3672
|
+
if (!local) {
|
|
3673
|
+
pushBranch(projectDir);
|
|
3674
|
+
}
|
|
3675
|
+
return { outcome: "merged" };
|
|
3676
|
+
}
|
|
3677
|
+
const conflictedFiles = getConflictedFiles(projectDir);
|
|
3678
|
+
if (conflictedFiles.length === 0) {
|
|
3679
|
+
return { outcome: "failed", error: "Merge reported conflict but no conflicted files found" };
|
|
3680
|
+
}
|
|
3681
|
+
logger.info(` ${conflictedFiles.length} conflicted file(s): ${conflictedFiles.join(", ")}`);
|
|
3682
|
+
const conflictContext = getConflictContext(projectDir, conflictedFiles);
|
|
3683
|
+
const prompt = buildResolvePrompt(conflictedFiles, conflictContext, defaultBranch);
|
|
3684
|
+
const config = getProjectConfig();
|
|
3685
|
+
const runnerName = config.agent.defaultRunner ?? Object.keys(runners)[0] ?? "claude";
|
|
3686
|
+
const runner = runners[runnerName];
|
|
3687
|
+
if (!runner) {
|
|
3688
|
+
return { outcome: "failed", error: `Runner "${runnerName}" not found` };
|
|
3689
|
+
}
|
|
3690
|
+
const model = resolveModel("mid");
|
|
3691
|
+
const extraEnv = {};
|
|
3692
|
+
if (needsLitellmProxy(config)) {
|
|
3693
|
+
extraEnv.ANTHROPIC_BASE_URL = getLitellmUrl();
|
|
3694
|
+
}
|
|
3695
|
+
logger.info(` Running agent to resolve conflicts (model=${model})...`);
|
|
3696
|
+
const result = await runner.run("resolve", prompt, model, 3e5, projectDir, {
|
|
3697
|
+
cwd: projectDir,
|
|
3698
|
+
env: extraEnv
|
|
3699
|
+
});
|
|
3700
|
+
if (result.outcome !== "completed") {
|
|
3701
|
+
return { outcome: "failed", error: `Agent failed: ${result.error}` };
|
|
3702
|
+
}
|
|
3703
|
+
logger.info(" Verifying resolution...");
|
|
3704
|
+
const verify = runQualityGates(projectDir, projectDir);
|
|
3705
|
+
if (!verify.pass) {
|
|
3706
|
+
const errorSummary = verify.errors.slice(0, 5).join("\n");
|
|
3707
|
+
logger.error(` Verification failed:
|
|
3708
|
+
${errorSummary}`);
|
|
3709
|
+
return { outcome: "failed", error: `Conflict resolution failed verification:
|
|
3710
|
+
${errorSummary}` };
|
|
3711
|
+
}
|
|
3712
|
+
logger.info(" Verification passed");
|
|
3713
|
+
commitAll(`chore: resolve merge conflicts with ${defaultBranch}`, projectDir);
|
|
3714
|
+
if (!local) {
|
|
3715
|
+
pushBranch(projectDir);
|
|
3716
|
+
try {
|
|
3717
|
+
const fileList = conflictedFiles.map((f) => `- \`${f}\``).join("\n");
|
|
3718
|
+
postPRComment(
|
|
3719
|
+
prNumber,
|
|
3720
|
+
`\u2705 **Merge conflicts resolved** with \`${defaultBranch}\`
|
|
3721
|
+
|
|
3722
|
+
**Conflicted files:**
|
|
3723
|
+
${fileList}
|
|
3724
|
+
|
|
3725
|
+
_Verification passed. Please review the resolution._`
|
|
3726
|
+
);
|
|
3727
|
+
} catch {
|
|
3728
|
+
}
|
|
3729
|
+
}
|
|
3730
|
+
return { outcome: "resolved" };
|
|
3731
|
+
}
|
|
3732
|
+
function buildResolvePrompt(files, conflictContext, defaultBranch) {
|
|
3733
|
+
return `You are resolving merge conflicts between a feature branch and the \`${defaultBranch}\` branch.
|
|
3734
|
+
|
|
3735
|
+
## Conflicted files
|
|
3736
|
+
${files.map((f) => `- ${f}`).join("\n")}
|
|
3737
|
+
|
|
3738
|
+
## Conflict diffs
|
|
3739
|
+
${conflictContext}
|
|
3740
|
+
|
|
3741
|
+
## Instructions
|
|
3742
|
+
1. Read each conflicted file
|
|
3743
|
+
2. Resolve the conflict markers (<<<<<<< / ======= / >>>>>>>) by combining both sides correctly:
|
|
3744
|
+
- For feature/business logic: preserve the PR branch's intent
|
|
3745
|
+
- For infrastructure/config/dependencies: prefer the \`${defaultBranch}\` branch
|
|
3746
|
+
- For imports/types: merge both sides
|
|
3747
|
+
3. Write the resolved file using the Edit or Write tool
|
|
3748
|
+
4. Do NOT add new features or refactor \u2014 only resolve the conflicts
|
|
3749
|
+
5. After resolving all files, run \`git add .\` to stage the resolution`;
|
|
3750
|
+
}
|
|
3751
|
+
var init_resolve = __esm({
|
|
3752
|
+
"src/resolve.ts"() {
|
|
3753
|
+
"use strict";
|
|
3754
|
+
init_git_utils();
|
|
3755
|
+
init_github_api();
|
|
3756
|
+
init_verify_runner();
|
|
3757
|
+
init_logger();
|
|
3758
|
+
init_context();
|
|
3759
|
+
init_config();
|
|
3760
|
+
}
|
|
3761
|
+
});
|
|
3762
|
+
|
|
3596
3763
|
// src/entry.ts
|
|
3597
3764
|
var entry_exports = {};
|
|
3598
3765
|
import * as fs21 from "fs";
|
|
@@ -3638,7 +3805,7 @@ async function runModelHealthCheck(config) {
|
|
|
3638
3805
|
logger.warn(`Skipping model health check \u2014 ${keyName} not set`);
|
|
3639
3806
|
return;
|
|
3640
3807
|
}
|
|
3641
|
-
const model =
|
|
3808
|
+
const model = config.agent.modelMap.cheap;
|
|
3642
3809
|
logger.info(`Model health check (${model} via ${usesProxy ? "LiteLLM" : "Anthropic"})...`);
|
|
3643
3810
|
const result = await checkModelHealth(baseUrl, apiKey, model);
|
|
3644
3811
|
if (result.ok) {
|
|
@@ -3782,6 +3949,42 @@ async function main() {
|
|
|
3782
3949
|
}
|
|
3783
3950
|
process.exit(0);
|
|
3784
3951
|
}
|
|
3952
|
+
if (input.command === "resolve") {
|
|
3953
|
+
if (!input.prNumber) {
|
|
3954
|
+
console.error("--pr-number is required for resolve command");
|
|
3955
|
+
process.exit(1);
|
|
3956
|
+
}
|
|
3957
|
+
runPreflight();
|
|
3958
|
+
const config2 = getProjectConfig();
|
|
3959
|
+
const litellmProcess2 = await ensureLitellmProxy(config2, projectDir);
|
|
3960
|
+
await runModelHealthCheck(config2);
|
|
3961
|
+
const runners2 = createRunners(config2);
|
|
3962
|
+
const defaultRunnerName2 = config2.agent.defaultRunner ?? Object.keys(runners2)[0] ?? "claude";
|
|
3963
|
+
const defaultRunner2 = runners2[defaultRunnerName2];
|
|
3964
|
+
if (!defaultRunner2) {
|
|
3965
|
+
console.error(`Default runner "${defaultRunnerName2}" not configured`);
|
|
3966
|
+
process.exit(1);
|
|
3967
|
+
}
|
|
3968
|
+
const healthy2 = await defaultRunner2.healthCheck();
|
|
3969
|
+
if (!healthy2) {
|
|
3970
|
+
console.error(`Runner "${defaultRunnerName2}" health check failed`);
|
|
3971
|
+
process.exit(1);
|
|
3972
|
+
}
|
|
3973
|
+
const { runResolve: runResolve2 } = await Promise.resolve().then(() => (init_resolve(), resolve_exports));
|
|
3974
|
+
const result = await runResolve2({
|
|
3975
|
+
prNumber: input.prNumber,
|
|
3976
|
+
projectDir,
|
|
3977
|
+
runners: runners2,
|
|
3978
|
+
local: input.local ?? true
|
|
3979
|
+
});
|
|
3980
|
+
if (litellmProcess2) litellmProcess2.kill?.();
|
|
3981
|
+
if (result.outcome === "failed") {
|
|
3982
|
+
console.error(`Resolve failed: ${result.error}`);
|
|
3983
|
+
process.exit(1);
|
|
3984
|
+
}
|
|
3985
|
+
console.log(`Resolve: ${result.outcome}`);
|
|
3986
|
+
process.exit(0);
|
|
3987
|
+
}
|
|
3785
3988
|
logger.info("Preflight checks:");
|
|
3786
3989
|
runPreflight();
|
|
3787
3990
|
if (input.task) {
|
|
@@ -4001,7 +4204,7 @@ var init_entry = __esm({
|
|
|
4001
4204
|
// src/bin/cli.ts
|
|
4002
4205
|
import * as fs22 from "fs";
|
|
4003
4206
|
import * as path21 from "path";
|
|
4004
|
-
import { execFileSync as
|
|
4207
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
4005
4208
|
import { fileURLToPath } from "url";
|
|
4006
4209
|
var __dirname = path21.dirname(fileURLToPath(import.meta.url));
|
|
4007
4210
|
var PKG_ROOT = path21.resolve(__dirname, "..", "..");
|
|
@@ -4012,7 +4215,7 @@ function getVersion() {
|
|
|
4012
4215
|
}
|
|
4013
4216
|
function checkCommand2(name, args2, fix) {
|
|
4014
4217
|
try {
|
|
4015
|
-
const output =
|
|
4218
|
+
const output = execFileSync12(name, args2, {
|
|
4016
4219
|
encoding: "utf-8",
|
|
4017
4220
|
timeout: 1e4,
|
|
4018
4221
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4030,7 +4233,7 @@ function checkFile(filePath, description, fix) {
|
|
|
4030
4233
|
}
|
|
4031
4234
|
function checkGhAuth(cwd) {
|
|
4032
4235
|
try {
|
|
4033
|
-
const output =
|
|
4236
|
+
const output = execFileSync12("gh", ["auth", "status"], {
|
|
4034
4237
|
encoding: "utf-8",
|
|
4035
4238
|
timeout: 1e4,
|
|
4036
4239
|
cwd,
|
|
@@ -4048,7 +4251,7 @@ function checkGhAuth(cwd) {
|
|
|
4048
4251
|
}
|
|
4049
4252
|
function checkGhRepoAccess(cwd) {
|
|
4050
4253
|
try {
|
|
4051
|
-
const remote =
|
|
4254
|
+
const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
|
|
4052
4255
|
encoding: "utf-8",
|
|
4053
4256
|
timeout: 5e3,
|
|
4054
4257
|
cwd,
|
|
@@ -4059,7 +4262,7 @@ function checkGhRepoAccess(cwd) {
|
|
|
4059
4262
|
return { name: "GitHub repo", ok: false, fix: "Set git remote origin to a GitHub URL" };
|
|
4060
4263
|
}
|
|
4061
4264
|
const repoSlug = `${match[1]}/${match[2]}`;
|
|
4062
|
-
|
|
4265
|
+
execFileSync12("gh", ["repo", "view", repoSlug, "--json", "name"], {
|
|
4063
4266
|
encoding: "utf-8",
|
|
4064
4267
|
timeout: 1e4,
|
|
4065
4268
|
cwd,
|
|
@@ -4072,7 +4275,7 @@ function checkGhRepoAccess(cwd) {
|
|
|
4072
4275
|
}
|
|
4073
4276
|
function checkGhSecret(repoSlug, secretName) {
|
|
4074
4277
|
try {
|
|
4075
|
-
const output =
|
|
4278
|
+
const output = execFileSync12("gh", ["secret", "list", "--repo", repoSlug], {
|
|
4076
4279
|
encoding: "utf-8",
|
|
4077
4280
|
timeout: 1e4,
|
|
4078
4281
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4100,7 +4303,7 @@ function detectBasicConfig(cwd) {
|
|
|
4100
4303
|
else if (!fs22.existsSync(path21.join(cwd, "pnpm-lock.yaml")) && fs22.existsSync(path21.join(cwd, "package-lock.json"))) pm = "npm";
|
|
4101
4304
|
let defaultBranch = "main";
|
|
4102
4305
|
try {
|
|
4103
|
-
const ref =
|
|
4306
|
+
const ref = execFileSync12("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
|
|
4104
4307
|
encoding: "utf-8",
|
|
4105
4308
|
timeout: 5e3,
|
|
4106
4309
|
cwd,
|
|
@@ -4109,7 +4312,7 @@ function detectBasicConfig(cwd) {
|
|
|
4109
4312
|
defaultBranch = ref.replace("refs/remotes/origin/", "");
|
|
4110
4313
|
} catch {
|
|
4111
4314
|
try {
|
|
4112
|
-
|
|
4315
|
+
execFileSync12("git", ["rev-parse", "--verify", "origin/dev"], {
|
|
4113
4316
|
encoding: "utf-8",
|
|
4114
4317
|
timeout: 5e3,
|
|
4115
4318
|
cwd,
|
|
@@ -4122,7 +4325,7 @@ function detectBasicConfig(cwd) {
|
|
|
4122
4325
|
let owner = "";
|
|
4123
4326
|
let repo = "";
|
|
4124
4327
|
try {
|
|
4125
|
-
const remote =
|
|
4328
|
+
const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
|
|
4126
4329
|
encoding: "utf-8",
|
|
4127
4330
|
timeout: 5e3,
|
|
4128
4331
|
cwd,
|
|
@@ -4314,7 +4517,7 @@ function initCommand(opts) {
|
|
|
4314
4517
|
if (filesToCommit.length > 0) {
|
|
4315
4518
|
try {
|
|
4316
4519
|
const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
|
|
4317
|
-
|
|
4520
|
+
execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
|
|
4318
4521
|
cwd,
|
|
4319
4522
|
encoding: "utf-8",
|
|
4320
4523
|
timeout: 3e4,
|
|
@@ -4325,13 +4528,13 @@ function initCommand(opts) {
|
|
|
4325
4528
|
}
|
|
4326
4529
|
if (filesToCommit.length > 0) {
|
|
4327
4530
|
try {
|
|
4328
|
-
|
|
4329
|
-
const staged =
|
|
4531
|
+
execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
|
|
4532
|
+
const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
|
|
4330
4533
|
if (staged) {
|
|
4331
|
-
|
|
4534
|
+
execFileSync12("git", ["commit", "-m", "chore: Add Kody Engine workflow and config\n\nAdd GitHub Actions workflow and auto-detected configuration for Kody Engine Lite."], { cwd, stdio: "pipe" });
|
|
4332
4535
|
console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
|
|
4333
4536
|
try {
|
|
4334
|
-
|
|
4537
|
+
execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
|
|
4335
4538
|
console.log(" \u2713 Pushed to origin");
|
|
4336
4539
|
} catch {
|
|
4337
4540
|
console.log(" \u25CB Push failed \u2014 run 'git push' manually");
|
|
@@ -4425,7 +4628,7 @@ function ghComment(issueNumber, body, cwd) {
|
|
|
4425
4628
|
} catch {
|
|
4426
4629
|
}
|
|
4427
4630
|
if (!repoSlug) return;
|
|
4428
|
-
|
|
4631
|
+
execFileSync12("gh", [
|
|
4429
4632
|
"issue",
|
|
4430
4633
|
"comment",
|
|
4431
4634
|
String(issueNumber),
|
|
@@ -4558,7 +4761,7 @@ Output ONLY valid JSON. No markdown fences. No explanation.
|
|
|
4558
4761
|
${repoContext}`;
|
|
4559
4762
|
console.log(" \u23F3 Analyzing project...");
|
|
4560
4763
|
try {
|
|
4561
|
-
const output =
|
|
4764
|
+
const output = execFileSync12("claude", [
|
|
4562
4765
|
"--print",
|
|
4563
4766
|
"--model",
|
|
4564
4767
|
"haiku",
|
|
@@ -4661,7 +4864,7 @@ ${repoContext}
|
|
|
4661
4864
|
|
|
4662
4865
|
REMINDER: Output the full prompt template first (unchanged), then your three appended sections. Do NOT include "${contextPlaceholder}".`;
|
|
4663
4866
|
try {
|
|
4664
|
-
const output =
|
|
4867
|
+
const output = execFileSync12("claude", [
|
|
4665
4868
|
"--print",
|
|
4666
4869
|
"--model",
|
|
4667
4870
|
"haiku",
|
|
@@ -4718,7 +4921,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
|
|
|
4718
4921
|
];
|
|
4719
4922
|
for (const label of labels) {
|
|
4720
4923
|
try {
|
|
4721
|
-
|
|
4924
|
+
execFileSync12("gh", [
|
|
4722
4925
|
"label",
|
|
4723
4926
|
"create",
|
|
4724
4927
|
label.name,
|
|
@@ -4738,7 +4941,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
|
|
|
4738
4941
|
console.log(` \u2713 ${label.name}`);
|
|
4739
4942
|
} catch {
|
|
4740
4943
|
try {
|
|
4741
|
-
|
|
4944
|
+
execFileSync12("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
|
|
4742
4945
|
cwd,
|
|
4743
4946
|
encoding: "utf-8",
|
|
4744
4947
|
timeout: 1e4,
|
|
@@ -4777,7 +4980,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
|
|
|
4777
4980
|
try {
|
|
4778
4981
|
const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
|
|
4779
4982
|
for (let pass = 0; pass < 2; pass++) {
|
|
4780
|
-
|
|
4983
|
+
execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
|
|
4781
4984
|
cwd,
|
|
4782
4985
|
encoding: "utf-8",
|
|
4783
4986
|
timeout: 3e4,
|
|
@@ -4793,12 +4996,12 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
|
|
|
4793
4996
|
try {
|
|
4794
4997
|
if (isCI3) {
|
|
4795
4998
|
const branchName = `kody-bootstrap-${Date.now()}`;
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
const staged =
|
|
4999
|
+
execFileSync12("git", ["checkout", "-b", branchName], { cwd, stdio: "pipe" });
|
|
5000
|
+
execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
|
|
5001
|
+
const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
|
|
4799
5002
|
if (staged) {
|
|
4800
|
-
|
|
4801
|
-
|
|
5003
|
+
execFileSync12("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
|
|
5004
|
+
execFileSync12("git", ["push", "-u", "origin", branchName], { cwd, stdio: "pipe", timeout: 6e4 });
|
|
4802
5005
|
console.log(` \u2713 Pushed branch: ${branchName}`);
|
|
4803
5006
|
let baseBranch = "main";
|
|
4804
5007
|
try {
|
|
@@ -4810,7 +5013,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
|
|
|
4810
5013
|
} catch {
|
|
4811
5014
|
}
|
|
4812
5015
|
try {
|
|
4813
|
-
const prUrl =
|
|
5016
|
+
const prUrl = execFileSync12("gh", [
|
|
4814
5017
|
"pr",
|
|
4815
5018
|
"create",
|
|
4816
5019
|
"--title",
|
|
@@ -4849,13 +5052,13 @@ Create it manually.`, cwd);
|
|
|
4849
5052
|
console.log(" \u25CB No new changes to commit");
|
|
4850
5053
|
}
|
|
4851
5054
|
} else {
|
|
4852
|
-
|
|
4853
|
-
const staged =
|
|
5055
|
+
execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
|
|
5056
|
+
const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
|
|
4854
5057
|
if (staged) {
|
|
4855
|
-
|
|
5058
|
+
execFileSync12("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
|
|
4856
5059
|
console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
|
|
4857
5060
|
try {
|
|
4858
|
-
|
|
5061
|
+
execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
|
|
4859
5062
|
console.log(" \u2713 Pushed to origin");
|
|
4860
5063
|
} catch {
|
|
4861
5064
|
console.log(" \u25CB Push failed \u2014 run 'git push' manually");
|
|
@@ -4976,7 +5179,7 @@ function installSkillsForProject(cwd) {
|
|
|
4976
5179
|
}
|
|
4977
5180
|
try {
|
|
4978
5181
|
console.log(` Installing: ${skill.label} (${skill.package})`);
|
|
4979
|
-
|
|
5182
|
+
execFileSync12("npx", ["skills", "add", skill.package, "--yes"], {
|
|
4980
5183
|
cwd,
|
|
4981
5184
|
encoding: "utf-8",
|
|
4982
5185
|
timeout: 6e4,
|
package/package.json
CHANGED
package/templates/kody.yml
CHANGED
|
@@ -119,7 +119,7 @@ jobs:
|
|
|
119
119
|
|
|
120
120
|
# Validate mode
|
|
121
121
|
case "$MODE" in
|
|
122
|
-
full|rerun|fix|fix-ci|status|approve|review|bootstrap) ;;
|
|
122
|
+
full|rerun|fix|fix-ci|status|approve|review|resolve|bootstrap) ;;
|
|
123
123
|
*)
|
|
124
124
|
# If first arg isn't a mode, it might be a task-id or nothing
|
|
125
125
|
if [ -n "$MODE" ] && [ "$MODE" != "" ]; then
|
|
@@ -219,7 +219,7 @@ jobs:
|
|
|
219
219
|
token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
220
220
|
|
|
221
221
|
- name: Checkout PR branch (for fix/rerun/review on PRs)
|
|
222
|
-
if: github.event.issue.pull_request && (needs.parse.outputs.mode == 'fix' || needs.parse.outputs.mode == 'fix-ci' || needs.parse.outputs.mode == 'rerun' || needs.parse.outputs.mode == 'review')
|
|
222
|
+
if: github.event.issue.pull_request && (needs.parse.outputs.mode == 'fix' || needs.parse.outputs.mode == 'fix-ci' || needs.parse.outputs.mode == 'rerun' || needs.parse.outputs.mode == 'review' || needs.parse.outputs.mode == 'resolve')
|
|
223
223
|
env:
|
|
224
224
|
GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
225
225
|
run: |
|
|
@@ -277,6 +277,7 @@ jobs:
|
|
|
277
277
|
[ "$MODE" = "fix" ] && CMD="fix"
|
|
278
278
|
[ "$MODE" = "fix-ci" ] && CMD="fix-ci"
|
|
279
279
|
[ "$MODE" = "review" ] && CMD="review"
|
|
280
|
+
[ "$MODE" = "resolve" ] && CMD="resolve"
|
|
280
281
|
ARGS="--issue-number $ISSUE_NUMBER"
|
|
281
282
|
[ -n "$TASK_ID" ] && ARGS="$ARGS --task-id $TASK_ID"
|
|
282
283
|
[ -n "$PR_NUMBER" ] && ARGS="$ARGS --pr-number $PR_NUMBER"
|
package/dist/agent-runner.d.ts
DELETED