@kody-ade/kody-engine 0.4.129 → 0.4.131
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
CHANGED
|
@@ -880,7 +880,7 @@ var init_loadPriorArt = __esm({
|
|
|
880
880
|
// package.json
|
|
881
881
|
var package_default = {
|
|
882
882
|
name: "@kody-ade/kody-engine",
|
|
883
|
-
version: "0.4.
|
|
883
|
+
version: "0.4.131",
|
|
884
884
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
885
885
|
license: "MIT",
|
|
886
886
|
type: "module",
|
|
@@ -6499,6 +6499,44 @@ function stripQuotes(value) {
|
|
|
6499
6499
|
// src/scripts/jobState/contentsApiBackend.ts
|
|
6500
6500
|
init_issue();
|
|
6501
6501
|
|
|
6502
|
+
// src/stateBranch.ts
|
|
6503
|
+
init_issue();
|
|
6504
|
+
var STATE_BRANCH = "kody-state";
|
|
6505
|
+
function is404(err) {
|
|
6506
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6507
|
+
return /HTTP 404/i.test(msg) || /Not Found/i.test(msg);
|
|
6508
|
+
}
|
|
6509
|
+
function ensureStateBranch(owner, repo, cwd) {
|
|
6510
|
+
try {
|
|
6511
|
+
gh(["api", `/repos/${owner}/${repo}/git/ref/heads/${STATE_BRANCH}`], { cwd });
|
|
6512
|
+
return;
|
|
6513
|
+
} catch (err) {
|
|
6514
|
+
if (!is404(err)) throw err;
|
|
6515
|
+
}
|
|
6516
|
+
const repoInfo = JSON.parse(gh(["api", `/repos/${owner}/${repo}`], { cwd }));
|
|
6517
|
+
const defaultBranch2 = repoInfo.default_branch;
|
|
6518
|
+
if (!defaultBranch2) {
|
|
6519
|
+
throw new Error(`ensureStateBranch: could not resolve default branch for ${owner}/${repo}`);
|
|
6520
|
+
}
|
|
6521
|
+
const headRef = JSON.parse(
|
|
6522
|
+
gh(["api", `/repos/${owner}/${repo}/git/ref/heads/${defaultBranch2}`], { cwd })
|
|
6523
|
+
);
|
|
6524
|
+
const sha = headRef.object?.sha;
|
|
6525
|
+
if (!sha) {
|
|
6526
|
+
throw new Error(`ensureStateBranch: could not resolve head sha for ${owner}/${repo}@${defaultBranch2}`);
|
|
6527
|
+
}
|
|
6528
|
+
try {
|
|
6529
|
+
gh(["api", "--method", "POST", `/repos/${owner}/${repo}/git/refs`, "--input", "-"], {
|
|
6530
|
+
cwd,
|
|
6531
|
+
input: JSON.stringify({ ref: `refs/heads/${STATE_BRANCH}`, sha })
|
|
6532
|
+
});
|
|
6533
|
+
} catch (err) {
|
|
6534
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6535
|
+
if (/already exists/i.test(msg) || /HTTP 422/i.test(msg)) return;
|
|
6536
|
+
throw err;
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
|
|
6502
6540
|
// src/scripts/issueStateComment.ts
|
|
6503
6541
|
init_issue();
|
|
6504
6542
|
function isStateEnvelope(x) {
|
|
@@ -6617,7 +6655,9 @@ var ContentsApiBackend = class {
|
|
|
6617
6655
|
const filePath = stateFilePath(this.jobsDir, slug);
|
|
6618
6656
|
let raw = "";
|
|
6619
6657
|
try {
|
|
6620
|
-
raw = gh(["api", `/repos/${this.owner}/${this.repo}/contents/${filePath}`], {
|
|
6658
|
+
raw = gh(["api", `/repos/${this.owner}/${this.repo}/contents/${filePath}?ref=${STATE_BRANCH}`], {
|
|
6659
|
+
cwd: this.cwd
|
|
6660
|
+
});
|
|
6621
6661
|
} catch (err) {
|
|
6622
6662
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6623
6663
|
if (/HTTP 404/i.test(msg) || /Not Found/i.test(msg)) {
|
|
@@ -6658,9 +6698,12 @@ var ContentsApiBackend = class {
|
|
|
6658
6698
|
const body = JSON.stringify(next, null, 2) + "\n";
|
|
6659
6699
|
const payload = {
|
|
6660
6700
|
message: `chore(jobs): update state for ${slug} (rev ${next.rev})`,
|
|
6661
|
-
content: Buffer.from(body, "utf-8").toString("base64")
|
|
6701
|
+
content: Buffer.from(body, "utf-8").toString("base64"),
|
|
6702
|
+
// Commit to the dedicated state branch instead of the default branch.
|
|
6703
|
+
branch: STATE_BRANCH
|
|
6662
6704
|
};
|
|
6663
6705
|
if (typeof loaded.handle === "string") payload.sha = loaded.handle;
|
|
6706
|
+
ensureStateBranch(this.owner, this.repo, this.cwd);
|
|
6664
6707
|
gh(["api", "--method", "PUT", `/repos/${this.owner}/${this.repo}/contents/${loaded.path}`, "--input", "-"], {
|
|
6665
6708
|
cwd: this.cwd,
|
|
6666
6709
|
input: JSON.stringify(payload)
|
|
@@ -11195,11 +11238,13 @@ var saveGoalState = async (ctx) => {
|
|
|
11195
11238
|
ctx.skipAgent = true;
|
|
11196
11239
|
return;
|
|
11197
11240
|
}
|
|
11241
|
+
const prev = goal.raw;
|
|
11242
|
+
const changed = !prev || prev.state !== goal.state || prev.lastDispatchedIssue !== goal.lastDispatchedIssue;
|
|
11198
11243
|
const updated = {
|
|
11199
|
-
...
|
|
11244
|
+
...prev ?? { state: goal.state, extra: {} },
|
|
11200
11245
|
state: goal.state,
|
|
11201
11246
|
lastDispatchedIssue: goal.lastDispatchedIssue,
|
|
11202
|
-
updatedAt: nowIso()
|
|
11247
|
+
updatedAt: changed ? nowIso() : prev?.updatedAt
|
|
11203
11248
|
};
|
|
11204
11249
|
writeGoalState(ctx.cwd, goal.id, updated);
|
|
11205
11250
|
ctx.skipAgent = true;
|
|
@@ -11891,6 +11936,69 @@ function sleep3(ms) {
|
|
|
11891
11936
|
return new Promise((res) => setTimeout(res, ms));
|
|
11892
11937
|
}
|
|
11893
11938
|
|
|
11939
|
+
// src/scripts/appendCompanyActivity.ts
|
|
11940
|
+
init_issue();
|
|
11941
|
+
function resolveTrigger(force) {
|
|
11942
|
+
const event = process.env.GITHUB_EVENT_NAME ?? "";
|
|
11943
|
+
if (event === "schedule") return "schedule";
|
|
11944
|
+
if (force || event === "issue_comment" || event === "workflow_dispatch")
|
|
11945
|
+
return "manual";
|
|
11946
|
+
return "event";
|
|
11947
|
+
}
|
|
11948
|
+
function appendLine(owner, repo, cwd, record) {
|
|
11949
|
+
const filePath = `.kody/activity/${record.ts.slice(0, 10)}.jsonl`;
|
|
11950
|
+
let existing = "";
|
|
11951
|
+
let sha;
|
|
11952
|
+
try {
|
|
11953
|
+
const out = gh(["api", `/repos/${owner}/${repo}/contents/${filePath}`], { cwd });
|
|
11954
|
+
const json = JSON.parse(out);
|
|
11955
|
+
if (json.sha) sha = json.sha;
|
|
11956
|
+
if (json.content) existing = Buffer.from(json.content, "base64").toString("utf-8");
|
|
11957
|
+
} catch {
|
|
11958
|
+
}
|
|
11959
|
+
const body = `${existing}${JSON.stringify(record)}
|
|
11960
|
+
`;
|
|
11961
|
+
const payload = {
|
|
11962
|
+
message: `chore(activity): ${record.action}`,
|
|
11963
|
+
content: Buffer.from(body, "utf-8").toString("base64")
|
|
11964
|
+
};
|
|
11965
|
+
if (sha) payload.sha = sha;
|
|
11966
|
+
gh(
|
|
11967
|
+
["api", "--method", "PUT", `/repos/${owner}/${repo}/contents/${filePath}`, "--input", "-"],
|
|
11968
|
+
{ cwd, input: JSON.stringify(payload) }
|
|
11969
|
+
);
|
|
11970
|
+
}
|
|
11971
|
+
var appendCompanyActivity = async (ctx, _profile, agentResult) => {
|
|
11972
|
+
try {
|
|
11973
|
+
const owner = ctx.config?.github?.owner;
|
|
11974
|
+
const repo = ctx.config?.github?.repo;
|
|
11975
|
+
const duty = String(ctx.data.jobSlug ?? ctx.args?.job ?? "").trim();
|
|
11976
|
+
if (!owner || !repo || !duty) return;
|
|
11977
|
+
const dutyTitle = ctx.data.jobTitle ?? null;
|
|
11978
|
+
const staff = ctx.data.workerSlug || null;
|
|
11979
|
+
const staffTitle = ctx.data.workerTitle || null;
|
|
11980
|
+
const force = ctx.args?.force === true;
|
|
11981
|
+
const record = {
|
|
11982
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11983
|
+
action: `Ran duty: ${dutyTitle ?? duty}`,
|
|
11984
|
+
duty,
|
|
11985
|
+
dutyTitle,
|
|
11986
|
+
staff,
|
|
11987
|
+
staffTitle,
|
|
11988
|
+
trigger: resolveTrigger(force),
|
|
11989
|
+
outcome: agentResult?.outcome ?? "unknown",
|
|
11990
|
+
durationMs: agentResult?.durationMs ?? null,
|
|
11991
|
+
runUrl: getRunUrl() || null
|
|
11992
|
+
};
|
|
11993
|
+
appendLine(owner, repo, ctx.cwd, record);
|
|
11994
|
+
} catch (err) {
|
|
11995
|
+
process.stderr.write(
|
|
11996
|
+
`[activity] company-activity append failed: ${err instanceof Error ? err.message : String(err)}
|
|
11997
|
+
`
|
|
11998
|
+
);
|
|
11999
|
+
}
|
|
12000
|
+
};
|
|
12001
|
+
|
|
11894
12002
|
// src/scripts/warmupMcp.ts
|
|
11895
12003
|
import { spawn as spawn7 } from "child_process";
|
|
11896
12004
|
var PER_SERVER_TIMEOUT_MS = 6e4;
|
|
@@ -12073,7 +12181,7 @@ var writeIssueStateComment = async (ctx, _profile, _agentResult, args) => {
|
|
|
12073
12181
|
};
|
|
12074
12182
|
|
|
12075
12183
|
// src/scripts/writeJobStateFile.ts
|
|
12076
|
-
var writeJobStateFile = async (ctx, _profile,
|
|
12184
|
+
var writeJobStateFile = async (ctx, _profile, agentResult, args) => {
|
|
12077
12185
|
const parseError = ctx.data.nextStateParseError;
|
|
12078
12186
|
if (parseError) {
|
|
12079
12187
|
process.stderr.write(`[kody] job state write skipped: ${parseError}
|
|
@@ -12094,7 +12202,11 @@ var writeJobStateFile = async (ctx, _profile, _agentResult, args) => {
|
|
|
12094
12202
|
...next,
|
|
12095
12203
|
data: {
|
|
12096
12204
|
...next.data,
|
|
12097
|
-
lastFiredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12205
|
+
lastFiredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12206
|
+
...agentResult ? {
|
|
12207
|
+
lastOutcome: agentResult.outcome,
|
|
12208
|
+
lastDurationMs: agentResult.durationMs ?? null
|
|
12209
|
+
} : {}
|
|
12098
12210
|
}
|
|
12099
12211
|
};
|
|
12100
12212
|
const jobsDir = String(args?.jobsDir ?? ".kody/duties");
|
|
@@ -12185,6 +12297,7 @@ var postflightScripts = {
|
|
|
12185
12297
|
parseReproOutput,
|
|
12186
12298
|
writeIssueStateComment,
|
|
12187
12299
|
writeJobStateFile,
|
|
12300
|
+
appendCompanyActivity,
|
|
12188
12301
|
requireFeedbackActions,
|
|
12189
12302
|
requirePlanDeviations,
|
|
12190
12303
|
verify,
|
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.131",
|
|
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",
|