@kody-ade/kody-engine 0.4.410 → 0.4.412
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 +322 -312
- package/package.json +26 -24
- package/templates/kody.yml +88 -0
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.412",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -50,6 +50,7 @@ var init_package = __esm({
|
|
|
50
50
|
prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
|
|
51
51
|
},
|
|
52
52
|
dependencies: {
|
|
53
|
+
"@kody-ade/agency-domain": "0.1.1",
|
|
53
54
|
"@actions/cache": "^6.0.0",
|
|
54
55
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
@@ -746,7 +747,7 @@ function buildVerifyEnv(source = process.env) {
|
|
|
746
747
|
return env;
|
|
747
748
|
}
|
|
748
749
|
function runCommand(command, cwd) {
|
|
749
|
-
return new Promise((
|
|
750
|
+
return new Promise((resolve17) => {
|
|
750
751
|
const start = Date.now();
|
|
751
752
|
const child = spawn(command, {
|
|
752
753
|
cwd,
|
|
@@ -775,11 +776,11 @@ function runCommand(command, cwd) {
|
|
|
775
776
|
child.on("exit", (code) => {
|
|
776
777
|
clearTimeout(timer);
|
|
777
778
|
const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
|
|
778
|
-
|
|
779
|
+
resolve17({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
|
|
779
780
|
});
|
|
780
781
|
child.on("error", (err) => {
|
|
781
782
|
clearTimeout(timer);
|
|
782
|
-
|
|
783
|
+
resolve17({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
|
|
783
784
|
});
|
|
784
785
|
});
|
|
785
786
|
}
|
|
@@ -1088,7 +1089,7 @@ function cmsHeaders(opts) {
|
|
|
1088
1089
|
}
|
|
1089
1090
|
};
|
|
1090
1091
|
}
|
|
1091
|
-
async function callDashboardCms(opts,
|
|
1092
|
+
async function callDashboardCms(opts, path52, init = {}) {
|
|
1092
1093
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1093
1094
|
if (!baseUrl) {
|
|
1094
1095
|
return {
|
|
@@ -1100,7 +1101,7 @@ async function callDashboardCms(opts, path51, init = {}) {
|
|
|
1100
1101
|
const headerResult = cmsHeaders(opts);
|
|
1101
1102
|
if (!headerResult.ok) return headerResult;
|
|
1102
1103
|
try {
|
|
1103
|
-
const res = await fetch(`${baseUrl}${
|
|
1104
|
+
const res = await fetch(`${baseUrl}${path52}`, {
|
|
1104
1105
|
...init,
|
|
1105
1106
|
headers: {
|
|
1106
1107
|
...headerResult.headers,
|
|
@@ -1172,8 +1173,8 @@ function documentArg(value) {
|
|
|
1172
1173
|
function normalizeCmsDocumentIdInput(input) {
|
|
1173
1174
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1174
1175
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1175
|
-
const
|
|
1176
|
-
return
|
|
1176
|
+
const path52 = parseDocumentPath(withoutQuery);
|
|
1177
|
+
return path52 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1177
1178
|
}
|
|
1178
1179
|
function stripWrappingQuotes(value) {
|
|
1179
1180
|
let current = value;
|
|
@@ -1184,9 +1185,9 @@ function stripWrappingQuotes(value) {
|
|
|
1184
1185
|
}
|
|
1185
1186
|
}
|
|
1186
1187
|
function parseDocumentPath(value) {
|
|
1187
|
-
const
|
|
1188
|
-
if (!
|
|
1189
|
-
const parts =
|
|
1188
|
+
const path52 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1189
|
+
if (!path52?.includes("/content/entries/")) return null;
|
|
1190
|
+
const parts = path52.split("/").filter(Boolean).map(decodePathPart);
|
|
1190
1191
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1191
1192
|
const idPart = parts[entriesIndex + 3];
|
|
1192
1193
|
if (!idPart || idPart === "new") return null;
|
|
@@ -2435,6 +2436,46 @@ function createStateBackendFromEnv(env = process.env, client) {
|
|
|
2435
2436
|
updatedAt
|
|
2436
2437
|
});
|
|
2437
2438
|
},
|
|
2439
|
+
async listAgencyDefinitions(tenantId2) {
|
|
2440
|
+
const result = await transport.query(anyApi.agencyModel.listDefinitions, {
|
|
2441
|
+
tenantId: requireTenant(tenantId2)
|
|
2442
|
+
});
|
|
2443
|
+
return Array.isArray(result) ? result : [];
|
|
2444
|
+
},
|
|
2445
|
+
async getAgencyState(tenantId2, definitionId) {
|
|
2446
|
+
const result = await transport.query(anyApi.agencyModel.getState, {
|
|
2447
|
+
tenantId: requireTenant(tenantId2),
|
|
2448
|
+
definitionId: requireNonEmpty(definitionId, "definitionId")
|
|
2449
|
+
});
|
|
2450
|
+
return result ?? null;
|
|
2451
|
+
},
|
|
2452
|
+
async putAgencyState(tenantId2, definitionId, kind, schemaVersion, data, updatedAt) {
|
|
2453
|
+
await transport.mutation(anyApi.agencyModel.putState, {
|
|
2454
|
+
tenantId: requireTenant(tenantId2),
|
|
2455
|
+
definitionId: requireNonEmpty(definitionId, "definitionId"),
|
|
2456
|
+
kind,
|
|
2457
|
+
schemaVersion,
|
|
2458
|
+
data,
|
|
2459
|
+
updatedAt
|
|
2460
|
+
});
|
|
2461
|
+
},
|
|
2462
|
+
async appendAgencyOutput(tenantId2, recordId, schemaVersion, data) {
|
|
2463
|
+
await transport.mutation(anyApi.agencyModel.appendOutput, {
|
|
2464
|
+
tenantId: requireTenant(tenantId2),
|
|
2465
|
+
envelope: {
|
|
2466
|
+
schemaVersion,
|
|
2467
|
+
recordId: requireNonEmpty(recordId, "recordId"),
|
|
2468
|
+
data
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
},
|
|
2472
|
+
async listAgencyOutputs(tenantId2, runId) {
|
|
2473
|
+
const result = await transport.query(anyApi.agencyModel.listOutputs, {
|
|
2474
|
+
tenantId: requireTenant(tenantId2),
|
|
2475
|
+
...runId ? { runId: requireNonEmpty(runId, "runId") } : {}
|
|
2476
|
+
});
|
|
2477
|
+
return Array.isArray(result) ? result : [];
|
|
2478
|
+
},
|
|
2438
2479
|
async appendRunEvent(tenantId2, runId, goalId, event, time) {
|
|
2439
2480
|
await transport.mutation(anyApi.runEvents.append, {
|
|
2440
2481
|
tenantId: requireTenant(tenantId2),
|
|
@@ -3153,7 +3194,7 @@ var init_repoWorkspace = __esm({
|
|
|
3153
3194
|
defaultCloneRepo = (repo, token, dir) => {
|
|
3154
3195
|
fs7.mkdirSync(path8.dirname(dir), { recursive: true });
|
|
3155
3196
|
const clone = buildCloneProcess(repo, token);
|
|
3156
|
-
return new Promise((
|
|
3197
|
+
return new Promise((resolve17, reject) => {
|
|
3157
3198
|
const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
|
|
3158
3199
|
env: clone.env,
|
|
3159
3200
|
stdio: "inherit"
|
|
@@ -3173,7 +3214,7 @@ var init_repoWorkspace = __esm({
|
|
|
3173
3214
|
}
|
|
3174
3215
|
} catch {
|
|
3175
3216
|
}
|
|
3176
|
-
|
|
3217
|
+
resolve17();
|
|
3177
3218
|
});
|
|
3178
3219
|
child.on("error", reject);
|
|
3179
3220
|
});
|
|
@@ -3484,10 +3525,10 @@ async function runAgent(opts) {
|
|
|
3484
3525
|
let timer;
|
|
3485
3526
|
let next;
|
|
3486
3527
|
if (turnTimeoutMs > 0) {
|
|
3487
|
-
const timeoutPromise = new Promise((
|
|
3528
|
+
const timeoutPromise = new Promise((resolve17) => {
|
|
3488
3529
|
timer = setTimeout(() => {
|
|
3489
3530
|
timedOut = true;
|
|
3490
|
-
|
|
3531
|
+
resolve17({ done: true, value: void 0 });
|
|
3491
3532
|
}, turnTimeoutMs);
|
|
3492
3533
|
});
|
|
3493
3534
|
next = await Promise.race([nextPromise, timeoutPromise]);
|
|
@@ -3503,7 +3544,7 @@ async function runAgent(opts) {
|
|
|
3503
3544
|
try {
|
|
3504
3545
|
await Promise.race([
|
|
3505
3546
|
iterator.return(void 0).catch(() => void 0),
|
|
3506
|
-
new Promise((
|
|
3547
|
+
new Promise((resolve17) => setTimeout(resolve17, 1e4).unref())
|
|
3507
3548
|
]);
|
|
3508
3549
|
} catch {
|
|
3509
3550
|
}
|
|
@@ -3769,7 +3810,7 @@ function prepareTaskArtifactsDir(cwd, taskId) {
|
|
|
3769
3810
|
function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
|
|
3770
3811
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3771
3812
|
const defaults = {
|
|
3772
|
-
"context.json": JSON.stringify(
|
|
3813
|
+
"context.json": `${JSON.stringify(
|
|
3773
3814
|
{
|
|
3774
3815
|
taskId: artifacts.taskId,
|
|
3775
3816
|
taskType: metadata.taskType,
|
|
@@ -3786,7 +3827,8 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
|
|
|
3786
3827
|
},
|
|
3787
3828
|
null,
|
|
3788
3829
|
2
|
|
3789
|
-
)
|
|
3830
|
+
)}
|
|
3831
|
+
`,
|
|
3790
3832
|
"memory-recs.json": "[]\n",
|
|
3791
3833
|
"followups.json": "[]\n",
|
|
3792
3834
|
"handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
|
|
@@ -6669,11 +6711,11 @@ async function nextAvailableLitellmUrl(url) {
|
|
|
6669
6711
|
throw new Error(`no free LiteLLM port found after ${startPort}`);
|
|
6670
6712
|
}
|
|
6671
6713
|
function canListen(port, host) {
|
|
6672
|
-
return new Promise((
|
|
6714
|
+
return new Promise((resolve17) => {
|
|
6673
6715
|
const server = net.createServer();
|
|
6674
|
-
server.once("error", () =>
|
|
6716
|
+
server.once("error", () => resolve17(false));
|
|
6675
6717
|
server.once("listening", () => {
|
|
6676
|
-
server.close(() =>
|
|
6718
|
+
server.close(() => resolve17(true));
|
|
6677
6719
|
});
|
|
6678
6720
|
server.listen(port, host);
|
|
6679
6721
|
});
|
|
@@ -7834,9 +7876,9 @@ import * as fs26 from "fs";
|
|
|
7834
7876
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
7835
7877
|
const logs = goalRunLogs(data);
|
|
7836
7878
|
const existing = logs[goalId];
|
|
7837
|
-
const
|
|
7879
|
+
const path52 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
7838
7880
|
logs[goalId] = {
|
|
7839
|
-
path:
|
|
7881
|
+
path: path52,
|
|
7840
7882
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
7841
7883
|
};
|
|
7842
7884
|
}
|
|
@@ -7961,7 +8003,7 @@ function buildGoalRunLogEvent(data, goalId, event, at) {
|
|
|
7961
8003
|
if (context !== void 0) base.dispatchContext = context;
|
|
7962
8004
|
return base;
|
|
7963
8005
|
}
|
|
7964
|
-
function enrichGoalRunLogEvent(config, data,
|
|
8006
|
+
function enrichGoalRunLogEvent(config, data, _logPath, event) {
|
|
7965
8007
|
const trigger = event.trigger ?? triggerContext();
|
|
7966
8008
|
const job = event.job ?? jobContext(data);
|
|
7967
8009
|
const run = event.run ?? runContext(data);
|
|
@@ -8252,7 +8294,7 @@ function backendTenant(config) {
|
|
|
8252
8294
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
8253
8295
|
}
|
|
8254
8296
|
function decodeGoal(doc) {
|
|
8255
|
-
if (!doc
|
|
8297
|
+
if (!doc?.state || typeof doc.state !== "object" || Array.isArray(doc.state)) return null;
|
|
8256
8298
|
const state = doc.state;
|
|
8257
8299
|
if (typeof state.state !== "string" || !state.extra || typeof state.extra !== "object") return null;
|
|
8258
8300
|
return state;
|
|
@@ -8809,11 +8851,11 @@ function validateWorkflow(value, options = {}) {
|
|
|
8809
8851
|
function formatWorkflowValidationIssues(issues) {
|
|
8810
8852
|
return issues.map((entry) => `${entry.path}: ${entry.message}`);
|
|
8811
8853
|
}
|
|
8812
|
-
function validateDataMatch(value,
|
|
8854
|
+
function validateDataMatch(value, path52, issues, capabilityOutputs) {
|
|
8813
8855
|
if (value === void 0) return;
|
|
8814
8856
|
const match = asRecord2(value);
|
|
8815
8857
|
if (!match || Object.keys(match).length === 0) {
|
|
8816
|
-
issue(issues, "invalid_condition",
|
|
8858
|
+
issue(issues, "invalid_condition", path52, "workflow condition must contain at least one match");
|
|
8817
8859
|
return;
|
|
8818
8860
|
}
|
|
8819
8861
|
for (const [field, expected] of Object.entries(match)) {
|
|
@@ -8821,7 +8863,7 @@ function validateDataMatch(value, path51, issues, capabilityOutputs) {
|
|
|
8821
8863
|
issue(
|
|
8822
8864
|
issues,
|
|
8823
8865
|
"invalid_data_path",
|
|
8824
|
-
`${
|
|
8866
|
+
`${path52}.${field}`,
|
|
8825
8867
|
`workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
|
|
8826
8868
|
);
|
|
8827
8869
|
}
|
|
@@ -8829,12 +8871,12 @@ function validateDataMatch(value, path51, issues, capabilityOutputs) {
|
|
|
8829
8871
|
issue(
|
|
8830
8872
|
issues,
|
|
8831
8873
|
"undeclared_result_path",
|
|
8832
|
-
`${
|
|
8874
|
+
`${path52}.${field}`,
|
|
8833
8875
|
`workflow condition reads ${field}, but the source capability does not declare it`
|
|
8834
8876
|
);
|
|
8835
8877
|
}
|
|
8836
8878
|
if (!isComparable(expected)) {
|
|
8837
|
-
issue(issues, "invalid_condition_value", `${
|
|
8879
|
+
issue(issues, "invalid_condition_value", `${path52}.${field}`, "workflow condition value must be a JSON scalar");
|
|
8838
8880
|
}
|
|
8839
8881
|
}
|
|
8840
8882
|
}
|
|
@@ -8852,8 +8894,8 @@ function isComparable(value) {
|
|
|
8852
8894
|
if (value === null || ["string", "number", "boolean"].includes(typeof value)) return true;
|
|
8853
8895
|
return Array.isArray(value) && value.length > 0 && value.every((item) => isComparable(item) && !Array.isArray(item));
|
|
8854
8896
|
}
|
|
8855
|
-
function issue(issues, code,
|
|
8856
|
-
issues.push({ code, path:
|
|
8897
|
+
function issue(issues, code, path52, message) {
|
|
8898
|
+
issues.push({ code, path: path52, message });
|
|
8857
8899
|
}
|
|
8858
8900
|
var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
|
|
8859
8901
|
var init_workflowValidation = __esm({
|
|
@@ -9111,15 +9153,15 @@ var init_backendStateBackend = __esm({
|
|
|
9111
9153
|
this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
|
|
9112
9154
|
}
|
|
9113
9155
|
async load(slug) {
|
|
9114
|
-
const
|
|
9156
|
+
const path52 = stateFilePath(this.jobsDir, slug);
|
|
9115
9157
|
const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
|
|
9116
9158
|
if (!loaded) {
|
|
9117
|
-
return { path:
|
|
9159
|
+
return { path: path52, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
9118
9160
|
}
|
|
9119
9161
|
if (!isStateEnvelope(loaded.doc)) {
|
|
9120
9162
|
throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
|
|
9121
9163
|
}
|
|
9122
|
-
return { path:
|
|
9164
|
+
return { path: path52, handle: loaded.updatedAt, state: loaded.doc, created: false };
|
|
9123
9165
|
}
|
|
9124
9166
|
async save(loaded, next) {
|
|
9125
9167
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
|
|
@@ -13915,14 +13957,33 @@ var init_fixFlow = __esm({
|
|
|
13915
13957
|
}
|
|
13916
13958
|
});
|
|
13917
13959
|
|
|
13918
|
-
// src/
|
|
13919
|
-
import { execFileSync as execFileSync14 } from "child_process";
|
|
13960
|
+
// src/workflow-template.ts
|
|
13920
13961
|
import * as fs35 from "fs";
|
|
13921
13962
|
import * as path33 from "path";
|
|
13963
|
+
import { fileURLToPath } from "url";
|
|
13964
|
+
function loadKodyWorkflowTemplate() {
|
|
13965
|
+
const here = path33.dirname(fileURLToPath(import.meta.url));
|
|
13966
|
+
const candidates = [path33.resolve(here, "../templates/kody.yml"), path33.resolve(here, "../../templates/kody.yml")];
|
|
13967
|
+
const source = candidates.find((candidate) => fs35.existsSync(candidate));
|
|
13968
|
+
if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
|
|
13969
|
+
return fs35.readFileSync(source, "utf8");
|
|
13970
|
+
}
|
|
13971
|
+
var KODY_WORKFLOW_TEMPLATE_PATH;
|
|
13972
|
+
var init_workflow_template = __esm({
|
|
13973
|
+
"src/workflow-template.ts"() {
|
|
13974
|
+
"use strict";
|
|
13975
|
+
KODY_WORKFLOW_TEMPLATE_PATH = "templates/kody.yml";
|
|
13976
|
+
}
|
|
13977
|
+
});
|
|
13978
|
+
|
|
13979
|
+
// src/scripts/initFlow.ts
|
|
13980
|
+
import { execFileSync as execFileSync14 } from "child_process";
|
|
13981
|
+
import * as fs36 from "fs";
|
|
13982
|
+
import * as path34 from "path";
|
|
13922
13983
|
function detectPackageManager(cwd) {
|
|
13923
|
-
if (
|
|
13924
|
-
if (
|
|
13925
|
-
if (
|
|
13984
|
+
if (fs36.existsSync(path34.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
13985
|
+
if (fs36.existsSync(path34.join(cwd, "yarn.lock"))) return "yarn";
|
|
13986
|
+
if (fs36.existsSync(path34.join(cwd, "bun.lockb"))) return "bun";
|
|
13926
13987
|
return "npm";
|
|
13927
13988
|
}
|
|
13928
13989
|
function qualityCommandsFor(pm) {
|
|
@@ -13994,22 +14055,22 @@ function performInit(cwd, force) {
|
|
|
13994
14055
|
const pm = detectPackageManager(cwd);
|
|
13995
14056
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
13996
14057
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
13997
|
-
const configPath =
|
|
13998
|
-
if (
|
|
14058
|
+
const configPath = path34.join(cwd, "kody.config.json");
|
|
14059
|
+
if (fs36.existsSync(configPath) && !force) {
|
|
13999
14060
|
skipped.push("kody.config.json");
|
|
14000
14061
|
} else {
|
|
14001
14062
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
14002
|
-
|
|
14063
|
+
fs36.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
14003
14064
|
`);
|
|
14004
14065
|
wrote.push("kody.config.json");
|
|
14005
14066
|
}
|
|
14006
|
-
const workflowDir =
|
|
14007
|
-
const workflowPath =
|
|
14008
|
-
if (
|
|
14067
|
+
const workflowDir = path34.join(cwd, ".github", "workflows");
|
|
14068
|
+
const workflowPath = path34.join(workflowDir, "kody.yml");
|
|
14069
|
+
if (fs36.existsSync(workflowPath) && !force) {
|
|
14009
14070
|
skipped.push(".github/workflows/kody.yml");
|
|
14010
14071
|
} else {
|
|
14011
|
-
|
|
14012
|
-
|
|
14072
|
+
fs36.mkdirSync(workflowDir, { recursive: true });
|
|
14073
|
+
fs36.writeFileSync(workflowPath, loadKodyWorkflowTemplate());
|
|
14013
14074
|
wrote.push(".github/workflows/kody.yml");
|
|
14014
14075
|
}
|
|
14015
14076
|
for (const exe of listImplementations()) {
|
|
@@ -14020,12 +14081,12 @@ function performInit(cwd, force) {
|
|
|
14020
14081
|
continue;
|
|
14021
14082
|
}
|
|
14022
14083
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
14023
|
-
const target =
|
|
14024
|
-
if (
|
|
14084
|
+
const target = path34.join(workflowDir, `kody-${exe.name}.yml`);
|
|
14085
|
+
if (fs36.existsSync(target) && !force) {
|
|
14025
14086
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
14026
14087
|
continue;
|
|
14027
14088
|
}
|
|
14028
|
-
|
|
14089
|
+
fs36.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
14029
14090
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
14030
14091
|
}
|
|
14031
14092
|
let labels;
|
|
@@ -14071,7 +14132,7 @@ jobs:
|
|
|
14071
14132
|
run: npx -y -p @kody-ade/kody-engine@latest kody-engine implementation ${name}
|
|
14072
14133
|
`;
|
|
14073
14134
|
}
|
|
14074
|
-
var
|
|
14135
|
+
var initFlow;
|
|
14075
14136
|
var init_initFlow = __esm({
|
|
14076
14137
|
"src/scripts/initFlow.ts"() {
|
|
14077
14138
|
"use strict";
|
|
@@ -14079,67 +14140,7 @@ var init_initFlow = __esm({
|
|
|
14079
14140
|
init_lifecycleLabels();
|
|
14080
14141
|
init_profile();
|
|
14081
14142
|
init_registry();
|
|
14082
|
-
|
|
14083
|
-
#
|
|
14084
|
-
# Triggers: @kody comment on an issue or PR, or manual workflow_dispatch.
|
|
14085
|
-
# Everything else (install deps, set up LiteLLM, run the agent, open the PR)
|
|
14086
|
-
# is handled inside the @kody-ade/kody-engine package.
|
|
14087
|
-
#
|
|
14088
|
-
# Required repo secrets: at least one model provider key (e.g. MINIMAX_API_KEY,
|
|
14089
|
-
# ANTHROPIC_API_KEY). kody reads any *_API_KEY secret automatically via
|
|
14090
|
-
# toJSON(secrets) \u2014 no need to list them here.
|
|
14091
|
-
#
|
|
14092
|
-
# Recommended: KODY_TOKEN secret \u2014 a PAT or GitHub App token with repo
|
|
14093
|
-
# scope so kody's pushes trigger downstream CI and PR-body edits succeed.
|
|
14094
|
-
|
|
14095
|
-
name: kody
|
|
14096
|
-
|
|
14097
|
-
on:
|
|
14098
|
-
workflow_dispatch:
|
|
14099
|
-
inputs:
|
|
14100
|
-
issue_number:
|
|
14101
|
-
description: "GitHub issue number"
|
|
14102
|
-
required: true
|
|
14103
|
-
type: string
|
|
14104
|
-
capability:
|
|
14105
|
-
description: "Capability action to run (default: run)"
|
|
14106
|
-
required: false
|
|
14107
|
-
type: string
|
|
14108
|
-
default: ""
|
|
14109
|
-
issue_comment:
|
|
14110
|
-
types: [created]
|
|
14111
|
-
|
|
14112
|
-
jobs:
|
|
14113
|
-
run:
|
|
14114
|
-
if: >-
|
|
14115
|
-
\${{ github.event_name == 'workflow_dispatch' ||
|
|
14116
|
-
(github.event_name == 'issue_comment' &&
|
|
14117
|
-
contains(github.event.comment.body, '@kody')) }}
|
|
14118
|
-
runs-on: ubuntu-latest
|
|
14119
|
-
timeout-minutes: 60
|
|
14120
|
-
permissions:
|
|
14121
|
-
issues: write
|
|
14122
|
-
pull-requests: write
|
|
14123
|
-
contents: write
|
|
14124
|
-
actions: read
|
|
14125
|
-
steps:
|
|
14126
|
-
- uses: actions/checkout@v4
|
|
14127
|
-
with:
|
|
14128
|
-
fetch-depth: 0
|
|
14129
|
-
token: \${{ secrets.KODY_TOKEN || github.token }}
|
|
14130
|
-
|
|
14131
|
-
- uses: actions/setup-node@v4
|
|
14132
|
-
with:
|
|
14133
|
-
node-version: 22
|
|
14134
|
-
|
|
14135
|
-
- uses: actions/setup-python@v5
|
|
14136
|
-
with:
|
|
14137
|
-
python-version: "3.12"
|
|
14138
|
-
|
|
14139
|
-
- env:
|
|
14140
|
-
ALL_SECRETS: \${{ toJSON(secrets) }}
|
|
14141
|
-
run: npx -y -p @kody-ade/kody-engine@latest kody-engine ci
|
|
14142
|
-
`;
|
|
14143
|
+
init_workflow_template();
|
|
14143
14144
|
initFlow = async (ctx) => {
|
|
14144
14145
|
const force = ctx.args.force === true;
|
|
14145
14146
|
const cwd = ctx.cwd;
|
|
@@ -14173,7 +14174,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
14173
14174
|
});
|
|
14174
14175
|
|
|
14175
14176
|
// src/scripts/loadAgentAdhoc.ts
|
|
14176
|
-
import * as
|
|
14177
|
+
import * as fs37 from "fs";
|
|
14177
14178
|
function resolveMessage(messageArg) {
|
|
14178
14179
|
const fromComment = readCommentBody();
|
|
14179
14180
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -14181,9 +14182,9 @@ function resolveMessage(messageArg) {
|
|
|
14181
14182
|
}
|
|
14182
14183
|
function readCommentBody() {
|
|
14183
14184
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
14184
|
-
if (!eventPath || !
|
|
14185
|
+
if (!eventPath || !fs37.existsSync(eventPath)) return "";
|
|
14185
14186
|
try {
|
|
14186
|
-
const event = JSON.parse(
|
|
14187
|
+
const event = JSON.parse(fs37.readFileSync(eventPath, "utf-8"));
|
|
14187
14188
|
return String(event.comment?.body ?? "");
|
|
14188
14189
|
} catch {
|
|
14189
14190
|
return "";
|
|
@@ -14237,10 +14238,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
14237
14238
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
14238
14239
|
}
|
|
14239
14240
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14240
|
-
if (!
|
|
14241
|
+
if (!fs37.existsSync(agentPath)) {
|
|
14241
14242
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
14242
14243
|
}
|
|
14243
|
-
const { title, body } = parseAgentFile(
|
|
14244
|
+
const { title, body } = parseAgentFile(fs37.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
14244
14245
|
const message = resolveMessage(ctx.args.message);
|
|
14245
14246
|
if (!message) {
|
|
14246
14247
|
throw new Error(
|
|
@@ -14312,13 +14313,13 @@ var init_loadCapabilityState = __esm({
|
|
|
14312
14313
|
function isCompanyIntentId(value) {
|
|
14313
14314
|
return SLUG_RE.test(value);
|
|
14314
14315
|
}
|
|
14315
|
-
function normalizeCompanyIntent(
|
|
14316
|
+
function normalizeCompanyIntent(path52, raw) {
|
|
14316
14317
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
14317
|
-
throw new Error(`${
|
|
14318
|
+
throw new Error(`${path52}: intent must be JSON object`);
|
|
14318
14319
|
}
|
|
14319
14320
|
const input = raw;
|
|
14320
14321
|
const id = stringField4(input.id);
|
|
14321
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
14322
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path52}: invalid intent id`);
|
|
14322
14323
|
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
14323
14324
|
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
14324
14325
|
const description = stringField4(input.description);
|
|
@@ -14480,7 +14481,7 @@ function retryDelaysMs() {
|
|
|
14480
14481
|
}
|
|
14481
14482
|
function sleep(ms) {
|
|
14482
14483
|
if (ms <= 0) return Promise.resolve();
|
|
14483
|
-
return new Promise((
|
|
14484
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
14484
14485
|
}
|
|
14485
14486
|
async function fetchGoalStateWithRetry(config, goalId, cwd) {
|
|
14486
14487
|
let state = await fetchGoalStateAsync(config, goalId, cwd);
|
|
@@ -14609,8 +14610,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
14609
14610
|
});
|
|
14610
14611
|
|
|
14611
14612
|
// src/scripts/loadJobFromFile.ts
|
|
14612
|
-
import * as
|
|
14613
|
-
import * as
|
|
14613
|
+
import * as fs38 from "fs";
|
|
14614
|
+
import * as path35 from "path";
|
|
14614
14615
|
function parseJobFile(raw, slug) {
|
|
14615
14616
|
let stripped = raw;
|
|
14616
14617
|
if (stripped.startsWith("---\n")) {
|
|
@@ -14649,10 +14650,10 @@ var init_loadJobFromFile = __esm({
|
|
|
14649
14650
|
if (!slug) {
|
|
14650
14651
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
14651
14652
|
}
|
|
14652
|
-
const capability = resolveCapabilityFolder(slug,
|
|
14653
|
+
const capability = resolveCapabilityFolder(slug, path35.resolve(ctx.cwd, jobsDir));
|
|
14653
14654
|
if (!capability) {
|
|
14654
14655
|
throw new Error(
|
|
14655
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
14656
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path35.resolve(ctx.cwd, jobsDir, slug)}`
|
|
14656
14657
|
);
|
|
14657
14658
|
}
|
|
14658
14659
|
const { title, body, config } = capability;
|
|
@@ -14662,12 +14663,12 @@ var init_loadJobFromFile = __esm({
|
|
|
14662
14663
|
let agentIdentity = "";
|
|
14663
14664
|
if (agentSlug) {
|
|
14664
14665
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14665
|
-
if (!
|
|
14666
|
+
if (!fs38.existsSync(agentPath)) {
|
|
14666
14667
|
throw new Error(
|
|
14667
14668
|
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
14668
14669
|
);
|
|
14669
14670
|
}
|
|
14670
|
-
const agentRaw =
|
|
14671
|
+
const agentRaw = fs38.readFileSync(agentPath, "utf-8");
|
|
14671
14672
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
14672
14673
|
agentTitle = parsed.title;
|
|
14673
14674
|
agentIdentity = parsed.body;
|
|
@@ -14747,13 +14748,13 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
14747
14748
|
});
|
|
14748
14749
|
|
|
14749
14750
|
// src/scripts/kodyVariables.ts
|
|
14750
|
-
import * as
|
|
14751
|
-
import * as
|
|
14751
|
+
import * as fs39 from "fs";
|
|
14752
|
+
import * as path36 from "path";
|
|
14752
14753
|
function readKodyVariables(cwd) {
|
|
14753
|
-
const full =
|
|
14754
|
+
const full = path36.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
14754
14755
|
let raw;
|
|
14755
14756
|
try {
|
|
14756
|
-
raw =
|
|
14757
|
+
raw = fs39.readFileSync(full, "utf-8");
|
|
14757
14758
|
} catch {
|
|
14758
14759
|
return {};
|
|
14759
14760
|
}
|
|
@@ -14929,8 +14930,8 @@ var init_runtimeSecrets = __esm({
|
|
|
14929
14930
|
});
|
|
14930
14931
|
|
|
14931
14932
|
// src/scripts/loadQaContext.ts
|
|
14932
|
-
import * as
|
|
14933
|
-
import * as
|
|
14933
|
+
import * as fs40 from "fs";
|
|
14934
|
+
import * as path37 from "path";
|
|
14934
14935
|
function parseSlugList(value) {
|
|
14935
14936
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
14936
14937
|
return inner.split(",").map(
|
|
@@ -14959,18 +14960,18 @@ function readProfileAgents(raw) {
|
|
|
14959
14960
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
14960
14961
|
}
|
|
14961
14962
|
function readProfile(cwd) {
|
|
14962
|
-
const dir =
|
|
14963
|
-
if (!
|
|
14963
|
+
const dir = path37.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
14964
|
+
if (!fs40.existsSync(dir)) return "";
|
|
14964
14965
|
let entries;
|
|
14965
14966
|
try {
|
|
14966
|
-
entries =
|
|
14967
|
+
entries = fs40.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
14967
14968
|
} catch {
|
|
14968
14969
|
return "";
|
|
14969
14970
|
}
|
|
14970
14971
|
const blocks = [];
|
|
14971
14972
|
for (const file of entries) {
|
|
14972
14973
|
try {
|
|
14973
|
-
const raw =
|
|
14974
|
+
const raw = fs40.readFileSync(path37.join(dir, file), "utf-8");
|
|
14974
14975
|
const { agent, body } = readProfileAgents(raw);
|
|
14975
14976
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
14976
14977
|
blocks.push(`## ${file}
|
|
@@ -15019,8 +15020,8 @@ var init_loadQaContext = __esm({
|
|
|
15019
15020
|
});
|
|
15020
15021
|
|
|
15021
15022
|
// src/taskContext.ts
|
|
15022
|
-
import * as
|
|
15023
|
-
import * as
|
|
15023
|
+
import * as fs41 from "fs";
|
|
15024
|
+
import * as path38 from "path";
|
|
15024
15025
|
function buildTaskContext(args) {
|
|
15025
15026
|
return {
|
|
15026
15027
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -15036,9 +15037,9 @@ function buildTaskContext(args) {
|
|
|
15036
15037
|
function persistTaskContext(cwd, ctx) {
|
|
15037
15038
|
try {
|
|
15038
15039
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
15039
|
-
|
|
15040
|
-
const file =
|
|
15041
|
-
|
|
15040
|
+
fs41.mkdirSync(dir, { recursive: true });
|
|
15041
|
+
const file = path38.join(dir, "task-context.json");
|
|
15042
|
+
fs41.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
15042
15043
|
`);
|
|
15043
15044
|
return file;
|
|
15044
15045
|
} catch (err) {
|
|
@@ -15465,19 +15466,19 @@ function parseAgencyModelProposal(raw) {
|
|
|
15465
15466
|
function normalizeBundleFiles(bundle) {
|
|
15466
15467
|
const seen = /* @__PURE__ */ new Set();
|
|
15467
15468
|
return bundle.files.map((file, index) => {
|
|
15468
|
-
const
|
|
15469
|
-
const parts =
|
|
15470
|
-
if (!
|
|
15469
|
+
const path52 = file.path.replace(/^\/+/, "");
|
|
15470
|
+
const parts = path52.split("/");
|
|
15471
|
+
if (!path52 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
|
|
15471
15472
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
|
|
15472
15473
|
}
|
|
15473
15474
|
if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
|
|
15474
|
-
|
|
15475
|
+
path52
|
|
15475
15476
|
)) {
|
|
15476
15477
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
|
|
15477
15478
|
}
|
|
15478
|
-
if (seen.has(
|
|
15479
|
-
seen.add(
|
|
15480
|
-
return { path:
|
|
15479
|
+
if (seen.has(path52)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path52}`);
|
|
15480
|
+
seen.add(path52);
|
|
15481
|
+
return { path: path52, content: file.content.replace(/\r\n?/g, "\n") };
|
|
15481
15482
|
});
|
|
15482
15483
|
}
|
|
15483
15484
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
@@ -16421,9 +16422,9 @@ var init_postResearchComment = __esm({
|
|
|
16421
16422
|
});
|
|
16422
16423
|
|
|
16423
16424
|
// src/scripts/prepareBrowserAuth.ts
|
|
16424
|
-
import * as
|
|
16425
|
+
import * as fs42 from "fs";
|
|
16425
16426
|
import * as os6 from "os";
|
|
16426
|
-
import * as
|
|
16427
|
+
import * as path39 from "path";
|
|
16427
16428
|
function appendAuthMessage(ctx, message) {
|
|
16428
16429
|
const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
|
|
16429
16430
|
ctx.data.qaAuthBlock = current ? `${current}
|
|
@@ -16462,9 +16463,9 @@ async function githubJson(url, token) {
|
|
|
16462
16463
|
return await response.json();
|
|
16463
16464
|
}
|
|
16464
16465
|
function writeKodyStorageState(input) {
|
|
16465
|
-
const directory =
|
|
16466
|
-
|
|
16467
|
-
const file =
|
|
16466
|
+
const directory = fs42.mkdtempSync(path39.join(os6.tmpdir(), "kody-browser-auth-"));
|
|
16467
|
+
fs42.chmodSync(directory, 448);
|
|
16468
|
+
const file = path39.join(directory, "storage-state.json");
|
|
16468
16469
|
const now = Date.now();
|
|
16469
16470
|
const repoEntry = {
|
|
16470
16471
|
repoUrl: input.repoUrl,
|
|
@@ -16494,7 +16495,7 @@ function writeKodyStorageState(input) {
|
|
|
16494
16495
|
}
|
|
16495
16496
|
]
|
|
16496
16497
|
};
|
|
16497
|
-
|
|
16498
|
+
fs42.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
|
|
16498
16499
|
return { directory, file };
|
|
16499
16500
|
}
|
|
16500
16501
|
function configurePlaywright(profile, storageStatePath) {
|
|
@@ -16576,7 +16577,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
16576
16577
|
configurePlaywright(profile, state.file);
|
|
16577
16578
|
const authDirectory = state.directory;
|
|
16578
16579
|
registerRuntimeCleanup(ctx, () => {
|
|
16579
|
-
|
|
16580
|
+
fs42.rmSync(authDirectory, { recursive: true, force: true });
|
|
16580
16581
|
});
|
|
16581
16582
|
appendAuthMessage(
|
|
16582
16583
|
ctx,
|
|
@@ -16584,7 +16585,7 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
16584
16585
|
);
|
|
16585
16586
|
return true;
|
|
16586
16587
|
} catch (error) {
|
|
16587
|
-
if (state)
|
|
16588
|
+
if (state) fs42.rmSync(state.directory, { recursive: true, force: true });
|
|
16588
16589
|
const reason = error instanceof Error ? error.message : String(error);
|
|
16589
16590
|
appendAuthMessage(
|
|
16590
16591
|
ctx,
|
|
@@ -16697,9 +16698,9 @@ function latestResult(raw, agentResult) {
|
|
|
16697
16698
|
function recordField4(value) {
|
|
16698
16699
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
16699
16700
|
}
|
|
16700
|
-
function resolveDotted(root,
|
|
16701
|
-
if (!
|
|
16702
|
-
return
|
|
16701
|
+
function resolveDotted(root, path52) {
|
|
16702
|
+
if (!path52) return void 0;
|
|
16703
|
+
return path52.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
16703
16704
|
}
|
|
16704
16705
|
function stringValue4(value) {
|
|
16705
16706
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -17599,7 +17600,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
17599
17600
|
// src/scripts/previewBuildRun.ts
|
|
17600
17601
|
import { spawn as spawn5 } from "child_process";
|
|
17601
17602
|
async function runCmd(cmd, args, opts = {}) {
|
|
17602
|
-
await new Promise((
|
|
17603
|
+
await new Promise((resolve17, reject) => {
|
|
17603
17604
|
const child = spawn5(cmd, args, {
|
|
17604
17605
|
cwd: opts.cwd,
|
|
17605
17606
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -17611,7 +17612,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
17611
17612
|
}
|
|
17612
17613
|
child.on("error", reject);
|
|
17613
17614
|
child.on("close", (code) => {
|
|
17614
|
-
if (code === 0)
|
|
17615
|
+
if (code === 0) resolve17();
|
|
17615
17616
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
17616
17617
|
});
|
|
17617
17618
|
});
|
|
@@ -17683,12 +17684,12 @@ fi
|
|
|
17683
17684
|
|
|
17684
17685
|
// src/scripts/runPreviewBuild.ts
|
|
17685
17686
|
import { copyFile, writeFile } from "fs/promises";
|
|
17686
|
-
import * as
|
|
17687
|
-
import { fileURLToPath } from "url";
|
|
17687
|
+
import * as path40 from "path";
|
|
17688
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17688
17689
|
function bundledDockerfilePath(mode) {
|
|
17689
|
-
const here =
|
|
17690
|
+
const here = path40.dirname(fileURLToPath2(import.meta.url));
|
|
17690
17691
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
17691
|
-
return
|
|
17692
|
+
return path40.join(here, "preview-build-templates", file);
|
|
17692
17693
|
}
|
|
17693
17694
|
function required(name) {
|
|
17694
17695
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -17923,10 +17924,10 @@ var init_runPreviewBuild = __esm({
|
|
|
17923
17924
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
17924
17925
|
if (Object.keys(buildEnv).length > 0) {
|
|
17925
17926
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
17926
|
-
await writeFile(
|
|
17927
|
+
await writeFile(path40.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
17927
17928
|
`, "utf8");
|
|
17928
17929
|
}
|
|
17929
|
-
const consumerDockerfile =
|
|
17930
|
+
const consumerDockerfile = path40.join(ctx.cwd, "Dockerfile.preview");
|
|
17930
17931
|
const { stat } = await import("fs/promises");
|
|
17931
17932
|
let hasConsumerDockerfile = false;
|
|
17932
17933
|
try {
|
|
@@ -18110,8 +18111,8 @@ var init_tickShellRunner = __esm({
|
|
|
18110
18111
|
});
|
|
18111
18112
|
|
|
18112
18113
|
// src/scripts/runScheduledImplementationTick.ts
|
|
18113
|
-
import * as
|
|
18114
|
-
import * as
|
|
18114
|
+
import * as fs43 from "fs";
|
|
18115
|
+
import * as path41 from "path";
|
|
18115
18116
|
var runScheduledImplementationTick;
|
|
18116
18117
|
var init_runScheduledImplementationTick = __esm({
|
|
18117
18118
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -18132,14 +18133,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18132
18133
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
18133
18134
|
return;
|
|
18134
18135
|
}
|
|
18135
|
-
const capability = resolveCapabilityFolder(slug,
|
|
18136
|
+
const capability = resolveCapabilityFolder(slug, path41.resolve(ctx.cwd, jobsDir));
|
|
18136
18137
|
if (!capability) {
|
|
18137
18138
|
ctx.output.exitCode = 99;
|
|
18138
18139
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
18139
18140
|
return;
|
|
18140
18141
|
}
|
|
18141
|
-
const shellPath =
|
|
18142
|
-
if (!
|
|
18142
|
+
const shellPath = path41.join(profile.dir, shell);
|
|
18143
|
+
if (!fs43.existsSync(shellPath)) {
|
|
18143
18144
|
ctx.output.exitCode = 99;
|
|
18144
18145
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
18145
18146
|
return;
|
|
@@ -18170,8 +18171,8 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
18170
18171
|
});
|
|
18171
18172
|
|
|
18172
18173
|
// src/scripts/runTickScript.ts
|
|
18173
|
-
import * as
|
|
18174
|
-
import * as
|
|
18174
|
+
import * as fs44 from "fs";
|
|
18175
|
+
import * as path42 from "path";
|
|
18175
18176
|
var runTickScript;
|
|
18176
18177
|
var init_runTickScript = __esm({
|
|
18177
18178
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -18191,10 +18192,10 @@ var init_runTickScript = __esm({
|
|
|
18191
18192
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
18192
18193
|
return;
|
|
18193
18194
|
}
|
|
18194
|
-
const capability = readCapabilityFolder(
|
|
18195
|
+
const capability = readCapabilityFolder(path42.resolve(ctx.cwd, jobsDir), slug);
|
|
18195
18196
|
if (!capability) {
|
|
18196
18197
|
ctx.output.exitCode = 99;
|
|
18197
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
18198
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path42.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
18198
18199
|
return;
|
|
18199
18200
|
}
|
|
18200
18201
|
const tickScript = capability.config.tickScript;
|
|
@@ -18203,8 +18204,8 @@ var init_runTickScript = __esm({
|
|
|
18203
18204
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
18204
18205
|
return;
|
|
18205
18206
|
}
|
|
18206
|
-
const scriptPath =
|
|
18207
|
-
if (!
|
|
18207
|
+
const scriptPath = path42.isAbsolute(tickScript) ? tickScript : path42.join(ctx.cwd, tickScript);
|
|
18208
|
+
if (!fs44.existsSync(scriptPath)) {
|
|
18208
18209
|
ctx.output.exitCode = 99;
|
|
18209
18210
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
18210
18211
|
return;
|
|
@@ -18486,7 +18487,7 @@ var init_syncFlow = __esm({
|
|
|
18486
18487
|
});
|
|
18487
18488
|
|
|
18488
18489
|
// src/scripts/validateAgencyModelProposal.ts
|
|
18489
|
-
import * as
|
|
18490
|
+
import * as path43 from "path";
|
|
18490
18491
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
18491
18492
|
const failures = [];
|
|
18492
18493
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -18812,7 +18813,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
18812
18813
|
const bundle = parseAgencyModelProposal(raw);
|
|
18813
18814
|
const expectedKind = readExpectedModelKind(args);
|
|
18814
18815
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
18815
|
-
capabilityRoot:
|
|
18816
|
+
capabilityRoot: path43.join(ctx.cwd, ".kody", "capabilities")
|
|
18816
18817
|
});
|
|
18817
18818
|
if (failures.length > 0) {
|
|
18818
18819
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -18875,7 +18876,7 @@ function stripAnsi2(s) {
|
|
|
18875
18876
|
return s.replace(ANSI_RE2, "");
|
|
18876
18877
|
}
|
|
18877
18878
|
function runCommand2(command, cwd) {
|
|
18878
|
-
return new Promise((
|
|
18879
|
+
return new Promise((resolve17) => {
|
|
18879
18880
|
const child = spawn6(command, {
|
|
18880
18881
|
cwd,
|
|
18881
18882
|
shell: true,
|
|
@@ -18902,11 +18903,11 @@ function runCommand2(command, cwd) {
|
|
|
18902
18903
|
}, TEST_TIMEOUT_MS);
|
|
18903
18904
|
child.on("exit", (code) => {
|
|
18904
18905
|
clearTimeout(timer);
|
|
18905
|
-
|
|
18906
|
+
resolve17({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
18906
18907
|
});
|
|
18907
18908
|
child.on("error", (err) => {
|
|
18908
18909
|
clearTimeout(timer);
|
|
18909
|
-
|
|
18910
|
+
resolve17({ exitCode: -1, output: err.message });
|
|
18910
18911
|
});
|
|
18911
18912
|
});
|
|
18912
18913
|
}
|
|
@@ -19312,21 +19313,21 @@ function lineStream(stream) {
|
|
|
19312
19313
|
tryDeliver();
|
|
19313
19314
|
});
|
|
19314
19315
|
return {
|
|
19315
|
-
next: (timeoutMs) => new Promise((
|
|
19316
|
+
next: (timeoutMs) => new Promise((resolve17) => {
|
|
19316
19317
|
if (queue.length > 0) {
|
|
19317
|
-
|
|
19318
|
+
resolve17(queue.shift());
|
|
19318
19319
|
return;
|
|
19319
19320
|
}
|
|
19320
19321
|
if (ended) {
|
|
19321
|
-
|
|
19322
|
+
resolve17(null);
|
|
19322
19323
|
return;
|
|
19323
19324
|
}
|
|
19324
|
-
waiter =
|
|
19325
|
+
waiter = resolve17;
|
|
19325
19326
|
const t = setTimeout(
|
|
19326
19327
|
() => {
|
|
19327
|
-
if (waiter ===
|
|
19328
|
+
if (waiter === resolve17) {
|
|
19328
19329
|
waiter = null;
|
|
19329
|
-
|
|
19330
|
+
resolve17(null);
|
|
19330
19331
|
}
|
|
19331
19332
|
},
|
|
19332
19333
|
Math.max(0, timeoutMs)
|
|
@@ -19363,7 +19364,7 @@ var init_warmupMcp = __esm({
|
|
|
19363
19364
|
});
|
|
19364
19365
|
|
|
19365
19366
|
// src/scripts/writeAgentRunSummary.ts
|
|
19366
|
-
import * as
|
|
19367
|
+
import * as fs45 from "fs";
|
|
19367
19368
|
var writeAgentRunSummary;
|
|
19368
19369
|
var init_writeAgentRunSummary = __esm({
|
|
19369
19370
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -19389,7 +19390,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
19389
19390
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
19390
19391
|
lines.push("");
|
|
19391
19392
|
try {
|
|
19392
|
-
|
|
19393
|
+
fs45.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
19393
19394
|
`);
|
|
19394
19395
|
} catch {
|
|
19395
19396
|
}
|
|
@@ -19715,17 +19716,17 @@ var init_scripts = __esm({
|
|
|
19715
19716
|
});
|
|
19716
19717
|
|
|
19717
19718
|
// src/stateWorkspace.ts
|
|
19718
|
-
import * as
|
|
19719
|
-
import * as
|
|
19719
|
+
import * as fs46 from "fs";
|
|
19720
|
+
import * as path44 from "path";
|
|
19720
19721
|
function tenantId(config) {
|
|
19721
19722
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
19722
19723
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
19723
19724
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
19724
19725
|
}
|
|
19725
19726
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
19726
|
-
const target =
|
|
19727
|
-
|
|
19728
|
-
|
|
19727
|
+
const target = path44.join(cwd, RUNTIME_ROOT, relativePath);
|
|
19728
|
+
fs46.mkdirSync(path44.dirname(target), { recursive: true });
|
|
19729
|
+
fs46.writeFileSync(target, content, "utf8");
|
|
19729
19730
|
}
|
|
19730
19731
|
function record(value) {
|
|
19731
19732
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -19790,11 +19791,11 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
19790
19791
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
19791
19792
|
return;
|
|
19792
19793
|
}
|
|
19793
|
-
const key = `${
|
|
19794
|
+
const key = `${path44.resolve(cwd)}|${tenant}`;
|
|
19794
19795
|
if (hydratedWorkspaces.has(key)) return;
|
|
19795
19796
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
19796
|
-
const root =
|
|
19797
|
-
|
|
19797
|
+
const root = path44.join(cwd, RUNTIME_ROOT);
|
|
19798
|
+
fs46.rmSync(root, { recursive: true, force: true });
|
|
19798
19799
|
await Promise.all([
|
|
19799
19800
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
19800
19801
|
hydratePrefix(backend, tenant, cwd, "memory:"),
|
|
@@ -19810,7 +19811,7 @@ var init_stateWorkspace = __esm({
|
|
|
19810
19811
|
"src/stateWorkspace.ts"() {
|
|
19811
19812
|
"use strict";
|
|
19812
19813
|
init_state_backend();
|
|
19813
|
-
RUNTIME_ROOT =
|
|
19814
|
+
RUNTIME_ROOT = path44.join(".kody-engine", "runtime");
|
|
19814
19815
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
19815
19816
|
}
|
|
19816
19817
|
});
|
|
@@ -19881,9 +19882,9 @@ var init_tools = __esm({
|
|
|
19881
19882
|
|
|
19882
19883
|
// src/executor.ts
|
|
19883
19884
|
import { spawn as spawn8 } from "child_process";
|
|
19884
|
-
import * as
|
|
19885
|
+
import * as fs47 from "fs";
|
|
19885
19886
|
import * as os7 from "os";
|
|
19886
|
-
import * as
|
|
19887
|
+
import * as path45 from "path";
|
|
19887
19888
|
function isMutatingPostflight(scriptName) {
|
|
19888
19889
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
19889
19890
|
}
|
|
@@ -20115,7 +20116,7 @@ async function runImplementation(profileName, input) {
|
|
|
20115
20116
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
20116
20117
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
20117
20118
|
const invokeAgent = async (prompt) => {
|
|
20118
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
20119
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path45.isAbsolute(p) ? p : path45.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
20119
20120
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
20120
20121
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
20121
20122
|
const agents = loadSubagents(profile);
|
|
@@ -20553,17 +20554,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
20553
20554
|
function resolveProfilePath(profileName) {
|
|
20554
20555
|
const found = resolveImplementation(profileName);
|
|
20555
20556
|
if (found) return found;
|
|
20556
|
-
const here =
|
|
20557
|
+
const here = path45.dirname(new URL(import.meta.url).pathname);
|
|
20557
20558
|
const candidates = [
|
|
20558
|
-
|
|
20559
|
+
path45.join(here, "implementations", profileName, "profile.json"),
|
|
20559
20560
|
// same-dir sibling (dev)
|
|
20560
|
-
|
|
20561
|
+
path45.join(here, "..", "implementations", profileName, "profile.json"),
|
|
20561
20562
|
// up one (prod: dist/bin → dist/implementations)
|
|
20562
|
-
|
|
20563
|
+
path45.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
20563
20564
|
// fallback
|
|
20564
20565
|
];
|
|
20565
20566
|
for (const c of candidates) {
|
|
20566
|
-
if (
|
|
20567
|
+
if (fs47.existsSync(c)) return c;
|
|
20567
20568
|
}
|
|
20568
20569
|
return candidates[0];
|
|
20569
20570
|
}
|
|
@@ -20678,15 +20679,15 @@ function resolveShellTimeoutMs(entry) {
|
|
|
20678
20679
|
}
|
|
20679
20680
|
async function runShellEntry(entry, ctx, profile) {
|
|
20680
20681
|
const shellName = entry.shell;
|
|
20681
|
-
const shellPath =
|
|
20682
|
-
if (!
|
|
20682
|
+
const shellPath = path45.join(profile.dir, shellName);
|
|
20683
|
+
if (!fs47.existsSync(shellPath)) {
|
|
20683
20684
|
ctx.skipAgent = true;
|
|
20684
20685
|
ctx.output.exitCode = 99;
|
|
20685
20686
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
20686
20687
|
return;
|
|
20687
20688
|
}
|
|
20688
20689
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
20689
|
-
const outputFile =
|
|
20690
|
+
const outputFile = path45.join(
|
|
20690
20691
|
os7.tmpdir(),
|
|
20691
20692
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
20692
20693
|
);
|
|
@@ -20721,14 +20722,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
20721
20722
|
let killTimer;
|
|
20722
20723
|
let escalateTimer;
|
|
20723
20724
|
const result = await new Promise(
|
|
20724
|
-
(
|
|
20725
|
+
(resolve17) => {
|
|
20725
20726
|
let settled = false;
|
|
20726
20727
|
const settle = (code, signal, spawnErr) => {
|
|
20727
20728
|
if (settled) return;
|
|
20728
20729
|
settled = true;
|
|
20729
20730
|
if (killTimer) clearTimeout(killTimer);
|
|
20730
20731
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
20731
|
-
|
|
20732
|
+
resolve17({ code, signal, spawnErr });
|
|
20732
20733
|
};
|
|
20733
20734
|
child.on("error", (err) => settle(null, null, err));
|
|
20734
20735
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -20758,9 +20759,9 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
20758
20759
|
}
|
|
20759
20760
|
let sideChannelText = "";
|
|
20760
20761
|
try {
|
|
20761
|
-
if (
|
|
20762
|
-
sideChannelText =
|
|
20763
|
-
|
|
20762
|
+
if (fs47.existsSync(outputFile)) {
|
|
20763
|
+
sideChannelText = fs47.readFileSync(outputFile, "utf-8");
|
|
20764
|
+
fs47.rmSync(outputFile, { force: true });
|
|
20764
20765
|
}
|
|
20765
20766
|
} catch {
|
|
20766
20767
|
}
|
|
@@ -20931,7 +20932,7 @@ __export(job_exports, {
|
|
|
20931
20932
|
stableJobKey: () => stableJobKey,
|
|
20932
20933
|
validateJob: () => validateJob
|
|
20933
20934
|
});
|
|
20934
|
-
import * as
|
|
20935
|
+
import * as path46 from "path";
|
|
20935
20936
|
function newJobId(flavor) {
|
|
20936
20937
|
localJobSeq += 1;
|
|
20937
20938
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -21394,11 +21395,11 @@ function selectWorkflowTransition(step, data, counts) {
|
|
|
21394
21395
|
}
|
|
21395
21396
|
function workflowResultConditionPaths(transitions) {
|
|
21396
21397
|
return transitions.flatMap(
|
|
21397
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
21398
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path52) => path52.startsWith("result."))
|
|
21398
21399
|
);
|
|
21399
21400
|
}
|
|
21400
21401
|
function conditionMatches(condition, context) {
|
|
21401
|
-
return Object.entries(condition).every(([
|
|
21402
|
+
return Object.entries(condition).every(([path52, expected]) => valueMatches(resolveDottedPath2(context, path52), expected));
|
|
21402
21403
|
}
|
|
21403
21404
|
function withWorkflowBoundaryEval(capability, result) {
|
|
21404
21405
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -21556,7 +21557,7 @@ function loadCapabilityContext(slug, cwd) {
|
|
|
21556
21557
|
return resolveCapabilityFolder(slug, hydratedCapabilitiesRoot(cwd));
|
|
21557
21558
|
}
|
|
21558
21559
|
function hydratedCapabilitiesRoot(cwd) {
|
|
21559
|
-
return
|
|
21560
|
+
return path46.join(cwd, ".kody-engine", "definitions", "capabilities");
|
|
21560
21561
|
}
|
|
21561
21562
|
function loadWorkflowContext(slug, base) {
|
|
21562
21563
|
if (!slug || !base.config || !isWorkflowDefinitionId(slug)) return null;
|
|
@@ -21719,7 +21720,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
21719
21720
|
|
|
21720
21721
|
// src/servers/brain-serve.ts
|
|
21721
21722
|
import { createServer as createServer2 } from "http";
|
|
21722
|
-
import * as
|
|
21723
|
+
import * as path49 from "path";
|
|
21723
21724
|
|
|
21724
21725
|
// src/chat/loop.ts
|
|
21725
21726
|
init_agent();
|
|
@@ -21873,9 +21874,9 @@ var CodexAppServerClient = class {
|
|
|
21873
21874
|
await this.request("thread/resume", { threadId });
|
|
21874
21875
|
}
|
|
21875
21876
|
async runTurn(args) {
|
|
21876
|
-
await new Promise((
|
|
21877
|
+
await new Promise((resolve17, reject) => {
|
|
21877
21878
|
this.process.turnWaiters.set(args.threadId, {
|
|
21878
|
-
resolve:
|
|
21879
|
+
resolve: resolve17,
|
|
21879
21880
|
reject,
|
|
21880
21881
|
onNotification: args.onNotification,
|
|
21881
21882
|
queue: Promise.resolve()
|
|
@@ -21892,8 +21893,8 @@ var CodexAppServerClient = class {
|
|
|
21892
21893
|
}
|
|
21893
21894
|
request(method, params) {
|
|
21894
21895
|
const id = this.process.nextId++;
|
|
21895
|
-
return new Promise((
|
|
21896
|
-
this.process.pending.set(id, { resolve:
|
|
21896
|
+
return new Promise((resolve17, reject) => {
|
|
21897
|
+
this.process.pending.set(id, { resolve: resolve17, reject });
|
|
21897
21898
|
this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
|
|
21898
21899
|
`);
|
|
21899
21900
|
});
|
|
@@ -22761,8 +22762,8 @@ init_config();
|
|
|
22761
22762
|
|
|
22762
22763
|
// src/kody-cli.ts
|
|
22763
22764
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
22764
|
-
import * as
|
|
22765
|
-
import * as
|
|
22765
|
+
import * as fs48 from "fs";
|
|
22766
|
+
import * as path47 from "path";
|
|
22766
22767
|
|
|
22767
22768
|
// src/app-auth.ts
|
|
22768
22769
|
import { createSign } from "crypto";
|
|
@@ -23530,6 +23531,20 @@ function recoverCheckoutToken(env = process.env, cwd = process.cwd()) {
|
|
|
23530
23531
|
return token;
|
|
23531
23532
|
}
|
|
23532
23533
|
async function resolveAuthToken(env = process.env) {
|
|
23534
|
+
const readySources = [
|
|
23535
|
+
["GH_PAT", env.GH_PAT],
|
|
23536
|
+
["KODY_TOKEN", env.KODY_TOKEN],
|
|
23537
|
+
["GH_TOKEN", env.GH_TOKEN]
|
|
23538
|
+
];
|
|
23539
|
+
const ready = readySources.find(([, value]) => !!value?.trim());
|
|
23540
|
+
if (ready?.[1]) {
|
|
23541
|
+
const token2 = ready[1].trim();
|
|
23542
|
+
env.GH_TOKEN = token2;
|
|
23543
|
+
recoverCheckoutToken(env);
|
|
23544
|
+
process.stdout.write(`\u2192 kody: GH_TOKEN sourced from env.${ready[0]}
|
|
23545
|
+
`);
|
|
23546
|
+
return token2;
|
|
23547
|
+
}
|
|
23533
23548
|
const creds = readAppCreds(env);
|
|
23534
23549
|
if (creds) {
|
|
23535
23550
|
try {
|
|
@@ -23543,12 +23558,7 @@ async function resolveAuthToken(env = process.env) {
|
|
|
23543
23558
|
`);
|
|
23544
23559
|
}
|
|
23545
23560
|
}
|
|
23546
|
-
const sources = [
|
|
23547
|
-
["KODY_TOKEN", env.KODY_TOKEN],
|
|
23548
|
-
["GH_TOKEN", env.GH_TOKEN],
|
|
23549
|
-
["GITHUB_TOKEN", env.GITHUB_TOKEN],
|
|
23550
|
-
["GH_PAT", env.GH_PAT]
|
|
23551
|
-
];
|
|
23561
|
+
const sources = [["GITHUB_TOKEN", env.GITHUB_TOKEN]];
|
|
23552
23562
|
const picked = sources.find(([, v]) => !!v);
|
|
23553
23563
|
const token = picked?.[1];
|
|
23554
23564
|
if (token && !env.GH_TOKEN) env.GH_TOKEN = token;
|
|
@@ -23564,9 +23574,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
23564
23574
|
return void 0;
|
|
23565
23575
|
}
|
|
23566
23576
|
function detectPackageManager2(cwd) {
|
|
23567
|
-
if (
|
|
23568
|
-
if (
|
|
23569
|
-
if (
|
|
23577
|
+
if (fs48.existsSync(path47.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
23578
|
+
if (fs48.existsSync(path47.join(cwd, "yarn.lock"))) return "yarn";
|
|
23579
|
+
if (fs48.existsSync(path47.join(cwd, "bun.lockb"))) return "bun";
|
|
23570
23580
|
return "npm";
|
|
23571
23581
|
}
|
|
23572
23582
|
function shouldChainScheduledWatch(match) {
|
|
@@ -23659,8 +23669,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
23659
23669
|
const logPath = lastRunLogPath(cwd);
|
|
23660
23670
|
let tail = "";
|
|
23661
23671
|
try {
|
|
23662
|
-
if (
|
|
23663
|
-
const content =
|
|
23672
|
+
if (fs48.existsSync(logPath)) {
|
|
23673
|
+
const content = fs48.readFileSync(logPath, "utf-8");
|
|
23664
23674
|
tail = content.slice(-3e3);
|
|
23665
23675
|
}
|
|
23666
23676
|
} catch {
|
|
@@ -23689,7 +23699,7 @@ async function runCi(argv) {
|
|
|
23689
23699
|
return 0;
|
|
23690
23700
|
}
|
|
23691
23701
|
const args = parseCiArgs(argv);
|
|
23692
|
-
const cwd = args.cwd ?
|
|
23702
|
+
const cwd = args.cwd ? path47.resolve(args.cwd) : process.cwd();
|
|
23693
23703
|
try {
|
|
23694
23704
|
const n = unpackAllSecrets();
|
|
23695
23705
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -23748,9 +23758,9 @@ async function runCi(argv) {
|
|
|
23748
23758
|
forceRunCliArgs = { goal: envForceMessage };
|
|
23749
23759
|
}
|
|
23750
23760
|
}
|
|
23751
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
23761
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs48.existsSync(dispatchEventPath)) {
|
|
23752
23762
|
try {
|
|
23753
|
-
const evt = JSON.parse(
|
|
23763
|
+
const evt = JSON.parse(fs48.readFileSync(dispatchEventPath, "utf-8"));
|
|
23754
23764
|
const inputs = objectValue2(evt.inputs);
|
|
23755
23765
|
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
23756
23766
|
const sessionInput = String(inputs?.sessionId ?? "");
|
|
@@ -24123,8 +24133,8 @@ init_repoWorkspace();
|
|
|
24123
24133
|
|
|
24124
24134
|
// src/scripts/brainTurnLog.ts
|
|
24125
24135
|
init_runtimePaths();
|
|
24126
|
-
import * as
|
|
24127
|
-
import * as
|
|
24136
|
+
import * as fs49 from "fs";
|
|
24137
|
+
import * as path48 from "path";
|
|
24128
24138
|
import posixPath4 from "path/posix";
|
|
24129
24139
|
var live = /* @__PURE__ */ new Map();
|
|
24130
24140
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -24132,8 +24142,8 @@ function brainEventsFilePath(dir, chatId) {
|
|
|
24132
24142
|
}
|
|
24133
24143
|
function lastPersistedSeq(dir, chatId) {
|
|
24134
24144
|
const p = brainEventsFilePath(dir, chatId);
|
|
24135
|
-
if (!
|
|
24136
|
-
const lines =
|
|
24145
|
+
if (!fs49.existsSync(p)) return 0;
|
|
24146
|
+
const lines = fs49.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
24137
24147
|
if (lines.length === 0) return 0;
|
|
24138
24148
|
try {
|
|
24139
24149
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -24143,9 +24153,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
24143
24153
|
}
|
|
24144
24154
|
function readSince(dir, chatId, since) {
|
|
24145
24155
|
const p = brainEventsFilePath(dir, chatId);
|
|
24146
|
-
if (!
|
|
24156
|
+
if (!fs49.existsSync(p)) return [];
|
|
24147
24157
|
const out = [];
|
|
24148
|
-
for (const line of
|
|
24158
|
+
for (const line of fs49.readFileSync(p, "utf-8").split("\n")) {
|
|
24149
24159
|
if (!line) continue;
|
|
24150
24160
|
try {
|
|
24151
24161
|
const rec = JSON.parse(line);
|
|
@@ -24171,12 +24181,12 @@ function beginTurn(dir, chatId) {
|
|
|
24171
24181
|
};
|
|
24172
24182
|
live.set(chatId, state);
|
|
24173
24183
|
const p = brainEventsFilePath(dir, chatId);
|
|
24174
|
-
|
|
24184
|
+
fs49.mkdirSync(path48.dirname(p), { recursive: true });
|
|
24175
24185
|
return (event) => {
|
|
24176
24186
|
state.seq += 1;
|
|
24177
24187
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
24178
24188
|
try {
|
|
24179
|
-
|
|
24189
|
+
fs49.appendFileSync(p, `${JSON.stringify(rec)}
|
|
24180
24190
|
`);
|
|
24181
24191
|
} catch (err) {
|
|
24182
24192
|
process.stderr.write(
|
|
@@ -24215,7 +24225,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
24215
24225
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
24216
24226
|
};
|
|
24217
24227
|
try {
|
|
24218
|
-
|
|
24228
|
+
fs49.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
24219
24229
|
`);
|
|
24220
24230
|
} catch {
|
|
24221
24231
|
}
|
|
@@ -24309,17 +24319,17 @@ function authOk(req, expected) {
|
|
|
24309
24319
|
return false;
|
|
24310
24320
|
}
|
|
24311
24321
|
function readJsonBody(req) {
|
|
24312
|
-
return new Promise((
|
|
24322
|
+
return new Promise((resolve17, reject) => {
|
|
24313
24323
|
const chunks = [];
|
|
24314
24324
|
req.on("data", (c) => chunks.push(c));
|
|
24315
24325
|
req.on("end", () => {
|
|
24316
24326
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
24317
24327
|
if (!raw.trim()) {
|
|
24318
|
-
|
|
24328
|
+
resolve17({});
|
|
24319
24329
|
return;
|
|
24320
24330
|
}
|
|
24321
24331
|
try {
|
|
24322
|
-
|
|
24332
|
+
resolve17(JSON.parse(raw));
|
|
24323
24333
|
} catch (err) {
|
|
24324
24334
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
24325
24335
|
}
|
|
@@ -24578,7 +24588,7 @@ function buildServer(opts) {
|
|
|
24578
24588
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
24579
24589
|
const createStore = opts.createStore ?? createSessionStore;
|
|
24580
24590
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
24581
|
-
const reposRoot = opts.reposRoot ??
|
|
24591
|
+
const reposRoot = opts.reposRoot ?? path49.join(path49.dirname(path49.resolve(opts.cwd)), "repos");
|
|
24582
24592
|
return createServer2(async (req, res) => {
|
|
24583
24593
|
if (!req.method || !req.url) {
|
|
24584
24594
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -24659,11 +24669,11 @@ async function brainServe(opts) {
|
|
|
24659
24669
|
litellmUrl,
|
|
24660
24670
|
driver
|
|
24661
24671
|
});
|
|
24662
|
-
await new Promise((
|
|
24672
|
+
await new Promise((resolve17) => {
|
|
24663
24673
|
server.listen(port, "0.0.0.0", () => {
|
|
24664
24674
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
24665
24675
|
`);
|
|
24666
|
-
|
|
24676
|
+
resolve17();
|
|
24667
24677
|
});
|
|
24668
24678
|
});
|
|
24669
24679
|
const shutdown = (signal) => {
|
|
@@ -24918,14 +24928,14 @@ async function startBrainProxy(opts) {
|
|
|
24918
24928
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
24919
24929
|
const port = opts.port ?? 0;
|
|
24920
24930
|
const host = opts.host ?? "127.0.0.1";
|
|
24921
|
-
await new Promise((
|
|
24931
|
+
await new Promise((resolve17) => httpServer.listen(port, host, () => resolve17()));
|
|
24922
24932
|
const addr = httpServer.address();
|
|
24923
24933
|
return {
|
|
24924
24934
|
httpServer,
|
|
24925
24935
|
port: addr.port,
|
|
24926
24936
|
url: `http://${host}:${addr.port}`,
|
|
24927
|
-
stop: () => new Promise((
|
|
24928
|
-
httpServer.close(() =>
|
|
24937
|
+
stop: () => new Promise((resolve17) => {
|
|
24938
|
+
httpServer.close(() => resolve17());
|
|
24929
24939
|
}),
|
|
24930
24940
|
handler
|
|
24931
24941
|
};
|
|
@@ -25075,23 +25085,23 @@ function buildMcpHttpServer(opts) {
|
|
|
25075
25085
|
httpServer,
|
|
25076
25086
|
routes,
|
|
25077
25087
|
port,
|
|
25078
|
-
stop: () => new Promise((
|
|
25088
|
+
stop: () => new Promise((resolve17) => {
|
|
25079
25089
|
let pending = transports.size;
|
|
25080
25090
|
if (pending === 0) {
|
|
25081
|
-
httpServer.close(() =>
|
|
25091
|
+
httpServer.close(() => resolve17());
|
|
25082
25092
|
return;
|
|
25083
25093
|
}
|
|
25084
25094
|
for (const transport of transports.values()) {
|
|
25085
25095
|
void transport.close().finally(() => {
|
|
25086
25096
|
pending--;
|
|
25087
|
-
if (pending === 0) httpServer.close(() =>
|
|
25097
|
+
if (pending === 0) httpServer.close(() => resolve17());
|
|
25088
25098
|
});
|
|
25089
25099
|
}
|
|
25090
25100
|
})
|
|
25091
25101
|
};
|
|
25092
25102
|
}
|
|
25093
25103
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
25094
|
-
return new Promise((
|
|
25104
|
+
return new Promise((resolve17, reject) => {
|
|
25095
25105
|
server.httpServer.once("error", reject);
|
|
25096
25106
|
server.httpServer.listen(server.port, host, () => {
|
|
25097
25107
|
server.httpServer.off("error", reject);
|
|
@@ -25099,7 +25109,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
25099
25109
|
if (addr && typeof addr === "object") {
|
|
25100
25110
|
server.port = addr.port;
|
|
25101
25111
|
}
|
|
25102
|
-
|
|
25112
|
+
resolve17();
|
|
25103
25113
|
});
|
|
25104
25114
|
});
|
|
25105
25115
|
}
|
|
@@ -25182,7 +25192,7 @@ async function loadConfigSafe() {
|
|
|
25182
25192
|
}
|
|
25183
25193
|
|
|
25184
25194
|
// src/chat-cli.ts
|
|
25185
|
-
import * as
|
|
25195
|
+
import * as path50 from "path";
|
|
25186
25196
|
|
|
25187
25197
|
// src/chat/inbox.ts
|
|
25188
25198
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -25249,7 +25259,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
25249
25259
|
}
|
|
25250
25260
|
}
|
|
25251
25261
|
function sleep3(ms) {
|
|
25252
|
-
return new Promise((
|
|
25262
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
25253
25263
|
}
|
|
25254
25264
|
function currentBranch(cwd) {
|
|
25255
25265
|
try {
|
|
@@ -25463,7 +25473,7 @@ async function runChat(argv) {
|
|
|
25463
25473
|
${CHAT_HELP}`);
|
|
25464
25474
|
return 64;
|
|
25465
25475
|
}
|
|
25466
|
-
const cwd = args.cwd ?
|
|
25476
|
+
const cwd = args.cwd ? path50.resolve(args.cwd) : process.cwd();
|
|
25467
25477
|
const sessionId = args.sessionId;
|
|
25468
25478
|
const runRequest = readRunRequestFromEnv();
|
|
25469
25479
|
if (runRequest && "request" in runRequest) {
|
|
@@ -25584,8 +25594,8 @@ init_config();
|
|
|
25584
25594
|
// src/definition-hydration.ts
|
|
25585
25595
|
init_state_backend();
|
|
25586
25596
|
import { createHash as createHash5 } from "crypto";
|
|
25587
|
-
import * as
|
|
25588
|
-
import * as
|
|
25597
|
+
import * as fs50 from "fs";
|
|
25598
|
+
import * as path51 from "path";
|
|
25589
25599
|
var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
25590
25600
|
function assertSafeDefinitionPath(filePath) {
|
|
25591
25601
|
const segments = filePath.split("/");
|
|
@@ -25619,32 +25629,32 @@ function writeDefinition(root, kind, definition) {
|
|
|
25619
25629
|
if (kind === "agent") {
|
|
25620
25630
|
const raw = bundle.files["agent.md"];
|
|
25621
25631
|
if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
|
|
25622
|
-
|
|
25632
|
+
fs50.writeFileSync(path51.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
25623
25633
|
return;
|
|
25624
25634
|
}
|
|
25625
25635
|
if (kind === "goal") {
|
|
25626
|
-
const goalRoot =
|
|
25636
|
+
const goalRoot = path51.join(root, "goals", definition.slug);
|
|
25627
25637
|
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
25628
|
-
const target =
|
|
25629
|
-
|
|
25630
|
-
|
|
25638
|
+
const target = path51.join(goalRoot, filePath);
|
|
25639
|
+
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
25640
|
+
fs50.writeFileSync(target, contents, "utf8");
|
|
25631
25641
|
}
|
|
25632
25642
|
return;
|
|
25633
25643
|
}
|
|
25634
|
-
const capabilityRoot =
|
|
25644
|
+
const capabilityRoot = path51.join(root, "capabilities", definition.slug);
|
|
25635
25645
|
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
25636
|
-
const target =
|
|
25637
|
-
|
|
25638
|
-
|
|
25646
|
+
const target = path51.join(capabilityRoot, filePath);
|
|
25647
|
+
fs50.mkdirSync(path51.dirname(target), { recursive: true });
|
|
25648
|
+
fs50.writeFileSync(target, contents, "utf8");
|
|
25639
25649
|
}
|
|
25640
25650
|
}
|
|
25641
25651
|
async function hydrateDefinitions(options) {
|
|
25642
|
-
const root =
|
|
25652
|
+
const root = path51.join(options.cwd, ".kody-engine", "definitions");
|
|
25643
25653
|
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
25644
|
-
|
|
25645
|
-
|
|
25646
|
-
|
|
25647
|
-
|
|
25654
|
+
fs50.rmSync(staging, { recursive: true, force: true });
|
|
25655
|
+
fs50.mkdirSync(path51.join(staging, "agents"), { recursive: true });
|
|
25656
|
+
fs50.mkdirSync(path51.join(staging, "capabilities"), { recursive: true });
|
|
25657
|
+
fs50.mkdirSync(path51.join(staging, "goals"), { recursive: true });
|
|
25648
25658
|
try {
|
|
25649
25659
|
const [capabilities, agents, goals] = await Promise.all([
|
|
25650
25660
|
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
@@ -25670,13 +25680,13 @@ async function hydrateDefinitions(options) {
|
|
|
25670
25680
|
hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25671
25681
|
versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
|
|
25672
25682
|
};
|
|
25673
|
-
|
|
25683
|
+
fs50.writeFileSync(path51.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
25674
25684
|
`, "utf8");
|
|
25675
|
-
|
|
25676
|
-
|
|
25685
|
+
fs50.rmSync(root, { recursive: true, force: true });
|
|
25686
|
+
fs50.renameSync(staging, root);
|
|
25677
25687
|
return { root, tenantId: options.tenantId, versions: manifest.versions };
|
|
25678
25688
|
} catch (error) {
|
|
25679
|
-
|
|
25689
|
+
fs50.rmSync(staging, { recursive: true, force: true });
|
|
25680
25690
|
throw error;
|
|
25681
25691
|
}
|
|
25682
25692
|
}
|
|
@@ -25769,8 +25779,8 @@ var FlyClient = class {
|
|
|
25769
25779
|
get fetch() {
|
|
25770
25780
|
return this.opts.fetchImpl ?? fetch;
|
|
25771
25781
|
}
|
|
25772
|
-
async call(
|
|
25773
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
25782
|
+
async call(path52, init = {}) {
|
|
25783
|
+
const res = await this.fetch(`${FLY_API_BASE}${path52}`, {
|
|
25774
25784
|
method: init.method ?? "GET",
|
|
25775
25785
|
headers: {
|
|
25776
25786
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -25781,7 +25791,7 @@ var FlyClient = class {
|
|
|
25781
25791
|
if (res.status === 404 && init.allow404) return null;
|
|
25782
25792
|
if (!res.ok) {
|
|
25783
25793
|
const text2 = await res.text().catch(() => "");
|
|
25784
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
25794
|
+
throw new Error(`Fly API ${res.status} on ${path52}: ${text2.slice(0, 200) || res.statusText}`);
|
|
25785
25795
|
}
|
|
25786
25796
|
if (res.status === 204) return null;
|
|
25787
25797
|
const raw = await res.text();
|
|
@@ -26294,14 +26304,14 @@ function sendJson2(res, status, body) {
|
|
|
26294
26304
|
res.end(JSON.stringify(body));
|
|
26295
26305
|
}
|
|
26296
26306
|
function readJsonBody2(req) {
|
|
26297
|
-
return new Promise((
|
|
26307
|
+
return new Promise((resolve17, reject) => {
|
|
26298
26308
|
const chunks = [];
|
|
26299
26309
|
req.on("data", (c) => chunks.push(c));
|
|
26300
26310
|
req.on("end", () => {
|
|
26301
26311
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
26302
|
-
if (!raw.trim()) return
|
|
26312
|
+
if (!raw.trim()) return resolve17({});
|
|
26303
26313
|
try {
|
|
26304
|
-
|
|
26314
|
+
resolve17(JSON.parse(raw));
|
|
26305
26315
|
} catch (err) {
|
|
26306
26316
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
26307
26317
|
}
|
|
@@ -26512,10 +26522,10 @@ async function poolServe() {
|
|
|
26512
26522
|
}
|
|
26513
26523
|
});
|
|
26514
26524
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
26515
|
-
await new Promise((
|
|
26525
|
+
await new Promise((resolve17) => {
|
|
26516
26526
|
server.listen(apiPort, apiHost, () => {
|
|
26517
26527
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
26518
|
-
|
|
26528
|
+
resolve17();
|
|
26519
26529
|
});
|
|
26520
26530
|
});
|
|
26521
26531
|
if (loopTickEnabled) void runLoopTick();
|
|
@@ -26534,7 +26544,7 @@ async function poolServe() {
|
|
|
26534
26544
|
|
|
26535
26545
|
// src/servers/runner-serve.ts
|
|
26536
26546
|
import { spawn as spawn9 } from "child_process";
|
|
26537
|
-
import * as
|
|
26547
|
+
import * as fs51 from "fs";
|
|
26538
26548
|
import { createServer as createServer6 } from "http";
|
|
26539
26549
|
var DEFAULT_PORT2 = 8080;
|
|
26540
26550
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -26555,17 +26565,17 @@ function authOk2(req, expected) {
|
|
|
26555
26565
|
return false;
|
|
26556
26566
|
}
|
|
26557
26567
|
function readJsonBody3(req) {
|
|
26558
|
-
return new Promise((
|
|
26568
|
+
return new Promise((resolve17, reject) => {
|
|
26559
26569
|
const chunks = [];
|
|
26560
26570
|
req.on("data", (c) => chunks.push(c));
|
|
26561
26571
|
req.on("end", () => {
|
|
26562
26572
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
26563
26573
|
if (!raw.trim()) {
|
|
26564
|
-
|
|
26574
|
+
resolve17({});
|
|
26565
26575
|
return;
|
|
26566
26576
|
}
|
|
26567
26577
|
try {
|
|
26568
|
-
|
|
26578
|
+
resolve17(JSON.parse(raw));
|
|
26569
26579
|
} catch (err) {
|
|
26570
26580
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
26571
26581
|
}
|
|
@@ -26669,8 +26679,8 @@ async function defaultRunJob(job) {
|
|
|
26669
26679
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
26670
26680
|
const branch = job.ref ?? "main";
|
|
26671
26681
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
26672
|
-
|
|
26673
|
-
|
|
26682
|
+
fs51.rmSync(workdir, { recursive: true, force: true });
|
|
26683
|
+
fs51.mkdirSync(workdir, { recursive: true });
|
|
26674
26684
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
26675
26685
|
const target = job.runRequest.target;
|
|
26676
26686
|
const interactive = target.type === "chat";
|
|
@@ -26699,13 +26709,13 @@ async function defaultRunJob(job) {
|
|
|
26699
26709
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
26700
26710
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
26701
26711
|
};
|
|
26702
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
26712
|
+
const run = (cmd, args, cwd) => new Promise((resolve17) => {
|
|
26703
26713
|
const child = spawn9(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
26704
|
-
child.on("exit", (code) =>
|
|
26714
|
+
child.on("exit", (code) => resolve17(code ?? 0));
|
|
26705
26715
|
child.on("error", (err) => {
|
|
26706
26716
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
26707
26717
|
`);
|
|
26708
|
-
|
|
26718
|
+
resolve17(1);
|
|
26709
26719
|
});
|
|
26710
26720
|
});
|
|
26711
26721
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -26781,11 +26791,11 @@ async function runnerServe() {
|
|
|
26781
26791
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
26782
26792
|
const server = buildServer2({ apiKey });
|
|
26783
26793
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
26784
|
-
await new Promise((
|
|
26794
|
+
await new Promise((resolve17) => {
|
|
26785
26795
|
server.listen(port, host, () => {
|
|
26786
26796
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
26787
26797
|
`);
|
|
26788
|
-
|
|
26798
|
+
resolve17();
|
|
26789
26799
|
});
|
|
26790
26800
|
});
|
|
26791
26801
|
const shutdown = (signal) => {
|
|
@@ -26854,14 +26864,14 @@ async function serve(opts) {
|
|
|
26854
26864
|
`);
|
|
26855
26865
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
26856
26866
|
const child = spawn10("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
26857
|
-
const exitCode = await new Promise((
|
|
26858
|
-
child.on("exit", (code) =>
|
|
26867
|
+
const exitCode = await new Promise((resolve17) => {
|
|
26868
|
+
child.on("exit", (code) => resolve17(code ?? 0));
|
|
26859
26869
|
child.on("error", (err) => {
|
|
26860
26870
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
26861
26871
|
`);
|
|
26862
26872
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
26863
26873
|
`);
|
|
26864
|
-
|
|
26874
|
+
resolve17(1);
|
|
26865
26875
|
});
|
|
26866
26876
|
});
|
|
26867
26877
|
killProxy();
|
|
@@ -27245,7 +27255,7 @@ function parseArgs(argv) {
|
|
|
27245
27255
|
}
|
|
27246
27256
|
async function main(argv = process.argv.slice(2)) {
|
|
27247
27257
|
unpackAllSecrets();
|
|
27248
|
-
const cwdFlag = argv.
|
|
27258
|
+
const cwdFlag = argv.indexOf("--cwd");
|
|
27249
27259
|
const definitionCwd = cwdFlag >= 0 && argv[cwdFlag + 1] ? argv[cwdFlag + 1] : process.cwd();
|
|
27250
27260
|
const shouldHydrate = Boolean(process.env.CONVEX_URL?.trim()) || process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.GITHUB_EVENT_NAME);
|
|
27251
27261
|
if (shouldHydrate) {
|