@kody-ade/kody-engine-lite 0.1.42 → 0.1.44
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 +135 -85
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -249,6 +249,72 @@ var init_logger = __esm({
|
|
|
249
249
|
}
|
|
250
250
|
});
|
|
251
251
|
|
|
252
|
+
// src/config.ts
|
|
253
|
+
import * as fs from "fs";
|
|
254
|
+
import * as path from "path";
|
|
255
|
+
function setConfigDir(dir) {
|
|
256
|
+
_configDir = dir;
|
|
257
|
+
_config = null;
|
|
258
|
+
}
|
|
259
|
+
function getProjectConfig() {
|
|
260
|
+
if (_config) return _config;
|
|
261
|
+
const configPath = path.join(_configDir ?? process.cwd(), "kody.config.json");
|
|
262
|
+
if (fs.existsSync(configPath)) {
|
|
263
|
+
try {
|
|
264
|
+
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
265
|
+
_config = {
|
|
266
|
+
quality: { ...DEFAULT_CONFIG.quality, ...raw.quality },
|
|
267
|
+
git: { ...DEFAULT_CONFIG.git, ...raw.git },
|
|
268
|
+
github: { ...DEFAULT_CONFIG.github, ...raw.github },
|
|
269
|
+
paths: { ...DEFAULT_CONFIG.paths, ...raw.paths },
|
|
270
|
+
agent: { ...DEFAULT_CONFIG.agent, ...raw.agent }
|
|
271
|
+
};
|
|
272
|
+
} catch {
|
|
273
|
+
logger.warn("kody.config.json is invalid JSON \u2014 using defaults");
|
|
274
|
+
_config = { ...DEFAULT_CONFIG };
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
_config = { ...DEFAULT_CONFIG };
|
|
278
|
+
}
|
|
279
|
+
return _config;
|
|
280
|
+
}
|
|
281
|
+
var DEFAULT_CONFIG, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
|
|
282
|
+
var init_config = __esm({
|
|
283
|
+
"src/config.ts"() {
|
|
284
|
+
"use strict";
|
|
285
|
+
init_logger();
|
|
286
|
+
DEFAULT_CONFIG = {
|
|
287
|
+
quality: {
|
|
288
|
+
typecheck: "pnpm -s tsc --noEmit",
|
|
289
|
+
lint: "pnpm -s lint",
|
|
290
|
+
lintFix: "pnpm lint:fix",
|
|
291
|
+
format: "pnpm -s format:check",
|
|
292
|
+
formatFix: "pnpm format:fix",
|
|
293
|
+
testUnit: "pnpm -s test"
|
|
294
|
+
},
|
|
295
|
+
git: {
|
|
296
|
+
defaultBranch: "dev"
|
|
297
|
+
},
|
|
298
|
+
github: {
|
|
299
|
+
owner: "",
|
|
300
|
+
repo: ""
|
|
301
|
+
},
|
|
302
|
+
paths: {
|
|
303
|
+
taskDir: ".tasks"
|
|
304
|
+
},
|
|
305
|
+
agent: {
|
|
306
|
+
runner: "claude-code",
|
|
307
|
+
defaultRunner: "claude",
|
|
308
|
+
modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
312
|
+
FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
313
|
+
_config = null;
|
|
314
|
+
_configDir = null;
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
252
318
|
// src/git-utils.ts
|
|
253
319
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
254
320
|
function getHookSafeEnv() {
|
|
@@ -271,6 +337,13 @@ function deriveBranchName(issueNumber, title) {
|
|
|
271
337
|
return `${issueNumber}-${slug}`;
|
|
272
338
|
}
|
|
273
339
|
function getDefaultBranch(cwd) {
|
|
340
|
+
try {
|
|
341
|
+
const config = getProjectConfig();
|
|
342
|
+
if (config.git?.defaultBranch) {
|
|
343
|
+
return config.git.defaultBranch;
|
|
344
|
+
}
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
274
347
|
try {
|
|
275
348
|
const ref = git(["symbolic-ref", "refs/remotes/origin/HEAD"], { cwd });
|
|
276
349
|
return ref.replace("refs/remotes/origin/", "");
|
|
@@ -374,6 +447,7 @@ var init_git_utils = __esm({
|
|
|
374
447
|
"src/git-utils.ts"() {
|
|
375
448
|
"use strict";
|
|
376
449
|
init_logger();
|
|
450
|
+
init_config();
|
|
377
451
|
BASE_BRANCHES = ["dev", "main", "master"];
|
|
378
452
|
_hookSafeEnv = null;
|
|
379
453
|
}
|
|
@@ -441,6 +515,32 @@ function postComment(issueNumber, body) {
|
|
|
441
515
|
logger.warn(` Failed to post comment: ${err}`);
|
|
442
516
|
}
|
|
443
517
|
}
|
|
518
|
+
function getPRForBranch(branch) {
|
|
519
|
+
try {
|
|
520
|
+
const output = gh([
|
|
521
|
+
"pr",
|
|
522
|
+
"view",
|
|
523
|
+
branch,
|
|
524
|
+
"--json",
|
|
525
|
+
"number,url"
|
|
526
|
+
]);
|
|
527
|
+
const data = JSON.parse(output);
|
|
528
|
+
return { number: data.number, url: data.url };
|
|
529
|
+
} catch {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
function updatePR(prNumber, body) {
|
|
534
|
+
try {
|
|
535
|
+
gh(
|
|
536
|
+
["pr", "edit", String(prNumber), "--body-file", "-"],
|
|
537
|
+
{ input: body }
|
|
538
|
+
);
|
|
539
|
+
logger.info(` PR #${prNumber} body updated`);
|
|
540
|
+
} catch (err) {
|
|
541
|
+
logger.warn(` Failed to update PR #${prNumber}: ${err}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
444
544
|
function createPR(head, base, title, body) {
|
|
445
545
|
try {
|
|
446
546
|
const output = gh(
|
|
@@ -493,13 +593,13 @@ var init_github_api = __esm({
|
|
|
493
593
|
});
|
|
494
594
|
|
|
495
595
|
// src/pipeline/state.ts
|
|
496
|
-
import * as
|
|
497
|
-
import * as
|
|
596
|
+
import * as fs2 from "fs";
|
|
597
|
+
import * as path2 from "path";
|
|
498
598
|
function loadState(taskId, taskDir) {
|
|
499
|
-
const p =
|
|
500
|
-
if (!
|
|
599
|
+
const p = path2.join(taskDir, "status.json");
|
|
600
|
+
if (!fs2.existsSync(p)) return null;
|
|
501
601
|
try {
|
|
502
|
-
const raw = JSON.parse(
|
|
602
|
+
const raw = JSON.parse(fs2.readFileSync(p, "utf-8"));
|
|
503
603
|
if (raw.taskId === taskId) return raw;
|
|
504
604
|
return null;
|
|
505
605
|
} catch {
|
|
@@ -511,10 +611,10 @@ function writeState(state, taskDir) {
|
|
|
511
611
|
...state,
|
|
512
612
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
513
613
|
};
|
|
514
|
-
const target =
|
|
614
|
+
const target = path2.join(taskDir, "status.json");
|
|
515
615
|
const tmp = target + ".tmp";
|
|
516
|
-
|
|
517
|
-
|
|
616
|
+
fs2.writeFileSync(tmp, JSON.stringify(updated, null, 2));
|
|
617
|
+
fs2.renameSync(tmp, target);
|
|
518
618
|
state.updatedAt = updated.updatedAt;
|
|
519
619
|
}
|
|
520
620
|
function initState(taskId) {
|
|
@@ -553,16 +653,16 @@ var init_complexity = __esm({
|
|
|
553
653
|
});
|
|
554
654
|
|
|
555
655
|
// src/memory.ts
|
|
556
|
-
import * as
|
|
557
|
-
import * as
|
|
656
|
+
import * as fs3 from "fs";
|
|
657
|
+
import * as path3 from "path";
|
|
558
658
|
function readProjectMemory(projectDir) {
|
|
559
|
-
const memoryDir =
|
|
560
|
-
if (!
|
|
561
|
-
const files =
|
|
659
|
+
const memoryDir = path3.join(projectDir, ".kody", "memory");
|
|
660
|
+
if (!fs3.existsSync(memoryDir)) return "";
|
|
661
|
+
const files = fs3.readdirSync(memoryDir).filter((f) => f.endsWith(".md")).sort();
|
|
562
662
|
if (files.length === 0) return "";
|
|
563
663
|
const sections = [];
|
|
564
664
|
for (const file of files) {
|
|
565
|
-
const content =
|
|
665
|
+
const content = fs3.readFileSync(path3.join(memoryDir, file), "utf-8").trim();
|
|
566
666
|
if (content) {
|
|
567
667
|
sections.push(`## ${file.replace(".md", "")}
|
|
568
668
|
${content}`);
|
|
@@ -580,72 +680,6 @@ var init_memory = __esm({
|
|
|
580
680
|
}
|
|
581
681
|
});
|
|
582
682
|
|
|
583
|
-
// src/config.ts
|
|
584
|
-
import * as fs3 from "fs";
|
|
585
|
-
import * as path3 from "path";
|
|
586
|
-
function setConfigDir(dir) {
|
|
587
|
-
_configDir = dir;
|
|
588
|
-
_config = null;
|
|
589
|
-
}
|
|
590
|
-
function getProjectConfig() {
|
|
591
|
-
if (_config) return _config;
|
|
592
|
-
const configPath = path3.join(_configDir ?? process.cwd(), "kody.config.json");
|
|
593
|
-
if (fs3.existsSync(configPath)) {
|
|
594
|
-
try {
|
|
595
|
-
const raw = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
|
|
596
|
-
_config = {
|
|
597
|
-
quality: { ...DEFAULT_CONFIG.quality, ...raw.quality },
|
|
598
|
-
git: { ...DEFAULT_CONFIG.git, ...raw.git },
|
|
599
|
-
github: { ...DEFAULT_CONFIG.github, ...raw.github },
|
|
600
|
-
paths: { ...DEFAULT_CONFIG.paths, ...raw.paths },
|
|
601
|
-
agent: { ...DEFAULT_CONFIG.agent, ...raw.agent }
|
|
602
|
-
};
|
|
603
|
-
} catch {
|
|
604
|
-
logger.warn("kody.config.json is invalid JSON \u2014 using defaults");
|
|
605
|
-
_config = { ...DEFAULT_CONFIG };
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
_config = { ...DEFAULT_CONFIG };
|
|
609
|
-
}
|
|
610
|
-
return _config;
|
|
611
|
-
}
|
|
612
|
-
var DEFAULT_CONFIG, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
|
|
613
|
-
var init_config = __esm({
|
|
614
|
-
"src/config.ts"() {
|
|
615
|
-
"use strict";
|
|
616
|
-
init_logger();
|
|
617
|
-
DEFAULT_CONFIG = {
|
|
618
|
-
quality: {
|
|
619
|
-
typecheck: "pnpm -s tsc --noEmit",
|
|
620
|
-
lint: "pnpm -s lint",
|
|
621
|
-
lintFix: "pnpm lint:fix",
|
|
622
|
-
format: "pnpm -s format:check",
|
|
623
|
-
formatFix: "pnpm format:fix",
|
|
624
|
-
testUnit: "pnpm -s test"
|
|
625
|
-
},
|
|
626
|
-
git: {
|
|
627
|
-
defaultBranch: "dev"
|
|
628
|
-
},
|
|
629
|
-
github: {
|
|
630
|
-
owner: "",
|
|
631
|
-
repo: ""
|
|
632
|
-
},
|
|
633
|
-
paths: {
|
|
634
|
-
taskDir: ".tasks"
|
|
635
|
-
},
|
|
636
|
-
agent: {
|
|
637
|
-
runner: "claude-code",
|
|
638
|
-
defaultRunner: "claude",
|
|
639
|
-
modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
643
|
-
FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
644
|
-
_config = null;
|
|
645
|
-
_configDir = null;
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
|
|
649
683
|
// src/context.ts
|
|
650
684
|
import * as fs4 from "fs";
|
|
651
685
|
import * as path4 from "path";
|
|
@@ -1512,21 +1546,37 @@ function executeShipStage(ctx, _def) {
|
|
|
1512
1546
|
}
|
|
1513
1547
|
}
|
|
1514
1548
|
const body = buildPrBody(ctx);
|
|
1515
|
-
const
|
|
1516
|
-
if (
|
|
1549
|
+
const existingPr = getPRForBranch(head);
|
|
1550
|
+
if (existingPr) {
|
|
1551
|
+
updatePR(existingPr.number, body);
|
|
1517
1552
|
if (ctx.input.issueNumber && !ctx.input.local) {
|
|
1518
1553
|
try {
|
|
1519
|
-
postComment(ctx.input.issueNumber, `\
|
|
1554
|
+
postComment(ctx.input.issueNumber, `\u2705 Fix pushed to existing PR: ${existingPr.url}`);
|
|
1520
1555
|
} catch {
|
|
1521
1556
|
}
|
|
1522
1557
|
}
|
|
1523
1558
|
fs9.writeFileSync(shipPath, `# Ship
|
|
1524
1559
|
|
|
1560
|
+
Updated existing PR: ${existingPr.url}
|
|
1561
|
+
PR #${existingPr.number}
|
|
1562
|
+
`);
|
|
1563
|
+
} else {
|
|
1564
|
+
const pr = createPR(head, base, title, body);
|
|
1565
|
+
if (pr) {
|
|
1566
|
+
if (ctx.input.issueNumber && !ctx.input.local) {
|
|
1567
|
+
try {
|
|
1568
|
+
postComment(ctx.input.issueNumber, `\u{1F389} PR created: ${pr.url}`);
|
|
1569
|
+
} catch {
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
fs9.writeFileSync(shipPath, `# Ship
|
|
1573
|
+
|
|
1525
1574
|
PR created: ${pr.url}
|
|
1526
1575
|
PR #${pr.number}
|
|
1527
1576
|
`);
|
|
1528
|
-
|
|
1529
|
-
|
|
1577
|
+
} else {
|
|
1578
|
+
fs9.writeFileSync(shipPath, "# Ship\n\nPushed branch but failed to create PR.\n");
|
|
1579
|
+
}
|
|
1530
1580
|
}
|
|
1531
1581
|
return { outcome: "completed", outputFile: "ship.md", retries: 0 };
|
|
1532
1582
|
} catch (err) {
|