@kody-ade/kody-engine 0.4.307 → 0.4.308
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 +393 -310
- 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.308",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -1610,7 +1610,7 @@ function cmsHeaders(opts) {
|
|
|
1610
1610
|
}
|
|
1611
1611
|
};
|
|
1612
1612
|
}
|
|
1613
|
-
async function callDashboardCms(opts,
|
|
1613
|
+
async function callDashboardCms(opts, path51, init = {}) {
|
|
1614
1614
|
const baseUrl = dashboardBaseUrl(opts);
|
|
1615
1615
|
if (!baseUrl) {
|
|
1616
1616
|
return {
|
|
@@ -1622,7 +1622,7 @@ async function callDashboardCms(opts, path50, init = {}) {
|
|
|
1622
1622
|
const headerResult = cmsHeaders(opts);
|
|
1623
1623
|
if (!headerResult.ok) return headerResult;
|
|
1624
1624
|
try {
|
|
1625
|
-
const res = await fetch(`${baseUrl}${
|
|
1625
|
+
const res = await fetch(`${baseUrl}${path51}`, {
|
|
1626
1626
|
...init,
|
|
1627
1627
|
headers: {
|
|
1628
1628
|
...headerResult.headers,
|
|
@@ -1694,8 +1694,8 @@ function documentArg(value) {
|
|
|
1694
1694
|
function normalizeCmsDocumentIdInput(input) {
|
|
1695
1695
|
const trimmed = stripWrappingQuotes(input.trim());
|
|
1696
1696
|
const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
|
|
1697
|
-
const
|
|
1698
|
-
return
|
|
1697
|
+
const path51 = parseDocumentPath(withoutQuery);
|
|
1698
|
+
return path51 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
|
|
1699
1699
|
}
|
|
1700
1700
|
function stripWrappingQuotes(value) {
|
|
1701
1701
|
let current = value;
|
|
@@ -1706,9 +1706,9 @@ function stripWrappingQuotes(value) {
|
|
|
1706
1706
|
}
|
|
1707
1707
|
}
|
|
1708
1708
|
function parseDocumentPath(value) {
|
|
1709
|
-
const
|
|
1710
|
-
if (!
|
|
1711
|
-
const parts =
|
|
1709
|
+
const path51 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
|
|
1710
|
+
if (!path51?.includes("/content/entries/")) return null;
|
|
1711
|
+
const parts = path51.split("/").filter(Boolean).map(decodePathPart);
|
|
1712
1712
|
const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
|
|
1713
1713
|
const idPart = parts[entriesIndex + 3];
|
|
1714
1714
|
if (!idPart || idPart === "new") return null;
|
|
@@ -2041,6 +2041,23 @@ function getCompanyStoreAssetRoot(kind) {
|
|
|
2041
2041
|
if (fs5.existsSync(rootLayoutPath)) return rootLayoutPath;
|
|
2042
2042
|
return path7.join(root, ".kody", folderByKind[kind]);
|
|
2043
2043
|
}
|
|
2044
|
+
function resetCompanyStoreCacheForTests() {
|
|
2045
|
+
memo = null;
|
|
2046
|
+
}
|
|
2047
|
+
function applyCompanyStoreRuntimeConfig(input, env = process.env) {
|
|
2048
|
+
const repo = stringValue(input?.storeRepoUrl ?? input?.storeRepo);
|
|
2049
|
+
const ref = stringValue(input?.storeRef);
|
|
2050
|
+
let changed = false;
|
|
2051
|
+
if (repo && env[STORE_ENV] !== repo) {
|
|
2052
|
+
env[STORE_ENV] = repo;
|
|
2053
|
+
changed = true;
|
|
2054
|
+
}
|
|
2055
|
+
if (ref && env[REF_ENV] !== ref) {
|
|
2056
|
+
env[REF_ENV] = ref;
|
|
2057
|
+
changed = true;
|
|
2058
|
+
}
|
|
2059
|
+
if (changed) resetCompanyStoreCacheForTests();
|
|
2060
|
+
}
|
|
2044
2061
|
function resolveCompanyStore() {
|
|
2045
2062
|
const envStore = process.env[STORE_ENV]?.trim();
|
|
2046
2063
|
if (!envStore && process.env.VITEST) return null;
|
|
@@ -2050,6 +2067,9 @@ function resolveCompanyStore() {
|
|
|
2050
2067
|
if (!ref) return null;
|
|
2051
2068
|
return { repo, ref };
|
|
2052
2069
|
}
|
|
2070
|
+
function stringValue(value) {
|
|
2071
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2072
|
+
}
|
|
2053
2073
|
function fetchCompanyStore(repo, ref) {
|
|
2054
2074
|
const localRoot = localStoreRoot(repo);
|
|
2055
2075
|
if (localRoot) return localRoot;
|
|
@@ -6897,10 +6917,10 @@ var init_state2 = __esm({
|
|
|
6897
6917
|
"use strict";
|
|
6898
6918
|
VALID_STATES = /* @__PURE__ */ new Set(["active", "abandoned", "closed", "done"]);
|
|
6899
6919
|
GoalStateError = class extends Error {
|
|
6900
|
-
constructor(
|
|
6901
|
-
super(`Invalid goal state at ${
|
|
6920
|
+
constructor(path51, message) {
|
|
6921
|
+
super(`Invalid goal state at ${path51}:
|
|
6902
6922
|
${message}`);
|
|
6903
|
-
this.path =
|
|
6923
|
+
this.path = path51;
|
|
6904
6924
|
this.name = "GoalStateError";
|
|
6905
6925
|
}
|
|
6906
6926
|
path;
|
|
@@ -6913,9 +6933,9 @@ import * as fs25 from "fs";
|
|
|
6913
6933
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
6914
6934
|
const logs = goalRunLogs(data);
|
|
6915
6935
|
const existing = logs[goalId];
|
|
6916
|
-
const
|
|
6936
|
+
const path51 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
6917
6937
|
logs[goalId] = {
|
|
6918
|
-
path:
|
|
6938
|
+
path: path51,
|
|
6919
6939
|
events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
|
|
6920
6940
|
};
|
|
6921
6941
|
}
|
|
@@ -7002,7 +7022,7 @@ function goalRunStartedAt(data) {
|
|
|
7002
7022
|
function goalRunId(data) {
|
|
7003
7023
|
const existing = data[LOG_RUN_KEY];
|
|
7004
7024
|
if (typeof existing === "string" && existing.length > 0) return existing;
|
|
7005
|
-
const raw =
|
|
7025
|
+
const raw = stringValue2(data.jobId) ?? githubRunId() ?? `local-${process.pid}-${Date.now()}`;
|
|
7006
7026
|
const safe = safePathSegment(raw);
|
|
7007
7027
|
data[LOG_RUN_KEY] = safe;
|
|
7008
7028
|
return safe;
|
|
@@ -7101,7 +7121,7 @@ function triggerContext() {
|
|
|
7101
7121
|
issue: numberValue(recordValue2(event?.issue)?.number),
|
|
7102
7122
|
pullRequest: numberValue(recordValue2(event?.pull_request)?.number),
|
|
7103
7123
|
comment: numberValue(recordValue2(event?.comment)?.id),
|
|
7104
|
-
schedule:
|
|
7124
|
+
schedule: stringValue2(event?.schedule),
|
|
7105
7125
|
inputs: inputs ? pickRecord(inputs, ["issue_number", "sessionId", "message", "model", "title", "executable", "base"]) : void 0
|
|
7106
7126
|
});
|
|
7107
7127
|
return Object.keys(trigger).length > 0 ? trigger : void 0;
|
|
@@ -7120,16 +7140,16 @@ function triggerActorRole(eventName) {
|
|
|
7120
7140
|
}
|
|
7121
7141
|
function jobContext(data) {
|
|
7122
7142
|
const job = pruneUndefined({
|
|
7123
|
-
id:
|
|
7124
|
-
key:
|
|
7125
|
-
flavor:
|
|
7126
|
-
action:
|
|
7127
|
-
capability:
|
|
7128
|
-
executable:
|
|
7129
|
-
agent:
|
|
7130
|
-
schedule:
|
|
7143
|
+
id: stringValue2(data.jobId) ?? void 0,
|
|
7144
|
+
key: stringValue2(data.jobKey) ?? void 0,
|
|
7145
|
+
flavor: stringValue2(data.jobFlavor) ?? void 0,
|
|
7146
|
+
action: stringValue2(data.jobAction) ?? void 0,
|
|
7147
|
+
capability: stringValue2(data.jobCapability) ?? void 0,
|
|
7148
|
+
executable: stringValue2(data.jobExecutable) ?? void 0,
|
|
7149
|
+
agent: stringValue2(data.jobAgent) ?? void 0,
|
|
7150
|
+
schedule: stringValue2(data.jobSchedule) ?? void 0,
|
|
7131
7151
|
target: data.jobTarget ?? void 0,
|
|
7132
|
-
why: truncateString(
|
|
7152
|
+
why: truncateString(stringValue2(data.jobWhy), 1e3),
|
|
7133
7153
|
saveReport: data.jobSaveReport === true ? true : void 0
|
|
7134
7154
|
});
|
|
7135
7155
|
return Object.keys(job).length > 0 ? job : void 0;
|
|
@@ -7139,21 +7159,21 @@ function dispatchContext(event, trigger, job) {
|
|
|
7139
7159
|
const dispatch2 = event.dispatch ?? {};
|
|
7140
7160
|
const context = pruneUndefined({
|
|
7141
7161
|
triggeredBy: triggerLabel(trigger),
|
|
7142
|
-
triggerKind:
|
|
7162
|
+
triggerKind: stringValue2(trigger?.kind),
|
|
7143
7163
|
dispatchMode: dispatchMode(trigger),
|
|
7144
|
-
githubActor:
|
|
7145
|
-
githubActorRole:
|
|
7164
|
+
githubActor: stringValue2(trigger?.githubActor) ?? stringValue2(trigger?.actor),
|
|
7165
|
+
githubActorRole: stringValue2(trigger?.actorRole),
|
|
7146
7166
|
decidedBy: event.source,
|
|
7147
7167
|
dispatchedBy: event.source,
|
|
7148
7168
|
target: event.target,
|
|
7149
|
-
action: dispatch2.action ??
|
|
7150
|
-
capability: dispatch2.capability ??
|
|
7169
|
+
action: dispatch2.action ?? stringValue2(job?.action),
|
|
7170
|
+
capability: dispatch2.capability ?? stringValue2(job?.capability),
|
|
7151
7171
|
reason: event.reason
|
|
7152
7172
|
});
|
|
7153
7173
|
return Object.keys(context).length > 0 ? context : void 0;
|
|
7154
7174
|
}
|
|
7155
7175
|
function triggerLabel(trigger) {
|
|
7156
|
-
const kind =
|
|
7176
|
+
const kind = stringValue2(trigger?.kind);
|
|
7157
7177
|
if (kind === "schedule") return "GitHub schedule";
|
|
7158
7178
|
if (kind === "manual-workflow-dispatch") return "manual workflow dispatch";
|
|
7159
7179
|
if (kind === "issue_comment") return "GitHub issue comment";
|
|
@@ -7162,7 +7182,7 @@ function triggerLabel(trigger) {
|
|
|
7162
7182
|
return "local run";
|
|
7163
7183
|
}
|
|
7164
7184
|
function dispatchMode(trigger) {
|
|
7165
|
-
const kind =
|
|
7185
|
+
const kind = stringValue2(trigger?.kind);
|
|
7166
7186
|
if (kind === "schedule") return "automated";
|
|
7167
7187
|
if (kind === "manual-workflow-dispatch") return "manual";
|
|
7168
7188
|
if (kind) return "event-driven";
|
|
@@ -7174,10 +7194,10 @@ function linkContext(stateRepo) {
|
|
|
7174
7194
|
const repository = process.env.GITHUB_REPOSITORY?.trim();
|
|
7175
7195
|
const server = process.env.GITHUB_SERVER_URL?.trim() || "https://github.com";
|
|
7176
7196
|
if (runId && repository) links.workflowRun = `${server}/${repository}/actions/runs/${runId}`;
|
|
7177
|
-
const repo =
|
|
7178
|
-
const branch =
|
|
7179
|
-
const goalStatePath2 =
|
|
7180
|
-
const logPath =
|
|
7197
|
+
const repo = stringValue2(stateRepo?.repo);
|
|
7198
|
+
const branch = stringValue2(stateRepo?.branch);
|
|
7199
|
+
const goalStatePath2 = stringValue2(stateRepo?.goalStatePath);
|
|
7200
|
+
const logPath = stringValue2(stateRepo?.logPath);
|
|
7181
7201
|
if (repo && branch && goalStatePath2) links.goalState = githubBlobUrl(repo, branch, goalStatePath2);
|
|
7182
7202
|
if (repo && branch && logPath) links.log = githubBlobUrl(repo, branch, logPath);
|
|
7183
7203
|
return Object.keys(links).length > 0 ? links : void 0;
|
|
@@ -7257,7 +7277,7 @@ function truncateString(value, max) {
|
|
|
7257
7277
|
if (!value) return void 0;
|
|
7258
7278
|
return value.length > max ? `${value.slice(0, max)}...` : value;
|
|
7259
7279
|
}
|
|
7260
|
-
function
|
|
7280
|
+
function stringValue2(value) {
|
|
7261
7281
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
7262
7282
|
}
|
|
7263
7283
|
function safePathSegment(value) {
|
|
@@ -7430,6 +7450,8 @@ var init_managedTodoState = __esm({
|
|
|
7430
7450
|
});
|
|
7431
7451
|
|
|
7432
7452
|
// src/goal/stateStore.ts
|
|
7453
|
+
import * as fs26 from "fs";
|
|
7454
|
+
import * as path24 from "path";
|
|
7433
7455
|
function goalStatePath(goalId) {
|
|
7434
7456
|
return `todos/${goalId}.json`;
|
|
7435
7457
|
}
|
|
@@ -7438,7 +7460,55 @@ function fetchGoalState(config, goalId, cwd) {
|
|
|
7438
7460
|
const loaded = readStateText(config, cwd, filePath);
|
|
7439
7461
|
if (!loaded) return null;
|
|
7440
7462
|
if (!isManagedTodoRaw(loaded.content)) return null;
|
|
7441
|
-
return parseTodoGoalState(goalId, loaded.path, loaded.content);
|
|
7463
|
+
return resolveStoreBackedGoalState(parseTodoGoalState(goalId, loaded.path, loaded.content));
|
|
7464
|
+
}
|
|
7465
|
+
function resolveStoreBackedGoalState(state) {
|
|
7466
|
+
const templateId = templateIdFromGoalState(state);
|
|
7467
|
+
if (!templateId) return state;
|
|
7468
|
+
const template = readStoreGoalTemplate(templateId);
|
|
7469
|
+
if (!template) return state;
|
|
7470
|
+
const nextExtra = { ...state.extra };
|
|
7471
|
+
for (const key of [
|
|
7472
|
+
"type",
|
|
7473
|
+
"destination",
|
|
7474
|
+
"capabilities",
|
|
7475
|
+
"route",
|
|
7476
|
+
"schedule",
|
|
7477
|
+
"scheduleMode",
|
|
7478
|
+
"loopTarget",
|
|
7479
|
+
"preferredRunTime",
|
|
7480
|
+
"saveReport"
|
|
7481
|
+
]) {
|
|
7482
|
+
if (Object.hasOwn(template, key)) nextExtra[key] = template[key];
|
|
7483
|
+
else if (["schedule", "loopTarget", "preferredRunTime", "saveReport"].includes(key)) delete nextExtra[key];
|
|
7484
|
+
}
|
|
7485
|
+
nextExtra.facts = {
|
|
7486
|
+
...recordField2(template.facts) ?? {},
|
|
7487
|
+
...recordField2(state.extra.facts) ?? {}
|
|
7488
|
+
};
|
|
7489
|
+
return { ...state, extra: nextExtra };
|
|
7490
|
+
}
|
|
7491
|
+
function templateIdFromGoalState(state) {
|
|
7492
|
+
for (const key of ["sourceTemplate", "templateId", "template"]) {
|
|
7493
|
+
const value = state.extra[key];
|
|
7494
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
7495
|
+
}
|
|
7496
|
+
return "";
|
|
7497
|
+
}
|
|
7498
|
+
function readStoreGoalTemplate(templateId) {
|
|
7499
|
+
const root = getCompanyStoreAssetRoot("goals");
|
|
7500
|
+
if (!root) return null;
|
|
7501
|
+
const file = path24.join(root, "templates", templateId, "state.json");
|
|
7502
|
+
if (!fs26.existsSync(file)) return null;
|
|
7503
|
+
try {
|
|
7504
|
+
const parsed = JSON.parse(fs26.readFileSync(file, "utf8"));
|
|
7505
|
+
return recordField2(parsed);
|
|
7506
|
+
} catch {
|
|
7507
|
+
return null;
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7510
|
+
function recordField2(value) {
|
|
7511
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7442
7512
|
}
|
|
7443
7513
|
function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
|
|
7444
7514
|
const previous = readStateText(config, cwd, goalStatePath(goalId));
|
|
@@ -7463,12 +7533,13 @@ var init_stateStore = __esm({
|
|
|
7463
7533
|
"use strict";
|
|
7464
7534
|
init_stateRepo();
|
|
7465
7535
|
init_managedTodoState();
|
|
7536
|
+
init_companyStore();
|
|
7466
7537
|
}
|
|
7467
7538
|
});
|
|
7468
7539
|
|
|
7469
7540
|
// src/goal/targetLoopResolution.ts
|
|
7470
|
-
import * as
|
|
7471
|
-
import * as
|
|
7541
|
+
import * as fs27 from "fs";
|
|
7542
|
+
import * as path25 from "path";
|
|
7472
7543
|
function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
|
|
7473
7544
|
const targetId = loopGoal.loopTarget?.id.trim() ?? "";
|
|
7474
7545
|
assertSafeGoalId(targetId, "loop target");
|
|
@@ -7554,16 +7625,16 @@ function goalInstanceTime(state) {
|
|
|
7554
7625
|
return Number.isNaN(parsed) ? 0 : parsed;
|
|
7555
7626
|
}
|
|
7556
7627
|
function loadGoalTemplate(cwd, targetId) {
|
|
7557
|
-
const local =
|
|
7628
|
+
const local = path25.join(cwd, ".kody", "goals", "templates", targetId, "state.json");
|
|
7558
7629
|
const localTemplate = readJsonObject(local);
|
|
7559
7630
|
if (localTemplate) return localTemplate;
|
|
7560
7631
|
const storeGoalRoot = getCompanyStoreAssetRoot("goals");
|
|
7561
7632
|
if (!storeGoalRoot) return null;
|
|
7562
|
-
return readJsonObject(
|
|
7633
|
+
return readJsonObject(path25.join(storeGoalRoot, "templates", targetId, "state.json"));
|
|
7563
7634
|
}
|
|
7564
7635
|
function readJsonObject(filePath) {
|
|
7565
|
-
if (!
|
|
7566
|
-
const parsed = JSON.parse(
|
|
7636
|
+
if (!fs27.existsSync(filePath)) return null;
|
|
7637
|
+
const parsed = JSON.parse(fs27.readFileSync(filePath, "utf8"));
|
|
7567
7638
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7568
7639
|
throw new Error(`goal template ${filePath} must be a JSON object`);
|
|
7569
7640
|
}
|
|
@@ -7959,8 +8030,8 @@ var init_contentsApiBackend = __esm({
|
|
|
7959
8030
|
});
|
|
7960
8031
|
|
|
7961
8032
|
// src/scripts/jobState/localFileBackend.ts
|
|
7962
|
-
import * as
|
|
7963
|
-
import * as
|
|
8033
|
+
import * as fs28 from "fs";
|
|
8034
|
+
import * as path26 from "path";
|
|
7964
8035
|
function sanitizeKey(s) {
|
|
7965
8036
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
7966
8037
|
}
|
|
@@ -8016,7 +8087,7 @@ var init_localFileBackend = __esm({
|
|
|
8016
8087
|
if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
|
|
8017
8088
|
this.cwd = opts.cwd;
|
|
8018
8089
|
this.jobsDir = opts.jobsDir;
|
|
8019
|
-
this.absDir =
|
|
8090
|
+
this.absDir = path26.join(opts.cwd, opts.jobsDir);
|
|
8020
8091
|
this.owner = opts.owner;
|
|
8021
8092
|
this.repo = opts.repo;
|
|
8022
8093
|
this.cache = opts.cache ?? defaultCacheAdapter();
|
|
@@ -8031,7 +8102,7 @@ var init_localFileBackend = __esm({
|
|
|
8031
8102
|
`);
|
|
8032
8103
|
return;
|
|
8033
8104
|
}
|
|
8034
|
-
|
|
8105
|
+
fs28.mkdirSync(this.absDir, { recursive: true });
|
|
8035
8106
|
const prefix = this.cacheKeyPrefix();
|
|
8036
8107
|
const probeKey = `${prefix}probe-${Date.now()}`;
|
|
8037
8108
|
try {
|
|
@@ -8060,7 +8131,7 @@ var init_localFileBackend = __esm({
|
|
|
8060
8131
|
`);
|
|
8061
8132
|
return;
|
|
8062
8133
|
}
|
|
8063
|
-
if (!
|
|
8134
|
+
if (!fs28.existsSync(this.absDir)) {
|
|
8064
8135
|
return;
|
|
8065
8136
|
}
|
|
8066
8137
|
const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
|
|
@@ -8076,11 +8147,11 @@ var init_localFileBackend = __esm({
|
|
|
8076
8147
|
}
|
|
8077
8148
|
load(slug2) {
|
|
8078
8149
|
const relPath = stateFilePath(this.jobsDir, slug2);
|
|
8079
|
-
const absPath =
|
|
8080
|
-
if (!
|
|
8150
|
+
const absPath = path26.join(this.cwd, relPath);
|
|
8151
|
+
if (!fs28.existsSync(absPath)) {
|
|
8081
8152
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
8082
8153
|
}
|
|
8083
|
-
const raw =
|
|
8154
|
+
const raw = fs28.readFileSync(absPath, "utf-8");
|
|
8084
8155
|
let parsed;
|
|
8085
8156
|
try {
|
|
8086
8157
|
parsed = JSON.parse(raw);
|
|
@@ -8097,13 +8168,13 @@ var init_localFileBackend = __esm({
|
|
|
8097
8168
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
8098
8169
|
return false;
|
|
8099
8170
|
}
|
|
8100
|
-
const absPath =
|
|
8101
|
-
|
|
8171
|
+
const absPath = path26.join(this.cwd, loaded.path);
|
|
8172
|
+
fs28.mkdirSync(path26.dirname(absPath), { recursive: true });
|
|
8102
8173
|
const body = `${JSON.stringify(next, null, 2)}
|
|
8103
8174
|
`;
|
|
8104
8175
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
8105
|
-
|
|
8106
|
-
|
|
8176
|
+
fs28.writeFileSync(tmpPath, body, "utf-8");
|
|
8177
|
+
fs28.renameSync(tmpPath, absPath);
|
|
8107
8178
|
return true;
|
|
8108
8179
|
}
|
|
8109
8180
|
cacheKeyPrefix() {
|
|
@@ -8143,7 +8214,7 @@ var init_jobState = __esm({
|
|
|
8143
8214
|
});
|
|
8144
8215
|
|
|
8145
8216
|
// src/scripts/goalCapabilityScheduling.ts
|
|
8146
|
-
import * as
|
|
8217
|
+
import * as path27 from "path";
|
|
8147
8218
|
function isCapabilityCadenceGoal(goal, extra) {
|
|
8148
8219
|
return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
|
|
8149
8220
|
}
|
|
@@ -8199,7 +8270,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
8199
8270
|
}
|
|
8200
8271
|
async function planGoalCapabilitySchedule(opts) {
|
|
8201
8272
|
const jobsDir = opts.jobsDir ?? ".kody/capabilities";
|
|
8202
|
-
const jobsRoot =
|
|
8273
|
+
const jobsRoot = path27.join(opts.cwd, jobsDir);
|
|
8203
8274
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
8204
8275
|
const at = now.toISOString();
|
|
8205
8276
|
const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
|
|
@@ -9010,13 +9081,13 @@ function companyIntentPath(id) {
|
|
|
9010
9081
|
assertIntentId(id);
|
|
9011
9082
|
return `intents/${id}/intent.json`;
|
|
9012
9083
|
}
|
|
9013
|
-
function normalizeCompanyIntent(
|
|
9084
|
+
function normalizeCompanyIntent(path51, raw) {
|
|
9014
9085
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
9015
|
-
throw new Error(`${
|
|
9086
|
+
throw new Error(`${path51}: intent must be JSON object`);
|
|
9016
9087
|
}
|
|
9017
9088
|
const input = raw;
|
|
9018
9089
|
const id = stringField3(input.id);
|
|
9019
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
9090
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path51}: invalid intent id`);
|
|
9020
9091
|
const createdAt = stringField3(input.createdAt) || nowIso();
|
|
9021
9092
|
const updatedAt = stringField3(input.updatedAt) || createdAt;
|
|
9022
9093
|
const description = stringField3(input.description);
|
|
@@ -9033,21 +9104,21 @@ function normalizeCompanyIntent(path50, raw) {
|
|
|
9033
9104
|
"balanced"
|
|
9034
9105
|
),
|
|
9035
9106
|
scope: {
|
|
9036
|
-
repos: stringArray4(
|
|
9037
|
-
areas: stringArray4(
|
|
9107
|
+
repos: stringArray4(recordField3(input.scope)?.repos),
|
|
9108
|
+
areas: stringArray4(recordField3(input.scope)?.areas)
|
|
9038
9109
|
},
|
|
9039
9110
|
principles: stringArray4(input.principles),
|
|
9040
9111
|
metrics: stringArray4(input.metrics),
|
|
9041
9112
|
policy: {
|
|
9042
|
-
release: normalizeReleasePolicy(
|
|
9043
|
-
automation: normalizeAutomationPolicy(
|
|
9113
|
+
release: normalizeReleasePolicy(recordField3(recordField3(input.policy)?.release)),
|
|
9114
|
+
automation: normalizeAutomationPolicy(recordField3(recordField3(input.policy)?.automation))
|
|
9044
9115
|
},
|
|
9045
9116
|
portfolio: {
|
|
9046
|
-
goals: stringArray4(
|
|
9047
|
-
loops: stringArray4(
|
|
9048
|
-
capabilities: stringArray4(
|
|
9117
|
+
goals: stringArray4(recordField3(input.portfolio)?.goals).filter(isCompanyIntentId),
|
|
9118
|
+
loops: stringArray4(recordField3(input.portfolio)?.loops).filter(isCompanyIntentId),
|
|
9119
|
+
capabilities: stringArray4(recordField3(input.portfolio)?.capabilities).filter(isCompanyIntentId)
|
|
9049
9120
|
},
|
|
9050
|
-
manager: normalizeManager(
|
|
9121
|
+
manager: normalizeManager(recordField3(input.manager)),
|
|
9051
9122
|
createdAt,
|
|
9052
9123
|
updatedAt
|
|
9053
9124
|
};
|
|
@@ -9057,8 +9128,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
9057
9128
|
const records = [];
|
|
9058
9129
|
for (const entry of entries) {
|
|
9059
9130
|
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
9060
|
-
const
|
|
9061
|
-
const file = readStateText(config, cwd,
|
|
9131
|
+
const path51 = companyIntentPath(entry.name);
|
|
9132
|
+
const file = readStateText(config, cwd, path51);
|
|
9062
9133
|
if (!file) continue;
|
|
9063
9134
|
records.push({
|
|
9064
9135
|
id: entry.name,
|
|
@@ -9069,8 +9140,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
9069
9140
|
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
9070
9141
|
}
|
|
9071
9142
|
function readCompanyIntent(config, cwd, id) {
|
|
9072
|
-
const
|
|
9073
|
-
const file = readStateText(config, cwd,
|
|
9143
|
+
const path51 = companyIntentPath(id);
|
|
9144
|
+
const file = readStateText(config, cwd, path51);
|
|
9074
9145
|
if (!file) return null;
|
|
9075
9146
|
return { id, path: file.path, intent: normalizeCompanyIntent(file.path, JSON.parse(file.content)) };
|
|
9076
9147
|
}
|
|
@@ -9088,7 +9159,7 @@ function listCompanyPortfolio(config, cwd) {
|
|
|
9088
9159
|
if (!isCompanyIntentId(id)) continue;
|
|
9089
9160
|
const state = fetchGoalState(config, id, cwd);
|
|
9090
9161
|
if (!state) continue;
|
|
9091
|
-
const destination =
|
|
9162
|
+
const destination = recordField3(state.extra.destination);
|
|
9092
9163
|
goals.push({
|
|
9093
9164
|
id,
|
|
9094
9165
|
state: state.state,
|
|
@@ -9114,7 +9185,7 @@ function stringField3(value) {
|
|
|
9114
9185
|
function numberField(value, fallback) {
|
|
9115
9186
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
9116
9187
|
}
|
|
9117
|
-
function
|
|
9188
|
+
function recordField3(value) {
|
|
9118
9189
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9119
9190
|
}
|
|
9120
9191
|
function stringArray4(value) {
|
|
@@ -9502,7 +9573,7 @@ function capabilityEvidenceOutput(evidence) {
|
|
|
9502
9573
|
function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
9503
9574
|
const outputs = evidenceItems.map(capabilityEvidenceOutput);
|
|
9504
9575
|
const latestOutput = outputs.at(-1);
|
|
9505
|
-
const facts =
|
|
9576
|
+
const facts = recordField4(snapshot, "facts") ?? recordField4(state.extra, "facts") ?? {};
|
|
9506
9577
|
const blockers = uniqueStrings2([
|
|
9507
9578
|
...stringArrayField(snapshot, "blockers"),
|
|
9508
9579
|
...stringArrayField(latestEvent, "blockers"),
|
|
@@ -9554,7 +9625,7 @@ function capabilityEvidenceMarkdown(outputs) {
|
|
|
9554
9625
|
function decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers) {
|
|
9555
9626
|
if (state.state === "done") return "destination evidence satisfied";
|
|
9556
9627
|
if (blockers.length > 0) return blockers[0] ?? "blocked";
|
|
9557
|
-
const eventReason = stringField4(latestEvent, "reason") ?? stringField4(
|
|
9628
|
+
const eventReason = stringField4(latestEvent, "reason") ?? stringField4(recordField4(latestEvent, "decision"), "reason");
|
|
9558
9629
|
if (eventReason) return eventReason;
|
|
9559
9630
|
const summary = stringField4(latestOutput, "summary");
|
|
9560
9631
|
if (summary) return summary;
|
|
@@ -9567,18 +9638,18 @@ function evidenceOutputMarkdown(index, output) {
|
|
|
9567
9638
|
`- Status: ${stringField4(output, "status") ?? "unknown"}`,
|
|
9568
9639
|
`- Summary: ${stringField4(output, "summary") ?? "no summary"}`,
|
|
9569
9640
|
`- Sources: ${listOrNone(stringArrayField(output, "sources"))}`,
|
|
9570
|
-
`- Evidence values: ${inlineJson(
|
|
9641
|
+
`- Evidence values: ${inlineJson(recordField4(output, "evidence") ?? {})}`,
|
|
9571
9642
|
`- Missing evidence: ${listOrNone(stringArrayField(output, "missingEvidence"))}`,
|
|
9572
9643
|
`- Blockers: ${listOrNone(stringArrayField(output, "blockers"))}`,
|
|
9573
9644
|
""
|
|
9574
9645
|
];
|
|
9575
9646
|
}
|
|
9576
9647
|
function dispatchContextMarkdown(latestEvent) {
|
|
9577
|
-
const context =
|
|
9648
|
+
const context = recordField4(latestEvent, "dispatchContext");
|
|
9578
9649
|
if (!context) return ["- none"];
|
|
9579
9650
|
const githubActor = stringField4(context, "githubActor");
|
|
9580
9651
|
const githubActorRole = stringField4(context, "githubActorRole");
|
|
9581
|
-
const target = dispatchTargetLabel(
|
|
9652
|
+
const target = dispatchTargetLabel(recordField4(context, "target"));
|
|
9582
9653
|
return [
|
|
9583
9654
|
`- Triggered by: ${stringField4(context, "triggeredBy") ?? "unknown"}`,
|
|
9584
9655
|
`- Mode: ${stringField4(context, "dispatchMode") ?? "unknown"}`,
|
|
@@ -9617,7 +9688,7 @@ function stringField4(record2, key) {
|
|
|
9617
9688
|
const value = record2?.[key];
|
|
9618
9689
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
9619
9690
|
}
|
|
9620
|
-
function
|
|
9691
|
+
function recordField4(record2, key) {
|
|
9621
9692
|
const value = record2?.[key];
|
|
9622
9693
|
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : void 0;
|
|
9623
9694
|
}
|
|
@@ -9650,7 +9721,7 @@ ${artifact.path ?? ""}`;
|
|
|
9650
9721
|
}
|
|
9651
9722
|
function nextStepFromEvent(state, goalAfter, capabilityOutput, latestEvent) {
|
|
9652
9723
|
if (state.state === "done") return "done";
|
|
9653
|
-
const decisionKind = stringField4(
|
|
9724
|
+
const decisionKind = stringField4(recordField4(latestEvent, "decision"), "kind") ?? stringField4(latestEvent, "status");
|
|
9654
9725
|
if (decisionKind === "done") return "done";
|
|
9655
9726
|
if (decisionKind === "dispatch") return "dispatch";
|
|
9656
9727
|
if (decisionKind === "blocked" || decisionKind === "reject-evidence") return "block";
|
|
@@ -10113,8 +10184,8 @@ var init_classifyByLabel = __esm({
|
|
|
10113
10184
|
});
|
|
10114
10185
|
|
|
10115
10186
|
// src/scripts/commitAndPush.ts
|
|
10116
|
-
import * as
|
|
10117
|
-
import * as
|
|
10187
|
+
import * as fs29 from "fs";
|
|
10188
|
+
import * as path28 from "path";
|
|
10118
10189
|
function sentinelPathForStage(cwd, profileName) {
|
|
10119
10190
|
const runId = resolveRunId();
|
|
10120
10191
|
return runtimeStatePath(cwd, "agent-runs", runId, `commit-${profileName}.lock`);
|
|
@@ -10135,9 +10206,9 @@ var init_commitAndPush = __esm({
|
|
|
10135
10206
|
}
|
|
10136
10207
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
10137
10208
|
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
10138
|
-
if (sentinel &&
|
|
10209
|
+
if (sentinel && fs29.existsSync(sentinel)) {
|
|
10139
10210
|
try {
|
|
10140
|
-
const replay = JSON.parse(
|
|
10211
|
+
const replay = JSON.parse(fs29.readFileSync(sentinel, "utf-8"));
|
|
10141
10212
|
ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
|
|
10142
10213
|
if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
|
|
10143
10214
|
if (typeof replay.hasCommitsAhead === "boolean") ctx.data.hasCommitsAhead = replay.hasCommitsAhead;
|
|
@@ -10190,8 +10261,8 @@ var init_commitAndPush = __esm({
|
|
|
10190
10261
|
const result = ctx.data.commitResult;
|
|
10191
10262
|
if (sentinel && result?.committed) {
|
|
10192
10263
|
try {
|
|
10193
|
-
|
|
10194
|
-
|
|
10264
|
+
fs29.mkdirSync(path28.dirname(sentinel), { recursive: true });
|
|
10265
|
+
fs29.writeFileSync(
|
|
10195
10266
|
sentinel,
|
|
10196
10267
|
JSON.stringify(
|
|
10197
10268
|
{
|
|
@@ -10282,8 +10353,8 @@ var init_commitGoalState = __esm({
|
|
|
10282
10353
|
});
|
|
10283
10354
|
|
|
10284
10355
|
// src/scripts/composePrompt.ts
|
|
10285
|
-
import * as
|
|
10286
|
-
import * as
|
|
10356
|
+
import * as fs30 from "fs";
|
|
10357
|
+
import * as path29 from "path";
|
|
10287
10358
|
function fenceUntrusted(value) {
|
|
10288
10359
|
if (value.trim().length === 0) return value;
|
|
10289
10360
|
const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
|
|
@@ -10406,10 +10477,10 @@ var init_composePrompt = __esm({
|
|
|
10406
10477
|
const explicit = ctx.data.promptTemplate;
|
|
10407
10478
|
const mode = ctx.args.mode;
|
|
10408
10479
|
const candidates = [
|
|
10409
|
-
explicit ?
|
|
10410
|
-
mode ?
|
|
10411
|
-
|
|
10412
|
-
|
|
10480
|
+
explicit ? path29.join(profile.dir, explicit) : null,
|
|
10481
|
+
mode ? path29.join(profile.dir, "prompts", `${mode}.md`) : null,
|
|
10482
|
+
path29.join(profile.dir, "prompt.md"),
|
|
10483
|
+
path29.join(profile.dir, "capability.md")
|
|
10413
10484
|
].filter(Boolean);
|
|
10414
10485
|
let templatePath = "";
|
|
10415
10486
|
let template = "";
|
|
@@ -10422,7 +10493,7 @@ var init_composePrompt = __esm({
|
|
|
10422
10493
|
break;
|
|
10423
10494
|
}
|
|
10424
10495
|
try {
|
|
10425
|
-
template =
|
|
10496
|
+
template = fs30.readFileSync(c, "utf-8");
|
|
10426
10497
|
templatePath = c;
|
|
10427
10498
|
break;
|
|
10428
10499
|
} catch (err) {
|
|
@@ -10433,7 +10504,7 @@ var init_composePrompt = __esm({
|
|
|
10433
10504
|
if (!templatePath) {
|
|
10434
10505
|
let dirState;
|
|
10435
10506
|
try {
|
|
10436
|
-
dirState = `dir contents: [${
|
|
10507
|
+
dirState = `dir contents: [${fs30.readdirSync(profile.dir).join(", ")}]`;
|
|
10437
10508
|
} catch (err) {
|
|
10438
10509
|
dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
|
|
10439
10510
|
}
|
|
@@ -11118,19 +11189,19 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
11118
11189
|
|
|
11119
11190
|
// src/scripts/diagMcp.ts
|
|
11120
11191
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
11121
|
-
import * as
|
|
11192
|
+
import * as fs31 from "fs";
|
|
11122
11193
|
import * as os6 from "os";
|
|
11123
|
-
import * as
|
|
11194
|
+
import * as path30 from "path";
|
|
11124
11195
|
var diagMcp;
|
|
11125
11196
|
var init_diagMcp = __esm({
|
|
11126
11197
|
"src/scripts/diagMcp.ts"() {
|
|
11127
11198
|
"use strict";
|
|
11128
11199
|
diagMcp = async (_ctx) => {
|
|
11129
11200
|
const home = os6.homedir();
|
|
11130
|
-
const cacheDir =
|
|
11201
|
+
const cacheDir = path30.join(home, ".cache", "ms-playwright");
|
|
11131
11202
|
let entries = [];
|
|
11132
11203
|
try {
|
|
11133
|
-
entries =
|
|
11204
|
+
entries = fs31.readdirSync(cacheDir);
|
|
11134
11205
|
} catch {
|
|
11135
11206
|
}
|
|
11136
11207
|
const hasChromium = entries.some((e) => e.startsWith("chromium"));
|
|
@@ -11158,13 +11229,13 @@ var init_diagMcp = __esm({
|
|
|
11158
11229
|
});
|
|
11159
11230
|
|
|
11160
11231
|
// src/scripts/frameworkDetectors.ts
|
|
11161
|
-
import * as
|
|
11162
|
-
import * as
|
|
11232
|
+
import * as fs32 from "fs";
|
|
11233
|
+
import * as path31 from "path";
|
|
11163
11234
|
function detectFrameworks(cwd) {
|
|
11164
11235
|
const out = [];
|
|
11165
11236
|
let deps = {};
|
|
11166
11237
|
try {
|
|
11167
|
-
const pkg = JSON.parse(
|
|
11238
|
+
const pkg = JSON.parse(fs32.readFileSync(path31.join(cwd, "package.json"), "utf-8"));
|
|
11168
11239
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
11169
11240
|
} catch {
|
|
11170
11241
|
return out;
|
|
@@ -11201,25 +11272,25 @@ function detectFrameworks(cwd) {
|
|
|
11201
11272
|
}
|
|
11202
11273
|
function findFile(cwd, candidates) {
|
|
11203
11274
|
for (const c of candidates) {
|
|
11204
|
-
if (
|
|
11275
|
+
if (fs32.existsSync(path31.join(cwd, c))) return c;
|
|
11205
11276
|
}
|
|
11206
11277
|
return null;
|
|
11207
11278
|
}
|
|
11208
11279
|
function discoverPayloadCollections(cwd) {
|
|
11209
11280
|
const out = [];
|
|
11210
11281
|
for (const dir of COLLECTION_DIRS) {
|
|
11211
|
-
const full =
|
|
11212
|
-
if (!
|
|
11282
|
+
const full = path31.join(cwd, dir);
|
|
11283
|
+
if (!fs32.existsSync(full)) continue;
|
|
11213
11284
|
let files;
|
|
11214
11285
|
try {
|
|
11215
|
-
files =
|
|
11286
|
+
files = fs32.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
11216
11287
|
} catch {
|
|
11217
11288
|
continue;
|
|
11218
11289
|
}
|
|
11219
11290
|
for (const file of files) {
|
|
11220
11291
|
try {
|
|
11221
|
-
const filePath =
|
|
11222
|
-
const content =
|
|
11292
|
+
const filePath = path31.join(full, file);
|
|
11293
|
+
const content = fs32.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
11223
11294
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
11224
11295
|
if (!slugMatch) continue;
|
|
11225
11296
|
const slug2 = slugMatch[1];
|
|
@@ -11233,7 +11304,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
11233
11304
|
out.push({
|
|
11234
11305
|
name,
|
|
11235
11306
|
slug: slug2,
|
|
11236
|
-
filePath:
|
|
11307
|
+
filePath: path31.relative(cwd, filePath),
|
|
11237
11308
|
fields: fields.slice(0, 20),
|
|
11238
11309
|
hasAdmin
|
|
11239
11310
|
});
|
|
@@ -11246,28 +11317,28 @@ function discoverPayloadCollections(cwd) {
|
|
|
11246
11317
|
function discoverAdminComponents(cwd, collections) {
|
|
11247
11318
|
const out = [];
|
|
11248
11319
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
11249
|
-
const full =
|
|
11250
|
-
if (!
|
|
11320
|
+
const full = path31.join(cwd, dir);
|
|
11321
|
+
if (!fs32.existsSync(full)) continue;
|
|
11251
11322
|
let entries;
|
|
11252
11323
|
try {
|
|
11253
|
-
entries =
|
|
11324
|
+
entries = fs32.readdirSync(full, { withFileTypes: true });
|
|
11254
11325
|
} catch {
|
|
11255
11326
|
continue;
|
|
11256
11327
|
}
|
|
11257
11328
|
for (const entry of entries) {
|
|
11258
|
-
const entryPath =
|
|
11329
|
+
const entryPath = path31.join(full, entry.name);
|
|
11259
11330
|
let name;
|
|
11260
11331
|
let filePath;
|
|
11261
11332
|
if (entry.isDirectory()) {
|
|
11262
11333
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
11263
|
-
(f) =>
|
|
11334
|
+
(f) => fs32.existsSync(path31.join(entryPath, f))
|
|
11264
11335
|
);
|
|
11265
11336
|
if (!indexFile) continue;
|
|
11266
11337
|
name = entry.name;
|
|
11267
|
-
filePath =
|
|
11338
|
+
filePath = path31.relative(cwd, path31.join(entryPath, indexFile));
|
|
11268
11339
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
11269
11340
|
name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
|
|
11270
|
-
filePath =
|
|
11341
|
+
filePath = path31.relative(cwd, entryPath);
|
|
11271
11342
|
} else {
|
|
11272
11343
|
continue;
|
|
11273
11344
|
}
|
|
@@ -11275,7 +11346,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
11275
11346
|
if (collections) {
|
|
11276
11347
|
for (const col of collections) {
|
|
11277
11348
|
try {
|
|
11278
|
-
const colContent =
|
|
11349
|
+
const colContent = fs32.readFileSync(path31.join(cwd, col.filePath), "utf-8");
|
|
11279
11350
|
if (colContent.includes(name)) {
|
|
11280
11351
|
usedInCollection = col.slug;
|
|
11281
11352
|
break;
|
|
@@ -11293,8 +11364,8 @@ function scanApiRoutes(cwd) {
|
|
|
11293
11364
|
const out = [];
|
|
11294
11365
|
const appDirs = ["src/app", "app"];
|
|
11295
11366
|
for (const appDir of appDirs) {
|
|
11296
|
-
const apiDir =
|
|
11297
|
-
if (!
|
|
11367
|
+
const apiDir = path31.join(cwd, appDir, "api");
|
|
11368
|
+
if (!fs32.existsSync(apiDir)) continue;
|
|
11298
11369
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
11299
11370
|
break;
|
|
11300
11371
|
}
|
|
@@ -11303,14 +11374,14 @@ function scanApiRoutes(cwd) {
|
|
|
11303
11374
|
function walkApiRoutes(dir, prefix, cwd, out) {
|
|
11304
11375
|
let entries;
|
|
11305
11376
|
try {
|
|
11306
|
-
entries =
|
|
11377
|
+
entries = fs32.readdirSync(dir, { withFileTypes: true });
|
|
11307
11378
|
} catch {
|
|
11308
11379
|
return;
|
|
11309
11380
|
}
|
|
11310
11381
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
11311
11382
|
if (routeFile) {
|
|
11312
11383
|
try {
|
|
11313
|
-
const content =
|
|
11384
|
+
const content = fs32.readFileSync(path31.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
11314
11385
|
const methods = HTTP_METHODS.filter(
|
|
11315
11386
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
11316
11387
|
);
|
|
@@ -11318,7 +11389,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
11318
11389
|
out.push({
|
|
11319
11390
|
path: prefix,
|
|
11320
11391
|
methods,
|
|
11321
|
-
filePath:
|
|
11392
|
+
filePath: path31.relative(cwd, path31.join(dir, routeFile.name))
|
|
11322
11393
|
});
|
|
11323
11394
|
}
|
|
11324
11395
|
} catch {
|
|
@@ -11329,7 +11400,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
11329
11400
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
11330
11401
|
let segment = entry.name;
|
|
11331
11402
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
11332
|
-
walkApiRoutes(
|
|
11403
|
+
walkApiRoutes(path31.join(dir, entry.name), prefix, cwd, out);
|
|
11333
11404
|
continue;
|
|
11334
11405
|
}
|
|
11335
11406
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -11337,16 +11408,16 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
11337
11408
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
11338
11409
|
segment = `:${segment.slice(1, -1)}`;
|
|
11339
11410
|
}
|
|
11340
|
-
walkApiRoutes(
|
|
11411
|
+
walkApiRoutes(path31.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
|
|
11341
11412
|
}
|
|
11342
11413
|
}
|
|
11343
11414
|
function scanEnvVars(cwd) {
|
|
11344
11415
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
11345
11416
|
for (const envFile of candidates) {
|
|
11346
|
-
const envPath =
|
|
11347
|
-
if (!
|
|
11417
|
+
const envPath = path31.join(cwd, envFile);
|
|
11418
|
+
if (!fs32.existsSync(envPath)) continue;
|
|
11348
11419
|
try {
|
|
11349
|
-
const content =
|
|
11420
|
+
const content = fs32.readFileSync(envPath, "utf-8");
|
|
11350
11421
|
const vars = [];
|
|
11351
11422
|
for (const line of content.split("\n")) {
|
|
11352
11423
|
const trimmed = line.trim();
|
|
@@ -11391,8 +11462,8 @@ var init_frameworkDetectors = __esm({
|
|
|
11391
11462
|
});
|
|
11392
11463
|
|
|
11393
11464
|
// src/scripts/discoverQaContext.ts
|
|
11394
|
-
import * as
|
|
11395
|
-
import * as
|
|
11465
|
+
import * as fs33 from "fs";
|
|
11466
|
+
import * as path32 from "path";
|
|
11396
11467
|
function runQaDiscovery(cwd) {
|
|
11397
11468
|
const out = {
|
|
11398
11469
|
routes: [],
|
|
@@ -11423,9 +11494,9 @@ function runQaDiscovery(cwd) {
|
|
|
11423
11494
|
}
|
|
11424
11495
|
function detectDevServer(cwd, out) {
|
|
11425
11496
|
try {
|
|
11426
|
-
const pkg = JSON.parse(
|
|
11497
|
+
const pkg = JSON.parse(fs33.readFileSync(path32.join(cwd, "package.json"), "utf-8"));
|
|
11427
11498
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
11428
|
-
const pm =
|
|
11499
|
+
const pm = fs33.existsSync(path32.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs33.existsSync(path32.join(cwd, "yarn.lock")) ? "yarn" : fs33.existsSync(path32.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
11429
11500
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
11430
11501
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
11431
11502
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -11435,8 +11506,8 @@ function detectDevServer(cwd, out) {
|
|
|
11435
11506
|
function scanFrontendRoutes(cwd, out) {
|
|
11436
11507
|
const appDirs = ["src/app", "app"];
|
|
11437
11508
|
for (const appDir of appDirs) {
|
|
11438
|
-
const full =
|
|
11439
|
-
if (!
|
|
11509
|
+
const full = path32.join(cwd, appDir);
|
|
11510
|
+
if (!fs33.existsSync(full)) continue;
|
|
11440
11511
|
walkFrontendRoutes(full, "", out);
|
|
11441
11512
|
break;
|
|
11442
11513
|
}
|
|
@@ -11444,7 +11515,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
11444
11515
|
function walkFrontendRoutes(dir, prefix, out) {
|
|
11445
11516
|
let entries;
|
|
11446
11517
|
try {
|
|
11447
|
-
entries =
|
|
11518
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
11448
11519
|
} catch {
|
|
11449
11520
|
return;
|
|
11450
11521
|
}
|
|
@@ -11461,7 +11532,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
11461
11532
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
11462
11533
|
let segment = entry.name;
|
|
11463
11534
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
11464
|
-
walkFrontendRoutes(
|
|
11535
|
+
walkFrontendRoutes(path32.join(dir, entry.name), prefix, out);
|
|
11465
11536
|
continue;
|
|
11466
11537
|
}
|
|
11467
11538
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -11469,7 +11540,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
11469
11540
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
11470
11541
|
segment = `:${segment.slice(1, -1)}`;
|
|
11471
11542
|
}
|
|
11472
|
-
walkFrontendRoutes(
|
|
11543
|
+
walkFrontendRoutes(path32.join(dir, entry.name), `${prefix}/${segment}`, out);
|
|
11473
11544
|
}
|
|
11474
11545
|
}
|
|
11475
11546
|
function detectAuthFiles(cwd, out) {
|
|
@@ -11486,23 +11557,23 @@ function detectAuthFiles(cwd, out) {
|
|
|
11486
11557
|
"src/app/api/oauth"
|
|
11487
11558
|
];
|
|
11488
11559
|
for (const c of candidates) {
|
|
11489
|
-
if (
|
|
11560
|
+
if (fs33.existsSync(path32.join(cwd, c))) out.authFiles.push(c);
|
|
11490
11561
|
}
|
|
11491
11562
|
}
|
|
11492
11563
|
function detectRoles(cwd, out) {
|
|
11493
11564
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
11494
11565
|
for (const rp of rolePaths) {
|
|
11495
|
-
const dir =
|
|
11496
|
-
if (!
|
|
11566
|
+
const dir = path32.join(cwd, rp);
|
|
11567
|
+
if (!fs33.existsSync(dir)) continue;
|
|
11497
11568
|
let files;
|
|
11498
11569
|
try {
|
|
11499
|
-
files =
|
|
11570
|
+
files = fs33.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
11500
11571
|
} catch {
|
|
11501
11572
|
continue;
|
|
11502
11573
|
}
|
|
11503
11574
|
for (const f of files) {
|
|
11504
11575
|
try {
|
|
11505
|
-
const content =
|
|
11576
|
+
const content = fs33.readFileSync(path32.join(dir, f), "utf-8").slice(0, 5e3);
|
|
11506
11577
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
11507
11578
|
if (roleMatches) {
|
|
11508
11579
|
for (const m of roleMatches) {
|
|
@@ -12742,12 +12813,12 @@ var init_fixFlow = __esm({
|
|
|
12742
12813
|
|
|
12743
12814
|
// src/scripts/initFlow.ts
|
|
12744
12815
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
12745
|
-
import * as
|
|
12746
|
-
import * as
|
|
12816
|
+
import * as fs34 from "fs";
|
|
12817
|
+
import * as path33 from "path";
|
|
12747
12818
|
function detectPackageManager(cwd) {
|
|
12748
|
-
if (
|
|
12749
|
-
if (
|
|
12750
|
-
if (
|
|
12819
|
+
if (fs34.existsSync(path33.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
12820
|
+
if (fs34.existsSync(path33.join(cwd, "yarn.lock"))) return "yarn";
|
|
12821
|
+
if (fs34.existsSync(path33.join(cwd, "bun.lockb"))) return "bun";
|
|
12751
12822
|
return "npm";
|
|
12752
12823
|
}
|
|
12753
12824
|
function qualityCommandsFor(pm) {
|
|
@@ -12819,22 +12890,22 @@ function performInit(cwd, force) {
|
|
|
12819
12890
|
const pm = detectPackageManager(cwd);
|
|
12820
12891
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
12821
12892
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
12822
|
-
const configPath =
|
|
12823
|
-
if (
|
|
12893
|
+
const configPath = path33.join(cwd, "kody.config.json");
|
|
12894
|
+
if (fs34.existsSync(configPath) && !force) {
|
|
12824
12895
|
skipped.push("kody.config.json");
|
|
12825
12896
|
} else {
|
|
12826
12897
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
12827
|
-
|
|
12898
|
+
fs34.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
12828
12899
|
`);
|
|
12829
12900
|
wrote.push("kody.config.json");
|
|
12830
12901
|
}
|
|
12831
|
-
const workflowDir =
|
|
12832
|
-
const workflowPath =
|
|
12833
|
-
if (
|
|
12902
|
+
const workflowDir = path33.join(cwd, ".github", "workflows");
|
|
12903
|
+
const workflowPath = path33.join(workflowDir, "kody.yml");
|
|
12904
|
+
if (fs34.existsSync(workflowPath) && !force) {
|
|
12834
12905
|
skipped.push(".github/workflows/kody.yml");
|
|
12835
12906
|
} else {
|
|
12836
|
-
|
|
12837
|
-
|
|
12907
|
+
fs34.mkdirSync(workflowDir, { recursive: true });
|
|
12908
|
+
fs34.writeFileSync(workflowPath, WORKFLOW_TEMPLATE);
|
|
12838
12909
|
wrote.push(".github/workflows/kody.yml");
|
|
12839
12910
|
}
|
|
12840
12911
|
for (const exe of listExecutables()) {
|
|
@@ -12845,12 +12916,12 @@ function performInit(cwd, force) {
|
|
|
12845
12916
|
continue;
|
|
12846
12917
|
}
|
|
12847
12918
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
12848
|
-
const target =
|
|
12849
|
-
if (
|
|
12919
|
+
const target = path33.join(workflowDir, `kody-${exe.name}.yml`);
|
|
12920
|
+
if (fs34.existsSync(target) && !force) {
|
|
12850
12921
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
12851
12922
|
continue;
|
|
12852
12923
|
}
|
|
12853
|
-
|
|
12924
|
+
fs34.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
12854
12925
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
12855
12926
|
}
|
|
12856
12927
|
let labels;
|
|
@@ -12998,7 +13069,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
12998
13069
|
});
|
|
12999
13070
|
|
|
13000
13071
|
// src/scripts/loadAgentAdhoc.ts
|
|
13001
|
-
import * as
|
|
13072
|
+
import * as fs35 from "fs";
|
|
13002
13073
|
function resolveMessage(messageArg) {
|
|
13003
13074
|
const fromComment = readCommentBody();
|
|
13004
13075
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -13006,9 +13077,9 @@ function resolveMessage(messageArg) {
|
|
|
13006
13077
|
}
|
|
13007
13078
|
function readCommentBody() {
|
|
13008
13079
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
13009
|
-
if (!eventPath || !
|
|
13080
|
+
if (!eventPath || !fs35.existsSync(eventPath)) return "";
|
|
13010
13081
|
try {
|
|
13011
|
-
const event = JSON.parse(
|
|
13082
|
+
const event = JSON.parse(fs35.readFileSync(eventPath, "utf-8"));
|
|
13012
13083
|
return String(event.comment?.body ?? "");
|
|
13013
13084
|
} catch {
|
|
13014
13085
|
return "";
|
|
@@ -13061,10 +13132,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
13061
13132
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
13062
13133
|
}
|
|
13063
13134
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
13064
|
-
if (!
|
|
13135
|
+
if (!fs35.existsSync(agentPath)) {
|
|
13065
13136
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
13066
13137
|
}
|
|
13067
|
-
const { title, body } = parseAgentFile(
|
|
13138
|
+
const { title, body } = parseAgentFile(fs35.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
13068
13139
|
const message = resolveMessage(ctx.args.message);
|
|
13069
13140
|
if (!message) {
|
|
13070
13141
|
throw new Error(
|
|
@@ -13308,8 +13379,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
13308
13379
|
});
|
|
13309
13380
|
|
|
13310
13381
|
// src/scripts/loadJobFromFile.ts
|
|
13311
|
-
import * as
|
|
13312
|
-
import * as
|
|
13382
|
+
import * as fs36 from "fs";
|
|
13383
|
+
import * as path34 from "path";
|
|
13313
13384
|
function parseJobFile(raw, slug2) {
|
|
13314
13385
|
let stripped = raw;
|
|
13315
13386
|
if (stripped.startsWith("---\n")) {
|
|
@@ -13347,9 +13418,9 @@ var init_loadJobFromFile = __esm({
|
|
|
13347
13418
|
if (!slug2) {
|
|
13348
13419
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
13349
13420
|
}
|
|
13350
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
13421
|
+
const capability = resolveCapabilityFolder(slug2, path34.join(ctx.cwd, jobsDir));
|
|
13351
13422
|
if (!capability) {
|
|
13352
|
-
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${
|
|
13423
|
+
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${path34.join(ctx.cwd, jobsDir, slug2)}`);
|
|
13353
13424
|
}
|
|
13354
13425
|
const { title, body, config } = capability;
|
|
13355
13426
|
const mentions = (config.mentions ?? []).map((login) => `@${login}`).join(" ");
|
|
@@ -13358,12 +13429,12 @@ var init_loadJobFromFile = __esm({
|
|
|
13358
13429
|
let agentIdentity = "";
|
|
13359
13430
|
if (agentSlug) {
|
|
13360
13431
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
13361
|
-
if (!
|
|
13432
|
+
if (!fs36.existsSync(agentPath)) {
|
|
13362
13433
|
throw new Error(
|
|
13363
13434
|
`loadJobFromFile: capability '${slug2}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
13364
13435
|
);
|
|
13365
13436
|
}
|
|
13366
|
-
const agentRaw =
|
|
13437
|
+
const agentRaw = fs36.readFileSync(agentPath, "utf-8");
|
|
13367
13438
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
13368
13439
|
agentTitle = parsed.title;
|
|
13369
13440
|
agentIdentity = parsed.body;
|
|
@@ -13443,13 +13514,13 @@ ${truncate(issue.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
13443
13514
|
});
|
|
13444
13515
|
|
|
13445
13516
|
// src/scripts/kodyVariables.ts
|
|
13446
|
-
import * as
|
|
13447
|
-
import * as
|
|
13517
|
+
import * as fs37 from "fs";
|
|
13518
|
+
import * as path35 from "path";
|
|
13448
13519
|
function readKodyVariables(cwd) {
|
|
13449
|
-
const full =
|
|
13520
|
+
const full = path35.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
13450
13521
|
let raw;
|
|
13451
13522
|
try {
|
|
13452
|
-
raw =
|
|
13523
|
+
raw = fs37.readFileSync(full, "utf-8");
|
|
13453
13524
|
} catch {
|
|
13454
13525
|
return {};
|
|
13455
13526
|
}
|
|
@@ -13517,8 +13588,8 @@ var init_keys = __esm({
|
|
|
13517
13588
|
});
|
|
13518
13589
|
|
|
13519
13590
|
// src/stateRepoGithub.ts
|
|
13520
|
-
import * as
|
|
13521
|
-
import * as
|
|
13591
|
+
import * as fs38 from "fs";
|
|
13592
|
+
import * as path36 from "path";
|
|
13522
13593
|
function recordValue3(value) {
|
|
13523
13594
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
13524
13595
|
}
|
|
@@ -13658,15 +13729,15 @@ function mergeJsonl(localText, remoteText) {
|
|
|
13658
13729
|
async function syncJsonlFileFromGithubState(opts) {
|
|
13659
13730
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
13660
13731
|
if (!remote) return;
|
|
13661
|
-
const local =
|
|
13732
|
+
const local = fs38.existsSync(opts.localPath) ? fs38.readFileSync(opts.localPath, "utf-8") : "";
|
|
13662
13733
|
const next = mergeJsonl(local, remote.content);
|
|
13663
13734
|
if (next === local) return;
|
|
13664
|
-
|
|
13665
|
-
|
|
13735
|
+
fs38.mkdirSync(path36.dirname(opts.localPath), { recursive: true });
|
|
13736
|
+
fs38.writeFileSync(opts.localPath, next);
|
|
13666
13737
|
}
|
|
13667
13738
|
async function persistJsonlFileToGithubState(opts) {
|
|
13668
|
-
if (!
|
|
13669
|
-
const localText =
|
|
13739
|
+
if (!fs38.existsSync(opts.localPath)) return;
|
|
13740
|
+
const localText = fs38.readFileSync(opts.localPath, "utf-8");
|
|
13670
13741
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
13671
13742
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
13672
13743
|
const body = mergeJsonl(localText, remote?.content ?? "");
|
|
@@ -13805,8 +13876,8 @@ var init_runtimeSecrets = __esm({
|
|
|
13805
13876
|
});
|
|
13806
13877
|
|
|
13807
13878
|
// src/scripts/loadQaContext.ts
|
|
13808
|
-
import * as
|
|
13809
|
-
import * as
|
|
13879
|
+
import * as fs39 from "fs";
|
|
13880
|
+
import * as path37 from "path";
|
|
13810
13881
|
function parseSlugList(value) {
|
|
13811
13882
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
13812
13883
|
return inner.split(",").map(
|
|
@@ -13835,18 +13906,18 @@ function readProfileAgents(raw) {
|
|
|
13835
13906
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
13836
13907
|
}
|
|
13837
13908
|
function readProfile(cwd) {
|
|
13838
|
-
const dir =
|
|
13839
|
-
if (!
|
|
13909
|
+
const dir = path37.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
13910
|
+
if (!fs39.existsSync(dir)) return "";
|
|
13840
13911
|
let entries;
|
|
13841
13912
|
try {
|
|
13842
|
-
entries =
|
|
13913
|
+
entries = fs39.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
13843
13914
|
} catch {
|
|
13844
13915
|
return "";
|
|
13845
13916
|
}
|
|
13846
13917
|
const blocks = [];
|
|
13847
13918
|
for (const file of entries) {
|
|
13848
13919
|
try {
|
|
13849
|
-
const raw =
|
|
13920
|
+
const raw = fs39.readFileSync(path37.join(dir, file), "utf-8");
|
|
13850
13921
|
const { agent, body } = readProfileAgents(raw);
|
|
13851
13922
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
13852
13923
|
blocks.push(`## ${file}
|
|
@@ -13895,8 +13966,8 @@ var init_loadQaContext = __esm({
|
|
|
13895
13966
|
});
|
|
13896
13967
|
|
|
13897
13968
|
// src/taskContext.ts
|
|
13898
|
-
import * as
|
|
13899
|
-
import * as
|
|
13969
|
+
import * as fs40 from "fs";
|
|
13970
|
+
import * as path38 from "path";
|
|
13900
13971
|
function buildTaskContext(args) {
|
|
13901
13972
|
return {
|
|
13902
13973
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -13912,9 +13983,9 @@ function buildTaskContext(args) {
|
|
|
13912
13983
|
function persistTaskContext(cwd, ctx) {
|
|
13913
13984
|
try {
|
|
13914
13985
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
13915
|
-
|
|
13916
|
-
const file =
|
|
13917
|
-
|
|
13986
|
+
fs40.mkdirSync(dir, { recursive: true });
|
|
13987
|
+
const file = path38.join(dir, "task-context.json");
|
|
13988
|
+
fs40.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
13918
13989
|
`);
|
|
13919
13990
|
return file;
|
|
13920
13991
|
} catch (err) {
|
|
@@ -16394,12 +16465,12 @@ fi
|
|
|
16394
16465
|
|
|
16395
16466
|
// src/scripts/runPreviewBuild.ts
|
|
16396
16467
|
import { copyFile, writeFile } from "fs/promises";
|
|
16397
|
-
import * as
|
|
16468
|
+
import * as path39 from "path";
|
|
16398
16469
|
import { fileURLToPath } from "url";
|
|
16399
16470
|
function bundledDockerfilePath(mode) {
|
|
16400
|
-
const here =
|
|
16471
|
+
const here = path39.dirname(fileURLToPath(import.meta.url));
|
|
16401
16472
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
16402
|
-
return
|
|
16473
|
+
return path39.join(here, "preview-build-templates", file);
|
|
16403
16474
|
}
|
|
16404
16475
|
function required(name) {
|
|
16405
16476
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -16650,10 +16721,10 @@ var init_runPreviewBuild = __esm({
|
|
|
16650
16721
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
16651
16722
|
if (Object.keys(buildEnv).length > 0) {
|
|
16652
16723
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
16653
|
-
await writeFile(
|
|
16724
|
+
await writeFile(path39.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
16654
16725
|
`, "utf8");
|
|
16655
16726
|
}
|
|
16656
|
-
const consumerDockerfile =
|
|
16727
|
+
const consumerDockerfile = path39.join(ctx.cwd, "Dockerfile.preview");
|
|
16657
16728
|
const { stat } = await import("fs/promises");
|
|
16658
16729
|
let hasConsumerDockerfile = false;
|
|
16659
16730
|
try {
|
|
@@ -16837,8 +16908,8 @@ var init_tickShellRunner = __esm({
|
|
|
16837
16908
|
});
|
|
16838
16909
|
|
|
16839
16910
|
// src/scripts/runScheduledExecutableTick.ts
|
|
16840
|
-
import * as
|
|
16841
|
-
import * as
|
|
16911
|
+
import * as fs41 from "fs";
|
|
16912
|
+
import * as path40 from "path";
|
|
16842
16913
|
var runScheduledExecutableTick;
|
|
16843
16914
|
var init_runScheduledExecutableTick = __esm({
|
|
16844
16915
|
"src/scripts/runScheduledExecutableTick.ts"() {
|
|
@@ -16858,14 +16929,14 @@ var init_runScheduledExecutableTick = __esm({
|
|
|
16858
16929
|
ctx.output.reason = `runScheduledExecutableTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
16859
16930
|
return;
|
|
16860
16931
|
}
|
|
16861
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
16932
|
+
const capability = resolveCapabilityFolder(slug2, path40.join(ctx.cwd, jobsDir));
|
|
16862
16933
|
if (!capability) {
|
|
16863
16934
|
ctx.output.exitCode = 99;
|
|
16864
16935
|
ctx.output.reason = `runScheduledExecutableTick: capability folder not found or incomplete: ${slug2} (searched ${jobsDir} and company store)`;
|
|
16865
16936
|
return;
|
|
16866
16937
|
}
|
|
16867
|
-
const shellPath =
|
|
16868
|
-
if (!
|
|
16938
|
+
const shellPath = path40.join(profile.dir, shell);
|
|
16939
|
+
if (!fs41.existsSync(shellPath)) {
|
|
16869
16940
|
ctx.output.exitCode = 99;
|
|
16870
16941
|
ctx.output.reason = `runScheduledExecutableTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
16871
16942
|
return;
|
|
@@ -16896,8 +16967,8 @@ var init_runScheduledExecutableTick = __esm({
|
|
|
16896
16967
|
});
|
|
16897
16968
|
|
|
16898
16969
|
// src/scripts/runTickScript.ts
|
|
16899
|
-
import * as
|
|
16900
|
-
import * as
|
|
16970
|
+
import * as fs42 from "fs";
|
|
16971
|
+
import * as path41 from "path";
|
|
16901
16972
|
var runTickScript;
|
|
16902
16973
|
var init_runTickScript = __esm({
|
|
16903
16974
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -16916,10 +16987,10 @@ var init_runTickScript = __esm({
|
|
|
16916
16987
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
16917
16988
|
return;
|
|
16918
16989
|
}
|
|
16919
|
-
const capability = readCapabilityFolder(
|
|
16990
|
+
const capability = readCapabilityFolder(path41.join(ctx.cwd, jobsDir), slug2);
|
|
16920
16991
|
if (!capability) {
|
|
16921
16992
|
ctx.output.exitCode = 99;
|
|
16922
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
16993
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path41.join(ctx.cwd, jobsDir, slug2)}`;
|
|
16923
16994
|
return;
|
|
16924
16995
|
}
|
|
16925
16996
|
const tickScript = capability.config.tickScript;
|
|
@@ -16928,8 +16999,8 @@ var init_runTickScript = __esm({
|
|
|
16928
16999
|
ctx.output.reason = `runTickScript: capability ${slug2} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
16929
17000
|
return;
|
|
16930
17001
|
}
|
|
16931
|
-
const scriptPath =
|
|
16932
|
-
if (!
|
|
17002
|
+
const scriptPath = path41.isAbsolute(tickScript) ? tickScript : path41.join(ctx.cwd, tickScript);
|
|
17003
|
+
if (!fs42.existsSync(scriptPath)) {
|
|
16933
17004
|
ctx.output.exitCode = 99;
|
|
16934
17005
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
16935
17006
|
return;
|
|
@@ -17752,7 +17823,7 @@ var init_warmupMcp = __esm({
|
|
|
17752
17823
|
});
|
|
17753
17824
|
|
|
17754
17825
|
// src/scripts/writeAgentRunSummary.ts
|
|
17755
|
-
import * as
|
|
17826
|
+
import * as fs43 from "fs";
|
|
17756
17827
|
var writeAgentRunSummary;
|
|
17757
17828
|
var init_writeAgentRunSummary = __esm({
|
|
17758
17829
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -17778,7 +17849,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
17778
17849
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
17779
17850
|
lines.push("");
|
|
17780
17851
|
try {
|
|
17781
|
-
|
|
17852
|
+
fs43.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
17782
17853
|
`);
|
|
17783
17854
|
} catch {
|
|
17784
17855
|
}
|
|
@@ -18100,53 +18171,53 @@ var init_scripts = __esm({
|
|
|
18100
18171
|
// src/stateWorkspace.ts
|
|
18101
18172
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
18102
18173
|
import * as crypto3 from "crypto";
|
|
18103
|
-
import * as
|
|
18174
|
+
import * as fs44 from "fs";
|
|
18104
18175
|
import * as os7 from "os";
|
|
18105
|
-
import * as
|
|
18176
|
+
import * as path42 from "path";
|
|
18106
18177
|
function writeLocalFile(cwd, relativePath, content) {
|
|
18107
|
-
const fullPath =
|
|
18108
|
-
|
|
18109
|
-
|
|
18178
|
+
const fullPath = path42.join(cwd, relativePath);
|
|
18179
|
+
fs44.mkdirSync(path42.dirname(fullPath), { recursive: true });
|
|
18180
|
+
fs44.writeFileSync(fullPath, content);
|
|
18110
18181
|
}
|
|
18111
18182
|
function copyPath(source, target) {
|
|
18112
|
-
const st =
|
|
18113
|
-
|
|
18183
|
+
const st = fs44.lstatSync(source);
|
|
18184
|
+
fs44.rmSync(target, { recursive: true, force: true });
|
|
18114
18185
|
if (st.isSymbolicLink()) return;
|
|
18115
|
-
|
|
18116
|
-
|
|
18186
|
+
fs44.mkdirSync(path42.dirname(target), { recursive: true });
|
|
18187
|
+
fs44.cpSync(source, target, { recursive: true, force: true });
|
|
18117
18188
|
}
|
|
18118
18189
|
function overlayDirectoryChildren(cwd, sourceDir, localDir) {
|
|
18119
|
-
if (!
|
|
18120
|
-
for (const entry of
|
|
18121
|
-
const source =
|
|
18122
|
-
const target =
|
|
18190
|
+
if (!fs44.existsSync(sourceDir)) return;
|
|
18191
|
+
for (const entry of fs44.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
18192
|
+
const source = path42.join(sourceDir, entry.name);
|
|
18193
|
+
const target = path42.join(cwd, localDir, entry.name);
|
|
18123
18194
|
copyPath(source, target);
|
|
18124
18195
|
}
|
|
18125
18196
|
}
|
|
18126
18197
|
function hydrateStateWorkspace(config, cwd) {
|
|
18127
18198
|
if (process.env.VITEST && process.env[TEST_FETCH_ENV] !== "1") return;
|
|
18128
18199
|
const parsed = parseStateRepo(config);
|
|
18129
|
-
const hydrateKey = `${
|
|
18200
|
+
const hydrateKey = `${path42.resolve(cwd)}|${parsed.owner}/${parsed.repo}|${parsed.basePath}|${parsed.branch}`;
|
|
18130
18201
|
if (hydratedWorkspaces.has(hydrateKey)) return;
|
|
18131
18202
|
const snapshotRoot = fetchStateSnapshot(parsed);
|
|
18132
18203
|
for (const mapping of DIR_MAPPINGS) {
|
|
18133
|
-
overlayDirectoryChildren(cwd,
|
|
18204
|
+
overlayDirectoryChildren(cwd, path42.join(snapshotRoot, mapping.stateDir), mapping.localDir);
|
|
18134
18205
|
}
|
|
18135
18206
|
for (const mapping of FILE_MAPPINGS) {
|
|
18136
|
-
const source =
|
|
18137
|
-
if (
|
|
18138
|
-
writeLocalFile(cwd, mapping.localPath,
|
|
18207
|
+
const source = path42.join(snapshotRoot, mapping.statePath);
|
|
18208
|
+
if (fs44.existsSync(source) && !fs44.lstatSync(source).isSymbolicLink() && fs44.statSync(source).isFile()) {
|
|
18209
|
+
writeLocalFile(cwd, mapping.localPath, fs44.readFileSync(source, "utf-8"));
|
|
18139
18210
|
}
|
|
18140
18211
|
}
|
|
18141
18212
|
hydratedWorkspaces.add(hydrateKey);
|
|
18142
18213
|
}
|
|
18143
18214
|
function fetchStateSnapshot(parsed) {
|
|
18144
|
-
const cacheDir =
|
|
18215
|
+
const cacheDir = path42.join(cacheRoot2(), cacheKey3(parsed));
|
|
18145
18216
|
const url = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
18146
18217
|
try {
|
|
18147
|
-
|
|
18148
|
-
if (!
|
|
18149
|
-
|
|
18218
|
+
fs44.mkdirSync(path42.dirname(cacheDir), { recursive: true });
|
|
18219
|
+
if (!fs44.existsSync(path42.join(cacheDir, ".git"))) {
|
|
18220
|
+
fs44.rmSync(cacheDir, { recursive: true, force: true });
|
|
18150
18221
|
runGit3(["clone", "--no-checkout", "--filter=blob:none", url, cacheDir]);
|
|
18151
18222
|
}
|
|
18152
18223
|
runGit3(["-C", cacheDir, "remote", "set-url", "origin", url]);
|
|
@@ -18161,10 +18232,10 @@ function fetchStateSnapshot(parsed) {
|
|
|
18161
18232
|
`stateWorkspace: failed to fetch ${parsed.owner}/${parsed.repo}:${parsed.basePath}@${parsed.branch}: ${msg}`
|
|
18162
18233
|
);
|
|
18163
18234
|
}
|
|
18164
|
-
return
|
|
18235
|
+
return path42.join(cacheDir, parsed.basePath);
|
|
18165
18236
|
}
|
|
18166
18237
|
function cacheRoot2() {
|
|
18167
|
-
return process.env[CACHE_ENV2]?.trim() ||
|
|
18238
|
+
return process.env[CACHE_ENV2]?.trim() || path42.join(os7.homedir(), ".cache", "kody", "state-repo");
|
|
18168
18239
|
}
|
|
18169
18240
|
function cacheKey3(parsed) {
|
|
18170
18241
|
return crypto3.createHash("sha256").update(`${parsed.owner}/${parsed.repo}#${parsed.branch}#${parsed.basePath}`).digest("hex").slice(0, 24);
|
|
@@ -18204,15 +18275,15 @@ var init_stateWorkspace = __esm({
|
|
|
18204
18275
|
"use strict";
|
|
18205
18276
|
init_stateRepo();
|
|
18206
18277
|
DIR_MAPPINGS = [
|
|
18207
|
-
{ stateDir: "capabilities", localDir:
|
|
18208
|
-
{ stateDir: "agents", localDir:
|
|
18209
|
-
{ stateDir: "context", localDir:
|
|
18210
|
-
{ stateDir: "memory", localDir:
|
|
18278
|
+
{ stateDir: "capabilities", localDir: path42.join(".kody", "capabilities") },
|
|
18279
|
+
{ stateDir: "agents", localDir: path42.join(".kody", "agents") },
|
|
18280
|
+
{ stateDir: "context", localDir: path42.join(".kody", "context") },
|
|
18281
|
+
{ stateDir: "memory", localDir: path42.join(".kody", "memory") }
|
|
18211
18282
|
];
|
|
18212
18283
|
FILE_MAPPINGS = [
|
|
18213
|
-
{ statePath: "instructions.md", localPath:
|
|
18214
|
-
{ statePath: "variables.json", localPath:
|
|
18215
|
-
{ statePath: "secrets.enc", localPath:
|
|
18284
|
+
{ statePath: "instructions.md", localPath: path42.join(".kody", "instructions.md") },
|
|
18285
|
+
{ statePath: "variables.json", localPath: path42.join(".kody", "variables.json") },
|
|
18286
|
+
{ statePath: "secrets.enc", localPath: path42.join(".kody", "secrets.enc") }
|
|
18216
18287
|
];
|
|
18217
18288
|
CACHE_ENV2 = "KODY_STATE_REPO_CACHE";
|
|
18218
18289
|
TEST_FETCH_ENV = "KODY_STATE_WORKSPACE_FETCH_FOR_TESTS";
|
|
@@ -18286,8 +18357,8 @@ var init_tools = __esm({
|
|
|
18286
18357
|
|
|
18287
18358
|
// src/executor.ts
|
|
18288
18359
|
import { spawn as spawn7 } from "child_process";
|
|
18289
|
-
import * as
|
|
18290
|
-
import * as
|
|
18360
|
+
import * as fs45 from "fs";
|
|
18361
|
+
import * as path43 from "path";
|
|
18291
18362
|
function isMutatingPostflight(scriptName) {
|
|
18292
18363
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
18293
18364
|
}
|
|
@@ -18468,7 +18539,7 @@ async function runExecutable(profileName, input) {
|
|
|
18468
18539
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
18469
18540
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
18470
18541
|
const invokeAgent = async (prompt) => {
|
|
18471
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
18542
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path43.isAbsolute(p) ? p : path43.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
18472
18543
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
18473
18544
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
18474
18545
|
const agents = loadSubagents(profile);
|
|
@@ -18861,17 +18932,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
18861
18932
|
function resolveProfilePath(profileName) {
|
|
18862
18933
|
const found = resolveExecutable(profileName);
|
|
18863
18934
|
if (found) return found;
|
|
18864
|
-
const here =
|
|
18935
|
+
const here = path43.dirname(new URL(import.meta.url).pathname);
|
|
18865
18936
|
const candidates = [
|
|
18866
|
-
|
|
18937
|
+
path43.join(here, "executables", profileName, "profile.json"),
|
|
18867
18938
|
// same-dir sibling (dev)
|
|
18868
|
-
|
|
18939
|
+
path43.join(here, "..", "executables", profileName, "profile.json"),
|
|
18869
18940
|
// up one (prod: dist/bin → dist/executables)
|
|
18870
|
-
|
|
18941
|
+
path43.join(here, "..", "src", "executables", profileName, "profile.json")
|
|
18871
18942
|
// fallback
|
|
18872
18943
|
];
|
|
18873
18944
|
for (const c of candidates) {
|
|
18874
|
-
if (
|
|
18945
|
+
if (fs45.existsSync(c)) return c;
|
|
18875
18946
|
}
|
|
18876
18947
|
return candidates[0];
|
|
18877
18948
|
}
|
|
@@ -18986,8 +19057,8 @@ function resolveShellTimeoutMs(entry) {
|
|
|
18986
19057
|
}
|
|
18987
19058
|
async function runShellEntry(entry, ctx, profile) {
|
|
18988
19059
|
const shellName = entry.shell;
|
|
18989
|
-
const shellPath =
|
|
18990
|
-
if (!
|
|
19060
|
+
const shellPath = path43.join(profile.dir, shellName);
|
|
19061
|
+
if (!fs45.existsSync(shellPath)) {
|
|
18991
19062
|
ctx.skipAgent = true;
|
|
18992
19063
|
ctx.output.exitCode = 99;
|
|
18993
19064
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -19137,8 +19208,8 @@ var init_executor = __esm({
|
|
|
19137
19208
|
});
|
|
19138
19209
|
|
|
19139
19210
|
// src/workflowDefinitions.ts
|
|
19140
|
-
import * as
|
|
19141
|
-
import * as
|
|
19211
|
+
import * as fs46 from "fs";
|
|
19212
|
+
import * as path44 from "path";
|
|
19142
19213
|
function isWorkflowDefinitionId(value) {
|
|
19143
19214
|
return WORKFLOW_ID_PATTERN.test(value);
|
|
19144
19215
|
}
|
|
@@ -19152,13 +19223,11 @@ function normalizeWorkflowDefinition(value) {
|
|
|
19152
19223
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
19153
19224
|
const raw = value;
|
|
19154
19225
|
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
19155
|
-
const instructions = typeof raw.instructions === "string" ? raw.instructions.trim() : "";
|
|
19156
19226
|
const capabilities = normalizeWorkflowCapabilities(raw.capabilities);
|
|
19157
|
-
if (!name ||
|
|
19227
|
+
if (!name || capabilities.length === 0) return null;
|
|
19158
19228
|
return {
|
|
19159
19229
|
version: 1,
|
|
19160
19230
|
name,
|
|
19161
|
-
instructions,
|
|
19162
19231
|
capabilities,
|
|
19163
19232
|
...typeof raw.createdAt === "string" ? { createdAt: raw.createdAt } : {},
|
|
19164
19233
|
...typeof raw.updatedAt === "string" ? { updatedAt: raw.updatedAt } : {}
|
|
@@ -19172,17 +19241,17 @@ function readWorkflowDefinition(config, cwd, id) {
|
|
|
19172
19241
|
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
19173
19242
|
return {
|
|
19174
19243
|
slug: id,
|
|
19175
|
-
dir:
|
|
19244
|
+
dir: path44.dirname(source),
|
|
19176
19245
|
profilePath: source,
|
|
19177
19246
|
bodyPath: source,
|
|
19178
19247
|
title: workflow.name,
|
|
19179
|
-
body:
|
|
19180
|
-
rawBody:
|
|
19248
|
+
body: "",
|
|
19249
|
+
rawBody: "",
|
|
19181
19250
|
rawProfile: { name: id, workflow },
|
|
19182
19251
|
config: {
|
|
19183
19252
|
action: id,
|
|
19184
19253
|
workflow: workflowDefinitionToConfig(workflow),
|
|
19185
|
-
describe: workflow.
|
|
19254
|
+
describe: workflow.name
|
|
19186
19255
|
}
|
|
19187
19256
|
};
|
|
19188
19257
|
}
|
|
@@ -19207,9 +19276,9 @@ function workflowDefinitionToConfig(workflow) {
|
|
|
19207
19276
|
function readCompanyStoreWorkflowDefinition(id) {
|
|
19208
19277
|
const root = getCompanyStoreAssetRoot("workflows");
|
|
19209
19278
|
if (!root) return null;
|
|
19210
|
-
const filePath =
|
|
19211
|
-
if (!
|
|
19212
|
-
return parseWorkflowDefinition(
|
|
19279
|
+
const filePath = path44.join(root, id, "workflow.json");
|
|
19280
|
+
if (!fs46.existsSync(filePath)) return null;
|
|
19281
|
+
return parseWorkflowDefinition(fs46.readFileSync(filePath, "utf8"));
|
|
19213
19282
|
}
|
|
19214
19283
|
function parseWorkflowDefinition(content) {
|
|
19215
19284
|
try {
|
|
@@ -19241,7 +19310,7 @@ __export(job_exports, {
|
|
|
19241
19310
|
stableJobKey: () => stableJobKey,
|
|
19242
19311
|
validateJob: () => validateJob
|
|
19243
19312
|
});
|
|
19244
|
-
import * as
|
|
19313
|
+
import * as path45 from "path";
|
|
19245
19314
|
function newJobId(flavor) {
|
|
19246
19315
|
localJobSeq += 1;
|
|
19247
19316
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -19293,7 +19362,7 @@ function parseCapabilityResultTarget(raw) {
|
|
|
19293
19362
|
async function runJob(job, base) {
|
|
19294
19363
|
const valid = validateJob(job);
|
|
19295
19364
|
const action = valid.action ?? valid.capability;
|
|
19296
|
-
const projectCapabilitiesRoot =
|
|
19365
|
+
const projectCapabilitiesRoot = path45.join(base.cwd, ".kody", "capabilities");
|
|
19297
19366
|
const resolvedCapability = !valid.workflow && action ? resolveCapabilityAction(action, projectCapabilitiesRoot) : null;
|
|
19298
19367
|
const capabilityIdentity = valid.capability ?? resolvedCapability?.capability;
|
|
19299
19368
|
const capabilityContext = valid.workflow ? null : loadCapabilityContext(capabilityIdentity, base.cwd);
|
|
@@ -19306,7 +19375,7 @@ async function runJob(job, base) {
|
|
|
19306
19375
|
}
|
|
19307
19376
|
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
19308
19377
|
const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
|
|
19309
|
-
const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
19378
|
+
const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.implementation ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
19310
19379
|
const profileName = valid.executable ?? capabilitySelectedExecutable;
|
|
19311
19380
|
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedExecutable, base)) {
|
|
19312
19381
|
const workflowCapability = capabilityContext ?? workflowContext;
|
|
@@ -19479,7 +19548,7 @@ function shouldRunWorkflowStep(step, data) {
|
|
|
19479
19548
|
if (!step.runWhen) return true;
|
|
19480
19549
|
const context = workflowConditionContext(data);
|
|
19481
19550
|
return Object.entries(step.runWhen).every(
|
|
19482
|
-
([
|
|
19551
|
+
([path51, expected]) => valueMatches(resolveDottedPath2(context, path51), expected)
|
|
19483
19552
|
);
|
|
19484
19553
|
}
|
|
19485
19554
|
function canContinueWorkflow(step, outcome) {
|
|
@@ -19549,7 +19618,7 @@ function composeStepWhy(parentWhy, step) {
|
|
|
19549
19618
|
}
|
|
19550
19619
|
function loadCapabilityContext(slug2, cwd) {
|
|
19551
19620
|
if (!slug2) return null;
|
|
19552
|
-
return resolveCapabilityFolder(slug2,
|
|
19621
|
+
return resolveCapabilityFolder(slug2, path45.join(cwd, ".kody", "capabilities"));
|
|
19553
19622
|
}
|
|
19554
19623
|
function loadWorkflowContext(slug2, base) {
|
|
19555
19624
|
if (!slug2 || !base.config || !isWorkflowDefinitionId(slug2)) return null;
|
|
@@ -19707,9 +19776,9 @@ function translateOpenAISseToBrain(opts) {
|
|
|
19707
19776
|
}
|
|
19708
19777
|
|
|
19709
19778
|
// src/servers/brain-serve.ts
|
|
19710
|
-
import * as
|
|
19779
|
+
import * as fs49 from "fs";
|
|
19711
19780
|
import { createServer as createServer2 } from "http";
|
|
19712
|
-
import * as
|
|
19781
|
+
import * as path48 from "path";
|
|
19713
19782
|
|
|
19714
19783
|
// src/chat/loop.ts
|
|
19715
19784
|
init_agent();
|
|
@@ -20385,8 +20454,8 @@ init_config();
|
|
|
20385
20454
|
|
|
20386
20455
|
// src/kody-cli.ts
|
|
20387
20456
|
import { execFileSync as execFileSync26 } from "child_process";
|
|
20388
|
-
import * as
|
|
20389
|
-
import * as
|
|
20457
|
+
import * as fs47 from "fs";
|
|
20458
|
+
import * as path46 from "path";
|
|
20390
20459
|
|
|
20391
20460
|
// src/app-auth.ts
|
|
20392
20461
|
import { createSign } from "crypto";
|
|
@@ -20889,6 +20958,7 @@ init_gha();
|
|
|
20889
20958
|
init_issue();
|
|
20890
20959
|
init_job();
|
|
20891
20960
|
init_lifecycleLabels();
|
|
20961
|
+
init_companyStore();
|
|
20892
20962
|
init_registry();
|
|
20893
20963
|
|
|
20894
20964
|
// src/run-request.ts
|
|
@@ -20959,6 +21029,9 @@ var FAILED_DISPATCH_LABEL = {
|
|
|
20959
21029
|
color: "e11d21",
|
|
20960
21030
|
description: "Kody failed or rejected the run"
|
|
20961
21031
|
};
|
|
21032
|
+
function objectValue2(value) {
|
|
21033
|
+
return value && typeof value === "object" ? value : void 0;
|
|
21034
|
+
}
|
|
20962
21035
|
var CI_HELP = `kody ci \u2014 minimal-YAML autonomous engineer (CI preflight + run)
|
|
20963
21036
|
|
|
20964
21037
|
Usage:
|
|
@@ -21116,9 +21189,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
21116
21189
|
return void 0;
|
|
21117
21190
|
}
|
|
21118
21191
|
function detectPackageManager2(cwd) {
|
|
21119
|
-
if (
|
|
21120
|
-
if (
|
|
21121
|
-
if (
|
|
21192
|
+
if (fs47.existsSync(path46.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
21193
|
+
if (fs47.existsSync(path46.join(cwd, "yarn.lock"))) return "yarn";
|
|
21194
|
+
if (fs47.existsSync(path46.join(cwd, "bun.lockb"))) return "bun";
|
|
21122
21195
|
return "npm";
|
|
21123
21196
|
}
|
|
21124
21197
|
function shouldChainScheduledWatch(match) {
|
|
@@ -21211,8 +21284,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
21211
21284
|
const logPath = lastRunLogPath(cwd);
|
|
21212
21285
|
let tail = "";
|
|
21213
21286
|
try {
|
|
21214
|
-
if (
|
|
21215
|
-
const content =
|
|
21287
|
+
if (fs47.existsSync(logPath)) {
|
|
21288
|
+
const content = fs47.readFileSync(logPath, "utf-8");
|
|
21216
21289
|
tail = content.slice(-3e3);
|
|
21217
21290
|
}
|
|
21218
21291
|
} catch {
|
|
@@ -21241,7 +21314,7 @@ async function runCi(argv) {
|
|
|
21241
21314
|
return 0;
|
|
21242
21315
|
}
|
|
21243
21316
|
const args = parseCiArgs(argv);
|
|
21244
|
-
const cwd = args.cwd ?
|
|
21317
|
+
const cwd = args.cwd ? path46.resolve(args.cwd) : process.cwd();
|
|
21245
21318
|
let earlyConfig;
|
|
21246
21319
|
let earlyConfigError;
|
|
21247
21320
|
try {
|
|
@@ -21264,6 +21337,9 @@ async function runCi(argv) {
|
|
|
21264
21337
|
`);
|
|
21265
21338
|
return 64;
|
|
21266
21339
|
}
|
|
21340
|
+
if (parsedRunRequest && "request" in parsedRunRequest) {
|
|
21341
|
+
applyCompanyStoreRuntimeConfig(parsedRunRequest.request.input);
|
|
21342
|
+
}
|
|
21267
21343
|
if (!args.issueNumber && !autoFallback && parsedRunRequest && "request" in parsedRunRequest) {
|
|
21268
21344
|
const route = routeRunRequest(parsedRunRequest.request);
|
|
21269
21345
|
if (route.kind === "error") {
|
|
@@ -21287,13 +21363,15 @@ async function runCi(argv) {
|
|
|
21287
21363
|
forceRunCliArgs = { goal: envForceMessage };
|
|
21288
21364
|
}
|
|
21289
21365
|
}
|
|
21290
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
21366
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs47.existsSync(dispatchEventPath)) {
|
|
21291
21367
|
try {
|
|
21292
|
-
const evt = JSON.parse(
|
|
21293
|
-
const
|
|
21294
|
-
|
|
21295
|
-
const
|
|
21296
|
-
const
|
|
21368
|
+
const evt = JSON.parse(fs47.readFileSync(dispatchEventPath, "utf-8"));
|
|
21369
|
+
const inputs = objectValue2(evt.inputs);
|
|
21370
|
+
applyCompanyStoreRuntimeConfig(inputs);
|
|
21371
|
+
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
21372
|
+
const sessionInput = String(inputs?.sessionId ?? "");
|
|
21373
|
+
const capabilityInput = String(inputs?.capability ?? inputs?.executable ?? "").trim();
|
|
21374
|
+
const messageInput = String(inputs?.message ?? "").trim();
|
|
21297
21375
|
const noTarget = !sessionInput && !(Number.isFinite(issueInput) && issueInput > 0);
|
|
21298
21376
|
if (noTarget && capabilityInput) {
|
|
21299
21377
|
forceRunAction = capabilityInput;
|
|
@@ -21651,8 +21729,8 @@ init_repoWorkspace();
|
|
|
21651
21729
|
|
|
21652
21730
|
// src/scripts/brainTurnLog.ts
|
|
21653
21731
|
init_runtimePaths();
|
|
21654
|
-
import * as
|
|
21655
|
-
import * as
|
|
21732
|
+
import * as fs48 from "fs";
|
|
21733
|
+
import * as path47 from "path";
|
|
21656
21734
|
import posixPath4 from "path/posix";
|
|
21657
21735
|
var live = /* @__PURE__ */ new Map();
|
|
21658
21736
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -21663,8 +21741,8 @@ function brainEventsStatePath(chatId) {
|
|
|
21663
21741
|
}
|
|
21664
21742
|
function lastPersistedSeq(dir, chatId) {
|
|
21665
21743
|
const p = brainEventsFilePath(dir, chatId);
|
|
21666
|
-
if (!
|
|
21667
|
-
const lines =
|
|
21744
|
+
if (!fs48.existsSync(p)) return 0;
|
|
21745
|
+
const lines = fs48.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
21668
21746
|
if (lines.length === 0) return 0;
|
|
21669
21747
|
try {
|
|
21670
21748
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -21674,9 +21752,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
21674
21752
|
}
|
|
21675
21753
|
function readSince(dir, chatId, since) {
|
|
21676
21754
|
const p = brainEventsFilePath(dir, chatId);
|
|
21677
|
-
if (!
|
|
21755
|
+
if (!fs48.existsSync(p)) return [];
|
|
21678
21756
|
const out = [];
|
|
21679
|
-
for (const line of
|
|
21757
|
+
for (const line of fs48.readFileSync(p, "utf-8").split("\n")) {
|
|
21680
21758
|
if (!line) continue;
|
|
21681
21759
|
try {
|
|
21682
21760
|
const rec = JSON.parse(line);
|
|
@@ -21702,12 +21780,12 @@ function beginTurn(dir, chatId) {
|
|
|
21702
21780
|
};
|
|
21703
21781
|
live.set(chatId, state);
|
|
21704
21782
|
const p = brainEventsFilePath(dir, chatId);
|
|
21705
|
-
|
|
21783
|
+
fs48.mkdirSync(path47.dirname(p), { recursive: true });
|
|
21706
21784
|
return (event) => {
|
|
21707
21785
|
state.seq += 1;
|
|
21708
21786
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
21709
21787
|
try {
|
|
21710
|
-
|
|
21788
|
+
fs48.appendFileSync(p, `${JSON.stringify(rec)}
|
|
21711
21789
|
`);
|
|
21712
21790
|
} catch (err) {
|
|
21713
21791
|
process.stderr.write(
|
|
@@ -21746,7 +21824,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
21746
21824
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
21747
21825
|
};
|
|
21748
21826
|
try {
|
|
21749
|
-
|
|
21827
|
+
fs48.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
21750
21828
|
`);
|
|
21751
21829
|
} catch {
|
|
21752
21830
|
}
|
|
@@ -22070,7 +22148,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
22070
22148
|
);
|
|
22071
22149
|
}
|
|
22072
22150
|
}
|
|
22073
|
-
|
|
22151
|
+
fs49.mkdirSync(path48.dirname(sessionFile), { recursive: true });
|
|
22074
22152
|
appendTurn(sessionFile, {
|
|
22075
22153
|
role: "user",
|
|
22076
22154
|
content: message,
|
|
@@ -22145,7 +22223,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
22145
22223
|
function buildServer(opts) {
|
|
22146
22224
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
22147
22225
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
22148
|
-
const reposRoot = opts.reposRoot ??
|
|
22226
|
+
const reposRoot = opts.reposRoot ?? path48.join(path48.dirname(path48.resolve(opts.cwd)), "repos");
|
|
22149
22227
|
return createServer2(async (req, res) => {
|
|
22150
22228
|
if (!req.method || !req.url) {
|
|
22151
22229
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -22748,8 +22826,8 @@ async function loadConfigSafe() {
|
|
|
22748
22826
|
}
|
|
22749
22827
|
|
|
22750
22828
|
// src/chat-cli.ts
|
|
22751
|
-
import * as
|
|
22752
|
-
import * as
|
|
22829
|
+
import * as fs51 from "fs";
|
|
22830
|
+
import * as path50 from "path";
|
|
22753
22831
|
|
|
22754
22832
|
// src/chat/inbox.ts
|
|
22755
22833
|
import { execFileSync as execFileSync27 } from "child_process";
|
|
@@ -22821,8 +22899,8 @@ function currentBranch(cwd) {
|
|
|
22821
22899
|
|
|
22822
22900
|
// src/chat/state-sync.ts
|
|
22823
22901
|
init_stateRepo();
|
|
22824
|
-
import * as
|
|
22825
|
-
import * as
|
|
22902
|
+
import * as fs50 from "fs";
|
|
22903
|
+
import * as path49 from "path";
|
|
22826
22904
|
function jsonlLines2(text) {
|
|
22827
22905
|
return text.split("\n").filter((line) => line.length > 0);
|
|
22828
22906
|
}
|
|
@@ -22839,15 +22917,15 @@ function mergeJsonl2(localText, remoteText) {
|
|
|
22839
22917
|
function syncJsonlFileFromState(opts) {
|
|
22840
22918
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
22841
22919
|
if (!remote) return;
|
|
22842
|
-
const local =
|
|
22920
|
+
const local = fs50.existsSync(opts.localPath) ? fs50.readFileSync(opts.localPath, "utf-8") : "";
|
|
22843
22921
|
const next = mergeJsonl2(local, remote.content);
|
|
22844
22922
|
if (next === local) return;
|
|
22845
|
-
|
|
22846
|
-
|
|
22923
|
+
fs50.mkdirSync(path49.dirname(opts.localPath), { recursive: true });
|
|
22924
|
+
fs50.writeFileSync(opts.localPath, next);
|
|
22847
22925
|
}
|
|
22848
22926
|
function persistJsonlFileToState(opts) {
|
|
22849
|
-
if (!
|
|
22850
|
-
const localText =
|
|
22927
|
+
if (!fs50.existsSync(opts.localPath)) return;
|
|
22928
|
+
const localText = fs50.readFileSync(opts.localPath, "utf-8");
|
|
22851
22929
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
22852
22930
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
22853
22931
|
const body = mergeJsonl2(localText, remote?.content ?? "");
|
|
@@ -23031,6 +23109,7 @@ async function emit2(sink, type, sessionId, suffix, payload) {
|
|
|
23031
23109
|
init_config();
|
|
23032
23110
|
init_litellm();
|
|
23033
23111
|
init_stateWorkspace();
|
|
23112
|
+
init_companyStore();
|
|
23034
23113
|
var DEFAULT_MODEL2 = "claude/claude-haiku-4-5-20251001";
|
|
23035
23114
|
var CHAT_HELP = `kody chat \u2014 dashboard-driven chat session
|
|
23036
23115
|
|
|
@@ -23111,8 +23190,12 @@ async function runChat(argv) {
|
|
|
23111
23190
|
${CHAT_HELP}`);
|
|
23112
23191
|
return 64;
|
|
23113
23192
|
}
|
|
23114
|
-
const cwd = args.cwd ?
|
|
23193
|
+
const cwd = args.cwd ? path50.resolve(args.cwd) : process.cwd();
|
|
23115
23194
|
const sessionId = args.sessionId;
|
|
23195
|
+
const runRequest = readRunRequestFromEnv();
|
|
23196
|
+
if (runRequest && "request" in runRequest) {
|
|
23197
|
+
applyCompanyStoreRuntimeConfig(runRequest.request.input);
|
|
23198
|
+
}
|
|
23116
23199
|
const unpackedSecrets = unpackAllSecrets();
|
|
23117
23200
|
if (unpackedSecrets > 0) {
|
|
23118
23201
|
process.stdout.write(`\u2192 kody: unpacked ${unpackedSecrets} secret(s) from ALL_SECRETS
|
|
@@ -23172,7 +23255,7 @@ ${CHAT_HELP}`);
|
|
|
23172
23255
|
const sink = buildSink(cwd, sessionId, args.dashboardUrl);
|
|
23173
23256
|
const meta = readMeta(sessionFile);
|
|
23174
23257
|
process.stdout.write(
|
|
23175
|
-
`\u2192 kody:chat: session file=${sessionFile} exists=${
|
|
23258
|
+
`\u2192 kody:chat: session file=${sessionFile} exists=${fs51.existsSync(sessionFile)} meta=${meta ? meta.mode : "none"}
|
|
23176
23259
|
`
|
|
23177
23260
|
);
|
|
23178
23261
|
try {
|
|
@@ -23302,8 +23385,8 @@ var FlyClient = class {
|
|
|
23302
23385
|
get fetch() {
|
|
23303
23386
|
return this.opts.fetchImpl ?? fetch;
|
|
23304
23387
|
}
|
|
23305
|
-
async call(
|
|
23306
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
23388
|
+
async call(path51, init = {}) {
|
|
23389
|
+
const res = await this.fetch(`${FLY_API_BASE}${path51}`, {
|
|
23307
23390
|
method: init.method ?? "GET",
|
|
23308
23391
|
headers: {
|
|
23309
23392
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -23314,7 +23397,7 @@ var FlyClient = class {
|
|
|
23314
23397
|
if (res.status === 404 && init.allow404) return null;
|
|
23315
23398
|
if (!res.ok) {
|
|
23316
23399
|
const text = await res.text().catch(() => "");
|
|
23317
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
23400
|
+
throw new Error(`Fly API ${res.status} on ${path51}: ${text.slice(0, 200) || res.statusText}`);
|
|
23318
23401
|
}
|
|
23319
23402
|
if (res.status === 204) return null;
|
|
23320
23403
|
const raw = await res.text();
|
|
@@ -24032,7 +24115,7 @@ async function poolServe() {
|
|
|
24032
24115
|
|
|
24033
24116
|
// src/servers/runner-serve.ts
|
|
24034
24117
|
import { spawn as spawn8 } from "child_process";
|
|
24035
|
-
import * as
|
|
24118
|
+
import * as fs52 from "fs";
|
|
24036
24119
|
import { createServer as createServer6 } from "http";
|
|
24037
24120
|
var DEFAULT_PORT2 = 8080;
|
|
24038
24121
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -24167,8 +24250,8 @@ async function defaultRunJob(job) {
|
|
|
24167
24250
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
24168
24251
|
const branch = job.ref ?? "main";
|
|
24169
24252
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
24170
|
-
|
|
24171
|
-
|
|
24253
|
+
fs52.rmSync(workdir, { recursive: true, force: true });
|
|
24254
|
+
fs52.mkdirSync(workdir, { recursive: true });
|
|
24172
24255
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
24173
24256
|
const target = job.runRequest.target;
|
|
24174
24257
|
const interactive = target.type === "chat";
|