@kody-ade/kody-engine 0.4.571 → 0.4.572
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 +428 -418
- package/package.json +1 -1
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.572",
|
|
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",
|
|
@@ -151,17 +151,23 @@ var init_claudeBinary = __esm({
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
// src/completionGuard.ts
|
|
154
|
+
import * as path2 from "path";
|
|
154
155
|
function completionToolCutoffAt(startedAtMs, deadlineAtMs) {
|
|
155
156
|
const availableMs = Math.max(0, deadlineAtMs - startedAtMs);
|
|
156
|
-
const reserveMs = Math.min(MAX_COMPLETION_RESERVE_MS, Math.floor(availableMs /
|
|
157
|
+
const reserveMs = Math.min(MAX_COMPLETION_RESERVE_MS, Math.floor(availableMs / 2));
|
|
157
158
|
return deadlineAtMs - reserveMs;
|
|
158
159
|
}
|
|
159
|
-
function createCompletionToolGuard(cutoffAtMs, now = Date.now) {
|
|
160
|
-
return async () => {
|
|
160
|
+
function createCompletionToolGuard(cutoffAtMs, now = Date.now, requiredOutputPath) {
|
|
161
|
+
return async (input) => {
|
|
161
162
|
if (now() < cutoffAtMs) return {};
|
|
163
|
+
const toolInput = input?.tool_input;
|
|
164
|
+
const filePath = toolInput && typeof toolInput === "object" && !Array.isArray(toolInput) ? toolInput.file_path : void 0;
|
|
165
|
+
if (requiredOutputPath && input?.tool_name === "Write" && typeof filePath === "string" && path2.resolve(filePath) === path2.resolve(requiredOutputPath)) {
|
|
166
|
+
return {};
|
|
167
|
+
}
|
|
162
168
|
return {
|
|
163
169
|
decision: "block",
|
|
164
|
-
reason: "The run has entered its reserved completion window. Do not call more tools. Use the evidence and changes already present, state any verification limits clearly, and return your final response now."
|
|
170
|
+
reason: "The run has entered its reserved completion window. Do not call more tools. " + (requiredOutputPath ? `If the required structured result is missing, write only ${requiredOutputPath}. ` : "") + "Use the evidence and changes already present, state any verification limits clearly, and return your final response now."
|
|
165
171
|
};
|
|
166
172
|
};
|
|
167
173
|
}
|
|
@@ -169,13 +175,13 @@ var MAX_COMPLETION_RESERVE_MS;
|
|
|
169
175
|
var init_completionGuard = __esm({
|
|
170
176
|
"src/completionGuard.ts"() {
|
|
171
177
|
"use strict";
|
|
172
|
-
MAX_COMPLETION_RESERVE_MS =
|
|
178
|
+
MAX_COMPLETION_RESERVE_MS = 15 * 6e4;
|
|
173
179
|
}
|
|
174
180
|
});
|
|
175
181
|
|
|
176
182
|
// src/config.ts
|
|
177
183
|
import * as fs2 from "fs";
|
|
178
|
-
import * as
|
|
184
|
+
import * as path3 from "path";
|
|
179
185
|
function parseReasoningEffort(raw) {
|
|
180
186
|
if (!raw) return null;
|
|
181
187
|
const v = raw.trim().toLowerCase();
|
|
@@ -240,7 +246,7 @@ function needsLitellmProxy(model) {
|
|
|
240
246
|
return model.provider !== "claude" && model.provider !== "anthropic";
|
|
241
247
|
}
|
|
242
248
|
function loadConfig(projectDir = process.cwd()) {
|
|
243
|
-
const configPath =
|
|
249
|
+
const configPath = path3.join(projectDir, "kody.config.json");
|
|
244
250
|
if (!fs2.existsSync(configPath)) {
|
|
245
251
|
throw new Error(`kody.config.json not found at ${configPath}`);
|
|
246
252
|
}
|
|
@@ -573,15 +579,15 @@ var init_config = __esm({
|
|
|
573
579
|
|
|
574
580
|
// src/fileEditGuards.ts
|
|
575
581
|
import * as fs3 from "fs";
|
|
576
|
-
import * as
|
|
582
|
+
import * as path4 from "path";
|
|
577
583
|
function createMissingParentWriteGuard(cwd) {
|
|
578
584
|
return async (input) => {
|
|
579
585
|
const toolInput = input.tool_input;
|
|
580
586
|
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
|
|
581
587
|
const filePath = toolInput.file_path;
|
|
582
588
|
if (typeof filePath !== "string" || filePath.length === 0) return {};
|
|
583
|
-
const resolvedPath =
|
|
584
|
-
if (fs3.existsSync(
|
|
589
|
+
const resolvedPath = path4.resolve(cwd, filePath);
|
|
590
|
+
if (fs3.existsSync(path4.dirname(resolvedPath))) return {};
|
|
585
591
|
return {
|
|
586
592
|
decision: "block",
|
|
587
593
|
reason: `Cannot write ${resolvedPath}: its parent directory does not exist. Locate and edit the real repository source path first. If this task genuinely requires a new directory, create that directory explicitly before writing the file.`
|
|
@@ -788,7 +794,7 @@ var init_capability_contract_validation = __esm({
|
|
|
788
794
|
|
|
789
795
|
// src/outputContractHooks.ts
|
|
790
796
|
import * as fs4 from "fs";
|
|
791
|
-
import * as
|
|
797
|
+
import * as path5 from "path";
|
|
792
798
|
function outputContractError(contract) {
|
|
793
799
|
let value;
|
|
794
800
|
try {
|
|
@@ -807,12 +813,12 @@ function correctionMessage(contract, error) {
|
|
|
807
813
|
return `The authoritative output does not match its required contract: ${error}. Please overwrite ${contract.path} with only the required JSON shape before finishing.`;
|
|
808
814
|
}
|
|
809
815
|
function createOutputContractPostWriteHook(contract) {
|
|
810
|
-
const expectedPath =
|
|
816
|
+
const expectedPath = path5.resolve(contract.path);
|
|
811
817
|
return async (input) => {
|
|
812
818
|
const toolInput = input.tool_input;
|
|
813
819
|
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
|
|
814
820
|
const filePath = toolInput.file_path;
|
|
815
|
-
if (typeof filePath !== "string" ||
|
|
821
|
+
if (typeof filePath !== "string" || path5.resolve(filePath) !== expectedPath) return {};
|
|
816
822
|
const error = outputContractError(contract);
|
|
817
823
|
if (!error) return {};
|
|
818
824
|
return {
|
|
@@ -856,21 +862,21 @@ __export(runtimePaths_exports, {
|
|
|
856
862
|
});
|
|
857
863
|
import { createHash } from "crypto";
|
|
858
864
|
import * as os2 from "os";
|
|
859
|
-
import * as
|
|
865
|
+
import * as path6 from "path";
|
|
860
866
|
function runtimeDirForCwd(cwd, ...parts) {
|
|
861
|
-
const key = createHash("sha256").update(
|
|
862
|
-
return
|
|
867
|
+
const key = createHash("sha256").update(path6.resolve(cwd)).digest("hex").slice(0, 16);
|
|
868
|
+
return path6.join(os2.tmpdir(), "kody-engine", key, ...parts);
|
|
863
869
|
}
|
|
864
870
|
function runtimeStatePath(cwd, ...parts) {
|
|
865
871
|
const configuredRoot = process.env.KODY_RUNTIME_DIR?.trim();
|
|
866
|
-
const base = configuredRoot ?
|
|
867
|
-
return
|
|
872
|
+
const base = configuredRoot ? path6.resolve(configuredRoot) : runtimeDirForCwd(cwd);
|
|
873
|
+
return path6.join(base, ...parts);
|
|
868
874
|
}
|
|
869
875
|
function agentRunDir(cwd) {
|
|
870
876
|
return runtimeStatePath(cwd, "agent-runs");
|
|
871
877
|
}
|
|
872
878
|
function lastRunLogPath(cwd) {
|
|
873
|
-
return
|
|
879
|
+
return path6.join(agentRunDir(cwd), "last-run.jsonl");
|
|
874
880
|
}
|
|
875
881
|
var init_runtimePaths = __esm({
|
|
876
882
|
"src/runtimePaths.ts"() {
|
|
@@ -881,15 +887,15 @@ var init_runtimePaths = __esm({
|
|
|
881
887
|
// src/scripts/buildSyntheticPlugin.ts
|
|
882
888
|
import * as fs5 from "fs";
|
|
883
889
|
import * as os3 from "os";
|
|
884
|
-
import * as
|
|
890
|
+
import * as path7 from "path";
|
|
885
891
|
function getPluginsCatalogRoot() {
|
|
886
|
-
const here =
|
|
892
|
+
const here = path7.dirname(new URL(import.meta.url).pathname);
|
|
887
893
|
const candidates = [
|
|
888
|
-
|
|
894
|
+
path7.join(here, "..", "plugins"),
|
|
889
895
|
// dev: src/scripts → src/plugins
|
|
890
|
-
|
|
896
|
+
path7.join(here, "..", "..", "plugins"),
|
|
891
897
|
// built: dist/scripts → dist/plugins
|
|
892
|
-
|
|
898
|
+
path7.join(here, "..", "..", "src", "plugins")
|
|
893
899
|
// fallback
|
|
894
900
|
];
|
|
895
901
|
for (const c of candidates) {
|
|
@@ -900,8 +906,8 @@ function getPluginsCatalogRoot() {
|
|
|
900
906
|
function copyDir(src, dst) {
|
|
901
907
|
fs5.mkdirSync(dst, { recursive: true });
|
|
902
908
|
for (const ent of fs5.readdirSync(src, { withFileTypes: true })) {
|
|
903
|
-
const s =
|
|
904
|
-
const d =
|
|
909
|
+
const s = path7.join(src, ent.name);
|
|
910
|
+
const d = path7.join(dst, ent.name);
|
|
905
911
|
if (ent.isDirectory()) copyDir(s, d);
|
|
906
912
|
else if (ent.isFile()) fs5.copyFileSync(s, d);
|
|
907
913
|
}
|
|
@@ -916,35 +922,35 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
916
922
|
if (!needsSynthetic) return;
|
|
917
923
|
const catalog = getPluginsCatalogRoot();
|
|
918
924
|
const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
919
|
-
const root =
|
|
920
|
-
fs5.mkdirSync(
|
|
925
|
+
const root = path7.join(os3.tmpdir(), `kody-synth-${runId}`);
|
|
926
|
+
fs5.mkdirSync(path7.join(root, ".claude-plugin"), { recursive: true });
|
|
921
927
|
const resolvePart = (bucket, entry) => {
|
|
922
|
-
const local =
|
|
928
|
+
const local = path7.join(profile.dir, bucket, entry);
|
|
923
929
|
if (fs5.existsSync(local)) return local;
|
|
924
|
-
const shared =
|
|
930
|
+
const shared = path7.resolve(profile.dir, "..", "..", "shared", bucket, entry);
|
|
925
931
|
if (fs5.existsSync(shared)) return shared;
|
|
926
|
-
const central =
|
|
932
|
+
const central = path7.join(catalog, bucket, entry);
|
|
927
933
|
if (fs5.existsSync(central)) return central;
|
|
928
934
|
throw new Error(
|
|
929
|
-
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${
|
|
935
|
+
`buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path7.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
|
|
930
936
|
);
|
|
931
937
|
};
|
|
932
938
|
if (cc.skills.length > 0) {
|
|
933
|
-
const dst =
|
|
939
|
+
const dst = path7.join(root, "skills");
|
|
934
940
|
fs5.mkdirSync(dst, { recursive: true });
|
|
935
941
|
for (const name of cc.skills) {
|
|
936
|
-
copyDir(resolvePart("skills", name),
|
|
942
|
+
copyDir(resolvePart("skills", name), path7.join(dst, name));
|
|
937
943
|
}
|
|
938
944
|
}
|
|
939
945
|
if (cc.commands.length > 0) {
|
|
940
|
-
const dst =
|
|
946
|
+
const dst = path7.join(root, "commands");
|
|
941
947
|
fs5.mkdirSync(dst, { recursive: true });
|
|
942
948
|
for (const name of cc.commands) {
|
|
943
|
-
fs5.copyFileSync(resolvePart("commands", `${name}.md`),
|
|
949
|
+
fs5.copyFileSync(resolvePart("commands", `${name}.md`), path7.join(dst, `${name}.md`));
|
|
944
950
|
}
|
|
945
951
|
}
|
|
946
952
|
if (cc.hooks.length > 0) {
|
|
947
|
-
const dst =
|
|
953
|
+
const dst = path7.join(root, "hooks");
|
|
948
954
|
fs5.mkdirSync(dst, { recursive: true });
|
|
949
955
|
const merged = { hooks: {} };
|
|
950
956
|
for (const name of cc.hooks) {
|
|
@@ -956,7 +962,7 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
956
962
|
merged.hooks[event].push(...entries);
|
|
957
963
|
}
|
|
958
964
|
}
|
|
959
|
-
fs5.writeFileSync(
|
|
965
|
+
fs5.writeFileSync(path7.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
|
|
960
966
|
`);
|
|
961
967
|
}
|
|
962
968
|
const manifest = {
|
|
@@ -966,7 +972,7 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
966
972
|
};
|
|
967
973
|
if (cc.skills.length > 0) manifest.skills = ["./skills/"];
|
|
968
974
|
if (cc.commands.length > 0) manifest.commands = ["./commands/"];
|
|
969
|
-
fs5.writeFileSync(
|
|
975
|
+
fs5.writeFileSync(path7.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
|
|
970
976
|
`);
|
|
971
977
|
ctx.data.syntheticPluginPath = root;
|
|
972
978
|
};
|
|
@@ -975,7 +981,7 @@ var init_buildSyntheticPlugin = __esm({
|
|
|
975
981
|
|
|
976
982
|
// src/subagents.ts
|
|
977
983
|
import * as fs6 from "fs";
|
|
978
|
-
import * as
|
|
984
|
+
import * as path8 from "path";
|
|
979
985
|
async function enforceSubagentModelInheritance(input) {
|
|
980
986
|
const toolInput = input.tool_input;
|
|
981
987
|
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
|
|
@@ -1010,11 +1016,11 @@ function splitFrontmatter(raw) {
|
|
|
1010
1016
|
return { fm, body: (match[2] ?? "").trim() };
|
|
1011
1017
|
}
|
|
1012
1018
|
function resolveAgentFile(profileDir, name) {
|
|
1013
|
-
const local =
|
|
1019
|
+
const local = path8.join(profileDir, "agents", `${name}.md`);
|
|
1014
1020
|
if (fs6.existsSync(local)) return local;
|
|
1015
|
-
const shared =
|
|
1021
|
+
const shared = path8.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
|
|
1016
1022
|
if (fs6.existsSync(shared)) return shared;
|
|
1017
|
-
const central =
|
|
1023
|
+
const central = path8.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
|
|
1018
1024
|
if (fs6.existsSync(central)) return central;
|
|
1019
1025
|
throw new Error(
|
|
1020
1026
|
`loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
|
|
@@ -1071,7 +1077,7 @@ __export(events_exports, {
|
|
|
1071
1077
|
});
|
|
1072
1078
|
import * as crypto from "crypto";
|
|
1073
1079
|
import * as fs7 from "fs";
|
|
1074
|
-
import * as
|
|
1080
|
+
import * as path9 from "path";
|
|
1075
1081
|
function resolveRunId() {
|
|
1076
1082
|
if (process.env.KODY_RUN_ID) {
|
|
1077
1083
|
cachedRunId = process.env.KODY_RUN_ID;
|
|
@@ -1104,7 +1110,7 @@ function emitEvent(cwd, ev) {
|
|
|
1104
1110
|
...ev
|
|
1105
1111
|
};
|
|
1106
1112
|
const file = eventsPath(cwd, runId);
|
|
1107
|
-
fs7.mkdirSync(
|
|
1113
|
+
fs7.mkdirSync(path9.dirname(file), { recursive: true });
|
|
1108
1114
|
fs7.appendFileSync(file, `${JSON.stringify(fullEvent)}
|
|
1109
1115
|
`);
|
|
1110
1116
|
} catch {
|
|
@@ -1130,7 +1136,7 @@ function listRuns(cwd) {
|
|
|
1130
1136
|
if (!fs7.existsSync(runsDir)) return [];
|
|
1131
1137
|
return fs7.readdirSync(runsDir).filter((name) => {
|
|
1132
1138
|
try {
|
|
1133
|
-
return fs7.statSync(
|
|
1139
|
+
return fs7.statSync(path9.join(runsDir, name)).isDirectory();
|
|
1134
1140
|
} catch {
|
|
1135
1141
|
return false;
|
|
1136
1142
|
}
|
|
@@ -1171,10 +1177,10 @@ function abortMessage(signal) {
|
|
|
1171
1177
|
return reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "verification aborted";
|
|
1172
1178
|
}
|
|
1173
1179
|
function runCommand(command, cwd, signal) {
|
|
1174
|
-
return new Promise((
|
|
1180
|
+
return new Promise((resolve24) => {
|
|
1175
1181
|
const start = Date.now();
|
|
1176
1182
|
if (signal?.aborted) {
|
|
1177
|
-
|
|
1183
|
+
resolve24({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
|
|
1178
1184
|
return;
|
|
1179
1185
|
}
|
|
1180
1186
|
const child = spawn(command, {
|
|
@@ -1212,7 +1218,7 @@ function runCommand(command, cwd, signal) {
|
|
|
1212
1218
|
signal?.removeEventListener("abort", onAbort);
|
|
1213
1219
|
const output = Buffer.concat(buffers).toString("utf-8");
|
|
1214
1220
|
const tail = [output, extraTail].filter(Boolean).join("\n").slice(-TAIL_CHARS);
|
|
1215
|
-
|
|
1221
|
+
resolve24({ exitCode, durationMs: Date.now() - start, tail });
|
|
1216
1222
|
};
|
|
1217
1223
|
const terminate = () => {
|
|
1218
1224
|
killTree("SIGTERM");
|
|
@@ -1541,7 +1547,7 @@ function cmsHeaders(opts) {
|
|
|
1541
1547
|
}
|
|
1542
1548
|
};
|
|
1543
1549
|
}
|
|
1544
|
-
async function callDashboardCms(opts,
|
|
1550
|
+
async function callDashboardCms(opts, path59, init = {}) {
|
|
1545
1551
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1546
1552
|
if (!baseUrl) {
|
|
1547
1553
|
return {
|
|
@@ -1553,7 +1559,7 @@ async function callDashboardCms(opts, path58, init = {}) {
|
|
|
1553
1559
|
const headerResult = cmsHeaders(opts);
|
|
1554
1560
|
if (!headerResult.ok) return headerResult;
|
|
1555
1561
|
try {
|
|
1556
|
-
const res = await fetch(`${baseUrl}${
|
|
1562
|
+
const res = await fetch(`${baseUrl}${path59}`, {
|
|
1557
1563
|
...init,
|
|
1558
1564
|
headers: {
|
|
1559
1565
|
...headerResult.headers,
|
|
@@ -1625,8 +1631,8 @@ function documentArg(value) {
|
|
|
1625
1631
|
function normalizeCmsDocumentIdInput(input) {
|
|
1626
1632
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1627
1633
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1628
|
-
const
|
|
1629
|
-
return
|
|
1634
|
+
const path59 = parseDocumentPath(withoutQuery);
|
|
1635
|
+
return path59 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1630
1636
|
}
|
|
1631
1637
|
function stripWrappingQuotes(value) {
|
|
1632
1638
|
let current = value;
|
|
@@ -1637,9 +1643,9 @@ function stripWrappingQuotes(value) {
|
|
|
1637
1643
|
}
|
|
1638
1644
|
}
|
|
1639
1645
|
function parseDocumentPath(value) {
|
|
1640
|
-
const
|
|
1641
|
-
if (!
|
|
1642
|
-
const parts =
|
|
1646
|
+
const path59 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1647
|
+
if (!path59?.includes("/content/entries/")) return null;
|
|
1648
|
+
const parts = path59.split("/").filter(Boolean).map(decodePathPart);
|
|
1643
1649
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1644
1650
|
const idPart = parts[entriesIndex + 3];
|
|
1645
1651
|
if (!idPart || idPart === "new") return null;
|
|
@@ -2085,7 +2091,7 @@ var init_issue = __esm({
|
|
|
2085
2091
|
|
|
2086
2092
|
// src/capabilityFolders.ts
|
|
2087
2093
|
import * as fs8 from "fs";
|
|
2088
|
-
import * as
|
|
2094
|
+
import * as path10 from "path";
|
|
2089
2095
|
function capabilityOutputConditionPaths(config) {
|
|
2090
2096
|
if (config.outputSchema) {
|
|
2091
2097
|
return new Set(schemaPropertyPaths(config.outputSchema, "result"));
|
|
@@ -2107,35 +2113,35 @@ function listCapabilityFolderSlugs(absDir) {
|
|
|
2107
2113
|
} catch {
|
|
2108
2114
|
return [];
|
|
2109
2115
|
}
|
|
2110
|
-
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(
|
|
2116
|
+
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path10.join(absDir, e.name))).map((e) => e.name).sort();
|
|
2111
2117
|
}
|
|
2112
2118
|
function isCapabilityFolder(dir) {
|
|
2113
2119
|
const entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
2114
|
-
const legacyBody =
|
|
2120
|
+
const legacyBody = path10.join(dir, CAPABILITY_BODY_FILE);
|
|
2115
2121
|
if (fs8.existsSync(legacyBody)) {
|
|
2116
2122
|
return entries.every(
|
|
2117
2123
|
(entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
|
|
2118
2124
|
);
|
|
2119
2125
|
}
|
|
2120
|
-
const canonicalBody =
|
|
2121
|
-
const canonicalDefinition =
|
|
2126
|
+
const canonicalBody = path10.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
|
|
2127
|
+
const canonicalDefinition = path10.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
|
|
2122
2128
|
if (!fs8.existsSync(canonicalBody) || !fs8.existsSync(canonicalDefinition)) return false;
|
|
2123
2129
|
return entries.every(
|
|
2124
2130
|
(entry) => entry.name === CANONICAL_CAPABILITY_BODY_FILE || entry.name === CANONICAL_CAPABILITY_DEFINITION_FILE
|
|
2125
2131
|
);
|
|
2126
2132
|
}
|
|
2127
2133
|
function readCapabilityFolder(root, slug) {
|
|
2128
|
-
const dir =
|
|
2129
|
-
const legacyBodyPath =
|
|
2130
|
-
const canonicalBodyPath =
|
|
2134
|
+
const dir = path10.join(root, slug);
|
|
2135
|
+
const legacyBodyPath = path10.join(dir, CAPABILITY_BODY_FILE);
|
|
2136
|
+
const canonicalBodyPath = path10.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
|
|
2131
2137
|
const bodyPath = fs8.existsSync(legacyBodyPath) ? legacyBodyPath : canonicalBodyPath;
|
|
2132
|
-
const contractPath =
|
|
2138
|
+
const contractPath = path10.join(dir, CAPABILITY_CONTRACT_FILE);
|
|
2133
2139
|
if (!fs8.existsSync(bodyPath) || !fs8.statSync(bodyPath).isFile()) return null;
|
|
2134
2140
|
if (!isCapabilityFolder(dir)) return null;
|
|
2135
2141
|
try {
|
|
2136
2142
|
const rawBody = fs8.readFileSync(bodyPath, "utf-8");
|
|
2137
2143
|
if (bodyPath === canonicalBodyPath) {
|
|
2138
|
-
const definitionPath =
|
|
2144
|
+
const definitionPath = path10.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
|
|
2139
2145
|
const definition = JSON.parse(fs8.readFileSync(definitionPath, "utf-8"));
|
|
2140
2146
|
if (definition.id !== slug || typeof definition.action !== "string") return null;
|
|
2141
2147
|
const { title: title2, body: body2 } = parseCapabilityBody(rawBody, slug);
|
|
@@ -2157,7 +2163,7 @@ function readCapabilityFolder(root, slug) {
|
|
|
2157
2163
|
};
|
|
2158
2164
|
}
|
|
2159
2165
|
const contract = fs8.existsSync(contractPath) ? parseCapabilityContract(fs8.readFileSync(contractPath, "utf-8")) : void 0;
|
|
2160
|
-
if (contract?.execution === "script" && !isRegularFile(
|
|
2166
|
+
if (contract?.execution === "script" && !isRegularFile(path10.join(dir, "tools", "run.sh"))) {
|
|
2161
2167
|
throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
|
|
2162
2168
|
}
|
|
2163
2169
|
const { title, body } = parseCapabilityBody(rawBody, slug);
|
|
@@ -2279,8 +2285,8 @@ function isRegularFile(filePath) {
|
|
|
2279
2285
|
function schemaPropertyPaths(schema, prefix) {
|
|
2280
2286
|
const properties = isPlainObject(schema.properties) ? schema.properties : {};
|
|
2281
2287
|
return Object.entries(properties).flatMap(([name, property]) => {
|
|
2282
|
-
const
|
|
2283
|
-
return isPlainObject(property) ? [
|
|
2288
|
+
const path59 = `${prefix}.${name}`;
|
|
2289
|
+
return isPlainObject(property) ? [path59, ...schemaPropertyPaths(property, path59)] : [path59];
|
|
2284
2290
|
});
|
|
2285
2291
|
}
|
|
2286
2292
|
function parseCapabilityBody(raw, slug) {
|
|
@@ -2447,47 +2453,47 @@ var init_capabilityFolders = __esm({
|
|
|
2447
2453
|
|
|
2448
2454
|
// src/definition-paths.ts
|
|
2449
2455
|
import * as fs9 from "fs";
|
|
2450
|
-
import * as
|
|
2456
|
+
import * as path11 from "path";
|
|
2451
2457
|
function definitionsRoot(cwd = process.cwd()) {
|
|
2452
2458
|
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
2453
2459
|
const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
2454
|
-
if (override && overrideCwd &&
|
|
2455
|
-
return storeCatalogRoot(
|
|
2460
|
+
if (override && overrideCwd && path11.resolve(cwd) === path11.resolve(overrideCwd)) {
|
|
2461
|
+
return storeCatalogRoot(path11.resolve(override));
|
|
2456
2462
|
}
|
|
2457
|
-
const hydrated =
|
|
2463
|
+
const hydrated = path11.join(cwd, ".kody-engine", "definitions");
|
|
2458
2464
|
if (fs9.existsSync(hydrated)) return hydrated;
|
|
2459
|
-
return override ? storeCatalogRoot(
|
|
2465
|
+
return override ? storeCatalogRoot(path11.resolve(override)) : hydrated;
|
|
2460
2466
|
}
|
|
2461
2467
|
function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
|
|
2462
2468
|
const root = env.KODY_DEFINITIONS_ROOT?.trim();
|
|
2463
2469
|
const rootCwd = env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
2464
|
-
return Boolean(root && rootCwd &&
|
|
2470
|
+
return Boolean(root && rootCwd && path11.resolve(cwd) === path11.resolve(rootCwd));
|
|
2465
2471
|
}
|
|
2466
2472
|
function capabilitiesRoot(cwd = process.cwd()) {
|
|
2467
|
-
return storeAssetRoot(cwd, "capabilities") ??
|
|
2473
|
+
return storeAssetRoot(cwd, "capabilities") ?? path11.join(definitionsRoot(cwd), "capabilities");
|
|
2468
2474
|
}
|
|
2469
2475
|
function implementationsRoot(cwd = process.cwd()) {
|
|
2470
|
-
return
|
|
2476
|
+
return path11.join(definitionsRoot(cwd), "implementations");
|
|
2471
2477
|
}
|
|
2472
2478
|
function agentsRoot(cwd = process.cwd()) {
|
|
2473
|
-
return storeAssetRoot(cwd, "agent") ??
|
|
2479
|
+
return storeAssetRoot(cwd, "agent") ?? path11.join(definitionsRoot(cwd), "agents");
|
|
2474
2480
|
}
|
|
2475
2481
|
function storeCatalogRoot(root) {
|
|
2476
2482
|
const manifest = readStoreManifest(root);
|
|
2477
|
-
const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) =>
|
|
2478
|
-
return roots.length === 3 && new Set(roots).size === 1 ?
|
|
2483
|
+
const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path11.dirname(value));
|
|
2484
|
+
return roots.length === 3 && new Set(roots).size === 1 ? path11.join(root, roots[0]) : root;
|
|
2479
2485
|
}
|
|
2480
2486
|
function storeAssetRoot(cwd, kind) {
|
|
2481
2487
|
const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
|
|
2482
2488
|
if (!override) return null;
|
|
2483
2489
|
const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
|
|
2484
|
-
if (overrideCwd &&
|
|
2485
|
-
const root =
|
|
2490
|
+
if (overrideCwd && path11.resolve(cwd) !== path11.resolve(overrideCwd)) return null;
|
|
2491
|
+
const root = path11.resolve(override);
|
|
2486
2492
|
const configured = readStoreManifest(root)?.assetRoots?.[kind];
|
|
2487
|
-
return typeof configured === "string" && configured.trim() ?
|
|
2493
|
+
return typeof configured === "string" && configured.trim() ? path11.join(root, configured) : null;
|
|
2488
2494
|
}
|
|
2489
2495
|
function readStoreManifest(root) {
|
|
2490
|
-
const file =
|
|
2496
|
+
const file = path11.join(root, "kody-store.json");
|
|
2491
2497
|
if (!fs9.existsSync(file)) return null;
|
|
2492
2498
|
try {
|
|
2493
2499
|
return JSON.parse(fs9.readFileSync(file, "utf8"));
|
|
@@ -2503,15 +2509,15 @@ var init_definition_paths = __esm({
|
|
|
2503
2509
|
|
|
2504
2510
|
// src/registry.ts
|
|
2505
2511
|
import * as fs10 from "fs";
|
|
2506
|
-
import * as
|
|
2512
|
+
import * as path12 from "path";
|
|
2507
2513
|
function getImplementationsRoot() {
|
|
2508
|
-
const here =
|
|
2514
|
+
const here = path12.dirname(new URL(import.meta.url).pathname);
|
|
2509
2515
|
const candidates = [
|
|
2510
|
-
|
|
2516
|
+
path12.join(here, "implementations"),
|
|
2511
2517
|
// dev: src/
|
|
2512
|
-
|
|
2518
|
+
path12.join(here, "..", "implementations"),
|
|
2513
2519
|
// built: dist/bin → dist/implementations
|
|
2514
|
-
|
|
2520
|
+
path12.join(here, "..", "src", "implementations")
|
|
2515
2521
|
// fallback
|
|
2516
2522
|
];
|
|
2517
2523
|
for (const c of candidates) {
|
|
@@ -2520,11 +2526,11 @@ function getImplementationsRoot() {
|
|
|
2520
2526
|
return candidates[0];
|
|
2521
2527
|
}
|
|
2522
2528
|
function getRuntimeServicesRoot() {
|
|
2523
|
-
const here =
|
|
2529
|
+
const here = path12.dirname(new URL(import.meta.url).pathname);
|
|
2524
2530
|
const candidates = [
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2531
|
+
path12.join(here, "runtime-services"),
|
|
2532
|
+
path12.join(here, "..", "runtime-services"),
|
|
2533
|
+
path12.join(here, "..", "src", "runtime-services")
|
|
2528
2534
|
];
|
|
2529
2535
|
for (const candidate of candidates) {
|
|
2530
2536
|
if (fs10.existsSync(candidate) && fs10.statSync(candidate).isDirectory()) return candidate;
|
|
@@ -2535,13 +2541,13 @@ function getProjectCapabilitiesRoot() {
|
|
|
2535
2541
|
return capabilitiesRoot();
|
|
2536
2542
|
}
|
|
2537
2543
|
function getBuiltinCapabilitiesRoot() {
|
|
2538
|
-
const here =
|
|
2544
|
+
const here = path12.dirname(new URL(import.meta.url).pathname);
|
|
2539
2545
|
const candidates = [
|
|
2540
|
-
|
|
2546
|
+
path12.join(here, "capabilities"),
|
|
2541
2547
|
// dev: src/
|
|
2542
|
-
|
|
2548
|
+
path12.join(here, "..", "capabilities"),
|
|
2543
2549
|
// built: dist/bin → dist/capabilities
|
|
2544
|
-
|
|
2550
|
+
path12.join(here, "..", "src", "capabilities")
|
|
2545
2551
|
// fallback
|
|
2546
2552
|
];
|
|
2547
2553
|
for (const c of candidates) {
|
|
@@ -2685,17 +2691,17 @@ function isSafeName(name) {
|
|
|
2685
2691
|
return /^[a-z][a-z0-9-]*$/.test(name) && !name.includes("..");
|
|
2686
2692
|
}
|
|
2687
2693
|
function isCapabilityRoot(root) {
|
|
2688
|
-
const normalized =
|
|
2689
|
-
if (
|
|
2694
|
+
const normalized = path12.normalize(root);
|
|
2695
|
+
if (path12.basename(normalized) === "capabilities") return true;
|
|
2690
2696
|
const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
|
|
2691
|
-
return knownRoots.some((candidate) => candidate &&
|
|
2697
|
+
return knownRoots.some((candidate) => candidate && path12.normalize(candidate) === normalized);
|
|
2692
2698
|
}
|
|
2693
2699
|
function implementationRuntimePath(root, name) {
|
|
2694
|
-
const runtimePath =
|
|
2700
|
+
const runtimePath = path12.join(root, name, "runtime.json");
|
|
2695
2701
|
if (fs10.existsSync(runtimePath)) return runtimePath;
|
|
2696
|
-
const internalProfilePath =
|
|
2702
|
+
const internalProfilePath = path12.join(root, name, "profile.json");
|
|
2697
2703
|
if (fs10.existsSync(internalProfilePath)) return internalProfilePath;
|
|
2698
|
-
return
|
|
2704
|
+
return path12.join(root, name, CAPABILITY_PROFILE_FILE);
|
|
2699
2705
|
}
|
|
2700
2706
|
function isImplementationProfile(profilePath, requireImplementationProfile) {
|
|
2701
2707
|
if (!requireImplementationProfile) return true;
|
|
@@ -3862,7 +3868,7 @@ var init_capabilityMcp = __esm({
|
|
|
3862
3868
|
// src/repoWorkspace.ts
|
|
3863
3869
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
3864
3870
|
import * as fs11 from "fs";
|
|
3865
|
-
import * as
|
|
3871
|
+
import * as path13 from "path";
|
|
3866
3872
|
function buildCloneProcess(repo, token, baseEnv = process.env) {
|
|
3867
3873
|
const url = `https://github.com/${repo}.git`;
|
|
3868
3874
|
const env = { ...baseEnv };
|
|
@@ -3877,10 +3883,10 @@ function buildCloneProcess(repo, token, baseEnv = process.env) {
|
|
|
3877
3883
|
async function resolveAndClone(reposRoot, repo, repoToken, cloneRepo) {
|
|
3878
3884
|
const name = repo?.trim();
|
|
3879
3885
|
if (!name || !REPO_RE.test(name)) return null;
|
|
3880
|
-
const root =
|
|
3881
|
-
const dir =
|
|
3882
|
-
if (dir !== root && !dir.startsWith(root +
|
|
3883
|
-
if (fs11.existsSync(
|
|
3886
|
+
const root = path13.resolve(reposRoot);
|
|
3887
|
+
const dir = path13.resolve(root, name);
|
|
3888
|
+
if (dir !== root && !dir.startsWith(root + path13.sep)) return null;
|
|
3889
|
+
if (fs11.existsSync(path13.join(dir, ".git"))) return dir;
|
|
3884
3890
|
const inflight = repoClones.get(dir);
|
|
3885
3891
|
if (inflight) {
|
|
3886
3892
|
await inflight;
|
|
@@ -3912,9 +3918,9 @@ var init_repoWorkspace = __esm({
|
|
|
3912
3918
|
repoClones = /* @__PURE__ */ new Map();
|
|
3913
3919
|
GIT_CREDENTIAL_HELPER = `!f() { if [ "$1" = get ] && [ -n "$GITHUB_TOKEN" ]; then printf '%s\\n' username=x-access-token "password=$GITHUB_TOKEN"; fi; }; f`;
|
|
3914
3920
|
defaultCloneRepo = (repo, token, dir) => {
|
|
3915
|
-
fs11.mkdirSync(
|
|
3921
|
+
fs11.mkdirSync(path13.dirname(dir), { recursive: true });
|
|
3916
3922
|
const clone = buildCloneProcess(repo, token);
|
|
3917
|
-
return new Promise((
|
|
3923
|
+
return new Promise((resolve24, reject) => {
|
|
3918
3924
|
const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
|
|
3919
3925
|
env: clone.env,
|
|
3920
3926
|
stdio: "inherit"
|
|
@@ -3934,7 +3940,7 @@ var init_repoWorkspace = __esm({
|
|
|
3934
3940
|
}
|
|
3935
3941
|
} catch {
|
|
3936
3942
|
}
|
|
3937
|
-
|
|
3943
|
+
resolve24();
|
|
3938
3944
|
});
|
|
3939
3945
|
child.on("error", reject);
|
|
3940
3946
|
});
|
|
@@ -4007,7 +4013,7 @@ var init_fetchRepoMcp = __esm({
|
|
|
4007
4013
|
|
|
4008
4014
|
// src/agent.ts
|
|
4009
4015
|
import * as fs12 from "fs";
|
|
4010
|
-
import * as
|
|
4016
|
+
import * as path14 from "path";
|
|
4011
4017
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
4012
4018
|
function classifySubtype(subtype) {
|
|
4013
4019
|
if (!subtype) return "generic_failed";
|
|
@@ -4077,7 +4083,7 @@ function buildAgentEnvironment(baseEnv, repoToken, requestEnvironment) {
|
|
|
4077
4083
|
async function runAgent(opts) {
|
|
4078
4084
|
const ndjsonDir = opts.ndjsonDir ?? agentRunDir(opts.cwd);
|
|
4079
4085
|
fs12.mkdirSync(ndjsonDir, { recursive: true });
|
|
4080
|
-
const ndjsonPath =
|
|
4086
|
+
const ndjsonPath = path14.join(ndjsonDir, "last-run.jsonl");
|
|
4081
4087
|
const env = buildAgentEnvironment(process.env, opts.repoToken, opts.environment);
|
|
4082
4088
|
if (opts.litellmUrl) {
|
|
4083
4089
|
env.ANTHROPIC_BASE_URL = opts.litellmUrl;
|
|
@@ -4085,7 +4091,11 @@ async function runAgent(opts) {
|
|
|
4085
4091
|
}
|
|
4086
4092
|
const startedAt = Date.now();
|
|
4087
4093
|
const turnTimeoutMs = resolveTurnTimeoutMs(opts);
|
|
4088
|
-
const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(
|
|
4094
|
+
const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(
|
|
4095
|
+
completionToolCutoffAt(startedAt, opts.deadlineAtMs),
|
|
4096
|
+
Date.now,
|
|
4097
|
+
opts.outputContract?.path
|
|
4098
|
+
) : null;
|
|
4089
4099
|
let outcome = "failed";
|
|
4090
4100
|
let outcomeKind = "generic_failed";
|
|
4091
4101
|
let errorMessage2;
|
|
@@ -4294,10 +4304,10 @@ async function runAgent(opts) {
|
|
|
4294
4304
|
let timer;
|
|
4295
4305
|
let next;
|
|
4296
4306
|
if (turnTimeoutMs > 0) {
|
|
4297
|
-
const timeoutPromise = new Promise((
|
|
4307
|
+
const timeoutPromise = new Promise((resolve24) => {
|
|
4298
4308
|
timer = setTimeout(() => {
|
|
4299
4309
|
timedOut = true;
|
|
4300
|
-
|
|
4310
|
+
resolve24({ done: true, value: void 0 });
|
|
4301
4311
|
}, turnTimeoutMs);
|
|
4302
4312
|
});
|
|
4303
4313
|
next = await Promise.race([nextPromise, timeoutPromise]);
|
|
@@ -4313,7 +4323,7 @@ async function runAgent(opts) {
|
|
|
4313
4323
|
try {
|
|
4314
4324
|
await Promise.race([
|
|
4315
4325
|
iterator.return(void 0).catch(() => void 0),
|
|
4316
|
-
new Promise((
|
|
4326
|
+
new Promise((resolve24) => setTimeout(resolve24, 1e4).unref())
|
|
4317
4327
|
]);
|
|
4318
4328
|
} catch {
|
|
4319
4329
|
}
|
|
@@ -4520,7 +4530,7 @@ var init_agent = __esm({
|
|
|
4520
4530
|
|
|
4521
4531
|
// src/agents.ts
|
|
4522
4532
|
import * as fs13 from "fs";
|
|
4523
|
-
import * as
|
|
4533
|
+
import * as path15 from "path";
|
|
4524
4534
|
function stripFrontmatter(raw) {
|
|
4525
4535
|
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
4526
4536
|
return (match ? match[1] : raw).trim();
|
|
@@ -4541,7 +4551,7 @@ function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
|
|
|
4541
4551
|
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
4542
4552
|
}
|
|
4543
4553
|
function resolveAgentFile2(cwd, slug, agentsDir = agentsRoot(cwd)) {
|
|
4544
|
-
const localPath =
|
|
4554
|
+
const localPath = path15.resolve(cwd, agentsDir, `${slug}.md`);
|
|
4545
4555
|
if (fs13.existsSync(localPath)) return localPath;
|
|
4546
4556
|
return localPath;
|
|
4547
4557
|
}
|
|
@@ -4575,7 +4585,7 @@ var init_agents = __esm({
|
|
|
4575
4585
|
|
|
4576
4586
|
// src/task-artifacts.ts
|
|
4577
4587
|
import fs14 from "fs";
|
|
4578
|
-
import
|
|
4588
|
+
import path16 from "path";
|
|
4579
4589
|
import posixPath from "path/posix";
|
|
4580
4590
|
function prepareTaskArtifactsDir(cwd, taskId) {
|
|
4581
4591
|
const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -4611,14 +4621,14 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
|
|
|
4611
4621
|
"handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
|
|
4612
4622
|
};
|
|
4613
4623
|
for (const file of TASK_ARTIFACT_FILES) {
|
|
4614
|
-
const full =
|
|
4624
|
+
const full = path16.join(artifacts.absDir, file);
|
|
4615
4625
|
if (!fs14.existsSync(full)) fs14.writeFileSync(full, defaults[file], "utf8");
|
|
4616
4626
|
}
|
|
4617
4627
|
}
|
|
4618
4628
|
function verifyTaskArtifacts(absDir) {
|
|
4619
4629
|
const missing = [];
|
|
4620
4630
|
for (const name of TASK_ARTIFACT_FILES) {
|
|
4621
|
-
const full =
|
|
4631
|
+
const full = path16.join(absDir, name);
|
|
4622
4632
|
try {
|
|
4623
4633
|
const stat = fs14.statSync(full);
|
|
4624
4634
|
if (!stat.isFile() || stat.size === 0) missing.push(name);
|
|
@@ -4636,7 +4646,7 @@ async function persistTaskArtifactsToState(config, _cwd, artifacts) {
|
|
|
4636
4646
|
if (hasStateBackendConfig() && tenantId2) {
|
|
4637
4647
|
const backend = createStateBackendFromEnv();
|
|
4638
4648
|
for (const file of TASK_ARTIFACT_FILES) {
|
|
4639
|
-
const full =
|
|
4649
|
+
const full = path16.join(artifacts.absDir, file);
|
|
4640
4650
|
if (!fs14.existsSync(full)) continue;
|
|
4641
4651
|
const stat = fs14.statSync(full);
|
|
4642
4652
|
if (!stat.isFile() || stat.size === 0) continue;
|
|
@@ -4949,15 +4959,15 @@ function validateWorkflow(value, options = {}) {
|
|
|
4949
4959
|
}
|
|
4950
4960
|
return issues;
|
|
4951
4961
|
}
|
|
4952
|
-
function validateInputBindings(value,
|
|
4962
|
+
function validateInputBindings(value, path59, issues, declaredInputs) {
|
|
4953
4963
|
if (value === void 0) return;
|
|
4954
4964
|
const bindings = asRecord(value);
|
|
4955
4965
|
if (!bindings || Object.keys(bindings).length === 0) {
|
|
4956
|
-
issue(issues, "invalid_inputs",
|
|
4966
|
+
issue(issues, "invalid_inputs", path59, "workflow step inputs must contain at least one named mapping");
|
|
4957
4967
|
return;
|
|
4958
4968
|
}
|
|
4959
4969
|
for (const [name, value2] of Object.entries(bindings)) {
|
|
4960
|
-
const bindingPath = `${
|
|
4970
|
+
const bindingPath = `${path59}.${name}`;
|
|
4961
4971
|
if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(name)) {
|
|
4962
4972
|
issue(issues, "invalid_input_name", bindingPath, `workflow input name ${name} is invalid`);
|
|
4963
4973
|
}
|
|
@@ -4976,7 +4986,7 @@ function validateInputBindings(value, path58, issues, declaredInputs) {
|
|
|
4976
4986
|
}
|
|
4977
4987
|
}
|
|
4978
4988
|
}
|
|
4979
|
-
function validateInputBindingSources(value,
|
|
4989
|
+
function validateInputBindingSources(value, path59, issues, capabilitiesByStep, capabilityOutputs) {
|
|
4980
4990
|
const bindings = asRecord(value);
|
|
4981
4991
|
if (!bindings) return;
|
|
4982
4992
|
for (const [name, rawBinding] of Object.entries(bindings)) {
|
|
@@ -4989,7 +4999,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
|
|
|
4989
4999
|
issue(
|
|
4990
5000
|
issues,
|
|
4991
5001
|
"missing_input_step",
|
|
4992
|
-
`${
|
|
5002
|
+
`${path59}.${name}.from`,
|
|
4993
5003
|
`workflow input mapping references missing step ${sourceStep ?? "<none>"}`
|
|
4994
5004
|
);
|
|
4995
5005
|
continue;
|
|
@@ -5000,7 +5010,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
|
|
|
5000
5010
|
issue(
|
|
5001
5011
|
issues,
|
|
5002
5012
|
"undeclared_step_output",
|
|
5003
|
-
`${
|
|
5013
|
+
`${path59}.${name}.from`,
|
|
5004
5014
|
`workflow input mapping reads ${outputPath}, but step ${sourceStep} does not declare it`
|
|
5005
5015
|
);
|
|
5006
5016
|
}
|
|
@@ -5009,11 +5019,11 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
|
|
|
5009
5019
|
function formatWorkflowValidationIssues(issues) {
|
|
5010
5020
|
return issues.map((entry) => `${entry.path}: ${entry.message}`);
|
|
5011
5021
|
}
|
|
5012
|
-
function validateDataMatch(value,
|
|
5022
|
+
function validateDataMatch(value, path59, issues, capabilityOutputs) {
|
|
5013
5023
|
if (value === void 0) return;
|
|
5014
5024
|
const match = asRecord(value);
|
|
5015
5025
|
if (!match || Object.keys(match).length === 0) {
|
|
5016
|
-
issue(issues, "invalid_condition",
|
|
5026
|
+
issue(issues, "invalid_condition", path59, "workflow condition must contain at least one match");
|
|
5017
5027
|
return;
|
|
5018
5028
|
}
|
|
5019
5029
|
for (const [field, expected] of Object.entries(match)) {
|
|
@@ -5021,7 +5031,7 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
|
|
|
5021
5031
|
issue(
|
|
5022
5032
|
issues,
|
|
5023
5033
|
"invalid_data_path",
|
|
5024
|
-
`${
|
|
5034
|
+
`${path59}.${field}`,
|
|
5025
5035
|
`workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
|
|
5026
5036
|
);
|
|
5027
5037
|
}
|
|
@@ -5029,12 +5039,12 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
|
|
|
5029
5039
|
issue(
|
|
5030
5040
|
issues,
|
|
5031
5041
|
"undeclared_result_path",
|
|
5032
|
-
`${
|
|
5042
|
+
`${path59}.${field}`,
|
|
5033
5043
|
`workflow condition reads ${field}, but the source capability does not declare it`
|
|
5034
5044
|
);
|
|
5035
5045
|
}
|
|
5036
5046
|
if (!isComparable(expected)) {
|
|
5037
|
-
issue(issues, "invalid_condition_value", `${
|
|
5047
|
+
issue(issues, "invalid_condition_value", `${path59}.${field}`, "workflow condition value must be a JSON scalar");
|
|
5038
5048
|
}
|
|
5039
5049
|
}
|
|
5040
5050
|
}
|
|
@@ -5058,8 +5068,8 @@ function isJsonValue(value) {
|
|
|
5058
5068
|
if (!value || typeof value !== "object") return false;
|
|
5059
5069
|
return Object.values(value).every(isJsonValue);
|
|
5060
5070
|
}
|
|
5061
|
-
function issue(issues, code,
|
|
5062
|
-
issues.push({ code, path:
|
|
5071
|
+
function issue(issues, code, path59, message) {
|
|
5072
|
+
issues.push({ code, path: path59, message });
|
|
5063
5073
|
}
|
|
5064
5074
|
var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SAFE_INPUT_SOURCE, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
|
|
5065
5075
|
var init_workflowValidation = __esm({
|
|
@@ -5093,7 +5103,7 @@ var init_workflowValidation = __esm({
|
|
|
5093
5103
|
|
|
5094
5104
|
// src/workflowDefinitions.ts
|
|
5095
5105
|
import * as fs20 from "fs";
|
|
5096
|
-
import * as
|
|
5106
|
+
import * as path22 from "path";
|
|
5097
5107
|
function isWorkflowDefinitionId(value) {
|
|
5098
5108
|
return WORKFLOW_ID_PATTERN.test(value);
|
|
5099
5109
|
}
|
|
@@ -5138,8 +5148,8 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
5138
5148
|
const root = cwd ?? process.cwd();
|
|
5139
5149
|
const relativePath = workflowDefinitionPath(id);
|
|
5140
5150
|
const candidates = [
|
|
5141
|
-
|
|
5142
|
-
|
|
5151
|
+
path22.join(root, ".kody-engine", "runtime", relativePath),
|
|
5152
|
+
path22.join(definitionsRoot(root), relativePath)
|
|
5143
5153
|
];
|
|
5144
5154
|
for (const filePath of candidates) {
|
|
5145
5155
|
if (!fs20.existsSync(filePath)) continue;
|
|
@@ -5151,7 +5161,7 @@ function readWorkflowDefinition(_config, cwd, id) {
|
|
|
5151
5161
|
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
5152
5162
|
return {
|
|
5153
5163
|
slug: id,
|
|
5154
|
-
dir:
|
|
5164
|
+
dir: path22.dirname(source),
|
|
5155
5165
|
profilePath: source,
|
|
5156
5166
|
bodyPath: source,
|
|
5157
5167
|
title: workflow.name,
|
|
@@ -5752,7 +5762,7 @@ var init_lifecycles = __esm({
|
|
|
5752
5762
|
// src/profile.ts
|
|
5753
5763
|
import { createHash as createHash3 } from "crypto";
|
|
5754
5764
|
import * as fs24 from "fs";
|
|
5755
|
-
import * as
|
|
5765
|
+
import * as path24 from "path";
|
|
5756
5766
|
function loadProfile(profilePath) {
|
|
5757
5767
|
if (!fs24.existsSync(profilePath)) {
|
|
5758
5768
|
throw new ProfileError(profilePath, "file not found");
|
|
@@ -5771,7 +5781,7 @@ function loadProfile(profilePath) {
|
|
|
5771
5781
|
const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
|
|
5772
5782
|
if (unknownKeys.length > 0) {
|
|
5773
5783
|
process.stderr.write(
|
|
5774
|
-
`[kody profile] ${
|
|
5784
|
+
`[kody profile] ${path24.basename(path24.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
|
|
5775
5785
|
`
|
|
5776
5786
|
);
|
|
5777
5787
|
}
|
|
@@ -5781,7 +5791,7 @@ function loadProfile(profilePath) {
|
|
|
5781
5791
|
if (!refPath) {
|
|
5782
5792
|
throw new ProfileError(profilePath, `capability references unknown implementation '${execRef}'`);
|
|
5783
5793
|
}
|
|
5784
|
-
if (
|
|
5794
|
+
if (path24.resolve(refPath) === path24.resolve(profilePath)) {
|
|
5785
5795
|
} else {
|
|
5786
5796
|
const base = loadProfile(refPath);
|
|
5787
5797
|
return {
|
|
@@ -5879,8 +5889,8 @@ function loadProfile(profilePath) {
|
|
|
5879
5889
|
// Phase 5 in-process handoff opt-in. Default false; containers
|
|
5880
5890
|
// flip to true after end-to-end verification.
|
|
5881
5891
|
preloadContext: r.preloadContext === true,
|
|
5882
|
-
dir:
|
|
5883
|
-
promptTemplates: readPromptTemplates(
|
|
5892
|
+
dir: path24.dirname(profilePath),
|
|
5893
|
+
promptTemplates: readPromptTemplates(path24.dirname(profilePath))
|
|
5884
5894
|
};
|
|
5885
5895
|
if (lifecycle) {
|
|
5886
5896
|
applyLifecycle(profile, profilePath);
|
|
@@ -5915,19 +5925,19 @@ function loadProfile(profilePath) {
|
|
|
5915
5925
|
return profile;
|
|
5916
5926
|
}
|
|
5917
5927
|
function compileRuntimeDocument(runtimePath, document) {
|
|
5918
|
-
if (
|
|
5928
|
+
if (path24.basename(runtimePath) !== "runtime.json") return document;
|
|
5919
5929
|
if (document.adapter !== "kody-engine-profile") {
|
|
5920
5930
|
throw new ProfileError(runtimePath, "unsupported runtime adapter document");
|
|
5921
5931
|
}
|
|
5922
|
-
const implementationDir =
|
|
5923
|
-
const implementation = readJsonObject(
|
|
5924
|
-
const definitionsRoot2 =
|
|
5932
|
+
const implementationDir = path24.dirname(runtimePath);
|
|
5933
|
+
const implementation = readJsonObject(path24.join(implementationDir, "definition.json"), "Implementation definition");
|
|
5934
|
+
const definitionsRoot2 = path24.dirname(path24.dirname(implementationDir));
|
|
5925
5935
|
const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
|
|
5926
5936
|
if (typeof capabilityId !== "string" || !capabilityId) {
|
|
5927
5937
|
throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
|
|
5928
5938
|
}
|
|
5929
5939
|
const capability = readJsonObject(
|
|
5930
|
-
|
|
5940
|
+
path24.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
|
|
5931
5941
|
"Capability definition"
|
|
5932
5942
|
);
|
|
5933
5943
|
const {
|
|
@@ -5988,13 +5998,13 @@ function readPromptTemplates(dir) {
|
|
|
5988
5998
|
} catch {
|
|
5989
5999
|
}
|
|
5990
6000
|
};
|
|
5991
|
-
read(
|
|
5992
|
-
read(
|
|
5993
|
-
read(
|
|
6001
|
+
read(path24.join(dir, "prompt.md"));
|
|
6002
|
+
read(path24.join(dir, "capability.md"));
|
|
6003
|
+
read(path24.join(dir, "capability.md"));
|
|
5994
6004
|
try {
|
|
5995
|
-
const promptsDir =
|
|
6005
|
+
const promptsDir = path24.join(dir, "prompts");
|
|
5996
6006
|
for (const ent of fs24.readdirSync(promptsDir)) {
|
|
5997
|
-
if (ent.endsWith(".md")) read(
|
|
6007
|
+
if (ent.endsWith(".md")) read(path24.join(promptsDir, ent));
|
|
5998
6008
|
}
|
|
5999
6009
|
} catch {
|
|
6000
6010
|
}
|
|
@@ -6772,11 +6782,11 @@ var init_state = __esm({
|
|
|
6772
6782
|
|
|
6773
6783
|
// src/prompt.ts
|
|
6774
6784
|
import * as fs25 from "fs";
|
|
6775
|
-
import * as
|
|
6785
|
+
import * as path25 from "path";
|
|
6776
6786
|
function loadProjectConventions(projectDir) {
|
|
6777
6787
|
const out = [];
|
|
6778
6788
|
for (const rel of CONVENTION_FILES) {
|
|
6779
|
-
const abs =
|
|
6789
|
+
const abs = path25.join(projectDir, rel);
|
|
6780
6790
|
if (!fs25.existsSync(abs)) continue;
|
|
6781
6791
|
let content;
|
|
6782
6792
|
try {
|
|
@@ -7016,7 +7026,7 @@ __export(loadMemoryContext_exports, {
|
|
|
7016
7026
|
loadMemoryContext: () => loadMemoryContext
|
|
7017
7027
|
});
|
|
7018
7028
|
import * as fs26 from "fs";
|
|
7019
|
-
import * as
|
|
7029
|
+
import * as path26 from "path";
|
|
7020
7030
|
function formatBlockFromBackend(docs) {
|
|
7021
7031
|
const pages = docs.flatMap((record2) => {
|
|
7022
7032
|
if (!record2.doc || typeof record2.doc !== "object") return [];
|
|
@@ -7050,10 +7060,10 @@ function collectPages(memoryAbs) {
|
|
|
7050
7060
|
return;
|
|
7051
7061
|
}
|
|
7052
7062
|
const fm = raw.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
7053
|
-
const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ??
|
|
7063
|
+
const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path26.basename(file, ".md");
|
|
7054
7064
|
const updated = fm?.[1]?.match(/^updated:\s*([0-9T:.+\-Z]+)/m)?.[1]?.trim() ?? "";
|
|
7055
7065
|
out.push({
|
|
7056
|
-
relPath:
|
|
7066
|
+
relPath: path26.relative(memoryAbs, file),
|
|
7057
7067
|
title,
|
|
7058
7068
|
updated,
|
|
7059
7069
|
content: raw.length > PER_PAGE_MAX_BYTES ? raw.slice(0, PER_PAGE_MAX_BYTES) + TRUNCATED_SUFFIX2 : raw,
|
|
@@ -7127,7 +7137,7 @@ function walkMd(root, visit) {
|
|
|
7127
7137
|
}
|
|
7128
7138
|
for (const name of names) {
|
|
7129
7139
|
if (name.startsWith(".")) continue;
|
|
7130
|
-
const full =
|
|
7140
|
+
const full = path26.join(dir, name);
|
|
7131
7141
|
let stat;
|
|
7132
7142
|
try {
|
|
7133
7143
|
stat = fs26.statSync(full);
|
|
@@ -7165,7 +7175,7 @@ var init_loadMemoryContext = __esm({
|
|
|
7165
7175
|
}
|
|
7166
7176
|
return;
|
|
7167
7177
|
}
|
|
7168
|
-
const memoryAbs =
|
|
7178
|
+
const memoryAbs = path26.join(ctx.cwd, MEMORY_DIR_RELATIVE);
|
|
7169
7179
|
if (!fs26.existsSync(memoryAbs)) {
|
|
7170
7180
|
ctx.data.memoryContext = "";
|
|
7171
7181
|
return;
|
|
@@ -7681,7 +7691,7 @@ import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
|
|
|
7681
7691
|
import * as fs28 from "fs";
|
|
7682
7692
|
import * as net from "net";
|
|
7683
7693
|
import * as os4 from "os";
|
|
7684
|
-
import * as
|
|
7694
|
+
import * as path27 from "path";
|
|
7685
7695
|
async function checkLitellmHealth(url) {
|
|
7686
7696
|
try {
|
|
7687
7697
|
const response = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3e3) });
|
|
@@ -7794,10 +7804,10 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
|
|
|
7794
7804
|
const spawnProxy = () => {
|
|
7795
7805
|
const portMatch = activeUrl.match(/:(\d+)/);
|
|
7796
7806
|
const port = portMatch ? portMatch[1] : "4000";
|
|
7797
|
-
const configPath =
|
|
7807
|
+
const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
|
|
7798
7808
|
fs28.writeFileSync(configPath, generateLitellmConfigYaml(model));
|
|
7799
7809
|
const args = ["--config", configPath, "--port", port];
|
|
7800
|
-
const nextLogPath =
|
|
7810
|
+
const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
|
|
7801
7811
|
const outFd = fs28.openSync(nextLogPath, "w");
|
|
7802
7812
|
child = spawn4(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
|
|
7803
7813
|
fs28.closeSync(outFd);
|
|
@@ -7887,17 +7897,17 @@ async function nextAvailableLitellmUrl(url) {
|
|
|
7887
7897
|
throw new Error(`no free LiteLLM port found after ${startPort}`);
|
|
7888
7898
|
}
|
|
7889
7899
|
function canListen(port, host) {
|
|
7890
|
-
return new Promise((
|
|
7900
|
+
return new Promise((resolve24) => {
|
|
7891
7901
|
const server = net.createServer();
|
|
7892
|
-
server.once("error", () =>
|
|
7902
|
+
server.once("error", () => resolve24(false));
|
|
7893
7903
|
server.once("listening", () => {
|
|
7894
|
-
server.close(() =>
|
|
7904
|
+
server.close(() => resolve24(true));
|
|
7895
7905
|
});
|
|
7896
7906
|
server.listen(port, host);
|
|
7897
7907
|
});
|
|
7898
7908
|
}
|
|
7899
7909
|
function readDotenvApiKeys(projectDir) {
|
|
7900
|
-
const dotenvPath =
|
|
7910
|
+
const dotenvPath = path27.join(projectDir, ".env");
|
|
7901
7911
|
if (!fs28.existsSync(dotenvPath)) return {};
|
|
7902
7912
|
const result = {};
|
|
7903
7913
|
for (const rawLine of fs28.readFileSync(dotenvPath, "utf-8").split("\n")) {
|
|
@@ -8560,7 +8570,7 @@ var init_pushWithRetry = __esm({
|
|
|
8560
8570
|
// src/commit.ts
|
|
8561
8571
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
8562
8572
|
import * as fs29 from "fs";
|
|
8563
|
-
import * as
|
|
8573
|
+
import * as path28 from "path";
|
|
8564
8574
|
function isGitHubYamlPath(filePath) {
|
|
8565
8575
|
const normalized = filePath.replace(/^\.\/+/, "");
|
|
8566
8576
|
return normalized.startsWith(".github/") && /\.ya?ml$/i.test(normalized);
|
|
@@ -8602,18 +8612,18 @@ function ensureGitIdentity(cwd) {
|
|
|
8602
8612
|
}
|
|
8603
8613
|
function abortUnfinishedGitOps(cwd) {
|
|
8604
8614
|
const aborted = [];
|
|
8605
|
-
const gitDir =
|
|
8615
|
+
const gitDir = path28.join(cwd ?? process.cwd(), ".git");
|
|
8606
8616
|
if (!fs29.existsSync(gitDir)) return aborted;
|
|
8607
|
-
if (fs29.existsSync(
|
|
8617
|
+
if (fs29.existsSync(path28.join(gitDir, "MERGE_HEAD"))) {
|
|
8608
8618
|
if (tryGit(["merge", "--abort"], cwd)) aborted.push("merge");
|
|
8609
8619
|
}
|
|
8610
|
-
if (fs29.existsSync(
|
|
8620
|
+
if (fs29.existsSync(path28.join(gitDir, "CHERRY_PICK_HEAD"))) {
|
|
8611
8621
|
if (tryGit(["cherry-pick", "--abort"], cwd)) aborted.push("cherry-pick");
|
|
8612
8622
|
}
|
|
8613
|
-
if (fs29.existsSync(
|
|
8623
|
+
if (fs29.existsSync(path28.join(gitDir, "REVERT_HEAD"))) {
|
|
8614
8624
|
if (tryGit(["revert", "--abort"], cwd)) aborted.push("revert");
|
|
8615
8625
|
}
|
|
8616
|
-
if (fs29.existsSync(
|
|
8626
|
+
if (fs29.existsSync(path28.join(gitDir, "rebase-merge")) || fs29.existsSync(path28.join(gitDir, "rebase-apply"))) {
|
|
8617
8627
|
if (tryGit(["rebase", "--abort"], cwd)) aborted.push("rebase");
|
|
8618
8628
|
}
|
|
8619
8629
|
try {
|
|
@@ -8670,7 +8680,7 @@ function normalizeCommitMessage(raw) {
|
|
|
8670
8680
|
function commitAndPush(branch, agentMessage, cwd) {
|
|
8671
8681
|
const allChanged = listChangedFiles(cwd);
|
|
8672
8682
|
const allowedFiles = allChanged.filter((f) => !isForbiddenPath(f));
|
|
8673
|
-
const mergeHeadExists = fs29.existsSync(
|
|
8683
|
+
const mergeHeadExists = fs29.existsSync(path28.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
|
|
8674
8684
|
if (allowedFiles.length === 0 && !mergeHeadExists) {
|
|
8675
8685
|
return { committed: false, pushed: false, sha: "", message: "" };
|
|
8676
8686
|
}
|
|
@@ -9314,9 +9324,9 @@ import * as fs30 from "fs";
|
|
|
9314
9324
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
9315
9325
|
const logs = goalRunLogs(data);
|
|
9316
9326
|
const existing = logs[goalId];
|
|
9317
|
-
const
|
|
9327
|
+
const path59 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
9318
9328
|
logs[goalId] = {
|
|
9319
|
-
path:
|
|
9329
|
+
path: path59,
|
|
9320
9330
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
9321
9331
|
};
|
|
9322
9332
|
}
|
|
@@ -9764,7 +9774,7 @@ var init_stateStore = __esm({
|
|
|
9764
9774
|
|
|
9765
9775
|
// src/goal/targetLoopResolution.ts
|
|
9766
9776
|
import * as fs31 from "fs";
|
|
9767
|
-
import * as
|
|
9777
|
+
import * as path29 from "path";
|
|
9768
9778
|
async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
|
|
9769
9779
|
const targetId = loopGoal.loopTarget?.id.trim() ?? "";
|
|
9770
9780
|
assertSafeGoalId(targetId, "loop target");
|
|
@@ -9842,7 +9852,7 @@ function goalInstanceTime(state) {
|
|
|
9842
9852
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
9843
9853
|
}
|
|
9844
9854
|
function loadGoalTemplate(cwd, targetId) {
|
|
9845
|
-
return readJsonObject2(
|
|
9855
|
+
return readJsonObject2(path29.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
|
|
9846
9856
|
}
|
|
9847
9857
|
function readJsonObject2(filePath) {
|
|
9848
9858
|
if (!fs31.existsSync(filePath)) return null;
|
|
@@ -10193,15 +10203,15 @@ var init_backendStateBackend = __esm({
|
|
|
10193
10203
|
this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
|
|
10194
10204
|
}
|
|
10195
10205
|
async load(slug) {
|
|
10196
|
-
const
|
|
10206
|
+
const path59 = stateFilePath(this.jobsDir, slug);
|
|
10197
10207
|
const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
|
|
10198
10208
|
if (!loaded) {
|
|
10199
|
-
return { path:
|
|
10209
|
+
return { path: path59, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
10200
10210
|
}
|
|
10201
10211
|
if (!isStateEnvelope(loaded.doc)) {
|
|
10202
10212
|
throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
|
|
10203
10213
|
}
|
|
10204
|
-
return { path:
|
|
10214
|
+
return { path: path59, handle: loaded.updatedAt, state: loaded.doc, created: false };
|
|
10205
10215
|
}
|
|
10206
10216
|
async save(loaded, next) {
|
|
10207
10217
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
|
|
@@ -10222,7 +10232,7 @@ var init_backendStateBackend = __esm({
|
|
|
10222
10232
|
|
|
10223
10233
|
// src/scripts/jobState/localFileBackend.ts
|
|
10224
10234
|
import * as fs32 from "fs";
|
|
10225
|
-
import * as
|
|
10235
|
+
import * as path30 from "path";
|
|
10226
10236
|
function sanitizeKey(s) {
|
|
10227
10237
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
10228
10238
|
}
|
|
@@ -10278,7 +10288,7 @@ var init_localFileBackend = __esm({
|
|
|
10278
10288
|
if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
|
|
10279
10289
|
this.cwd = opts.cwd;
|
|
10280
10290
|
this.jobsDir = opts.jobsDir;
|
|
10281
|
-
this.absDir =
|
|
10291
|
+
this.absDir = path30.resolve(opts.cwd, opts.jobsDir);
|
|
10282
10292
|
this.owner = opts.owner;
|
|
10283
10293
|
this.repo = opts.repo;
|
|
10284
10294
|
this.cache = opts.cache ?? defaultCacheAdapter();
|
|
@@ -10338,7 +10348,7 @@ var init_localFileBackend = __esm({
|
|
|
10338
10348
|
}
|
|
10339
10349
|
load(slug) {
|
|
10340
10350
|
const relPath = stateFilePath(this.jobsDir, slug);
|
|
10341
|
-
const absPath =
|
|
10351
|
+
const absPath = path30.resolve(this.cwd, relPath);
|
|
10342
10352
|
if (!fs32.existsSync(absPath)) {
|
|
10343
10353
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
10344
10354
|
}
|
|
@@ -10359,8 +10369,8 @@ var init_localFileBackend = __esm({
|
|
|
10359
10369
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
10360
10370
|
return false;
|
|
10361
10371
|
}
|
|
10362
|
-
const absPath =
|
|
10363
|
-
fs32.mkdirSync(
|
|
10372
|
+
const absPath = path30.resolve(this.cwd, loaded.path);
|
|
10373
|
+
fs32.mkdirSync(path30.dirname(absPath), { recursive: true });
|
|
10364
10374
|
const body = `${JSON.stringify(next, null, 2)}
|
|
10365
10375
|
`;
|
|
10366
10376
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
@@ -10397,7 +10407,7 @@ var init_jobState = __esm({
|
|
|
10397
10407
|
});
|
|
10398
10408
|
|
|
10399
10409
|
// src/scripts/goalCapabilityScheduling.ts
|
|
10400
|
-
import * as
|
|
10410
|
+
import * as path31 from "path";
|
|
10401
10411
|
function isCapabilityCadenceGoal(goal, extra) {
|
|
10402
10412
|
return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
|
|
10403
10413
|
}
|
|
@@ -10453,7 +10463,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
10453
10463
|
}
|
|
10454
10464
|
async function planGoalCapabilitySchedule(opts) {
|
|
10455
10465
|
const jobsDir = opts.jobsDir ?? capabilitiesRoot(opts.cwd);
|
|
10456
|
-
const jobsRoot =
|
|
10466
|
+
const jobsRoot = path31.resolve(opts.cwd, jobsDir);
|
|
10457
10467
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
10458
10468
|
const at = now.toISOString();
|
|
10459
10469
|
const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
|
|
@@ -12270,7 +12280,7 @@ var init_classifyByLabel = __esm({
|
|
|
12270
12280
|
// src/scripts/commitAndPush.ts
|
|
12271
12281
|
import { createHash as createHash5 } from "crypto";
|
|
12272
12282
|
import * as fs33 from "fs";
|
|
12273
|
-
import * as
|
|
12283
|
+
import * as path32 from "path";
|
|
12274
12284
|
function sentinelPathForStage(cwd, profileName, workflowExecutionKey) {
|
|
12275
12285
|
const runId = resolveRunId();
|
|
12276
12286
|
const executionSuffix = typeof workflowExecutionKey === "string" && workflowExecutionKey.length > 0 ? `-${createHash5("sha256").update(workflowExecutionKey).digest("hex").slice(0, 16)}` : "";
|
|
@@ -12354,7 +12364,7 @@ var init_commitAndPush = __esm({
|
|
|
12354
12364
|
const result = ctx.data.commitResult;
|
|
12355
12365
|
if (sentinel && result?.committed) {
|
|
12356
12366
|
try {
|
|
12357
|
-
fs33.mkdirSync(
|
|
12367
|
+
fs33.mkdirSync(path32.dirname(sentinel), { recursive: true });
|
|
12358
12368
|
fs33.writeFileSync(
|
|
12359
12369
|
sentinel,
|
|
12360
12370
|
JSON.stringify(
|
|
@@ -12450,7 +12460,7 @@ var init_commitGoalState = __esm({
|
|
|
12450
12460
|
|
|
12451
12461
|
// src/scripts/composePrompt.ts
|
|
12452
12462
|
import * as fs34 from "fs";
|
|
12453
|
-
import * as
|
|
12463
|
+
import * as path33 from "path";
|
|
12454
12464
|
function fenceUntrusted(value) {
|
|
12455
12465
|
if (value.trim().length === 0) return value;
|
|
12456
12466
|
const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
|
|
@@ -12574,10 +12584,10 @@ var init_composePrompt = __esm({
|
|
|
12574
12584
|
const explicit = ctx.data.promptTemplate;
|
|
12575
12585
|
const mode = ctx.args.mode;
|
|
12576
12586
|
const candidates = [
|
|
12577
|
-
explicit ?
|
|
12578
|
-
mode ?
|
|
12579
|
-
|
|
12580
|
-
|
|
12587
|
+
explicit ? path33.join(profile.dir, explicit) : null,
|
|
12588
|
+
mode ? path33.join(profile.dir, "prompts", `${mode}.md`) : null,
|
|
12589
|
+
path33.join(profile.dir, "prompt.md"),
|
|
12590
|
+
path33.join(profile.dir, "capability.md")
|
|
12581
12591
|
].filter(Boolean);
|
|
12582
12592
|
let templatePath = "";
|
|
12583
12593
|
let template = "";
|
|
@@ -13337,14 +13347,14 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
13337
13347
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
13338
13348
|
import * as fs35 from "fs";
|
|
13339
13349
|
import * as os5 from "os";
|
|
13340
|
-
import * as
|
|
13350
|
+
import * as path34 from "path";
|
|
13341
13351
|
var diagMcp;
|
|
13342
13352
|
var init_diagMcp = __esm({
|
|
13343
13353
|
"src/scripts/diagMcp.ts"() {
|
|
13344
13354
|
"use strict";
|
|
13345
13355
|
diagMcp = async (_ctx) => {
|
|
13346
13356
|
const home = os5.homedir();
|
|
13347
|
-
const cacheDir =
|
|
13357
|
+
const cacheDir = path34.join(home, ".cache", "ms-playwright");
|
|
13348
13358
|
let entries = [];
|
|
13349
13359
|
try {
|
|
13350
13360
|
entries = fs35.readdirSync(cacheDir);
|
|
@@ -13376,12 +13386,12 @@ var init_diagMcp = __esm({
|
|
|
13376
13386
|
|
|
13377
13387
|
// src/scripts/frameworkDetectors.ts
|
|
13378
13388
|
import * as fs36 from "fs";
|
|
13379
|
-
import * as
|
|
13389
|
+
import * as path35 from "path";
|
|
13380
13390
|
function detectFrameworks(cwd) {
|
|
13381
13391
|
const out = [];
|
|
13382
13392
|
let deps = {};
|
|
13383
13393
|
try {
|
|
13384
|
-
const pkg = JSON.parse(fs36.readFileSync(
|
|
13394
|
+
const pkg = JSON.parse(fs36.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
|
|
13385
13395
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
13386
13396
|
} catch {
|
|
13387
13397
|
return out;
|
|
@@ -13418,14 +13428,14 @@ function detectFrameworks(cwd) {
|
|
|
13418
13428
|
}
|
|
13419
13429
|
function findFile(cwd, candidates) {
|
|
13420
13430
|
for (const c of candidates) {
|
|
13421
|
-
if (fs36.existsSync(
|
|
13431
|
+
if (fs36.existsSync(path35.join(cwd, c))) return c;
|
|
13422
13432
|
}
|
|
13423
13433
|
return null;
|
|
13424
13434
|
}
|
|
13425
13435
|
function discoverPayloadCollections(cwd) {
|
|
13426
13436
|
const out = [];
|
|
13427
13437
|
for (const dir of COLLECTION_DIRS) {
|
|
13428
|
-
const full =
|
|
13438
|
+
const full = path35.join(cwd, dir);
|
|
13429
13439
|
if (!fs36.existsSync(full)) continue;
|
|
13430
13440
|
let files;
|
|
13431
13441
|
try {
|
|
@@ -13435,7 +13445,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
13435
13445
|
}
|
|
13436
13446
|
for (const file of files) {
|
|
13437
13447
|
try {
|
|
13438
|
-
const filePath =
|
|
13448
|
+
const filePath = path35.join(full, file);
|
|
13439
13449
|
const content = fs36.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
13440
13450
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
13441
13451
|
if (!slugMatch) continue;
|
|
@@ -13450,7 +13460,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
13450
13460
|
out.push({
|
|
13451
13461
|
name,
|
|
13452
13462
|
slug,
|
|
13453
|
-
filePath:
|
|
13463
|
+
filePath: path35.relative(cwd, filePath),
|
|
13454
13464
|
fields: fields.slice(0, 20),
|
|
13455
13465
|
hasAdmin
|
|
13456
13466
|
});
|
|
@@ -13463,7 +13473,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
13463
13473
|
function discoverAdminComponents(cwd, collections) {
|
|
13464
13474
|
const out = [];
|
|
13465
13475
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
13466
|
-
const full =
|
|
13476
|
+
const full = path35.join(cwd, dir);
|
|
13467
13477
|
if (!fs36.existsSync(full)) continue;
|
|
13468
13478
|
let entries;
|
|
13469
13479
|
try {
|
|
@@ -13472,19 +13482,19 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
13472
13482
|
continue;
|
|
13473
13483
|
}
|
|
13474
13484
|
for (const entry of entries) {
|
|
13475
|
-
const entryPath =
|
|
13485
|
+
const entryPath = path35.join(full, entry.name);
|
|
13476
13486
|
let name;
|
|
13477
13487
|
let filePath;
|
|
13478
13488
|
if (entry.isDirectory()) {
|
|
13479
13489
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
13480
|
-
(f) => fs36.existsSync(
|
|
13490
|
+
(f) => fs36.existsSync(path35.join(entryPath, f))
|
|
13481
13491
|
);
|
|
13482
13492
|
if (!indexFile) continue;
|
|
13483
13493
|
name = entry.name;
|
|
13484
|
-
filePath =
|
|
13494
|
+
filePath = path35.relative(cwd, path35.join(entryPath, indexFile));
|
|
13485
13495
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
13486
13496
|
name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
|
|
13487
|
-
filePath =
|
|
13497
|
+
filePath = path35.relative(cwd, entryPath);
|
|
13488
13498
|
} else {
|
|
13489
13499
|
continue;
|
|
13490
13500
|
}
|
|
@@ -13492,7 +13502,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
13492
13502
|
if (collections) {
|
|
13493
13503
|
for (const col of collections) {
|
|
13494
13504
|
try {
|
|
13495
|
-
const colContent = fs36.readFileSync(
|
|
13505
|
+
const colContent = fs36.readFileSync(path35.join(cwd, col.filePath), "utf-8");
|
|
13496
13506
|
if (colContent.includes(name)) {
|
|
13497
13507
|
usedInCollection = col.slug;
|
|
13498
13508
|
break;
|
|
@@ -13510,7 +13520,7 @@ function scanApiRoutes(cwd) {
|
|
|
13510
13520
|
const out = [];
|
|
13511
13521
|
const appDirs = ["src/app", "app"];
|
|
13512
13522
|
for (const appDir of appDirs) {
|
|
13513
|
-
const apiDir =
|
|
13523
|
+
const apiDir = path35.join(cwd, appDir, "api");
|
|
13514
13524
|
if (!fs36.existsSync(apiDir)) continue;
|
|
13515
13525
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
13516
13526
|
break;
|
|
@@ -13527,7 +13537,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
13527
13537
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
13528
13538
|
if (routeFile) {
|
|
13529
13539
|
try {
|
|
13530
|
-
const content = fs36.readFileSync(
|
|
13540
|
+
const content = fs36.readFileSync(path35.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
13531
13541
|
const methods = HTTP_METHODS.filter(
|
|
13532
13542
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
13533
13543
|
);
|
|
@@ -13535,7 +13545,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
13535
13545
|
out.push({
|
|
13536
13546
|
path: prefix,
|
|
13537
13547
|
methods,
|
|
13538
|
-
filePath:
|
|
13548
|
+
filePath: path35.relative(cwd, path35.join(dir, routeFile.name))
|
|
13539
13549
|
});
|
|
13540
13550
|
}
|
|
13541
13551
|
} catch {
|
|
@@ -13546,7 +13556,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
13546
13556
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
13547
13557
|
let segment = entry.name;
|
|
13548
13558
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
13549
|
-
walkApiRoutes(
|
|
13559
|
+
walkApiRoutes(path35.join(dir, entry.name), prefix, cwd, out);
|
|
13550
13560
|
continue;
|
|
13551
13561
|
}
|
|
13552
13562
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -13554,13 +13564,13 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
13554
13564
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
13555
13565
|
segment = `:${segment.slice(1, -1)}`;
|
|
13556
13566
|
}
|
|
13557
|
-
walkApiRoutes(
|
|
13567
|
+
walkApiRoutes(path35.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
|
|
13558
13568
|
}
|
|
13559
13569
|
}
|
|
13560
13570
|
function scanEnvVars(cwd) {
|
|
13561
13571
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
13562
13572
|
for (const envFile of candidates) {
|
|
13563
|
-
const envPath =
|
|
13573
|
+
const envPath = path35.join(cwd, envFile);
|
|
13564
13574
|
if (!fs36.existsSync(envPath)) continue;
|
|
13565
13575
|
try {
|
|
13566
13576
|
const content = fs36.readFileSync(envPath, "utf-8");
|
|
@@ -13609,7 +13619,7 @@ var init_frameworkDetectors = __esm({
|
|
|
13609
13619
|
|
|
13610
13620
|
// src/scripts/discoverQaContext.ts
|
|
13611
13621
|
import * as fs37 from "fs";
|
|
13612
|
-
import * as
|
|
13622
|
+
import * as path36 from "path";
|
|
13613
13623
|
function runQaDiscovery(cwd) {
|
|
13614
13624
|
const out = {
|
|
13615
13625
|
routes: [],
|
|
@@ -13640,9 +13650,9 @@ function runQaDiscovery(cwd) {
|
|
|
13640
13650
|
}
|
|
13641
13651
|
function detectDevServer(cwd, out) {
|
|
13642
13652
|
try {
|
|
13643
|
-
const pkg = JSON.parse(fs37.readFileSync(
|
|
13653
|
+
const pkg = JSON.parse(fs37.readFileSync(path36.join(cwd, "package.json"), "utf-8"));
|
|
13644
13654
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
13645
|
-
const pm = fs37.existsSync(
|
|
13655
|
+
const pm = fs37.existsSync(path36.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs37.existsSync(path36.join(cwd, "yarn.lock")) ? "yarn" : fs37.existsSync(path36.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
13646
13656
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
13647
13657
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
13648
13658
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -13652,7 +13662,7 @@ function detectDevServer(cwd, out) {
|
|
|
13652
13662
|
function scanFrontendRoutes(cwd, out) {
|
|
13653
13663
|
const appDirs = ["src/app", "app"];
|
|
13654
13664
|
for (const appDir of appDirs) {
|
|
13655
|
-
const full =
|
|
13665
|
+
const full = path36.join(cwd, appDir);
|
|
13656
13666
|
if (!fs37.existsSync(full)) continue;
|
|
13657
13667
|
walkFrontendRoutes(full, "", out);
|
|
13658
13668
|
break;
|
|
@@ -13678,7 +13688,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
13678
13688
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
13679
13689
|
let segment = entry.name;
|
|
13680
13690
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
13681
|
-
walkFrontendRoutes(
|
|
13691
|
+
walkFrontendRoutes(path36.join(dir, entry.name), prefix, out);
|
|
13682
13692
|
continue;
|
|
13683
13693
|
}
|
|
13684
13694
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -13686,7 +13696,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
13686
13696
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
13687
13697
|
segment = `:${segment.slice(1, -1)}`;
|
|
13688
13698
|
}
|
|
13689
|
-
walkFrontendRoutes(
|
|
13699
|
+
walkFrontendRoutes(path36.join(dir, entry.name), `${prefix}/${segment}`, out);
|
|
13690
13700
|
}
|
|
13691
13701
|
}
|
|
13692
13702
|
function detectAuthFiles(cwd, out) {
|
|
@@ -13703,13 +13713,13 @@ function detectAuthFiles(cwd, out) {
|
|
|
13703
13713
|
"src/app/api/oauth"
|
|
13704
13714
|
];
|
|
13705
13715
|
for (const c of candidates) {
|
|
13706
|
-
if (fs37.existsSync(
|
|
13716
|
+
if (fs37.existsSync(path36.join(cwd, c))) out.authFiles.push(c);
|
|
13707
13717
|
}
|
|
13708
13718
|
}
|
|
13709
13719
|
function detectRoles(cwd, out) {
|
|
13710
13720
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
13711
13721
|
for (const rp of rolePaths) {
|
|
13712
|
-
const dir =
|
|
13722
|
+
const dir = path36.join(cwd, rp);
|
|
13713
13723
|
if (!fs37.existsSync(dir)) continue;
|
|
13714
13724
|
let files;
|
|
13715
13725
|
try {
|
|
@@ -13719,7 +13729,7 @@ function detectRoles(cwd, out) {
|
|
|
13719
13729
|
}
|
|
13720
13730
|
for (const f of files) {
|
|
13721
13731
|
try {
|
|
13722
|
-
const content = fs37.readFileSync(
|
|
13732
|
+
const content = fs37.readFileSync(path36.join(dir, f), "utf-8").slice(0, 5e3);
|
|
13723
13733
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
13724
13734
|
if (roleMatches) {
|
|
13725
13735
|
for (const m of roleMatches) {
|
|
@@ -13981,7 +13991,7 @@ var init_dispatchClassified = __esm({
|
|
|
13981
13991
|
|
|
13982
13992
|
// src/loopDefinitions.ts
|
|
13983
13993
|
import * as fs38 from "fs";
|
|
13984
|
-
import * as
|
|
13994
|
+
import * as path37 from "path";
|
|
13985
13995
|
function normalizeLoopDefinition(value) {
|
|
13986
13996
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
13987
13997
|
const raw = value;
|
|
@@ -14008,7 +14018,7 @@ function readLoopDefinition(cwd, id) {
|
|
|
14008
14018
|
if (!ID.test(id)) return null;
|
|
14009
14019
|
const roots = loopRoots(cwd);
|
|
14010
14020
|
for (const root of roots) {
|
|
14011
|
-
const filePath =
|
|
14021
|
+
const filePath = path37.join(root, "loops", id, "loop.json");
|
|
14012
14022
|
if (!fs38.existsSync(filePath)) continue;
|
|
14013
14023
|
try {
|
|
14014
14024
|
const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
|
|
@@ -14021,7 +14031,7 @@ function readLoopDefinition(cwd, id) {
|
|
|
14021
14031
|
}
|
|
14022
14032
|
}
|
|
14023
14033
|
process.stderr.write(
|
|
14024
|
-
`[kody] Loop not found: ${id} (${roots.map((root) =>
|
|
14034
|
+
`[kody] Loop not found: ${id} (${roots.map((root) => path37.join(root, "loops", id, "loop.json")).join(", ")})
|
|
14025
14035
|
`
|
|
14026
14036
|
);
|
|
14027
14037
|
return null;
|
|
@@ -14030,11 +14040,11 @@ function listLoopDefinitions(cwd) {
|
|
|
14030
14040
|
const roots = loopRoots(cwd);
|
|
14031
14041
|
const byId = /* @__PURE__ */ new Map();
|
|
14032
14042
|
for (const root of roots.reverse()) {
|
|
14033
|
-
const loopsDir =
|
|
14043
|
+
const loopsDir = path37.join(root, "loops");
|
|
14034
14044
|
if (!fs38.existsSync(loopsDir)) continue;
|
|
14035
14045
|
for (const id of fs38.readdirSync(loopsDir).sort()) {
|
|
14036
14046
|
if (!ID.test(id)) continue;
|
|
14037
|
-
const filePath =
|
|
14047
|
+
const filePath = path37.join(loopsDir, id, "loop.json");
|
|
14038
14048
|
if (!fs38.existsSync(filePath)) continue;
|
|
14039
14049
|
try {
|
|
14040
14050
|
const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
|
|
@@ -14049,8 +14059,8 @@ function listLoopDefinitions(cwd) {
|
|
|
14049
14059
|
}
|
|
14050
14060
|
function loopRoots(cwd) {
|
|
14051
14061
|
return [
|
|
14052
|
-
|
|
14053
|
-
|
|
14062
|
+
path37.join(cwd, ".kody-engine", "runtime"),
|
|
14063
|
+
path37.join(cwd, ".kody-engine", "definitions"),
|
|
14054
14064
|
definitionsRoot(cwd)
|
|
14055
14065
|
].filter((root, index, roots) => roots.indexOf(root) === index);
|
|
14056
14066
|
}
|
|
@@ -15329,11 +15339,11 @@ var init_fixFlow = __esm({
|
|
|
15329
15339
|
|
|
15330
15340
|
// src/workflow-template.ts
|
|
15331
15341
|
import * as fs39 from "fs";
|
|
15332
|
-
import * as
|
|
15342
|
+
import * as path38 from "path";
|
|
15333
15343
|
import { fileURLToPath } from "url";
|
|
15334
15344
|
function loadKodyWorkflowTemplate() {
|
|
15335
|
-
const here =
|
|
15336
|
-
const candidates = [
|
|
15345
|
+
const here = path38.dirname(fileURLToPath(import.meta.url));
|
|
15346
|
+
const candidates = [path38.resolve(here, "../templates/kody.yml"), path38.resolve(here, "../../templates/kody.yml")];
|
|
15337
15347
|
const source = candidates.find((candidate) => fs39.existsSync(candidate));
|
|
15338
15348
|
if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
|
|
15339
15349
|
return fs39.readFileSync(source, "utf8");
|
|
@@ -15349,11 +15359,11 @@ var init_workflow_template = __esm({
|
|
|
15349
15359
|
// src/scripts/initFlow.ts
|
|
15350
15360
|
import { execFileSync as execFileSync14 } from "child_process";
|
|
15351
15361
|
import * as fs40 from "fs";
|
|
15352
|
-
import * as
|
|
15362
|
+
import * as path39 from "path";
|
|
15353
15363
|
function detectPackageManager(cwd) {
|
|
15354
|
-
if (fs40.existsSync(
|
|
15355
|
-
if (fs40.existsSync(
|
|
15356
|
-
if (fs40.existsSync(
|
|
15364
|
+
if (fs40.existsSync(path39.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
15365
|
+
if (fs40.existsSync(path39.join(cwd, "yarn.lock"))) return "yarn";
|
|
15366
|
+
if (fs40.existsSync(path39.join(cwd, "bun.lockb"))) return "bun";
|
|
15357
15367
|
return "npm";
|
|
15358
15368
|
}
|
|
15359
15369
|
function qualityCommandsFor(pm) {
|
|
@@ -15425,7 +15435,7 @@ function performInit(cwd, force) {
|
|
|
15425
15435
|
const pm = detectPackageManager(cwd);
|
|
15426
15436
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
15427
15437
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
15428
|
-
const configPath =
|
|
15438
|
+
const configPath = path39.join(cwd, "kody.config.json");
|
|
15429
15439
|
if (fs40.existsSync(configPath) && !force) {
|
|
15430
15440
|
skipped.push("kody.config.json");
|
|
15431
15441
|
} else {
|
|
@@ -15434,8 +15444,8 @@ function performInit(cwd, force) {
|
|
|
15434
15444
|
`);
|
|
15435
15445
|
wrote.push("kody.config.json");
|
|
15436
15446
|
}
|
|
15437
|
-
const workflowDir =
|
|
15438
|
-
const workflowPath =
|
|
15447
|
+
const workflowDir = path39.join(cwd, ".github", "workflows");
|
|
15448
|
+
const workflowPath = path39.join(workflowDir, "kody.yml");
|
|
15439
15449
|
if (fs40.existsSync(workflowPath) && !force) {
|
|
15440
15450
|
skipped.push(".github/workflows/kody.yml");
|
|
15441
15451
|
} else {
|
|
@@ -15630,13 +15640,13 @@ var init_loadCapabilityState = __esm({
|
|
|
15630
15640
|
function isCompanyIntentId(value) {
|
|
15631
15641
|
return SLUG_RE2.test(value);
|
|
15632
15642
|
}
|
|
15633
|
-
function normalizeCompanyIntent(
|
|
15643
|
+
function normalizeCompanyIntent(path59, raw) {
|
|
15634
15644
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15635
|
-
throw new Error(`${
|
|
15645
|
+
throw new Error(`${path59}: intent must be JSON object`);
|
|
15636
15646
|
}
|
|
15637
15647
|
const input = raw;
|
|
15638
15648
|
const id = stringField4(input.id);
|
|
15639
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
15649
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path59}: invalid intent id`);
|
|
15640
15650
|
const createdAt = stringField4(input.createdAt) || nowIso();
|
|
15641
15651
|
const updatedAt = stringField4(input.updatedAt) || createdAt;
|
|
15642
15652
|
const description = stringField4(input.description);
|
|
@@ -15798,7 +15808,7 @@ function retryDelaysMs() {
|
|
|
15798
15808
|
}
|
|
15799
15809
|
function sleep(ms) {
|
|
15800
15810
|
if (ms <= 0) return Promise.resolve();
|
|
15801
|
-
return new Promise((
|
|
15811
|
+
return new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
15802
15812
|
}
|
|
15803
15813
|
async function fetchGoalStateWithRetry(config, goalId, cwd) {
|
|
15804
15814
|
let state = await fetchGoalStateAsync(config, goalId, cwd);
|
|
@@ -15928,7 +15938,7 @@ var init_loadIssueStateComment = __esm({
|
|
|
15928
15938
|
|
|
15929
15939
|
// src/scripts/loadJobFromFile.ts
|
|
15930
15940
|
import * as fs42 from "fs";
|
|
15931
|
-
import * as
|
|
15941
|
+
import * as path40 from "path";
|
|
15932
15942
|
function parseJobFile(raw, slug) {
|
|
15933
15943
|
let stripped = raw;
|
|
15934
15944
|
if (stripped.startsWith("---\n")) {
|
|
@@ -15967,10 +15977,10 @@ var init_loadJobFromFile = __esm({
|
|
|
15967
15977
|
if (!slug) {
|
|
15968
15978
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
15969
15979
|
}
|
|
15970
|
-
const capability = resolveCapabilityFolder(slug,
|
|
15980
|
+
const capability = resolveCapabilityFolder(slug, path40.resolve(ctx.cwd, jobsDir));
|
|
15971
15981
|
if (!capability) {
|
|
15972
15982
|
throw new Error(
|
|
15973
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
15983
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path40.resolve(ctx.cwd, jobsDir, slug)}`
|
|
15974
15984
|
);
|
|
15975
15985
|
}
|
|
15976
15986
|
const { title, body, config } = capability;
|
|
@@ -16066,9 +16076,9 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
16066
16076
|
|
|
16067
16077
|
// src/scripts/kodyVariables.ts
|
|
16068
16078
|
import * as fs43 from "fs";
|
|
16069
|
-
import * as
|
|
16079
|
+
import * as path41 from "path";
|
|
16070
16080
|
function readKodyVariables(cwd) {
|
|
16071
|
-
const full =
|
|
16081
|
+
const full = path41.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
16072
16082
|
let raw;
|
|
16073
16083
|
try {
|
|
16074
16084
|
raw = fs43.readFileSync(full, "utf-8");
|
|
@@ -16097,7 +16107,7 @@ var init_kodyVariables = __esm({
|
|
|
16097
16107
|
|
|
16098
16108
|
// src/scripts/loadQaContext.ts
|
|
16099
16109
|
import * as fs44 from "fs";
|
|
16100
|
-
import * as
|
|
16110
|
+
import * as path42 from "path";
|
|
16101
16111
|
function parseSlugList(value) {
|
|
16102
16112
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
16103
16113
|
return inner.split(",").map(
|
|
@@ -16126,7 +16136,7 @@ function readProfileAgents(raw) {
|
|
|
16126
16136
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
16127
16137
|
}
|
|
16128
16138
|
function readProfile(cwd) {
|
|
16129
|
-
const dir =
|
|
16139
|
+
const dir = path42.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
16130
16140
|
if (!fs44.existsSync(dir)) return "";
|
|
16131
16141
|
let entries;
|
|
16132
16142
|
try {
|
|
@@ -16137,7 +16147,7 @@ function readProfile(cwd) {
|
|
|
16137
16147
|
const blocks = [];
|
|
16138
16148
|
for (const file of entries) {
|
|
16139
16149
|
try {
|
|
16140
|
-
const raw = fs44.readFileSync(
|
|
16150
|
+
const raw = fs44.readFileSync(path42.join(dir, file), "utf-8");
|
|
16141
16151
|
const { agent, body } = readProfileAgents(raw);
|
|
16142
16152
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
16143
16153
|
blocks.push(`## ${file}
|
|
@@ -16189,7 +16199,7 @@ var init_loadQaContext = __esm({
|
|
|
16189
16199
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
16190
16200
|
import * as fs45 from "fs";
|
|
16191
16201
|
import * as os6 from "os";
|
|
16192
|
-
import * as
|
|
16202
|
+
import * as path43 from "path";
|
|
16193
16203
|
function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
|
|
16194
16204
|
const subagentFiles = toolFiles.flatMap((file) => {
|
|
16195
16205
|
const match = /^agents\/([a-z][a-z0-9-]{0,63})\.md$/.exec(file);
|
|
@@ -16202,7 +16212,7 @@ function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
|
|
|
16202
16212
|
profile.subagentTemplates = {
|
|
16203
16213
|
...profile.subagentTemplates ?? {},
|
|
16204
16214
|
...Object.fromEntries(
|
|
16205
|
-
subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(
|
|
16215
|
+
subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(path43.join(toolRoot, file), "utf-8")])
|
|
16206
16216
|
)
|
|
16207
16217
|
};
|
|
16208
16218
|
if (!profile.claudeCode.tools.includes("Agent")) {
|
|
@@ -16247,10 +16257,10 @@ function listFiles(root) {
|
|
|
16247
16257
|
const files = [];
|
|
16248
16258
|
const visit = (dir) => {
|
|
16249
16259
|
for (const entry of fs45.readdirSync(dir, { withFileTypes: true })) {
|
|
16250
|
-
const absolute =
|
|
16260
|
+
const absolute = path43.join(dir, entry.name);
|
|
16251
16261
|
if (entry.isSymbolicLink()) continue;
|
|
16252
16262
|
if (entry.isDirectory()) visit(absolute);
|
|
16253
|
-
else if (entry.isFile()) files.push(
|
|
16263
|
+
else if (entry.isFile()) files.push(path43.relative(root, absolute));
|
|
16254
16264
|
}
|
|
16255
16265
|
};
|
|
16256
16266
|
visit(root);
|
|
@@ -16273,8 +16283,8 @@ var init_loadSimpleCapability = __esm({
|
|
|
16273
16283
|
if (!capability) {
|
|
16274
16284
|
throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
|
|
16275
16285
|
}
|
|
16276
|
-
const toolRoot =
|
|
16277
|
-
const skillRoot =
|
|
16286
|
+
const toolRoot = path43.join(capability.dir, "tools");
|
|
16287
|
+
const skillRoot = path43.join(capability.dir, "skills");
|
|
16278
16288
|
const toolFiles = listFiles(toolRoot);
|
|
16279
16289
|
const skillFiles = listFiles(skillRoot);
|
|
16280
16290
|
const parsedInput = parseInput(ctx.args.input);
|
|
@@ -16299,14 +16309,14 @@ var init_loadSimpleCapability = __esm({
|
|
|
16299
16309
|
}
|
|
16300
16310
|
if (requiredSubagents.length > 0) ctx.data.requiredSubagents = requiredSubagents;
|
|
16301
16311
|
if (capability.contract?.execution === "script") {
|
|
16302
|
-
ctx.data.capabilityScriptPath =
|
|
16312
|
+
ctx.data.capabilityScriptPath = path43.join(capability.dir, "tools", "run.sh");
|
|
16303
16313
|
ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
|
|
16304
16314
|
ctx.data.capabilityScriptTimeoutMs = capability.contract.timeoutMs;
|
|
16305
16315
|
}
|
|
16306
16316
|
if (capability.config.outputSchema) {
|
|
16307
16317
|
ctx.data.capabilityOutputSchema = capability.config.outputSchema;
|
|
16308
16318
|
}
|
|
16309
|
-
const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ?
|
|
16319
|
+
const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ? path43.join(os6.tmpdir(), `kody-capability-output-${randomUUID2()}.json`) : void 0;
|
|
16310
16320
|
if (outputPath) ctx.data.capabilityOutputPath = outputPath;
|
|
16311
16321
|
ctx.data.capabilityEnvironment = {
|
|
16312
16322
|
...capabilityInputEnvironment(input),
|
|
@@ -16329,7 +16339,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
16329
16339
|
...skillFiles.flatMap((file) => [
|
|
16330
16340
|
`### ${file}`,
|
|
16331
16341
|
"",
|
|
16332
|
-
fs45.readFileSync(
|
|
16342
|
+
fs45.readFileSync(path43.join(skillRoot, file), "utf-8"),
|
|
16333
16343
|
""
|
|
16334
16344
|
])
|
|
16335
16345
|
] : [],
|
|
@@ -16338,7 +16348,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
16338
16348
|
"## Tools",
|
|
16339
16349
|
"",
|
|
16340
16350
|
"Inspect or run these capability-owned files when needed:",
|
|
16341
|
-
...toolFiles.map((file) => `- ${
|
|
16351
|
+
...toolFiles.map((file) => `- ${path43.join(toolRoot, file)}`)
|
|
16342
16352
|
] : [],
|
|
16343
16353
|
"",
|
|
16344
16354
|
...capability.config.outputSchema ? [
|
|
@@ -16370,7 +16380,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
16370
16380
|
|
|
16371
16381
|
// src/taskContext.ts
|
|
16372
16382
|
import * as fs46 from "fs";
|
|
16373
|
-
import * as
|
|
16383
|
+
import * as path44 from "path";
|
|
16374
16384
|
function buildTaskContext(args) {
|
|
16375
16385
|
return {
|
|
16376
16386
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -16387,7 +16397,7 @@ function persistTaskContext(cwd, ctx) {
|
|
|
16387
16397
|
try {
|
|
16388
16398
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
16389
16399
|
fs46.mkdirSync(dir, { recursive: true });
|
|
16390
|
-
const file =
|
|
16400
|
+
const file = path44.join(dir, "task-context.json");
|
|
16391
16401
|
fs46.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
16392
16402
|
`);
|
|
16393
16403
|
return file;
|
|
@@ -16815,19 +16825,19 @@ function parseAgencyModelProposal(raw) {
|
|
|
16815
16825
|
function normalizeBundleFiles(bundle) {
|
|
16816
16826
|
const seen = /* @__PURE__ */ new Set();
|
|
16817
16827
|
return bundle.files.map((file, index) => {
|
|
16818
|
-
const
|
|
16819
|
-
const parts =
|
|
16820
|
-
if (!
|
|
16828
|
+
const path59 = file.path.replace(/^\/+/, "");
|
|
16829
|
+
const parts = path59.split("/");
|
|
16830
|
+
if (!path59 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
|
|
16821
16831
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
|
|
16822
16832
|
}
|
|
16823
16833
|
if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
|
|
16824
|
-
|
|
16834
|
+
path59
|
|
16825
16835
|
)) {
|
|
16826
16836
|
throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
|
|
16827
16837
|
}
|
|
16828
|
-
if (seen.has(
|
|
16829
|
-
seen.add(
|
|
16830
|
-
return { path:
|
|
16838
|
+
if (seen.has(path59)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path59}`);
|
|
16839
|
+
seen.add(path59);
|
|
16840
|
+
return { path: path59, content: file.content.replace(/\r\n?/g, "\n") };
|
|
16831
16841
|
});
|
|
16832
16842
|
}
|
|
16833
16843
|
function buildProposalId(issueNumber, bundle, sourceLabel) {
|
|
@@ -17939,7 +17949,7 @@ var init_postResearchComment = __esm({
|
|
|
17939
17949
|
// src/scripts/prepareBrowserAuth.ts
|
|
17940
17950
|
import * as fs48 from "fs";
|
|
17941
17951
|
import * as os7 from "os";
|
|
17942
|
-
import * as
|
|
17952
|
+
import * as path45 from "path";
|
|
17943
17953
|
function appendAuthMessage(ctx, message) {
|
|
17944
17954
|
const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
|
|
17945
17955
|
ctx.data.qaAuthBlock = current ? `${current}
|
|
@@ -17978,9 +17988,9 @@ async function githubJson(url, token) {
|
|
|
17978
17988
|
return await response.json();
|
|
17979
17989
|
}
|
|
17980
17990
|
function writeKodyStorageState(input) {
|
|
17981
|
-
const directory = fs48.mkdtempSync(
|
|
17991
|
+
const directory = fs48.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
|
|
17982
17992
|
fs48.chmodSync(directory, 448);
|
|
17983
|
-
const file =
|
|
17993
|
+
const file = path45.join(directory, "storage-state.json");
|
|
17984
17994
|
const now = Date.now();
|
|
17985
17995
|
const repoEntry = {
|
|
17986
17996
|
repoUrl: input.repoUrl,
|
|
@@ -18239,7 +18249,7 @@ var init_prepareCapabilityDelivery = __esm({
|
|
|
18239
18249
|
|
|
18240
18250
|
// src/scripts/prepareSimpleCapabilityRuntime.ts
|
|
18241
18251
|
import { isIP } from "net";
|
|
18242
|
-
import * as
|
|
18252
|
+
import * as path46 from "path";
|
|
18243
18253
|
function requirementsFrom(ctx) {
|
|
18244
18254
|
const raw = ctx.data.capabilityRequirements;
|
|
18245
18255
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
@@ -18283,7 +18293,7 @@ function browserRuntime(ctx, requirements) {
|
|
|
18283
18293
|
"--allowed-origins",
|
|
18284
18294
|
origin,
|
|
18285
18295
|
"--output-dir",
|
|
18286
|
-
|
|
18296
|
+
path46.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
|
|
18287
18297
|
]
|
|
18288
18298
|
};
|
|
18289
18299
|
}
|
|
@@ -18648,9 +18658,9 @@ function latestResult(raw, agentResult) {
|
|
|
18648
18658
|
function recordField4(value) {
|
|
18649
18659
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18650
18660
|
}
|
|
18651
|
-
function resolveDotted(root,
|
|
18652
|
-
if (!
|
|
18653
|
-
return
|
|
18661
|
+
function resolveDotted(root, path59) {
|
|
18662
|
+
if (!path59) return void 0;
|
|
18663
|
+
return path59.split(".").reduce((value, key) => recordField4(value)?.[key], root);
|
|
18654
18664
|
}
|
|
18655
18665
|
function stringValue5(value) {
|
|
18656
18666
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -19492,7 +19502,7 @@ var init_previewBuildHelpers = __esm({
|
|
|
19492
19502
|
// src/scripts/previewBuildRun.ts
|
|
19493
19503
|
import { spawn as spawn5 } from "child_process";
|
|
19494
19504
|
async function runCmd(cmd, args, opts = {}) {
|
|
19495
|
-
await new Promise((
|
|
19505
|
+
await new Promise((resolve24, reject) => {
|
|
19496
19506
|
const child = spawn5(cmd, args, {
|
|
19497
19507
|
cwd: opts.cwd,
|
|
19498
19508
|
env: { ...process.env, ...opts.env ?? {} },
|
|
@@ -19504,7 +19514,7 @@ async function runCmd(cmd, args, opts = {}) {
|
|
|
19504
19514
|
}
|
|
19505
19515
|
child.on("error", reject);
|
|
19506
19516
|
child.on("close", (code) => {
|
|
19507
|
-
if (code === 0)
|
|
19517
|
+
if (code === 0) resolve24();
|
|
19508
19518
|
else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
|
|
19509
19519
|
});
|
|
19510
19520
|
});
|
|
@@ -19576,12 +19586,12 @@ fi
|
|
|
19576
19586
|
|
|
19577
19587
|
// src/scripts/runPreviewBuild.ts
|
|
19578
19588
|
import { copyFile, writeFile } from "fs/promises";
|
|
19579
|
-
import * as
|
|
19589
|
+
import * as path47 from "path";
|
|
19580
19590
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19581
19591
|
function bundledDockerfilePath(mode) {
|
|
19582
|
-
const here =
|
|
19592
|
+
const here = path47.dirname(fileURLToPath2(import.meta.url));
|
|
19583
19593
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
19584
|
-
return
|
|
19594
|
+
return path47.join(here, "preview-build-templates", file);
|
|
19585
19595
|
}
|
|
19586
19596
|
function required(name) {
|
|
19587
19597
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -19816,10 +19826,10 @@ var init_runPreviewBuild = __esm({
|
|
|
19816
19826
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
19817
19827
|
if (Object.keys(buildEnv).length > 0) {
|
|
19818
19828
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
19819
|
-
await writeFile(
|
|
19829
|
+
await writeFile(path47.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
19820
19830
|
`, "utf8");
|
|
19821
19831
|
}
|
|
19822
|
-
const consumerDockerfile =
|
|
19832
|
+
const consumerDockerfile = path47.join(ctx.cwd, "Dockerfile.preview");
|
|
19823
19833
|
const { stat } = await import("fs/promises");
|
|
19824
19834
|
let hasConsumerDockerfile = false;
|
|
19825
19835
|
try {
|
|
@@ -20004,7 +20014,7 @@ var init_tickShellRunner = __esm({
|
|
|
20004
20014
|
|
|
20005
20015
|
// src/scripts/runScheduledImplementationTick.ts
|
|
20006
20016
|
import * as fs49 from "fs";
|
|
20007
|
-
import * as
|
|
20017
|
+
import * as path48 from "path";
|
|
20008
20018
|
var runScheduledImplementationTick;
|
|
20009
20019
|
var init_runScheduledImplementationTick = __esm({
|
|
20010
20020
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -20025,13 +20035,13 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
20025
20035
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
20026
20036
|
return;
|
|
20027
20037
|
}
|
|
20028
|
-
const capability = resolveCapabilityFolder(slug,
|
|
20038
|
+
const capability = resolveCapabilityFolder(slug, path48.resolve(ctx.cwd, jobsDir));
|
|
20029
20039
|
if (!capability) {
|
|
20030
20040
|
ctx.output.exitCode = 99;
|
|
20031
20041
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
|
|
20032
20042
|
return;
|
|
20033
20043
|
}
|
|
20034
|
-
const shellPath =
|
|
20044
|
+
const shellPath = path48.join(profile.dir, shell);
|
|
20035
20045
|
if (!fs49.existsSync(shellPath)) {
|
|
20036
20046
|
ctx.output.exitCode = 99;
|
|
20037
20047
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
@@ -20150,7 +20160,7 @@ var init_runSimpleCapabilityScript = __esm({
|
|
|
20150
20160
|
|
|
20151
20161
|
// src/scripts/runTickScript.ts
|
|
20152
20162
|
import * as fs51 from "fs";
|
|
20153
|
-
import * as
|
|
20163
|
+
import * as path49 from "path";
|
|
20154
20164
|
var runTickScript;
|
|
20155
20165
|
var init_runTickScript = __esm({
|
|
20156
20166
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -20170,10 +20180,10 @@ var init_runTickScript = __esm({
|
|
|
20170
20180
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
20171
20181
|
return;
|
|
20172
20182
|
}
|
|
20173
|
-
const capability = readCapabilityFolder(
|
|
20183
|
+
const capability = readCapabilityFolder(path49.resolve(ctx.cwd, jobsDir), slug);
|
|
20174
20184
|
if (!capability) {
|
|
20175
20185
|
ctx.output.exitCode = 99;
|
|
20176
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
20186
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path49.resolve(ctx.cwd, jobsDir, slug)}`;
|
|
20177
20187
|
return;
|
|
20178
20188
|
}
|
|
20179
20189
|
const tickScript = capability.config.tickScript;
|
|
@@ -20182,7 +20192,7 @@ var init_runTickScript = __esm({
|
|
|
20182
20192
|
ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
20183
20193
|
return;
|
|
20184
20194
|
}
|
|
20185
|
-
const scriptPath =
|
|
20195
|
+
const scriptPath = path49.isAbsolute(tickScript) ? tickScript : path49.join(ctx.cwd, tickScript);
|
|
20186
20196
|
if (!fs51.existsSync(scriptPath)) {
|
|
20187
20197
|
ctx.output.exitCode = 99;
|
|
20188
20198
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
@@ -20465,7 +20475,7 @@ var init_syncFlow = __esm({
|
|
|
20465
20475
|
});
|
|
20466
20476
|
|
|
20467
20477
|
// src/scripts/validateAgencyModelProposal.ts
|
|
20468
|
-
import * as
|
|
20478
|
+
import * as path50 from "path";
|
|
20469
20479
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
20470
20480
|
const failures = [];
|
|
20471
20481
|
validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
|
|
@@ -20783,7 +20793,7 @@ var init_validateAgencyModelProposal = __esm({
|
|
|
20783
20793
|
const bundle = parseAgencyModelProposal(raw);
|
|
20784
20794
|
const expectedKind = readExpectedModelKind(args);
|
|
20785
20795
|
const failures = validateModelBundle(bundle, expectedKind, {
|
|
20786
|
-
capabilityRoot:
|
|
20796
|
+
capabilityRoot: path50.join(ctx.cwd, ".kody", "capabilities")
|
|
20787
20797
|
});
|
|
20788
20798
|
if (failures.length > 0) {
|
|
20789
20799
|
throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
|
|
@@ -20846,7 +20856,7 @@ function stripAnsi2(s) {
|
|
|
20846
20856
|
return s.replace(ANSI_RE2, "");
|
|
20847
20857
|
}
|
|
20848
20858
|
function runCommand2(command, cwd) {
|
|
20849
|
-
return new Promise((
|
|
20859
|
+
return new Promise((resolve24) => {
|
|
20850
20860
|
const child = spawn6(command, {
|
|
20851
20861
|
cwd,
|
|
20852
20862
|
shell: true,
|
|
@@ -20873,11 +20883,11 @@ function runCommand2(command, cwd) {
|
|
|
20873
20883
|
}, TEST_TIMEOUT_MS);
|
|
20874
20884
|
child.on("exit", (code) => {
|
|
20875
20885
|
clearTimeout(timer);
|
|
20876
|
-
|
|
20886
|
+
resolve24({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
|
|
20877
20887
|
});
|
|
20878
20888
|
child.on("error", (err) => {
|
|
20879
20889
|
clearTimeout(timer);
|
|
20880
|
-
|
|
20890
|
+
resolve24({ exitCode: -1, output: err.message });
|
|
20881
20891
|
});
|
|
20882
20892
|
});
|
|
20883
20893
|
}
|
|
@@ -21291,21 +21301,21 @@ function lineStream(stream) {
|
|
|
21291
21301
|
tryDeliver();
|
|
21292
21302
|
});
|
|
21293
21303
|
return {
|
|
21294
|
-
next: (timeoutMs) => new Promise((
|
|
21304
|
+
next: (timeoutMs) => new Promise((resolve24) => {
|
|
21295
21305
|
if (queue.length > 0) {
|
|
21296
|
-
|
|
21306
|
+
resolve24(queue.shift());
|
|
21297
21307
|
return;
|
|
21298
21308
|
}
|
|
21299
21309
|
if (ended) {
|
|
21300
|
-
|
|
21310
|
+
resolve24(null);
|
|
21301
21311
|
return;
|
|
21302
21312
|
}
|
|
21303
|
-
waiter =
|
|
21313
|
+
waiter = resolve24;
|
|
21304
21314
|
const t = setTimeout(
|
|
21305
21315
|
() => {
|
|
21306
|
-
if (waiter ===
|
|
21316
|
+
if (waiter === resolve24) {
|
|
21307
21317
|
waiter = null;
|
|
21308
|
-
|
|
21318
|
+
resolve24(null);
|
|
21309
21319
|
}
|
|
21310
21320
|
},
|
|
21311
21321
|
Math.max(0, timeoutMs)
|
|
@@ -21707,15 +21717,15 @@ var init_scripts = __esm({
|
|
|
21707
21717
|
|
|
21708
21718
|
// src/stateWorkspace.ts
|
|
21709
21719
|
import * as fs53 from "fs";
|
|
21710
|
-
import * as
|
|
21720
|
+
import * as path51 from "path";
|
|
21711
21721
|
function tenantId(config) {
|
|
21712
21722
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
21713
21723
|
const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
|
|
21714
21724
|
return owner && repo ? `${owner}/${repo}` : null;
|
|
21715
21725
|
}
|
|
21716
21726
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
21717
|
-
const target =
|
|
21718
|
-
fs53.mkdirSync(
|
|
21727
|
+
const target = path51.join(cwd, RUNTIME_ROOT, relativePath);
|
|
21728
|
+
fs53.mkdirSync(path51.dirname(target), { recursive: true });
|
|
21719
21729
|
fs53.writeFileSync(target, content, "utf8");
|
|
21720
21730
|
}
|
|
21721
21731
|
function record(value) {
|
|
@@ -21781,10 +21791,10 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
|
21781
21791
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
21782
21792
|
return;
|
|
21783
21793
|
}
|
|
21784
|
-
const key = `${
|
|
21794
|
+
const key = `${path51.resolve(cwd)}|${tenant}`;
|
|
21785
21795
|
if (hydratedWorkspaces.has(key)) return;
|
|
21786
21796
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
21787
|
-
const root =
|
|
21797
|
+
const root = path51.join(cwd, RUNTIME_ROOT);
|
|
21788
21798
|
fs53.rmSync(root, { recursive: true, force: true });
|
|
21789
21799
|
await Promise.all([
|
|
21790
21800
|
hydratePrefix(backend, tenant, cwd, "context:"),
|
|
@@ -21801,7 +21811,7 @@ var init_stateWorkspace = __esm({
|
|
|
21801
21811
|
"src/stateWorkspace.ts"() {
|
|
21802
21812
|
"use strict";
|
|
21803
21813
|
init_state_backend();
|
|
21804
|
-
RUNTIME_ROOT =
|
|
21814
|
+
RUNTIME_ROOT = path51.join(".kody-engine", "runtime");
|
|
21805
21815
|
hydratedWorkspaces = /* @__PURE__ */ new Set();
|
|
21806
21816
|
}
|
|
21807
21817
|
});
|
|
@@ -21874,7 +21884,7 @@ var init_tools = __esm({
|
|
|
21874
21884
|
import { spawn as spawn8 } from "child_process";
|
|
21875
21885
|
import * as fs54 from "fs";
|
|
21876
21886
|
import * as os8 from "os";
|
|
21877
|
-
import * as
|
|
21887
|
+
import * as path52 from "path";
|
|
21878
21888
|
function isMutatingPostflight(scriptName) {
|
|
21879
21889
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
21880
21890
|
}
|
|
@@ -22131,7 +22141,7 @@ async function runImplementation(profileName, input) {
|
|
|
22131
22141
|
const reason = input.abortController.signal.reason;
|
|
22132
22142
|
throw reason instanceof Error ? reason : new Error("agent invocation aborted");
|
|
22133
22143
|
}
|
|
22134
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
22144
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path52.isAbsolute(p) ? p : path52.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
22135
22145
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
22136
22146
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
22137
22147
|
const agents = loadSubagents(profile);
|
|
@@ -22613,13 +22623,13 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
22613
22623
|
function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
22614
22624
|
const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
|
|
22615
22625
|
if (found) return found;
|
|
22616
|
-
const here =
|
|
22626
|
+
const here = path52.dirname(new URL(import.meta.url).pathname);
|
|
22617
22627
|
const candidates = [
|
|
22618
|
-
|
|
22628
|
+
path52.join(here, "implementations", profileName, "profile.json"),
|
|
22619
22629
|
// same-dir sibling (dev)
|
|
22620
|
-
|
|
22630
|
+
path52.join(here, "..", "implementations", profileName, "profile.json"),
|
|
22621
22631
|
// up one (prod: dist/bin → dist/implementations)
|
|
22622
|
-
|
|
22632
|
+
path52.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
22623
22633
|
// fallback
|
|
22624
22634
|
];
|
|
22625
22635
|
for (const c of candidates) {
|
|
@@ -22738,7 +22748,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
22738
22748
|
}
|
|
22739
22749
|
async function runShellEntry(entry, ctx, profile) {
|
|
22740
22750
|
const shellName = entry.shell;
|
|
22741
|
-
const shellPath =
|
|
22751
|
+
const shellPath = path52.join(profile.dir, shellName);
|
|
22742
22752
|
if (!fs54.existsSync(shellPath)) {
|
|
22743
22753
|
ctx.skipAgent = true;
|
|
22744
22754
|
ctx.output.exitCode = 99;
|
|
@@ -22746,7 +22756,7 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22746
22756
|
return;
|
|
22747
22757
|
}
|
|
22748
22758
|
const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
|
|
22749
|
-
const outputFile =
|
|
22759
|
+
const outputFile = path52.join(
|
|
22750
22760
|
os8.tmpdir(),
|
|
22751
22761
|
`kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
22752
22762
|
);
|
|
@@ -22776,14 +22786,14 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
22776
22786
|
let killTimer;
|
|
22777
22787
|
let escalateTimer;
|
|
22778
22788
|
const result = await new Promise(
|
|
22779
|
-
(
|
|
22789
|
+
(resolve24) => {
|
|
22780
22790
|
let settled = false;
|
|
22781
22791
|
const settle = (code, signal, spawnErr) => {
|
|
22782
22792
|
if (settled) return;
|
|
22783
22793
|
settled = true;
|
|
22784
22794
|
if (killTimer) clearTimeout(killTimer);
|
|
22785
22795
|
if (escalateTimer) clearTimeout(escalateTimer);
|
|
22786
|
-
|
|
22796
|
+
resolve24({ code, signal, spawnErr });
|
|
22787
22797
|
};
|
|
22788
22798
|
child.on("error", (err) => settle(null, null, err));
|
|
22789
22799
|
child.on("close", (code, signal) => settle(code, signal));
|
|
@@ -23828,11 +23838,11 @@ function exhaustedWorkflowTransitions(step, data, counts) {
|
|
|
23828
23838
|
}
|
|
23829
23839
|
function workflowResultConditionPaths(transitions) {
|
|
23830
23840
|
return transitions.flatMap(
|
|
23831
|
-
(transition) => Object.keys(transition.when ?? {}).filter((
|
|
23841
|
+
(transition) => Object.keys(transition.when ?? {}).filter((path59) => path59.startsWith("result."))
|
|
23832
23842
|
);
|
|
23833
23843
|
}
|
|
23834
23844
|
function conditionMatches(condition, context) {
|
|
23835
|
-
return Object.entries(condition).every(([
|
|
23845
|
+
return Object.entries(condition).every(([path59, expected]) => valueMatches(resolveDottedPath2(context, path59), expected));
|
|
23836
23846
|
}
|
|
23837
23847
|
function withWorkflowBoundaryEval(capability, result) {
|
|
23838
23848
|
const capabilityKind = capability.config.capabilityKind;
|
|
@@ -24307,7 +24317,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
24307
24317
|
|
|
24308
24318
|
// src/servers/brain-serve.ts
|
|
24309
24319
|
import { createServer as createServer2 } from "http";
|
|
24310
|
-
import * as
|
|
24320
|
+
import * as path55 from "path";
|
|
24311
24321
|
|
|
24312
24322
|
// src/chat/loop.ts
|
|
24313
24323
|
init_agent();
|
|
@@ -24316,12 +24326,12 @@ init_config();
|
|
|
24316
24326
|
init_registry();
|
|
24317
24327
|
init_task_artifacts();
|
|
24318
24328
|
import * as fs18 from "fs";
|
|
24319
|
-
import * as
|
|
24329
|
+
import * as path20 from "path";
|
|
24320
24330
|
|
|
24321
24331
|
// src/chat/attachments.ts
|
|
24322
24332
|
init_runtimePaths();
|
|
24323
24333
|
import * as fs15 from "fs";
|
|
24324
|
-
import * as
|
|
24334
|
+
import * as path17 from "path";
|
|
24325
24335
|
var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
|
|
24326
24336
|
var EXT_BY_MIME = {
|
|
24327
24337
|
"image/png": "png",
|
|
@@ -24357,7 +24367,7 @@ function prepareAttachments(turns, cwd, sessionId) {
|
|
|
24357
24367
|
fs15.mkdirSync(dir, { recursive: true });
|
|
24358
24368
|
dirEnsured = true;
|
|
24359
24369
|
}
|
|
24360
|
-
const filePath =
|
|
24370
|
+
const filePath = path17.join(dir, `${imageCounter}.${extFor(mime)}`);
|
|
24361
24371
|
fs15.writeFileSync(filePath, Buffer.from(data, "base64"));
|
|
24362
24372
|
imageCounter += 1;
|
|
24363
24373
|
imagePaths.push(filePath);
|
|
@@ -24376,7 +24386,7 @@ function prepareAttachments(turns, cwd, sessionId) {
|
|
|
24376
24386
|
// src/chat/codex-app-server.ts
|
|
24377
24387
|
import { spawn as spawn3 } from "child_process";
|
|
24378
24388
|
import * as fs16 from "fs";
|
|
24379
|
-
import * as
|
|
24389
|
+
import * as path18 from "path";
|
|
24380
24390
|
import { createInterface } from "readline";
|
|
24381
24391
|
function codexThreadStartParams(args) {
|
|
24382
24392
|
return {
|
|
@@ -24461,9 +24471,9 @@ var CodexAppServerClient = class {
|
|
|
24461
24471
|
await this.request("thread/resume", { threadId });
|
|
24462
24472
|
}
|
|
24463
24473
|
async runTurn(args) {
|
|
24464
|
-
await new Promise((
|
|
24474
|
+
await new Promise((resolve24, reject) => {
|
|
24465
24475
|
this.process.turnWaiters.set(args.threadId, {
|
|
24466
|
-
resolve:
|
|
24476
|
+
resolve: resolve24,
|
|
24467
24477
|
reject,
|
|
24468
24478
|
onNotification: args.onNotification,
|
|
24469
24479
|
queue: Promise.resolve()
|
|
@@ -24480,8 +24490,8 @@ var CodexAppServerClient = class {
|
|
|
24480
24490
|
}
|
|
24481
24491
|
request(method, params) {
|
|
24482
24492
|
const id = this.process.nextId++;
|
|
24483
|
-
return new Promise((
|
|
24484
|
-
this.process.pending.set(id, { resolve:
|
|
24493
|
+
return new Promise((resolve24, reject) => {
|
|
24494
|
+
this.process.pending.set(id, { resolve: resolve24, reject });
|
|
24485
24495
|
this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
|
|
24486
24496
|
`);
|
|
24487
24497
|
});
|
|
@@ -24547,7 +24557,7 @@ var CodexAppServerClient = class {
|
|
|
24547
24557
|
};
|
|
24548
24558
|
var clients = /* @__PURE__ */ new Map();
|
|
24549
24559
|
function threadMapPath(cwd) {
|
|
24550
|
-
return
|
|
24560
|
+
return path18.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
|
|
24551
24561
|
}
|
|
24552
24562
|
function readThreadMap(cwd) {
|
|
24553
24563
|
try {
|
|
@@ -24564,7 +24574,7 @@ function readThreadMap(cwd) {
|
|
|
24564
24574
|
}
|
|
24565
24575
|
function writeThreadMap(cwd, map) {
|
|
24566
24576
|
const file = threadMapPath(cwd);
|
|
24567
|
-
fs16.mkdirSync(
|
|
24577
|
+
fs16.mkdirSync(path18.dirname(file), { recursive: true });
|
|
24568
24578
|
fs16.writeFileSync(file, `${JSON.stringify(map, null, 2)}
|
|
24569
24579
|
`);
|
|
24570
24580
|
}
|
|
@@ -24656,7 +24666,7 @@ async function runCodexChatTurn(args) {
|
|
|
24656
24666
|
|
|
24657
24667
|
// src/chat/events.ts
|
|
24658
24668
|
import * as fs17 from "fs";
|
|
24659
|
-
import * as
|
|
24669
|
+
import * as path19 from "path";
|
|
24660
24670
|
import posixPath2 from "path/posix";
|
|
24661
24671
|
var BackendEventSink = class {
|
|
24662
24672
|
constructor(append, tenantId2, sessionId) {
|
|
@@ -24672,7 +24682,7 @@ var BackendEventSink = class {
|
|
|
24672
24682
|
}
|
|
24673
24683
|
};
|
|
24674
24684
|
function eventsFilePath(cwd, sessionId) {
|
|
24675
|
-
return
|
|
24685
|
+
return path19.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
|
|
24676
24686
|
}
|
|
24677
24687
|
var FileSink = class {
|
|
24678
24688
|
constructor(file) {
|
|
@@ -24680,7 +24690,7 @@ var FileSink = class {
|
|
|
24680
24690
|
}
|
|
24681
24691
|
file;
|
|
24682
24692
|
async emit(event) {
|
|
24683
|
-
fs17.mkdirSync(
|
|
24693
|
+
fs17.mkdirSync(path19.dirname(this.file), { recursive: true });
|
|
24684
24694
|
fs17.appendFileSync(this.file, `${JSON.stringify(event)}
|
|
24685
24695
|
`);
|
|
24686
24696
|
}
|
|
@@ -25068,7 +25078,7 @@ async function runChatTurn(opts) {
|
|
|
25068
25078
|
quiet: opts.quiet,
|
|
25069
25079
|
additionalDirectories: [
|
|
25070
25080
|
taskArtifactsPaths.absDir,
|
|
25071
|
-
...Array.from(new Set(imagePaths.map((p2) =>
|
|
25081
|
+
...Array.from(new Set(imagePaths.map((p2) => path20.dirname(p2))))
|
|
25072
25082
|
],
|
|
25073
25083
|
systemPromptAppend: systemPrompt,
|
|
25074
25084
|
...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
|
|
@@ -25256,7 +25266,7 @@ async function emit(sink, type, sessionId, suffix, payload) {
|
|
|
25256
25266
|
var MEMORY_INDEX_REL = ".kody-engine/runtime/memory/INDEX.md";
|
|
25257
25267
|
var MAX_INDEX_BYTES = 8e3;
|
|
25258
25268
|
function readMemoryIndexBlock(cwd) {
|
|
25259
|
-
const indexPath =
|
|
25269
|
+
const indexPath = path20.join(cwd, MEMORY_INDEX_REL);
|
|
25260
25270
|
let raw;
|
|
25261
25271
|
try {
|
|
25262
25272
|
raw = fs18.readFileSync(indexPath, "utf-8");
|
|
@@ -25279,7 +25289,7 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
|
|
|
25279
25289
|
var CONTEXT_DIR_REL = ".kody-engine/runtime/context";
|
|
25280
25290
|
var MAX_CONTEXT_BYTES = 12e3;
|
|
25281
25291
|
function readContextBlock(cwd) {
|
|
25282
|
-
const dir =
|
|
25292
|
+
const dir = path20.join(cwd, CONTEXT_DIR_REL);
|
|
25283
25293
|
let files;
|
|
25284
25294
|
try {
|
|
25285
25295
|
files = fs18.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
@@ -25289,7 +25299,7 @@ function readContextBlock(cwd) {
|
|
|
25289
25299
|
const sections = [];
|
|
25290
25300
|
for (const file of files) {
|
|
25291
25301
|
try {
|
|
25292
|
-
const content = fs18.readFileSync(
|
|
25302
|
+
const content = fs18.readFileSync(path20.join(dir, file), "utf-8").trim();
|
|
25293
25303
|
if (content) sections.push(`### ${file.replace(/\.md$/, "")}
|
|
25294
25304
|
|
|
25295
25305
|
${content}`);
|
|
@@ -25315,7 +25325,7 @@ var SYSTEM_PROMPT_OVERRIDE_REL = ".kody-engine/runtime/system-prompt.md";
|
|
|
25315
25325
|
function readSystemPromptOverride(cwd) {
|
|
25316
25326
|
let raw;
|
|
25317
25327
|
try {
|
|
25318
|
-
raw = fs18.readFileSync(
|
|
25328
|
+
raw = fs18.readFileSync(path20.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
|
|
25319
25329
|
} catch {
|
|
25320
25330
|
return null;
|
|
25321
25331
|
}
|
|
@@ -25323,7 +25333,7 @@ function readSystemPromptOverride(cwd) {
|
|
|
25323
25333
|
return trimmed.length > 0 ? trimmed : null;
|
|
25324
25334
|
}
|
|
25325
25335
|
function readInstructionsBlock(cwd) {
|
|
25326
|
-
const instructionsPath =
|
|
25336
|
+
const instructionsPath = path20.join(cwd, INSTRUCTIONS_REL);
|
|
25327
25337
|
let raw;
|
|
25328
25338
|
try {
|
|
25329
25339
|
raw = fs18.readFileSync(instructionsPath, "utf-8");
|
|
@@ -25361,10 +25371,10 @@ function resolveBrainDriver(runtime) {
|
|
|
25361
25371
|
|
|
25362
25372
|
// src/chat/session.ts
|
|
25363
25373
|
import * as fs19 from "fs";
|
|
25364
|
-
import * as
|
|
25374
|
+
import * as path21 from "path";
|
|
25365
25375
|
import posixPath3 from "path/posix";
|
|
25366
25376
|
function sessionFilePath(cwd, sessionId) {
|
|
25367
|
-
return
|
|
25377
|
+
return path21.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
|
|
25368
25378
|
}
|
|
25369
25379
|
function readSession(file) {
|
|
25370
25380
|
if (!fs19.existsSync(file)) return [];
|
|
@@ -25392,7 +25402,7 @@ init_state_backend();
|
|
|
25392
25402
|
init_workflowDefinitions();
|
|
25393
25403
|
import { createHash as createHash2 } from "crypto";
|
|
25394
25404
|
import * as fs21 from "fs";
|
|
25395
|
-
import * as
|
|
25405
|
+
import * as path23 from "path";
|
|
25396
25406
|
var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
|
|
25397
25407
|
var REPOSITORY_OWNED_NAMESPACES = ["loops"];
|
|
25398
25408
|
function assertSafeDefinitionPath(filePath) {
|
|
@@ -25424,8 +25434,8 @@ function verifyDefinition(definition) {
|
|
|
25424
25434
|
}
|
|
25425
25435
|
function writeBundle(root, bundle) {
|
|
25426
25436
|
for (const [filePath, contents] of Object.entries(bundle.files)) {
|
|
25427
|
-
const target =
|
|
25428
|
-
fs21.mkdirSync(
|
|
25437
|
+
const target = path23.join(root, filePath);
|
|
25438
|
+
fs21.mkdirSync(path23.dirname(target), { recursive: true });
|
|
25429
25439
|
fs21.writeFileSync(target, contents, "utf8");
|
|
25430
25440
|
}
|
|
25431
25441
|
}
|
|
@@ -25434,22 +25444,22 @@ function writeDefinition(root, kind, definition) {
|
|
|
25434
25444
|
if (kind === "agent") {
|
|
25435
25445
|
const raw = bundle.files["agent.md"];
|
|
25436
25446
|
if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
|
|
25437
|
-
fs21.writeFileSync(
|
|
25447
|
+
fs21.writeFileSync(path23.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
|
|
25438
25448
|
return;
|
|
25439
25449
|
}
|
|
25440
25450
|
if (kind === "goal") {
|
|
25441
|
-
writeBundle(
|
|
25451
|
+
writeBundle(path23.join(root, "goals", definition.slug), bundle);
|
|
25442
25452
|
return;
|
|
25443
25453
|
}
|
|
25444
25454
|
if (kind === "implementation") {
|
|
25445
|
-
writeBundle(
|
|
25455
|
+
writeBundle(path23.join(root, "implementations", definition.slug), bundle);
|
|
25446
25456
|
return;
|
|
25447
25457
|
}
|
|
25448
25458
|
if (kind === "asset") {
|
|
25449
|
-
writeBundle(
|
|
25459
|
+
writeBundle(path23.join(root, "shared"), bundle);
|
|
25450
25460
|
return;
|
|
25451
25461
|
}
|
|
25452
|
-
writeBundle(
|
|
25462
|
+
writeBundle(path23.join(root, "capabilities", definition.slug), bundle);
|
|
25453
25463
|
}
|
|
25454
25464
|
function writeWorkflow(root, document) {
|
|
25455
25465
|
const workflow = normalizeWorkflowDefinition(document.definition);
|
|
@@ -25457,28 +25467,28 @@ function writeWorkflow(root, document) {
|
|
|
25457
25467
|
const contents = `${JSON.stringify(workflow, null, 2)}
|
|
25458
25468
|
`;
|
|
25459
25469
|
const bundle = { schemaVersion: 1, files: { "workflow.json": contents } };
|
|
25460
|
-
const target =
|
|
25461
|
-
fs21.mkdirSync(
|
|
25470
|
+
const target = path23.join(root, workflowDefinitionPath(document.workflowId));
|
|
25471
|
+
fs21.mkdirSync(path23.dirname(target), { recursive: true });
|
|
25462
25472
|
fs21.writeFileSync(target, contents, "utf8");
|
|
25463
25473
|
return definitionVersion(bundle);
|
|
25464
25474
|
}
|
|
25465
25475
|
function preserveRepositoryDefinitions(root, staging) {
|
|
25466
25476
|
for (const namespace of REPOSITORY_OWNED_NAMESPACES) {
|
|
25467
|
-
const source =
|
|
25477
|
+
const source = path23.join(root, namespace);
|
|
25468
25478
|
if (!fs21.existsSync(source)) continue;
|
|
25469
|
-
fs21.cpSync(source,
|
|
25479
|
+
fs21.cpSync(source, path23.join(staging, namespace), { recursive: true });
|
|
25470
25480
|
}
|
|
25471
25481
|
}
|
|
25472
25482
|
async function hydrateDefinitions(options) {
|
|
25473
|
-
const root =
|
|
25483
|
+
const root = path23.join(options.cwd, ".kody-engine", "definitions");
|
|
25474
25484
|
const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
|
|
25475
25485
|
fs21.rmSync(staging, { recursive: true, force: true });
|
|
25476
|
-
fs21.mkdirSync(
|
|
25477
|
-
fs21.mkdirSync(
|
|
25478
|
-
fs21.mkdirSync(
|
|
25479
|
-
fs21.mkdirSync(
|
|
25480
|
-
fs21.mkdirSync(
|
|
25481
|
-
fs21.mkdirSync(
|
|
25486
|
+
fs21.mkdirSync(path23.join(staging, "agents"), { recursive: true });
|
|
25487
|
+
fs21.mkdirSync(path23.join(staging, "capabilities"), { recursive: true });
|
|
25488
|
+
fs21.mkdirSync(path23.join(staging, "goals"), { recursive: true });
|
|
25489
|
+
fs21.mkdirSync(path23.join(staging, "implementations"), { recursive: true });
|
|
25490
|
+
fs21.mkdirSync(path23.join(staging, "shared"), { recursive: true });
|
|
25491
|
+
fs21.mkdirSync(path23.join(staging, "workflows"), { recursive: true });
|
|
25482
25492
|
try {
|
|
25483
25493
|
const [capabilities, agents, goals, implementations, assets, workflows] = await Promise.all([
|
|
25484
25494
|
options.backend.listDefinitions(options.tenantId, "capability"),
|
|
@@ -25519,7 +25529,7 @@ async function hydrateDefinitions(options) {
|
|
|
25519
25529
|
hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25520
25530
|
versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
|
|
25521
25531
|
};
|
|
25522
|
-
fs21.writeFileSync(
|
|
25532
|
+
fs21.writeFileSync(path23.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
25523
25533
|
`, "utf8");
|
|
25524
25534
|
fs21.rmSync(root, { recursive: true, force: true });
|
|
25525
25535
|
fs21.renameSync(staging, root);
|
|
@@ -25548,7 +25558,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
25548
25558
|
// src/kody-cli.ts
|
|
25549
25559
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
25550
25560
|
import * as fs55 from "fs";
|
|
25551
|
-
import * as
|
|
25561
|
+
import * as path53 from "path";
|
|
25552
25562
|
|
|
25553
25563
|
// src/app-auth.ts
|
|
25554
25564
|
import { createSign } from "crypto";
|
|
@@ -26350,9 +26360,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
26350
26360
|
return void 0;
|
|
26351
26361
|
}
|
|
26352
26362
|
function detectPackageManager2(cwd) {
|
|
26353
|
-
if (fs55.existsSync(
|
|
26354
|
-
if (fs55.existsSync(
|
|
26355
|
-
if (fs55.existsSync(
|
|
26363
|
+
if (fs55.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
26364
|
+
if (fs55.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
|
|
26365
|
+
if (fs55.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
|
|
26356
26366
|
return "npm";
|
|
26357
26367
|
}
|
|
26358
26368
|
function shouldChainScheduledWatch(match) {
|
|
@@ -26485,7 +26495,7 @@ async function runCi(argv) {
|
|
|
26485
26495
|
return 0;
|
|
26486
26496
|
}
|
|
26487
26497
|
const args = parseCiArgs(argv);
|
|
26488
|
-
const cwd = args.cwd ?
|
|
26498
|
+
const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
|
|
26489
26499
|
try {
|
|
26490
26500
|
const n = unpackAllSecrets();
|
|
26491
26501
|
if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
|
|
@@ -26969,7 +26979,7 @@ init_repoWorkspace();
|
|
|
26969
26979
|
// src/scripts/brainTurnLog.ts
|
|
26970
26980
|
init_runtimePaths();
|
|
26971
26981
|
import * as fs56 from "fs";
|
|
26972
|
-
import * as
|
|
26982
|
+
import * as path54 from "path";
|
|
26973
26983
|
import posixPath4 from "path/posix";
|
|
26974
26984
|
var live = /* @__PURE__ */ new Map();
|
|
26975
26985
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -27016,7 +27026,7 @@ function beginTurn(dir, chatId) {
|
|
|
27016
27026
|
};
|
|
27017
27027
|
live.set(chatId, state);
|
|
27018
27028
|
const p = brainEventsFilePath(dir, chatId);
|
|
27019
|
-
fs56.mkdirSync(
|
|
27029
|
+
fs56.mkdirSync(path54.dirname(p), { recursive: true });
|
|
27020
27030
|
return (event) => {
|
|
27021
27031
|
state.seq += 1;
|
|
27022
27032
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
@@ -27154,17 +27164,17 @@ function authOk(req, expected) {
|
|
|
27154
27164
|
return false;
|
|
27155
27165
|
}
|
|
27156
27166
|
function readJsonBody(req) {
|
|
27157
|
-
return new Promise((
|
|
27167
|
+
return new Promise((resolve24, reject) => {
|
|
27158
27168
|
const chunks = [];
|
|
27159
27169
|
req.on("data", (c) => chunks.push(c));
|
|
27160
27170
|
req.on("end", () => {
|
|
27161
27171
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
27162
27172
|
if (!raw.trim()) {
|
|
27163
|
-
|
|
27173
|
+
resolve24({});
|
|
27164
27174
|
return;
|
|
27165
27175
|
}
|
|
27166
27176
|
try {
|
|
27167
|
-
|
|
27177
|
+
resolve24(JSON.parse(raw));
|
|
27168
27178
|
} catch (err) {
|
|
27169
27179
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
27170
27180
|
}
|
|
@@ -27456,7 +27466,7 @@ function buildServer(opts) {
|
|
|
27456
27466
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
27457
27467
|
const createStore = opts.createStore ?? createSessionStore;
|
|
27458
27468
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
27459
|
-
const reposRoot = opts.reposRoot ??
|
|
27469
|
+
const reposRoot = opts.reposRoot ?? path55.join(path55.dirname(path55.resolve(opts.cwd)), "repos");
|
|
27460
27470
|
return createServer2(async (req, res) => {
|
|
27461
27471
|
if (!req.method || !req.url) {
|
|
27462
27472
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -27537,11 +27547,11 @@ async function brainServe(opts) {
|
|
|
27537
27547
|
litellmUrl,
|
|
27538
27548
|
driver
|
|
27539
27549
|
});
|
|
27540
|
-
await new Promise((
|
|
27550
|
+
await new Promise((resolve24) => {
|
|
27541
27551
|
server.listen(port, "0.0.0.0", () => {
|
|
27542
27552
|
process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
|
|
27543
27553
|
`);
|
|
27544
|
-
|
|
27554
|
+
resolve24();
|
|
27545
27555
|
});
|
|
27546
27556
|
});
|
|
27547
27557
|
const shutdown = (signal) => {
|
|
@@ -27796,14 +27806,14 @@ async function startBrainProxy(opts) {
|
|
|
27796
27806
|
const { httpServer, handler } = buildBrainProxy(opts);
|
|
27797
27807
|
const port = opts.port ?? 0;
|
|
27798
27808
|
const host = opts.host ?? "127.0.0.1";
|
|
27799
|
-
await new Promise((
|
|
27809
|
+
await new Promise((resolve24) => httpServer.listen(port, host, () => resolve24()));
|
|
27800
27810
|
const addr = httpServer.address();
|
|
27801
27811
|
return {
|
|
27802
27812
|
httpServer,
|
|
27803
27813
|
port: addr.port,
|
|
27804
27814
|
url: `http://${host}:${addr.port}`,
|
|
27805
|
-
stop: () => new Promise((
|
|
27806
|
-
httpServer.close(() =>
|
|
27815
|
+
stop: () => new Promise((resolve24) => {
|
|
27816
|
+
httpServer.close(() => resolve24());
|
|
27807
27817
|
}),
|
|
27808
27818
|
handler
|
|
27809
27819
|
};
|
|
@@ -27953,23 +27963,23 @@ function buildMcpHttpServer(opts) {
|
|
|
27953
27963
|
httpServer,
|
|
27954
27964
|
routes,
|
|
27955
27965
|
port,
|
|
27956
|
-
stop: () => new Promise((
|
|
27966
|
+
stop: () => new Promise((resolve24) => {
|
|
27957
27967
|
let pending = transports.size;
|
|
27958
27968
|
if (pending === 0) {
|
|
27959
|
-
httpServer.close(() =>
|
|
27969
|
+
httpServer.close(() => resolve24());
|
|
27960
27970
|
return;
|
|
27961
27971
|
}
|
|
27962
27972
|
for (const transport of transports.values()) {
|
|
27963
27973
|
void transport.close().finally(() => {
|
|
27964
27974
|
pending--;
|
|
27965
|
-
if (pending === 0) httpServer.close(() =>
|
|
27975
|
+
if (pending === 0) httpServer.close(() => resolve24());
|
|
27966
27976
|
});
|
|
27967
27977
|
}
|
|
27968
27978
|
})
|
|
27969
27979
|
};
|
|
27970
27980
|
}
|
|
27971
27981
|
function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
27972
|
-
return new Promise((
|
|
27982
|
+
return new Promise((resolve24, reject) => {
|
|
27973
27983
|
server.httpServer.once("error", reject);
|
|
27974
27984
|
server.httpServer.listen(server.port, host, () => {
|
|
27975
27985
|
server.httpServer.off("error", reject);
|
|
@@ -27977,7 +27987,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
|
|
|
27977
27987
|
if (addr && typeof addr === "object") {
|
|
27978
27988
|
server.port = addr.port;
|
|
27979
27989
|
}
|
|
27980
|
-
|
|
27990
|
+
resolve24();
|
|
27981
27991
|
});
|
|
27982
27992
|
});
|
|
27983
27993
|
}
|
|
@@ -28060,7 +28070,7 @@ async function loadConfigSafe() {
|
|
|
28060
28070
|
}
|
|
28061
28071
|
|
|
28062
28072
|
// src/chat-cli.ts
|
|
28063
|
-
import * as
|
|
28073
|
+
import * as path56 from "path";
|
|
28064
28074
|
|
|
28065
28075
|
// src/chat/inbox.ts
|
|
28066
28076
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
@@ -28127,7 +28137,7 @@ async function waitForNextUserMessage(opts) {
|
|
|
28127
28137
|
}
|
|
28128
28138
|
}
|
|
28129
28139
|
function sleep3(ms) {
|
|
28130
|
-
return new Promise((
|
|
28140
|
+
return new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
28131
28141
|
}
|
|
28132
28142
|
function currentBranch(cwd) {
|
|
28133
28143
|
try {
|
|
@@ -28351,7 +28361,7 @@ async function runChat(argv) {
|
|
|
28351
28361
|
${CHAT_HELP}`);
|
|
28352
28362
|
return 64;
|
|
28353
28363
|
}
|
|
28354
|
-
const cwd = args.cwd ?
|
|
28364
|
+
const cwd = args.cwd ? path56.resolve(args.cwd) : process.cwd();
|
|
28355
28365
|
const sessionId = args.sessionId;
|
|
28356
28366
|
const runRequest = readRunRequestFromEnv();
|
|
28357
28367
|
if (runRequest && "request" in runRequest) {
|
|
@@ -28478,7 +28488,7 @@ init_registry();
|
|
|
28478
28488
|
|
|
28479
28489
|
// src/servers/brain-terminal-agent.ts
|
|
28480
28490
|
init_repoWorkspace();
|
|
28481
|
-
import * as
|
|
28491
|
+
import * as path58 from "path";
|
|
28482
28492
|
import { createInterface as createInterface2 } from "readline";
|
|
28483
28493
|
|
|
28484
28494
|
// src/terminal/brain-terminal-session.ts
|
|
@@ -28792,10 +28802,10 @@ var BrainTerminalSessionAgent = class {
|
|
|
28792
28802
|
// src/terminal/brain-terminal-adapters.ts
|
|
28793
28803
|
import { createHash as createHash10, randomBytes as randomBytes2 } from "crypto";
|
|
28794
28804
|
import { mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
|
|
28795
|
-
import * as
|
|
28805
|
+
import * as path57 from "path";
|
|
28796
28806
|
import { spawn as spawn9 } from "child_process";
|
|
28797
28807
|
function runTerminalCommand(command, args, input) {
|
|
28798
|
-
return new Promise((
|
|
28808
|
+
return new Promise((resolve24, reject) => {
|
|
28799
28809
|
const child = spawn9(command, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
28800
28810
|
const stdout = [];
|
|
28801
28811
|
const stderr = [];
|
|
@@ -28803,7 +28813,7 @@ function runTerminalCommand(command, args, input) {
|
|
|
28803
28813
|
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
28804
28814
|
child.on("error", reject);
|
|
28805
28815
|
child.on("close", (code) => {
|
|
28806
|
-
|
|
28816
|
+
resolve24({
|
|
28807
28817
|
code: code ?? 1,
|
|
28808
28818
|
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
28809
28819
|
stderr: Buffer.concat(stderr).toString("utf8")
|
|
@@ -28827,7 +28837,7 @@ var FileBrainTerminalMetadataStore = class {
|
|
|
28827
28837
|
}
|
|
28828
28838
|
root;
|
|
28829
28839
|
file(id) {
|
|
28830
|
-
return
|
|
28840
|
+
return path57.join(this.root, `${storeKey(id)}.json`);
|
|
28831
28841
|
}
|
|
28832
28842
|
async read(id) {
|
|
28833
28843
|
try {
|
|
@@ -28948,8 +28958,8 @@ async function brainTerminalAgent(options) {
|
|
|
28948
28958
|
const input = options.input ?? process.stdin;
|
|
28949
28959
|
const output = options.output ?? process.stdout;
|
|
28950
28960
|
const error = options.error ?? process.stderr;
|
|
28951
|
-
const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() ||
|
|
28952
|
-
const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() ||
|
|
28961
|
+
const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() || path58.join(path58.dirname(path58.resolve(options.cwd)), "repos");
|
|
28962
|
+
const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() || path58.join(path58.dirname(reposRoot), ".kody", "terminal-sessions");
|
|
28953
28963
|
const agent = new BrainTerminalSessionAgent({
|
|
28954
28964
|
store: new FileBrainTerminalMetadataStore(stateRoot),
|
|
28955
28965
|
runtime: new TmuxBrainTerminalRuntime()
|
|
@@ -29116,8 +29126,8 @@ var FlyClient = class {
|
|
|
29116
29126
|
get fetch() {
|
|
29117
29127
|
return this.opts.fetchImpl ?? fetch;
|
|
29118
29128
|
}
|
|
29119
|
-
async call(
|
|
29120
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
29129
|
+
async call(path59, init = {}) {
|
|
29130
|
+
const res = await this.fetch(`${FLY_API_BASE}${path59}`, {
|
|
29121
29131
|
method: init.method ?? "GET",
|
|
29122
29132
|
headers: {
|
|
29123
29133
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -29128,7 +29138,7 @@ var FlyClient = class {
|
|
|
29128
29138
|
if (res.status === 404 && init.allow404) return null;
|
|
29129
29139
|
if (!res.ok) {
|
|
29130
29140
|
const text2 = await res.text().catch(() => "");
|
|
29131
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
29141
|
+
throw new Error(`Fly API ${res.status} on ${path59}: ${text2.slice(0, 200) || res.statusText}`);
|
|
29132
29142
|
}
|
|
29133
29143
|
if (res.status === 204) return null;
|
|
29134
29144
|
const raw = await res.text();
|
|
@@ -29641,14 +29651,14 @@ function sendJson2(res, status, body) {
|
|
|
29641
29651
|
res.end(JSON.stringify(body));
|
|
29642
29652
|
}
|
|
29643
29653
|
function readJsonBody2(req) {
|
|
29644
|
-
return new Promise((
|
|
29654
|
+
return new Promise((resolve24, reject) => {
|
|
29645
29655
|
const chunks = [];
|
|
29646
29656
|
req.on("data", (c) => chunks.push(c));
|
|
29647
29657
|
req.on("end", () => {
|
|
29648
29658
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
29649
|
-
if (!raw.trim()) return
|
|
29659
|
+
if (!raw.trim()) return resolve24({});
|
|
29650
29660
|
try {
|
|
29651
|
-
|
|
29661
|
+
resolve24(JSON.parse(raw));
|
|
29652
29662
|
} catch (err) {
|
|
29653
29663
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
29654
29664
|
}
|
|
@@ -29802,10 +29812,10 @@ async function poolServe() {
|
|
|
29802
29812
|
}
|
|
29803
29813
|
});
|
|
29804
29814
|
const apiHost = process.env.POOL_API_HOST ?? "::";
|
|
29805
|
-
await new Promise((
|
|
29815
|
+
await new Promise((resolve24) => {
|
|
29806
29816
|
server.listen(apiPort, apiHost, () => {
|
|
29807
29817
|
log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
|
|
29808
|
-
|
|
29818
|
+
resolve24();
|
|
29809
29819
|
});
|
|
29810
29820
|
});
|
|
29811
29821
|
if (loopTickEnabled) void runLoopTick();
|
|
@@ -29845,17 +29855,17 @@ function authOk2(req, expected) {
|
|
|
29845
29855
|
return false;
|
|
29846
29856
|
}
|
|
29847
29857
|
function readJsonBody3(req) {
|
|
29848
|
-
return new Promise((
|
|
29858
|
+
return new Promise((resolve24, reject) => {
|
|
29849
29859
|
const chunks = [];
|
|
29850
29860
|
req.on("data", (c) => chunks.push(c));
|
|
29851
29861
|
req.on("end", () => {
|
|
29852
29862
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
29853
29863
|
if (!raw.trim()) {
|
|
29854
|
-
|
|
29864
|
+
resolve24({});
|
|
29855
29865
|
return;
|
|
29856
29866
|
}
|
|
29857
29867
|
try {
|
|
29858
|
-
|
|
29868
|
+
resolve24(JSON.parse(raw));
|
|
29859
29869
|
} catch (err) {
|
|
29860
29870
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
29861
29871
|
}
|
|
@@ -29930,13 +29940,13 @@ async function defaultRunJob(job) {
|
|
|
29930
29940
|
...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
|
|
29931
29941
|
...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
|
|
29932
29942
|
};
|
|
29933
|
-
const run = (cmd, args, cwd) => new Promise((
|
|
29943
|
+
const run = (cmd, args, cwd) => new Promise((resolve24) => {
|
|
29934
29944
|
const child = spawn10(cmd, args, { stdio: "inherit", env: childEnv, cwd });
|
|
29935
|
-
child.on("exit", (code) =>
|
|
29945
|
+
child.on("exit", (code) => resolve24(code ?? 0));
|
|
29936
29946
|
child.on("error", (err) => {
|
|
29937
29947
|
process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
|
|
29938
29948
|
`);
|
|
29939
|
-
|
|
29949
|
+
resolve24(1);
|
|
29940
29950
|
});
|
|
29941
29951
|
});
|
|
29942
29952
|
process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
|
|
@@ -30012,11 +30022,11 @@ async function runnerServe() {
|
|
|
30012
30022
|
const port = Number(process.env.PORT ?? DEFAULT_PORT2);
|
|
30013
30023
|
const server = buildServer2({ apiKey });
|
|
30014
30024
|
const host = process.env.RUNNER_HOST ?? "::";
|
|
30015
|
-
await new Promise((
|
|
30025
|
+
await new Promise((resolve24) => {
|
|
30016
30026
|
server.listen(port, host, () => {
|
|
30017
30027
|
process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
|
|
30018
30028
|
`);
|
|
30019
|
-
|
|
30029
|
+
resolve24();
|
|
30020
30030
|
});
|
|
30021
30031
|
});
|
|
30022
30032
|
const shutdown = (signal) => {
|
|
@@ -30085,14 +30095,14 @@ async function serve(opts) {
|
|
|
30085
30095
|
`);
|
|
30086
30096
|
const args = ["--dangerously-skip-permissions", "--model", model.model];
|
|
30087
30097
|
const child = spawn11("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
|
|
30088
|
-
const exitCode = await new Promise((
|
|
30089
|
-
child.on("exit", (code) =>
|
|
30098
|
+
const exitCode = await new Promise((resolve24) => {
|
|
30099
|
+
child.on("exit", (code) => resolve24(code ?? 0));
|
|
30090
30100
|
child.on("error", (err) => {
|
|
30091
30101
|
process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
|
|
30092
30102
|
`);
|
|
30093
30103
|
process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
|
|
30094
30104
|
`);
|
|
30095
|
-
|
|
30105
|
+
resolve24(1);
|
|
30096
30106
|
});
|
|
30097
30107
|
});
|
|
30098
30108
|
killProxy();
|