@kody-ade/kody-engine 0.2.55 → 0.2.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kody2.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@kody-ade/kody-engine",
|
|
6
|
-
version: "0.2.
|
|
6
|
+
version: "0.2.57",
|
|
7
7
|
description: "kody2 \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
8
8
|
license: "MIT",
|
|
9
9
|
type: "module",
|
|
@@ -50,7 +50,7 @@ var package_default = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
// src/chat-cli.ts
|
|
53
|
-
import { execFileSync as
|
|
53
|
+
import { execFileSync as execFileSync22 } from "child_process";
|
|
54
54
|
import * as fs22 from "fs";
|
|
55
55
|
import * as path19 from "path";
|
|
56
56
|
|
|
@@ -543,7 +543,7 @@ async function emit(sink, type, sessionId, suffix, payload) {
|
|
|
543
543
|
}
|
|
544
544
|
|
|
545
545
|
// src/kody2-cli.ts
|
|
546
|
-
import { execFileSync as
|
|
546
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
547
547
|
import * as fs21 from "fs";
|
|
548
548
|
import * as path18 from "path";
|
|
549
549
|
|
|
@@ -4486,6 +4486,269 @@ function tryPostPr4(prNumber, body, cwd) {
|
|
|
4486
4486
|
}
|
|
4487
4487
|
}
|
|
4488
4488
|
|
|
4489
|
+
// src/scripts/riskGate.ts
|
|
4490
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
4491
|
+
var ALL_GATES = ["secrets", "workflow-edit", "large-diff", "dep-change", "test-deletion"];
|
|
4492
|
+
var HARD_GATES = /* @__PURE__ */ new Set(["secrets"]);
|
|
4493
|
+
var APPROVE_ALL = "kody-approve:all";
|
|
4494
|
+
var GATED_LABEL = "kody:gated";
|
|
4495
|
+
var DEFAULT_MAX_FILES = 20;
|
|
4496
|
+
var DEFAULT_MAX_DELETIONS = 500;
|
|
4497
|
+
var riskGate = async (ctx, profile, _agent, args) => {
|
|
4498
|
+
const changedFiles = collectBranchChangedFiles(ctx);
|
|
4499
|
+
const gatesToRun = parseGates(args?.gates);
|
|
4500
|
+
const violations = evaluateGates(ctx, profile.name, changedFiles, gatesToRun, args);
|
|
4501
|
+
if (violations.length === 0) {
|
|
4502
|
+
ctx.data.riskGate = { violations: [], pending: [], decision: "allow" };
|
|
4503
|
+
return;
|
|
4504
|
+
}
|
|
4505
|
+
const targetType = ctx.data.commentTargetType;
|
|
4506
|
+
const targetNumber = Number(ctx.data.commentTargetNumber ?? 0);
|
|
4507
|
+
const labels = targetNumber > 0 ? getIssueLabels(targetNumber, ctx.cwd) : [];
|
|
4508
|
+
const approveAll = labels.includes(APPROVE_ALL);
|
|
4509
|
+
const pending = violations.filter((v) => !isApproved(v, labels, approveAll));
|
|
4510
|
+
ctx.data.riskGate = {
|
|
4511
|
+
violations,
|
|
4512
|
+
pending,
|
|
4513
|
+
decision: pending.length === 0 ? "allow" : "halt"
|
|
4514
|
+
};
|
|
4515
|
+
if (pending.length === 0 || !targetType || targetNumber <= 0) return;
|
|
4516
|
+
for (const v of pending) {
|
|
4517
|
+
ensureApproveLabel(v.name, ctx.cwd);
|
|
4518
|
+
}
|
|
4519
|
+
try {
|
|
4520
|
+
setKodyLabel(
|
|
4521
|
+
targetNumber,
|
|
4522
|
+
{
|
|
4523
|
+
label: GATED_LABEL,
|
|
4524
|
+
color: "fbca04",
|
|
4525
|
+
description: "kody2: awaiting human approval of risk gate(s)"
|
|
4526
|
+
},
|
|
4527
|
+
ctx.cwd
|
|
4528
|
+
);
|
|
4529
|
+
} catch {
|
|
4530
|
+
}
|
|
4531
|
+
const body = formatAdvisory(pending);
|
|
4532
|
+
try {
|
|
4533
|
+
if (targetType === "issue") postIssueComment(targetNumber, body, ctx.cwd);
|
|
4534
|
+
else postPrReviewComment(targetNumber, body, ctx.cwd);
|
|
4535
|
+
} catch {
|
|
4536
|
+
}
|
|
4537
|
+
if (!ctx.output.reason) {
|
|
4538
|
+
ctx.output.reason = `risk gate halt: ${pending.map((p) => p.name).join(", ")}`;
|
|
4539
|
+
}
|
|
4540
|
+
};
|
|
4541
|
+
function evaluateGates(ctx, profileName, changedFiles, gatesToRun, args) {
|
|
4542
|
+
const violations = [];
|
|
4543
|
+
if (gatesToRun.includes("secrets")) {
|
|
4544
|
+
const hits = changedFiles.filter(isSecretPath);
|
|
4545
|
+
if (hits.length > 0) {
|
|
4546
|
+
violations.push({
|
|
4547
|
+
name: "secrets",
|
|
4548
|
+
severity: "hard",
|
|
4549
|
+
reason: `secret/credential files touched: ${preview(hits)}`
|
|
4550
|
+
});
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
if (gatesToRun.includes("workflow-edit")) {
|
|
4554
|
+
const hits = changedFiles.filter((f) => f.startsWith(".github/workflows/"));
|
|
4555
|
+
if (hits.length > 0) {
|
|
4556
|
+
violations.push({
|
|
4557
|
+
name: "workflow-edit",
|
|
4558
|
+
severity: "soft",
|
|
4559
|
+
reason: `CI workflow files modified: ${preview(hits)}`
|
|
4560
|
+
});
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
if (gatesToRun.includes("large-diff")) {
|
|
4564
|
+
const maxFiles = toPositiveInt(args?.maxFiles, DEFAULT_MAX_FILES);
|
|
4565
|
+
const maxDeletions = toPositiveInt(args?.maxDeletions, DEFAULT_MAX_DELETIONS);
|
|
4566
|
+
if (changedFiles.length > maxFiles) {
|
|
4567
|
+
violations.push({
|
|
4568
|
+
name: "large-diff",
|
|
4569
|
+
severity: "soft",
|
|
4570
|
+
reason: `${changedFiles.length} files changed (threshold: ${maxFiles})`
|
|
4571
|
+
});
|
|
4572
|
+
} else {
|
|
4573
|
+
const stats = computeDiffStats(ctx);
|
|
4574
|
+
if (stats && stats.deletions > maxDeletions) {
|
|
4575
|
+
violations.push({
|
|
4576
|
+
name: "large-diff",
|
|
4577
|
+
severity: "soft",
|
|
4578
|
+
reason: `${stats.deletions} lines deleted (threshold: ${maxDeletions})`
|
|
4579
|
+
});
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
if (gatesToRun.includes("dep-change") && profileName !== "chore") {
|
|
4584
|
+
const hits = changedFiles.filter(isDepFile);
|
|
4585
|
+
if (hits.length > 0) {
|
|
4586
|
+
violations.push({
|
|
4587
|
+
name: "dep-change",
|
|
4588
|
+
severity: "soft",
|
|
4589
|
+
reason: `dependency/lockfile changes outside a chore flow: ${preview(hits)}`
|
|
4590
|
+
});
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
if (gatesToRun.includes("test-deletion")) {
|
|
4594
|
+
const deleted = listDeletedFilesInHeadCommit(ctx.cwd).filter(isTestFile);
|
|
4595
|
+
if (deleted.length > 0) {
|
|
4596
|
+
violations.push({
|
|
4597
|
+
name: "test-deletion",
|
|
4598
|
+
severity: "soft",
|
|
4599
|
+
reason: `test files deleted: ${preview(deleted)}`
|
|
4600
|
+
});
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
return violations;
|
|
4604
|
+
}
|
|
4605
|
+
function isApproved(v, labels, approveAll) {
|
|
4606
|
+
if (labels.includes(`kody-approve:${v.name}`)) return true;
|
|
4607
|
+
if (!HARD_GATES.has(v.name) && approveAll) return true;
|
|
4608
|
+
return false;
|
|
4609
|
+
}
|
|
4610
|
+
function parseGates(spec) {
|
|
4611
|
+
if (spec === void 0 || spec === null || spec === "") return ALL_GATES;
|
|
4612
|
+
const list = String(spec).split(",").map((s) => s.trim()).filter(Boolean);
|
|
4613
|
+
const valid = ALL_GATES;
|
|
4614
|
+
const matched = list.filter((n) => valid.includes(n));
|
|
4615
|
+
return matched.length > 0 ? matched : ALL_GATES;
|
|
4616
|
+
}
|
|
4617
|
+
function toPositiveInt(v, fallback) {
|
|
4618
|
+
const n = typeof v === "number" ? v : parseInt(String(v ?? ""), 10);
|
|
4619
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
4620
|
+
}
|
|
4621
|
+
function preview(list, max = 5) {
|
|
4622
|
+
if (list.length <= max) return list.join(", ");
|
|
4623
|
+
return `${list.slice(0, max).join(", ")} (+${list.length - max} more)`;
|
|
4624
|
+
}
|
|
4625
|
+
var SECRET_PATTERNS = [
|
|
4626
|
+
/(^|\/)\.env(\.|$)/i,
|
|
4627
|
+
/\.pem$/i,
|
|
4628
|
+
/\.key$/i,
|
|
4629
|
+
/(^|\/)(id_rsa|id_ed25519|id_ecdsa)(\.|$)/i,
|
|
4630
|
+
/credentials?(\.|\/|$)/i,
|
|
4631
|
+
/(^|\/)(private|secret)[^/]*\.json$/i,
|
|
4632
|
+
/(^|\/)\.netrc$/i,
|
|
4633
|
+
/(^|\/)\.npmrc$/i
|
|
4634
|
+
];
|
|
4635
|
+
function isSecretPath(p) {
|
|
4636
|
+
return SECRET_PATTERNS.some((r) => r.test(p));
|
|
4637
|
+
}
|
|
4638
|
+
var DEP_FILES = /* @__PURE__ */ new Set([
|
|
4639
|
+
"package.json",
|
|
4640
|
+
"pnpm-lock.yaml",
|
|
4641
|
+
"package-lock.json",
|
|
4642
|
+
"yarn.lock",
|
|
4643
|
+
"requirements.txt",
|
|
4644
|
+
"Pipfile",
|
|
4645
|
+
"Pipfile.lock",
|
|
4646
|
+
"poetry.lock",
|
|
4647
|
+
"go.mod",
|
|
4648
|
+
"go.sum",
|
|
4649
|
+
"Cargo.toml",
|
|
4650
|
+
"Cargo.lock",
|
|
4651
|
+
"Gemfile",
|
|
4652
|
+
"Gemfile.lock"
|
|
4653
|
+
]);
|
|
4654
|
+
function isDepFile(p) {
|
|
4655
|
+
return DEP_FILES.has(p.split("/").pop() ?? "");
|
|
4656
|
+
}
|
|
4657
|
+
function isTestFile(p) {
|
|
4658
|
+
return /(^|\/)(tests?|__tests__|spec)\//i.test(p) || /\.(test|spec)\.[a-z0-9]+$/i.test(p);
|
|
4659
|
+
}
|
|
4660
|
+
function collectBranchChangedFiles(ctx) {
|
|
4661
|
+
const base = ctx.config.git.defaultBranch;
|
|
4662
|
+
for (const ref of [`origin/${base}...HEAD`, `${base}...HEAD`]) {
|
|
4663
|
+
try {
|
|
4664
|
+
const out = execFileSync17("git", ["diff", "--name-only", ref], {
|
|
4665
|
+
cwd: ctx.cwd,
|
|
4666
|
+
encoding: "utf-8",
|
|
4667
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4668
|
+
});
|
|
4669
|
+
const files = out.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
4670
|
+
if (files.length > 0) return files;
|
|
4671
|
+
} catch {
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4674
|
+
return ctx.data.changedFiles ?? [];
|
|
4675
|
+
}
|
|
4676
|
+
function computeDiffStats(ctx) {
|
|
4677
|
+
const base = ctx.config.git.defaultBranch;
|
|
4678
|
+
for (const ref of [`origin/${base}...HEAD`, `${base}...HEAD`]) {
|
|
4679
|
+
try {
|
|
4680
|
+
const out = execFileSync17("git", ["diff", "--shortstat", ref], {
|
|
4681
|
+
cwd: ctx.cwd,
|
|
4682
|
+
encoding: "utf-8",
|
|
4683
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4684
|
+
}).trim();
|
|
4685
|
+
if (out) return parseShortstat(out);
|
|
4686
|
+
} catch {
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
return null;
|
|
4690
|
+
}
|
|
4691
|
+
function parseShortstat(s) {
|
|
4692
|
+
const ins = /(\d+)\s+insertions?/.exec(s);
|
|
4693
|
+
const del = /(\d+)\s+deletions?/.exec(s);
|
|
4694
|
+
return {
|
|
4695
|
+
insertions: ins ? parseInt(ins[1], 10) : 0,
|
|
4696
|
+
deletions: del ? parseInt(del[1], 10) : 0
|
|
4697
|
+
};
|
|
4698
|
+
}
|
|
4699
|
+
function listDeletedFilesInHeadCommit(cwd) {
|
|
4700
|
+
try {
|
|
4701
|
+
const out = execFileSync17("git", ["show", "--name-status", "--pretty=format:", "HEAD"], {
|
|
4702
|
+
cwd,
|
|
4703
|
+
encoding: "utf-8",
|
|
4704
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4705
|
+
});
|
|
4706
|
+
return out.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("D ")).map((l) => l.slice(2).trim()).filter(Boolean);
|
|
4707
|
+
} catch {
|
|
4708
|
+
return [];
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
function ensureApproveLabel(gate, cwd) {
|
|
4712
|
+
try {
|
|
4713
|
+
gh2(
|
|
4714
|
+
[
|
|
4715
|
+
"label",
|
|
4716
|
+
"create",
|
|
4717
|
+
`kody-approve:${gate}`,
|
|
4718
|
+
"--force",
|
|
4719
|
+
"--color",
|
|
4720
|
+
"0e8a16",
|
|
4721
|
+
"--description",
|
|
4722
|
+
`kody2: approve the ${gate} risk gate and resume the flow`
|
|
4723
|
+
],
|
|
4724
|
+
{ cwd }
|
|
4725
|
+
);
|
|
4726
|
+
} catch {
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
function formatAdvisory(pending) {
|
|
4730
|
+
const lines = [];
|
|
4731
|
+
lines.push("\u23F8\uFE0F **kody2 risk gate halted the flow.**");
|
|
4732
|
+
lines.push("");
|
|
4733
|
+
lines.push("The changes were committed and pushed, but the flow will **not progress** until a human approves:");
|
|
4734
|
+
lines.push("");
|
|
4735
|
+
for (const v of pending) {
|
|
4736
|
+
lines.push(`- **\`${v.name}\`** _(${v.severity})_ \u2014 ${v.reason}`);
|
|
4737
|
+
}
|
|
4738
|
+
lines.push("");
|
|
4739
|
+
lines.push("**To approve and resume**, add one of these labels to this issue/PR:");
|
|
4740
|
+
const perGate = pending.map((v) => `\`kody-approve:${v.name}\``).join(", ");
|
|
4741
|
+
lines.push(`- ${perGate}`);
|
|
4742
|
+
if (pending.some((v) => v.severity === "soft")) {
|
|
4743
|
+
lines.push("- `kody-approve:all` \u2014 bypass **soft** gates at once (hard gates still require their specific label)");
|
|
4744
|
+
}
|
|
4745
|
+
lines.push("");
|
|
4746
|
+
lines.push(
|
|
4747
|
+
"Then re-trigger kody2 (e.g. post a new `@kody2 \u2026` comment). The branch already holds the committed work, so the re-run resumes from the same point."
|
|
4748
|
+
);
|
|
4749
|
+
return lines.join("\n");
|
|
4750
|
+
}
|
|
4751
|
+
|
|
4489
4752
|
// src/scripts/runFlow.ts
|
|
4490
4753
|
var runFlow = async (ctx) => {
|
|
4491
4754
|
const issueNumber = ctx.args.issue;
|
|
@@ -4582,7 +4845,7 @@ var skipAgent = async (ctx) => {
|
|
|
4582
4845
|
};
|
|
4583
4846
|
|
|
4584
4847
|
// src/scripts/startFlow.ts
|
|
4585
|
-
import { execFileSync as
|
|
4848
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
4586
4849
|
var API_TIMEOUT_MS7 = 3e4;
|
|
4587
4850
|
var startFlow = async (ctx, profile, _agentResult, args) => {
|
|
4588
4851
|
const entry = args?.entry;
|
|
@@ -4616,7 +4879,7 @@ function postKody2Comment(target, issueNumber, state, next, cwd) {
|
|
|
4616
4879
|
const sub = target === "pr" && state?.core.prUrl ? "pr" : "issue";
|
|
4617
4880
|
const body = `@kody2 ${next}`;
|
|
4618
4881
|
try {
|
|
4619
|
-
|
|
4882
|
+
execFileSync18("gh", [sub, "comment", String(targetNumber), "--body", body], {
|
|
4620
4883
|
timeout: API_TIMEOUT_MS7,
|
|
4621
4884
|
cwd,
|
|
4622
4885
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4636,7 +4899,7 @@ function parsePr2(url) {
|
|
|
4636
4899
|
}
|
|
4637
4900
|
|
|
4638
4901
|
// src/scripts/syncFlow.ts
|
|
4639
|
-
import { execFileSync as
|
|
4902
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
4640
4903
|
var syncFlow = async (ctx) => {
|
|
4641
4904
|
ctx.skipAgent = true;
|
|
4642
4905
|
const prNumber = ctx.args.pr;
|
|
@@ -4695,7 +4958,7 @@ function bail2(ctx, prNumber, reason) {
|
|
|
4695
4958
|
}
|
|
4696
4959
|
function revParseHead(cwd) {
|
|
4697
4960
|
try {
|
|
4698
|
-
return
|
|
4961
|
+
return execFileSync19("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
4699
4962
|
} catch {
|
|
4700
4963
|
return "";
|
|
4701
4964
|
}
|
|
@@ -4703,9 +4966,9 @@ function revParseHead(cwd) {
|
|
|
4703
4966
|
function pushBranch(branch, cwd) {
|
|
4704
4967
|
const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
|
|
4705
4968
|
try {
|
|
4706
|
-
|
|
4969
|
+
execFileSync19("git", ["push", "-u", "origin", branch], { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
4707
4970
|
} catch {
|
|
4708
|
-
|
|
4971
|
+
execFileSync19("git", ["push", "--force-with-lease", "-u", "origin", branch], {
|
|
4709
4972
|
cwd,
|
|
4710
4973
|
env,
|
|
4711
4974
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4947,7 +5210,8 @@ var postflightScripts = {
|
|
|
4947
5210
|
finishFlow,
|
|
4948
5211
|
advanceFlow,
|
|
4949
5212
|
persistFlowState,
|
|
4950
|
-
postClassification
|
|
5213
|
+
postClassification,
|
|
5214
|
+
riskGate
|
|
4951
5215
|
};
|
|
4952
5216
|
var allScriptNames = /* @__PURE__ */ new Set([
|
|
4953
5217
|
...Object.keys(preflightScripts),
|
|
@@ -4955,7 +5219,7 @@ var allScriptNames = /* @__PURE__ */ new Set([
|
|
|
4955
5219
|
]);
|
|
4956
5220
|
|
|
4957
5221
|
// src/tools.ts
|
|
4958
|
-
import { execFileSync as
|
|
5222
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
4959
5223
|
function verifyCliTools(tools, cwd) {
|
|
4960
5224
|
const out = [];
|
|
4961
5225
|
for (const t of tools) out.push(verifyOne(t, cwd));
|
|
@@ -4988,7 +5252,7 @@ function verifyOne(tool, cwd) {
|
|
|
4988
5252
|
}
|
|
4989
5253
|
function runShell2(cmd, cwd, timeoutMs = 3e4) {
|
|
4990
5254
|
try {
|
|
4991
|
-
|
|
5255
|
+
execFileSync20("sh", ["-c", cmd], { cwd, stdio: "pipe", timeout: timeoutMs });
|
|
4992
5256
|
return true;
|
|
4993
5257
|
} catch {
|
|
4994
5258
|
return false;
|
|
@@ -5318,7 +5582,7 @@ function detectPackageManager2(cwd) {
|
|
|
5318
5582
|
}
|
|
5319
5583
|
function shellOut(cmd, args, cwd, stream = true) {
|
|
5320
5584
|
try {
|
|
5321
|
-
|
|
5585
|
+
execFileSync21(cmd, args, {
|
|
5322
5586
|
cwd,
|
|
5323
5587
|
stdio: stream ? "inherit" : "pipe",
|
|
5324
5588
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" }
|
|
@@ -5331,7 +5595,7 @@ function shellOut(cmd, args, cwd, stream = true) {
|
|
|
5331
5595
|
}
|
|
5332
5596
|
function isOnPath(bin) {
|
|
5333
5597
|
try {
|
|
5334
|
-
|
|
5598
|
+
execFileSync21("which", [bin], { stdio: "pipe" });
|
|
5335
5599
|
return true;
|
|
5336
5600
|
} catch {
|
|
5337
5601
|
return false;
|
|
@@ -5365,7 +5629,7 @@ function installLitellmIfNeeded(cwd) {
|
|
|
5365
5629
|
} catch {
|
|
5366
5630
|
}
|
|
5367
5631
|
try {
|
|
5368
|
-
|
|
5632
|
+
execFileSync21("python3", ["-c", "import litellm"], { stdio: "pipe" });
|
|
5369
5633
|
process.stdout.write("\u2192 kody2: litellm already installed\n");
|
|
5370
5634
|
return 0;
|
|
5371
5635
|
} catch {
|
|
@@ -5375,16 +5639,16 @@ function installLitellmIfNeeded(cwd) {
|
|
|
5375
5639
|
}
|
|
5376
5640
|
function configureGitIdentity(cwd) {
|
|
5377
5641
|
try {
|
|
5378
|
-
const name =
|
|
5642
|
+
const name = execFileSync21("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
|
|
5379
5643
|
if (name) return;
|
|
5380
5644
|
} catch {
|
|
5381
5645
|
}
|
|
5382
5646
|
try {
|
|
5383
|
-
|
|
5647
|
+
execFileSync21("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
|
|
5384
5648
|
} catch {
|
|
5385
5649
|
}
|
|
5386
5650
|
try {
|
|
5387
|
-
|
|
5651
|
+
execFileSync21("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
|
|
5388
5652
|
cwd,
|
|
5389
5653
|
stdio: "pipe"
|
|
5390
5654
|
});
|
|
@@ -5561,9 +5825,9 @@ function commitChatFiles(cwd, sessionId, verbose) {
|
|
|
5561
5825
|
if (paths.length === 0) return;
|
|
5562
5826
|
const opts = { cwd, stdio: verbose ? "inherit" : "pipe" };
|
|
5563
5827
|
try {
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5828
|
+
execFileSync22("git", ["add", ...paths], opts);
|
|
5829
|
+
execFileSync22("git", ["commit", "--quiet", "-m", `chat: reply for ${sessionId}`], opts);
|
|
5830
|
+
execFileSync22("git", ["push", "--quiet", "origin", "HEAD"], opts);
|
|
5567
5831
|
} catch (err) {
|
|
5568
5832
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5569
5833
|
process.stderr.write(`[kody2:chat] commit/push skipped: ${msg}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.57",
|
|
4
4
|
"description": "kody2 — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|