@kody-ade/kody-engine 0.2.55 → 0.2.56
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.56",
|
|
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,253 @@ 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 = ctx.data.changedFiles ?? [];
|
|
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 computeDiffStats(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", "--shortstat", ref], {
|
|
4665
|
+
cwd: ctx.cwd,
|
|
4666
|
+
encoding: "utf-8",
|
|
4667
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4668
|
+
}).trim();
|
|
4669
|
+
if (out) return parseShortstat(out);
|
|
4670
|
+
} catch {
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
return null;
|
|
4674
|
+
}
|
|
4675
|
+
function parseShortstat(s) {
|
|
4676
|
+
const ins = /(\d+)\s+insertions?/.exec(s);
|
|
4677
|
+
const del = /(\d+)\s+deletions?/.exec(s);
|
|
4678
|
+
return {
|
|
4679
|
+
insertions: ins ? parseInt(ins[1], 10) : 0,
|
|
4680
|
+
deletions: del ? parseInt(del[1], 10) : 0
|
|
4681
|
+
};
|
|
4682
|
+
}
|
|
4683
|
+
function listDeletedFilesInHeadCommit(cwd) {
|
|
4684
|
+
try {
|
|
4685
|
+
const out = execFileSync17("git", ["show", "--name-status", "--pretty=format:", "HEAD"], {
|
|
4686
|
+
cwd,
|
|
4687
|
+
encoding: "utf-8",
|
|
4688
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4689
|
+
});
|
|
4690
|
+
return out.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("D ")).map((l) => l.slice(2).trim()).filter(Boolean);
|
|
4691
|
+
} catch {
|
|
4692
|
+
return [];
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
function ensureApproveLabel(gate, cwd) {
|
|
4696
|
+
try {
|
|
4697
|
+
gh2(
|
|
4698
|
+
[
|
|
4699
|
+
"label",
|
|
4700
|
+
"create",
|
|
4701
|
+
`kody-approve:${gate}`,
|
|
4702
|
+
"--force",
|
|
4703
|
+
"--color",
|
|
4704
|
+
"0e8a16",
|
|
4705
|
+
"--description",
|
|
4706
|
+
`kody2: approve the ${gate} risk gate and resume the flow`
|
|
4707
|
+
],
|
|
4708
|
+
{ cwd }
|
|
4709
|
+
);
|
|
4710
|
+
} catch {
|
|
4711
|
+
}
|
|
4712
|
+
}
|
|
4713
|
+
function formatAdvisory(pending) {
|
|
4714
|
+
const lines = [];
|
|
4715
|
+
lines.push("\u23F8\uFE0F **kody2 risk gate halted the flow.**");
|
|
4716
|
+
lines.push("");
|
|
4717
|
+
lines.push("The changes were committed and pushed, but the flow will **not progress** until a human approves:");
|
|
4718
|
+
lines.push("");
|
|
4719
|
+
for (const v of pending) {
|
|
4720
|
+
lines.push(`- **\`${v.name}\`** _(${v.severity})_ \u2014 ${v.reason}`);
|
|
4721
|
+
}
|
|
4722
|
+
lines.push("");
|
|
4723
|
+
lines.push("**To approve and resume**, add one of these labels to this issue/PR:");
|
|
4724
|
+
const perGate = pending.map((v) => `\`kody-approve:${v.name}\``).join(", ");
|
|
4725
|
+
lines.push(`- ${perGate}`);
|
|
4726
|
+
if (pending.some((v) => v.severity === "soft")) {
|
|
4727
|
+
lines.push("- `kody-approve:all` \u2014 bypass **soft** gates at once (hard gates still require their specific label)");
|
|
4728
|
+
}
|
|
4729
|
+
lines.push("");
|
|
4730
|
+
lines.push(
|
|
4731
|
+
"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."
|
|
4732
|
+
);
|
|
4733
|
+
return lines.join("\n");
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4489
4736
|
// src/scripts/runFlow.ts
|
|
4490
4737
|
var runFlow = async (ctx) => {
|
|
4491
4738
|
const issueNumber = ctx.args.issue;
|
|
@@ -4582,7 +4829,7 @@ var skipAgent = async (ctx) => {
|
|
|
4582
4829
|
};
|
|
4583
4830
|
|
|
4584
4831
|
// src/scripts/startFlow.ts
|
|
4585
|
-
import { execFileSync as
|
|
4832
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
4586
4833
|
var API_TIMEOUT_MS7 = 3e4;
|
|
4587
4834
|
var startFlow = async (ctx, profile, _agentResult, args) => {
|
|
4588
4835
|
const entry = args?.entry;
|
|
@@ -4616,7 +4863,7 @@ function postKody2Comment(target, issueNumber, state, next, cwd) {
|
|
|
4616
4863
|
const sub = target === "pr" && state?.core.prUrl ? "pr" : "issue";
|
|
4617
4864
|
const body = `@kody2 ${next}`;
|
|
4618
4865
|
try {
|
|
4619
|
-
|
|
4866
|
+
execFileSync18("gh", [sub, "comment", String(targetNumber), "--body", body], {
|
|
4620
4867
|
timeout: API_TIMEOUT_MS7,
|
|
4621
4868
|
cwd,
|
|
4622
4869
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4636,7 +4883,7 @@ function parsePr2(url) {
|
|
|
4636
4883
|
}
|
|
4637
4884
|
|
|
4638
4885
|
// src/scripts/syncFlow.ts
|
|
4639
|
-
import { execFileSync as
|
|
4886
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
4640
4887
|
var syncFlow = async (ctx) => {
|
|
4641
4888
|
ctx.skipAgent = true;
|
|
4642
4889
|
const prNumber = ctx.args.pr;
|
|
@@ -4695,7 +4942,7 @@ function bail2(ctx, prNumber, reason) {
|
|
|
4695
4942
|
}
|
|
4696
4943
|
function revParseHead(cwd) {
|
|
4697
4944
|
try {
|
|
4698
|
-
return
|
|
4945
|
+
return execFileSync19("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
4699
4946
|
} catch {
|
|
4700
4947
|
return "";
|
|
4701
4948
|
}
|
|
@@ -4703,9 +4950,9 @@ function revParseHead(cwd) {
|
|
|
4703
4950
|
function pushBranch(branch, cwd) {
|
|
4704
4951
|
const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
|
|
4705
4952
|
try {
|
|
4706
|
-
|
|
4953
|
+
execFileSync19("git", ["push", "-u", "origin", branch], { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
4707
4954
|
} catch {
|
|
4708
|
-
|
|
4955
|
+
execFileSync19("git", ["push", "--force-with-lease", "-u", "origin", branch], {
|
|
4709
4956
|
cwd,
|
|
4710
4957
|
env,
|
|
4711
4958
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4947,7 +5194,8 @@ var postflightScripts = {
|
|
|
4947
5194
|
finishFlow,
|
|
4948
5195
|
advanceFlow,
|
|
4949
5196
|
persistFlowState,
|
|
4950
|
-
postClassification
|
|
5197
|
+
postClassification,
|
|
5198
|
+
riskGate
|
|
4951
5199
|
};
|
|
4952
5200
|
var allScriptNames = /* @__PURE__ */ new Set([
|
|
4953
5201
|
...Object.keys(preflightScripts),
|
|
@@ -4955,7 +5203,7 @@ var allScriptNames = /* @__PURE__ */ new Set([
|
|
|
4955
5203
|
]);
|
|
4956
5204
|
|
|
4957
5205
|
// src/tools.ts
|
|
4958
|
-
import { execFileSync as
|
|
5206
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
4959
5207
|
function verifyCliTools(tools, cwd) {
|
|
4960
5208
|
const out = [];
|
|
4961
5209
|
for (const t of tools) out.push(verifyOne(t, cwd));
|
|
@@ -4988,7 +5236,7 @@ function verifyOne(tool, cwd) {
|
|
|
4988
5236
|
}
|
|
4989
5237
|
function runShell2(cmd, cwd, timeoutMs = 3e4) {
|
|
4990
5238
|
try {
|
|
4991
|
-
|
|
5239
|
+
execFileSync20("sh", ["-c", cmd], { cwd, stdio: "pipe", timeout: timeoutMs });
|
|
4992
5240
|
return true;
|
|
4993
5241
|
} catch {
|
|
4994
5242
|
return false;
|
|
@@ -5318,7 +5566,7 @@ function detectPackageManager2(cwd) {
|
|
|
5318
5566
|
}
|
|
5319
5567
|
function shellOut(cmd, args, cwd, stream = true) {
|
|
5320
5568
|
try {
|
|
5321
|
-
|
|
5569
|
+
execFileSync21(cmd, args, {
|
|
5322
5570
|
cwd,
|
|
5323
5571
|
stdio: stream ? "inherit" : "pipe",
|
|
5324
5572
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" }
|
|
@@ -5331,7 +5579,7 @@ function shellOut(cmd, args, cwd, stream = true) {
|
|
|
5331
5579
|
}
|
|
5332
5580
|
function isOnPath(bin) {
|
|
5333
5581
|
try {
|
|
5334
|
-
|
|
5582
|
+
execFileSync21("which", [bin], { stdio: "pipe" });
|
|
5335
5583
|
return true;
|
|
5336
5584
|
} catch {
|
|
5337
5585
|
return false;
|
|
@@ -5365,7 +5613,7 @@ function installLitellmIfNeeded(cwd) {
|
|
|
5365
5613
|
} catch {
|
|
5366
5614
|
}
|
|
5367
5615
|
try {
|
|
5368
|
-
|
|
5616
|
+
execFileSync21("python3", ["-c", "import litellm"], { stdio: "pipe" });
|
|
5369
5617
|
process.stdout.write("\u2192 kody2: litellm already installed\n");
|
|
5370
5618
|
return 0;
|
|
5371
5619
|
} catch {
|
|
@@ -5375,16 +5623,16 @@ function installLitellmIfNeeded(cwd) {
|
|
|
5375
5623
|
}
|
|
5376
5624
|
function configureGitIdentity(cwd) {
|
|
5377
5625
|
try {
|
|
5378
|
-
const name =
|
|
5626
|
+
const name = execFileSync21("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
|
|
5379
5627
|
if (name) return;
|
|
5380
5628
|
} catch {
|
|
5381
5629
|
}
|
|
5382
5630
|
try {
|
|
5383
|
-
|
|
5631
|
+
execFileSync21("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
|
|
5384
5632
|
} catch {
|
|
5385
5633
|
}
|
|
5386
5634
|
try {
|
|
5387
|
-
|
|
5635
|
+
execFileSync21("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
|
|
5388
5636
|
cwd,
|
|
5389
5637
|
stdio: "pipe"
|
|
5390
5638
|
});
|
|
@@ -5561,9 +5809,9 @@ function commitChatFiles(cwd, sessionId, verbose) {
|
|
|
5561
5809
|
if (paths.length === 0) return;
|
|
5562
5810
|
const opts = { cwd, stdio: verbose ? "inherit" : "pipe" };
|
|
5563
5811
|
try {
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5812
|
+
execFileSync22("git", ["add", ...paths], opts);
|
|
5813
|
+
execFileSync22("git", ["commit", "--quiet", "-m", `chat: reply for ${sessionId}`], opts);
|
|
5814
|
+
execFileSync22("git", ["push", "--quiet", "origin", "HEAD"], opts);
|
|
5567
5815
|
} catch (err) {
|
|
5568
5816
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5569
5817
|
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.56",
|
|
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",
|