@kody-ade/kody-engine 0.4.273 → 0.4.275
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 +438 -265
- package/dist/executables/types.ts +1 -1
- 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.275",
|
|
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",
|
|
@@ -2217,7 +2217,7 @@ function cmsHeaders(opts) {
|
|
|
2217
2217
|
}
|
|
2218
2218
|
};
|
|
2219
2219
|
}
|
|
2220
|
-
async function callDashboardCms(opts,
|
|
2220
|
+
async function callDashboardCms(opts, path50, init = {}) {
|
|
2221
2221
|
const baseUrl = dashboardBaseUrl();
|
|
2222
2222
|
if (!baseUrl) {
|
|
2223
2223
|
return {
|
|
@@ -2229,7 +2229,7 @@ async function callDashboardCms(opts, path49, init = {}) {
|
|
|
2229
2229
|
const headerResult = cmsHeaders(opts);
|
|
2230
2230
|
if (!headerResult.ok) return headerResult;
|
|
2231
2231
|
try {
|
|
2232
|
-
const res = await fetch(`${baseUrl}${
|
|
2232
|
+
const res = await fetch(`${baseUrl}${path50}`, {
|
|
2233
2233
|
...init,
|
|
2234
2234
|
headers: {
|
|
2235
2235
|
...headerResult.headers,
|
|
@@ -6430,10 +6430,10 @@ var init_state2 = __esm({
|
|
|
6430
6430
|
"use strict";
|
|
6431
6431
|
VALID_STATES = /* @__PURE__ */ new Set(["active", "abandoned", "closed", "done"]);
|
|
6432
6432
|
GoalStateError = class extends Error {
|
|
6433
|
-
constructor(
|
|
6434
|
-
super(`Invalid goal state at ${
|
|
6433
|
+
constructor(path50, message) {
|
|
6434
|
+
super(`Invalid goal state at ${path50}:
|
|
6435
6435
|
${message}`);
|
|
6436
|
-
this.path =
|
|
6436
|
+
this.path = path50;
|
|
6437
6437
|
this.name = "GoalStateError";
|
|
6438
6438
|
}
|
|
6439
6439
|
path;
|
|
@@ -6446,9 +6446,9 @@ import * as fs25 from "fs";
|
|
|
6446
6446
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
6447
6447
|
const logs = goalRunLogs(data);
|
|
6448
6448
|
const existing = logs[goalId];
|
|
6449
|
-
const
|
|
6449
|
+
const path50 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
6450
6450
|
logs[goalId] = {
|
|
6451
|
-
path:
|
|
6451
|
+
path: path50,
|
|
6452
6452
|
events: [
|
|
6453
6453
|
...existing?.events ?? [],
|
|
6454
6454
|
buildGoalRunLogEvent(data, goalId, event, at)
|
|
@@ -6810,6 +6810,188 @@ var init_runLog = __esm({
|
|
|
6810
6810
|
}
|
|
6811
6811
|
});
|
|
6812
6812
|
|
|
6813
|
+
// src/goal/stateStore.ts
|
|
6814
|
+
function statePath(goalId) {
|
|
6815
|
+
return `goals/instances/${goalId}/state.json`;
|
|
6816
|
+
}
|
|
6817
|
+
function fetchGoalState(config, goalId, cwd) {
|
|
6818
|
+
const filePath = statePath(goalId);
|
|
6819
|
+
const loaded = readStateText(config, cwd, filePath);
|
|
6820
|
+
if (!loaded) return null;
|
|
6821
|
+
return parseGoalState(loaded.path, JSON.parse(loaded.content));
|
|
6822
|
+
}
|
|
6823
|
+
function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
|
|
6824
|
+
upsertStateText(config, cwd, statePath(goalId), serializeGoalState(state), message);
|
|
6825
|
+
}
|
|
6826
|
+
var init_stateStore = __esm({
|
|
6827
|
+
"src/goal/stateStore.ts"() {
|
|
6828
|
+
"use strict";
|
|
6829
|
+
init_stateRepo();
|
|
6830
|
+
init_state2();
|
|
6831
|
+
}
|
|
6832
|
+
});
|
|
6833
|
+
|
|
6834
|
+
// src/goal/targetLoopResolution.ts
|
|
6835
|
+
import * as fs26 from "fs";
|
|
6836
|
+
import * as path24 from "path";
|
|
6837
|
+
function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
|
|
6838
|
+
const targetId = loopGoal.loopTarget?.id.trim() ?? "";
|
|
6839
|
+
assertSafeGoalId(targetId, "loop target");
|
|
6840
|
+
if (!hasExplicitStateRepo(config)) {
|
|
6841
|
+
return { targetId, templateId: targetId, reason: "literal target; state repo not configured" };
|
|
6842
|
+
}
|
|
6843
|
+
const activeInstance = findActiveTargetInstance(config, cwd, loopGoalId, targetId);
|
|
6844
|
+
if (activeInstance) {
|
|
6845
|
+
return {
|
|
6846
|
+
targetId: activeInstance.id,
|
|
6847
|
+
templateId: targetId,
|
|
6848
|
+
reason: "active target instance"
|
|
6849
|
+
};
|
|
6850
|
+
}
|
|
6851
|
+
const directTarget = fetchGoalState(config, targetId, cwd);
|
|
6852
|
+
if (directTarget?.state === "active") {
|
|
6853
|
+
return { targetId, templateId: targetId, reason: "active target goal" };
|
|
6854
|
+
}
|
|
6855
|
+
const template = loadGoalTemplate(cwd, targetId);
|
|
6856
|
+
if (!template) {
|
|
6857
|
+
if (directTarget) {
|
|
6858
|
+
throw new Error(`goal target ${targetId} is ${directTarget.state}; no active instance or template found`);
|
|
6859
|
+
}
|
|
6860
|
+
return { targetId, templateId: targetId, reason: "literal target; no target state or template found" };
|
|
6861
|
+
}
|
|
6862
|
+
const instanceId = chooseTargetInstanceId(config, cwd, targetId, loopGoal.preferredRunTime?.timezone, now);
|
|
6863
|
+
const instance = buildGoalTargetInstance(template, targetId, now);
|
|
6864
|
+
putGoalState(config, instanceId, instance, `chore(goals): create ${instanceId}`, cwd);
|
|
6865
|
+
return {
|
|
6866
|
+
targetId: instanceId,
|
|
6867
|
+
templateId: targetId,
|
|
6868
|
+
reason: "created target instance from template",
|
|
6869
|
+
created: true
|
|
6870
|
+
};
|
|
6871
|
+
}
|
|
6872
|
+
function goalLoopNow() {
|
|
6873
|
+
const value = process.env.KODY_GOAL_LOOP_NOW?.trim();
|
|
6874
|
+
if (value) {
|
|
6875
|
+
const date = new Date(value);
|
|
6876
|
+
if (!Number.isNaN(date.getTime())) return date;
|
|
6877
|
+
}
|
|
6878
|
+
return /* @__PURE__ */ new Date();
|
|
6879
|
+
}
|
|
6880
|
+
function hasExplicitStateRepo(config) {
|
|
6881
|
+
const state = config.state;
|
|
6882
|
+
return !!state && typeof state.repo === "string" && state.repo.trim().length > 0 && typeof state.path === "string" && state.path.trim().length > 0;
|
|
6883
|
+
}
|
|
6884
|
+
function findActiveTargetInstance(config, cwd, loopGoalId, targetId) {
|
|
6885
|
+
const entries = listStateDirectory(config, cwd, "goals/instances");
|
|
6886
|
+
const candidates = [];
|
|
6887
|
+
for (const entry of entries) {
|
|
6888
|
+
const id = typeof entry.name === "string" ? entry.name.trim() : "";
|
|
6889
|
+
if (!id || id === loopGoalId || id === targetId || !id.startsWith(`${targetId}-`)) continue;
|
|
6890
|
+
assertSafeGoalId(id, "goal instance");
|
|
6891
|
+
const state = fetchGoalState(config, id, cwd);
|
|
6892
|
+
if (!state || state.state !== "active") continue;
|
|
6893
|
+
if (!isTargetInstanceState(id, state, targetId)) continue;
|
|
6894
|
+
candidates.push({ id, state });
|
|
6895
|
+
}
|
|
6896
|
+
candidates.sort(compareGoalInstanceAge);
|
|
6897
|
+
return candidates[0] ?? null;
|
|
6898
|
+
}
|
|
6899
|
+
function isTargetInstanceState(id, state, targetId) {
|
|
6900
|
+
if (id.startsWith(`${targetId}-`)) return true;
|
|
6901
|
+
return ["template", "sourceTemplate", "templateId", "type"].some((key) => state.extra[key] === targetId);
|
|
6902
|
+
}
|
|
6903
|
+
function compareGoalInstanceAge(a, b) {
|
|
6904
|
+
const byTime = goalInstanceTime(a.state) - goalInstanceTime(b.state);
|
|
6905
|
+
return byTime === 0 ? a.id.localeCompare(b.id) : byTime;
|
|
6906
|
+
}
|
|
6907
|
+
function goalInstanceTime(state) {
|
|
6908
|
+
const value = state.createdAt ?? state.startedAt ?? state.updatedAt;
|
|
6909
|
+
if (!value) return 0;
|
|
6910
|
+
const parsed = Date.parse(value);
|
|
6911
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
6912
|
+
}
|
|
6913
|
+
function loadGoalTemplate(cwd, targetId) {
|
|
6914
|
+
const local = path24.join(cwd, ".kody", "goals", "templates", targetId, "state.json");
|
|
6915
|
+
const localTemplate = readJsonObject(local);
|
|
6916
|
+
if (localTemplate) return localTemplate;
|
|
6917
|
+
const storeGoalRoot = getCompanyStoreAssetRoot("goals");
|
|
6918
|
+
if (!storeGoalRoot) return null;
|
|
6919
|
+
return readJsonObject(path24.join(storeGoalRoot, "templates", targetId, "state.json"));
|
|
6920
|
+
}
|
|
6921
|
+
function readJsonObject(filePath) {
|
|
6922
|
+
if (!fs26.existsSync(filePath)) return null;
|
|
6923
|
+
const parsed = JSON.parse(fs26.readFileSync(filePath, "utf8"));
|
|
6924
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
6925
|
+
throw new Error(`goal template ${filePath} must be a JSON object`);
|
|
6926
|
+
}
|
|
6927
|
+
return parsed;
|
|
6928
|
+
}
|
|
6929
|
+
function chooseTargetInstanceId(config, cwd, targetId, timezone, now) {
|
|
6930
|
+
const base = `${targetId}-${zonedDate(now, timezone ?? "UTC")}`;
|
|
6931
|
+
for (let index = 1; index <= 20; index += 1) {
|
|
6932
|
+
const id = index === 1 ? base : `${base}-${index}`;
|
|
6933
|
+
assertSafeGoalId(id, "goal instance");
|
|
6934
|
+
const existing = fetchGoalState(config, id, cwd);
|
|
6935
|
+
if (!existing || existing.state === "active") return id;
|
|
6936
|
+
}
|
|
6937
|
+
throw new Error(`could not allocate goal target instance id for ${targetId}`);
|
|
6938
|
+
}
|
|
6939
|
+
function buildGoalTargetInstance(template, targetId, now) {
|
|
6940
|
+
const extra = { ...template };
|
|
6941
|
+
for (const key of ["state", "createdAt", "updatedAt", "startedAt"]) {
|
|
6942
|
+
delete extra[key];
|
|
6943
|
+
}
|
|
6944
|
+
extra.kind = "instance";
|
|
6945
|
+
extra.template = targetId;
|
|
6946
|
+
extra.sourceTemplate = targetId;
|
|
6947
|
+
extra.templateId = targetId;
|
|
6948
|
+
if (!isPlainObject2(extra.facts)) extra.facts = {};
|
|
6949
|
+
if (!Array.isArray(extra.blockers)) extra.blockers = [];
|
|
6950
|
+
const at = isoNoMs(now);
|
|
6951
|
+
return {
|
|
6952
|
+
state: "active",
|
|
6953
|
+
createdAt: at,
|
|
6954
|
+
updatedAt: at,
|
|
6955
|
+
extra
|
|
6956
|
+
};
|
|
6957
|
+
}
|
|
6958
|
+
function isPlainObject2(value) {
|
|
6959
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6960
|
+
}
|
|
6961
|
+
function assertSafeGoalId(value, label) {
|
|
6962
|
+
if (!/^[A-Za-z0-9_.-]+$/.test(value)) {
|
|
6963
|
+
throw new Error(`${label} id must contain only letters, numbers, dot, underscore, or dash: ${value}`);
|
|
6964
|
+
}
|
|
6965
|
+
}
|
|
6966
|
+
function zonedDate(date, timezone) {
|
|
6967
|
+
try {
|
|
6968
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
6969
|
+
timeZone: timezone,
|
|
6970
|
+
year: "numeric",
|
|
6971
|
+
month: "2-digit",
|
|
6972
|
+
day: "2-digit"
|
|
6973
|
+
}).formatToParts(date);
|
|
6974
|
+
const get = (type) => parts.find((part) => part.type === type)?.value;
|
|
6975
|
+
const year = get("year");
|
|
6976
|
+
const month = get("month");
|
|
6977
|
+
const day = get("day");
|
|
6978
|
+
if (year && month && day) return `${year}-${month}-${day}`;
|
|
6979
|
+
} catch {
|
|
6980
|
+
}
|
|
6981
|
+
return date.toISOString().slice(0, 10);
|
|
6982
|
+
}
|
|
6983
|
+
function isoNoMs(date) {
|
|
6984
|
+
return date.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
6985
|
+
}
|
|
6986
|
+
var init_targetLoopResolution = __esm({
|
|
6987
|
+
"src/goal/targetLoopResolution.ts"() {
|
|
6988
|
+
"use strict";
|
|
6989
|
+
init_companyStore();
|
|
6990
|
+
init_stateRepo();
|
|
6991
|
+
init_stateStore();
|
|
6992
|
+
}
|
|
6993
|
+
});
|
|
6994
|
+
|
|
6813
6995
|
// src/goal/typeDefinitions.ts
|
|
6814
6996
|
function cloneRoute(route) {
|
|
6815
6997
|
return route.map((step) => ({
|
|
@@ -7136,8 +7318,8 @@ var init_contentsApiBackend = __esm({
|
|
|
7136
7318
|
});
|
|
7137
7319
|
|
|
7138
7320
|
// src/scripts/jobState/localFileBackend.ts
|
|
7139
|
-
import * as
|
|
7140
|
-
import * as
|
|
7321
|
+
import * as fs27 from "fs";
|
|
7322
|
+
import * as path25 from "path";
|
|
7141
7323
|
function sanitizeKey(s) {
|
|
7142
7324
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
7143
7325
|
}
|
|
@@ -7193,7 +7375,7 @@ var init_localFileBackend = __esm({
|
|
|
7193
7375
|
if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
|
|
7194
7376
|
this.cwd = opts.cwd;
|
|
7195
7377
|
this.jobsDir = opts.jobsDir;
|
|
7196
|
-
this.absDir =
|
|
7378
|
+
this.absDir = path25.join(opts.cwd, opts.jobsDir);
|
|
7197
7379
|
this.owner = opts.owner;
|
|
7198
7380
|
this.repo = opts.repo;
|
|
7199
7381
|
this.cache = opts.cache ?? defaultCacheAdapter();
|
|
@@ -7208,7 +7390,7 @@ var init_localFileBackend = __esm({
|
|
|
7208
7390
|
`);
|
|
7209
7391
|
return;
|
|
7210
7392
|
}
|
|
7211
|
-
|
|
7393
|
+
fs27.mkdirSync(this.absDir, { recursive: true });
|
|
7212
7394
|
const prefix = this.cacheKeyPrefix();
|
|
7213
7395
|
const probeKey = `${prefix}probe-${Date.now()}`;
|
|
7214
7396
|
try {
|
|
@@ -7237,7 +7419,7 @@ var init_localFileBackend = __esm({
|
|
|
7237
7419
|
`);
|
|
7238
7420
|
return;
|
|
7239
7421
|
}
|
|
7240
|
-
if (!
|
|
7422
|
+
if (!fs27.existsSync(this.absDir)) {
|
|
7241
7423
|
return;
|
|
7242
7424
|
}
|
|
7243
7425
|
const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
|
|
@@ -7253,11 +7435,11 @@ var init_localFileBackend = __esm({
|
|
|
7253
7435
|
}
|
|
7254
7436
|
load(slug2) {
|
|
7255
7437
|
const relPath = stateFilePath(this.jobsDir, slug2);
|
|
7256
|
-
const absPath =
|
|
7257
|
-
if (!
|
|
7438
|
+
const absPath = path25.join(this.cwd, relPath);
|
|
7439
|
+
if (!fs27.existsSync(absPath)) {
|
|
7258
7440
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
7259
7441
|
}
|
|
7260
|
-
const raw =
|
|
7442
|
+
const raw = fs27.readFileSync(absPath, "utf-8");
|
|
7261
7443
|
let parsed;
|
|
7262
7444
|
try {
|
|
7263
7445
|
parsed = JSON.parse(raw);
|
|
@@ -7274,13 +7456,13 @@ var init_localFileBackend = __esm({
|
|
|
7274
7456
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
7275
7457
|
return false;
|
|
7276
7458
|
}
|
|
7277
|
-
const absPath =
|
|
7278
|
-
|
|
7459
|
+
const absPath = path25.join(this.cwd, loaded.path);
|
|
7460
|
+
fs27.mkdirSync(path25.dirname(absPath), { recursive: true });
|
|
7279
7461
|
const body = `${JSON.stringify(next, null, 2)}
|
|
7280
7462
|
`;
|
|
7281
7463
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
7282
|
-
|
|
7283
|
-
|
|
7464
|
+
fs27.writeFileSync(tmpPath, body, "utf-8");
|
|
7465
|
+
fs27.renameSync(tmpPath, absPath);
|
|
7284
7466
|
return true;
|
|
7285
7467
|
}
|
|
7286
7468
|
cacheKeyPrefix() {
|
|
@@ -7320,7 +7502,7 @@ var init_jobState = __esm({
|
|
|
7320
7502
|
});
|
|
7321
7503
|
|
|
7322
7504
|
// src/scripts/goalCapabilityScheduling.ts
|
|
7323
|
-
import * as
|
|
7505
|
+
import * as path26 from "path";
|
|
7324
7506
|
function isCapabilityCadenceGoal(goal, extra) {
|
|
7325
7507
|
return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
|
|
7326
7508
|
}
|
|
@@ -7348,10 +7530,11 @@ function planTargetLoopSchedule(opts) {
|
|
|
7348
7530
|
const gate = preferredRunTimeGate(preferred, now, opts.previousScheduleState);
|
|
7349
7531
|
if (!gate.ok) return targetLoopDecision("idle", gate.reason, at);
|
|
7350
7532
|
}
|
|
7351
|
-
const
|
|
7533
|
+
const dispatchTargetId = target.type === "goal" && opts.resolvedGoalTargetId?.trim() ? opts.resolvedGoalTargetId.trim() : targetId;
|
|
7534
|
+
const dispatch2 = target.type === "goal" ? { action: "goal-manager", executable: "goal-manager", cliArgs: { goal: dispatchTargetId } } : { workflow: targetId, cliArgs: {} };
|
|
7352
7535
|
return {
|
|
7353
7536
|
kind: "dispatch",
|
|
7354
|
-
reason: `dispatch ${target.type} ${targetId}`,
|
|
7537
|
+
reason: `dispatch ${target.type} ${target.type === "goal" ? dispatchTargetId : targetId}`,
|
|
7355
7538
|
dispatch: dispatch2,
|
|
7356
7539
|
scheduleState: {
|
|
7357
7540
|
mode: "agentLoop",
|
|
@@ -7359,7 +7542,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
7359
7542
|
lastDecision: {
|
|
7360
7543
|
kind: "dispatch",
|
|
7361
7544
|
targetType: target.type,
|
|
7362
|
-
targetId,
|
|
7545
|
+
targetId: target.type === "goal" ? dispatchTargetId : targetId,
|
|
7363
7546
|
...dispatch2.action ? { action: dispatch2.action } : {},
|
|
7364
7547
|
...dispatch2.capability ? { capability: dispatch2.capability } : {},
|
|
7365
7548
|
...dispatch2.workflow ? { workflow: dispatch2.workflow } : {},
|
|
@@ -7373,7 +7556,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
7373
7556
|
}
|
|
7374
7557
|
async function planGoalCapabilitySchedule(opts) {
|
|
7375
7558
|
const jobsDir = opts.jobsDir ?? ".kody/capabilities";
|
|
7376
|
-
const jobsRoot =
|
|
7559
|
+
const jobsRoot = path26.join(opts.cwd, jobsDir);
|
|
7377
7560
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
7378
7561
|
const at = now.toISOString();
|
|
7379
7562
|
const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
|
|
@@ -7710,6 +7893,7 @@ var init_advanceManagedGoal = __esm({
|
|
|
7710
7893
|
init_manager();
|
|
7711
7894
|
init_runLog();
|
|
7712
7895
|
init_state2();
|
|
7896
|
+
init_targetLoopResolution();
|
|
7713
7897
|
init_typeDefinitions();
|
|
7714
7898
|
init_issue();
|
|
7715
7899
|
init_goalCapabilityScheduling();
|
|
@@ -7782,7 +7966,18 @@ var init_advanceManagedGoal = __esm({
|
|
|
7782
7966
|
if (isGoalTargetLoop(managed) || isWorkflowTargetLoop(managed)) {
|
|
7783
7967
|
const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7784
7968
|
const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
|
|
7785
|
-
const
|
|
7969
|
+
const now = goalLoopNow();
|
|
7970
|
+
let decision2 = planTargetLoopSchedule({ goal: managed, previousScheduleState, now });
|
|
7971
|
+
let targetResolution;
|
|
7972
|
+
if (decision2.kind === "dispatch" && decision2.dispatch && isGoalTargetLoop(managed)) {
|
|
7973
|
+
targetResolution = resolveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed, now);
|
|
7974
|
+
decision2 = planTargetLoopSchedule({
|
|
7975
|
+
goal: managed,
|
|
7976
|
+
previousScheduleState,
|
|
7977
|
+
now,
|
|
7978
|
+
resolvedGoalTargetId: targetResolution.targetId
|
|
7979
|
+
});
|
|
7980
|
+
}
|
|
7786
7981
|
restoreGoalIdFact();
|
|
7787
7982
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
7788
7983
|
goal.raw.extra.scheduleState = decision2.scheduleState;
|
|
@@ -7809,6 +8004,7 @@ var init_advanceManagedGoal = __esm({
|
|
|
7809
8004
|
goal: goalRunLogSnapshot(goal.id, goal.state, managed),
|
|
7810
8005
|
inspection: {
|
|
7811
8006
|
loopTarget: managed.loopTarget,
|
|
8007
|
+
...targetResolution ? { targetResolution } : {},
|
|
7812
8008
|
preferredRunTime: managed.preferredRunTime,
|
|
7813
8009
|
previousScheduleState,
|
|
7814
8010
|
scheduleState: decision2.scheduleState
|
|
@@ -8154,13 +8350,13 @@ function companyIntentPath(id) {
|
|
|
8154
8350
|
assertIntentId(id);
|
|
8155
8351
|
return `intents/${id}/intent.json`;
|
|
8156
8352
|
}
|
|
8157
|
-
function normalizeCompanyIntent(
|
|
8353
|
+
function normalizeCompanyIntent(path50, raw) {
|
|
8158
8354
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
8159
|
-
throw new Error(`${
|
|
8355
|
+
throw new Error(`${path50}: intent must be JSON object`);
|
|
8160
8356
|
}
|
|
8161
8357
|
const input = raw;
|
|
8162
8358
|
const id = stringField2(input.id);
|
|
8163
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
8359
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path50}: invalid intent id`);
|
|
8164
8360
|
const createdAt = stringField2(input.createdAt) || nowIso();
|
|
8165
8361
|
const updatedAt = stringField2(input.updatedAt) || createdAt;
|
|
8166
8362
|
return {
|
|
@@ -8199,8 +8395,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
8199
8395
|
const records = [];
|
|
8200
8396
|
for (const entry of entries) {
|
|
8201
8397
|
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
8202
|
-
const
|
|
8203
|
-
const file = readStateText(config, cwd,
|
|
8398
|
+
const path50 = companyIntentPath(entry.name);
|
|
8399
|
+
const file = readStateText(config, cwd, path50);
|
|
8204
8400
|
if (!file) continue;
|
|
8205
8401
|
records.push({
|
|
8206
8402
|
id: entry.name,
|
|
@@ -8211,8 +8407,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
8211
8407
|
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
8212
8408
|
}
|
|
8213
8409
|
function readCompanyIntent(config, cwd, id) {
|
|
8214
|
-
const
|
|
8215
|
-
const file = readStateText(config, cwd,
|
|
8410
|
+
const path50 = companyIntentPath(id);
|
|
8411
|
+
const file = readStateText(config, cwd, path50);
|
|
8216
8412
|
if (!file) return null;
|
|
8217
8413
|
return { id, path: file.path, intent: normalizeCompanyIntent(file.path, JSON.parse(file.content)) };
|
|
8218
8414
|
}
|
|
@@ -8304,27 +8500,6 @@ var init_companyIntent = __esm({
|
|
|
8304
8500
|
}
|
|
8305
8501
|
});
|
|
8306
8502
|
|
|
8307
|
-
// src/goal/stateStore.ts
|
|
8308
|
-
function statePath(goalId) {
|
|
8309
|
-
return `goals/instances/${goalId}/state.json`;
|
|
8310
|
-
}
|
|
8311
|
-
function fetchGoalState(config, goalId, cwd) {
|
|
8312
|
-
const filePath = statePath(goalId);
|
|
8313
|
-
const loaded = readStateText(config, cwd, filePath);
|
|
8314
|
-
if (!loaded) return null;
|
|
8315
|
-
return parseGoalState(loaded.path, JSON.parse(loaded.content));
|
|
8316
|
-
}
|
|
8317
|
-
function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
|
|
8318
|
-
upsertStateText(config, cwd, statePath(goalId), serializeGoalState(state), message);
|
|
8319
|
-
}
|
|
8320
|
-
var init_stateStore = __esm({
|
|
8321
|
-
"src/goal/stateStore.ts"() {
|
|
8322
|
-
"use strict";
|
|
8323
|
-
init_stateRepo();
|
|
8324
|
-
init_state2();
|
|
8325
|
-
}
|
|
8326
|
-
});
|
|
8327
|
-
|
|
8328
8503
|
// src/scripts/applyCompanyManagerDecision.ts
|
|
8329
8504
|
function applyAction(config, cwd, action) {
|
|
8330
8505
|
if (action.kind === "createManagedGoal") {
|
|
@@ -8633,7 +8808,7 @@ function refreshGoalDashboardReport(input) {
|
|
|
8633
8808
|
if (!REPORT_SLUG_RE.test(input.goalId)) {
|
|
8634
8809
|
throw new Error(`goal report: invalid goal id "${input.goalId}"`);
|
|
8635
8810
|
}
|
|
8636
|
-
const filePath =
|
|
8811
|
+
const filePath = goalDashboardReportRunPath(input.goalId);
|
|
8637
8812
|
const body = goalReportBody(
|
|
8638
8813
|
input.goalId,
|
|
8639
8814
|
input.state,
|
|
@@ -8641,17 +8816,15 @@ function refreshGoalDashboardReport(input) {
|
|
|
8641
8816
|
latestGoalRunLogEvent(input.data, input.goalId),
|
|
8642
8817
|
evidenceItems
|
|
8643
8818
|
);
|
|
8644
|
-
|
|
8645
|
-
if (current?.content === body) {
|
|
8646
|
-
const report2 = { slug: input.goalId, path: current.path, changed: false };
|
|
8647
|
-
recordGoalReport(input.data, report2);
|
|
8648
|
-
return report2;
|
|
8649
|
-
}
|
|
8650
|
-
upsertStateText(input.config, input.cwd, filePath, body, `chore(reports): refresh ${input.goalId}`);
|
|
8819
|
+
writeStateText(input.config, input.cwd, filePath, body, `chore(reports): add ${input.goalId} run`);
|
|
8651
8820
|
const report = { slug: input.goalId, path: filePath, changed: true };
|
|
8652
8821
|
recordGoalReport(input.data, report);
|
|
8653
8822
|
return report;
|
|
8654
8823
|
}
|
|
8824
|
+
function goalDashboardReportRunPath(goalId, now = /* @__PURE__ */ new Date()) {
|
|
8825
|
+
const runId = now.toISOString().replace(/\.\d{3}Z$/, "Z").replace(/:/g, "-");
|
|
8826
|
+
return `reports/${goalId}/runs/${runId}.md`;
|
|
8827
|
+
}
|
|
8655
8828
|
function capabilityEvidenceOutput(evidence) {
|
|
8656
8829
|
return {
|
|
8657
8830
|
kind: "capability-evidence",
|
|
@@ -9266,8 +9439,8 @@ var init_classifyByLabel = __esm({
|
|
|
9266
9439
|
});
|
|
9267
9440
|
|
|
9268
9441
|
// src/scripts/commitAndPush.ts
|
|
9269
|
-
import * as
|
|
9270
|
-
import * as
|
|
9442
|
+
import * as fs28 from "fs";
|
|
9443
|
+
import * as path27 from "path";
|
|
9271
9444
|
function sentinelPathForStage(cwd, profileName) {
|
|
9272
9445
|
const runId = resolveRunId();
|
|
9273
9446
|
return runtimeStatePath(cwd, "agent-runs", runId, `commit-${profileName}.lock`);
|
|
@@ -9288,9 +9461,9 @@ var init_commitAndPush = __esm({
|
|
|
9288
9461
|
}
|
|
9289
9462
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
9290
9463
|
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
9291
|
-
if (sentinel &&
|
|
9464
|
+
if (sentinel && fs28.existsSync(sentinel)) {
|
|
9292
9465
|
try {
|
|
9293
|
-
const replay = JSON.parse(
|
|
9466
|
+
const replay = JSON.parse(fs28.readFileSync(sentinel, "utf-8"));
|
|
9294
9467
|
ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
|
|
9295
9468
|
if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
|
|
9296
9469
|
if (typeof replay.hasCommitsAhead === "boolean") ctx.data.hasCommitsAhead = replay.hasCommitsAhead;
|
|
@@ -9343,8 +9516,8 @@ var init_commitAndPush = __esm({
|
|
|
9343
9516
|
const result = ctx.data.commitResult;
|
|
9344
9517
|
if (sentinel && result?.committed) {
|
|
9345
9518
|
try {
|
|
9346
|
-
|
|
9347
|
-
|
|
9519
|
+
fs28.mkdirSync(path27.dirname(sentinel), { recursive: true });
|
|
9520
|
+
fs28.writeFileSync(
|
|
9348
9521
|
sentinel,
|
|
9349
9522
|
JSON.stringify(
|
|
9350
9523
|
{
|
|
@@ -9435,8 +9608,8 @@ var init_commitGoalState = __esm({
|
|
|
9435
9608
|
});
|
|
9436
9609
|
|
|
9437
9610
|
// src/scripts/composePrompt.ts
|
|
9438
|
-
import * as
|
|
9439
|
-
import * as
|
|
9611
|
+
import * as fs29 from "fs";
|
|
9612
|
+
import * as path28 from "path";
|
|
9440
9613
|
function fenceUntrusted(value) {
|
|
9441
9614
|
if (value.trim().length === 0) return value;
|
|
9442
9615
|
const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
|
|
@@ -9559,10 +9732,10 @@ var init_composePrompt = __esm({
|
|
|
9559
9732
|
const explicit = ctx.data.promptTemplate;
|
|
9560
9733
|
const mode = ctx.args.mode;
|
|
9561
9734
|
const candidates = [
|
|
9562
|
-
explicit ?
|
|
9563
|
-
mode ?
|
|
9564
|
-
|
|
9565
|
-
|
|
9735
|
+
explicit ? path28.join(profile.dir, explicit) : null,
|
|
9736
|
+
mode ? path28.join(profile.dir, "prompts", `${mode}.md`) : null,
|
|
9737
|
+
path28.join(profile.dir, "prompt.md"),
|
|
9738
|
+
path28.join(profile.dir, "capability.md")
|
|
9566
9739
|
].filter(Boolean);
|
|
9567
9740
|
let templatePath = "";
|
|
9568
9741
|
let template = "";
|
|
@@ -9575,7 +9748,7 @@ var init_composePrompt = __esm({
|
|
|
9575
9748
|
break;
|
|
9576
9749
|
}
|
|
9577
9750
|
try {
|
|
9578
|
-
template =
|
|
9751
|
+
template = fs29.readFileSync(c, "utf-8");
|
|
9579
9752
|
templatePath = c;
|
|
9580
9753
|
break;
|
|
9581
9754
|
} catch (err) {
|
|
@@ -9586,7 +9759,7 @@ var init_composePrompt = __esm({
|
|
|
9586
9759
|
if (!templatePath) {
|
|
9587
9760
|
let dirState;
|
|
9588
9761
|
try {
|
|
9589
|
-
dirState = `dir contents: [${
|
|
9762
|
+
dirState = `dir contents: [${fs29.readdirSync(profile.dir).join(", ")}]`;
|
|
9590
9763
|
} catch (err) {
|
|
9591
9764
|
dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
|
|
9592
9765
|
}
|
|
@@ -10186,19 +10359,19 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
10186
10359
|
|
|
10187
10360
|
// src/scripts/diagMcp.ts
|
|
10188
10361
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
10189
|
-
import * as
|
|
10362
|
+
import * as fs30 from "fs";
|
|
10190
10363
|
import * as os6 from "os";
|
|
10191
|
-
import * as
|
|
10364
|
+
import * as path29 from "path";
|
|
10192
10365
|
var diagMcp;
|
|
10193
10366
|
var init_diagMcp = __esm({
|
|
10194
10367
|
"src/scripts/diagMcp.ts"() {
|
|
10195
10368
|
"use strict";
|
|
10196
10369
|
diagMcp = async (_ctx) => {
|
|
10197
10370
|
const home = os6.homedir();
|
|
10198
|
-
const cacheDir =
|
|
10371
|
+
const cacheDir = path29.join(home, ".cache", "ms-playwright");
|
|
10199
10372
|
let entries = [];
|
|
10200
10373
|
try {
|
|
10201
|
-
entries =
|
|
10374
|
+
entries = fs30.readdirSync(cacheDir);
|
|
10202
10375
|
} catch {
|
|
10203
10376
|
}
|
|
10204
10377
|
const hasChromium = entries.some((e) => e.startsWith("chromium"));
|
|
@@ -10226,13 +10399,13 @@ var init_diagMcp = __esm({
|
|
|
10226
10399
|
});
|
|
10227
10400
|
|
|
10228
10401
|
// src/scripts/frameworkDetectors.ts
|
|
10229
|
-
import * as
|
|
10230
|
-
import * as
|
|
10402
|
+
import * as fs31 from "fs";
|
|
10403
|
+
import * as path30 from "path";
|
|
10231
10404
|
function detectFrameworks(cwd) {
|
|
10232
10405
|
const out = [];
|
|
10233
10406
|
let deps = {};
|
|
10234
10407
|
try {
|
|
10235
|
-
const pkg = JSON.parse(
|
|
10408
|
+
const pkg = JSON.parse(fs31.readFileSync(path30.join(cwd, "package.json"), "utf-8"));
|
|
10236
10409
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
10237
10410
|
} catch {
|
|
10238
10411
|
return out;
|
|
@@ -10269,25 +10442,25 @@ function detectFrameworks(cwd) {
|
|
|
10269
10442
|
}
|
|
10270
10443
|
function findFile(cwd, candidates) {
|
|
10271
10444
|
for (const c of candidates) {
|
|
10272
|
-
if (
|
|
10445
|
+
if (fs31.existsSync(path30.join(cwd, c))) return c;
|
|
10273
10446
|
}
|
|
10274
10447
|
return null;
|
|
10275
10448
|
}
|
|
10276
10449
|
function discoverPayloadCollections(cwd) {
|
|
10277
10450
|
const out = [];
|
|
10278
10451
|
for (const dir of COLLECTION_DIRS) {
|
|
10279
|
-
const full =
|
|
10280
|
-
if (!
|
|
10452
|
+
const full = path30.join(cwd, dir);
|
|
10453
|
+
if (!fs31.existsSync(full)) continue;
|
|
10281
10454
|
let files;
|
|
10282
10455
|
try {
|
|
10283
|
-
files =
|
|
10456
|
+
files = fs31.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
10284
10457
|
} catch {
|
|
10285
10458
|
continue;
|
|
10286
10459
|
}
|
|
10287
10460
|
for (const file of files) {
|
|
10288
10461
|
try {
|
|
10289
|
-
const filePath =
|
|
10290
|
-
const content =
|
|
10462
|
+
const filePath = path30.join(full, file);
|
|
10463
|
+
const content = fs31.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
10291
10464
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
10292
10465
|
if (!slugMatch) continue;
|
|
10293
10466
|
const slug2 = slugMatch[1];
|
|
@@ -10301,7 +10474,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
10301
10474
|
out.push({
|
|
10302
10475
|
name,
|
|
10303
10476
|
slug: slug2,
|
|
10304
|
-
filePath:
|
|
10477
|
+
filePath: path30.relative(cwd, filePath),
|
|
10305
10478
|
fields: fields.slice(0, 20),
|
|
10306
10479
|
hasAdmin
|
|
10307
10480
|
});
|
|
@@ -10314,28 +10487,28 @@ function discoverPayloadCollections(cwd) {
|
|
|
10314
10487
|
function discoverAdminComponents(cwd, collections) {
|
|
10315
10488
|
const out = [];
|
|
10316
10489
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
10317
|
-
const full =
|
|
10318
|
-
if (!
|
|
10490
|
+
const full = path30.join(cwd, dir);
|
|
10491
|
+
if (!fs31.existsSync(full)) continue;
|
|
10319
10492
|
let entries;
|
|
10320
10493
|
try {
|
|
10321
|
-
entries =
|
|
10494
|
+
entries = fs31.readdirSync(full, { withFileTypes: true });
|
|
10322
10495
|
} catch {
|
|
10323
10496
|
continue;
|
|
10324
10497
|
}
|
|
10325
10498
|
for (const entry of entries) {
|
|
10326
|
-
const entryPath =
|
|
10499
|
+
const entryPath = path30.join(full, entry.name);
|
|
10327
10500
|
let name;
|
|
10328
10501
|
let filePath;
|
|
10329
10502
|
if (entry.isDirectory()) {
|
|
10330
10503
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
10331
|
-
(f) =>
|
|
10504
|
+
(f) => fs31.existsSync(path30.join(entryPath, f))
|
|
10332
10505
|
);
|
|
10333
10506
|
if (!indexFile) continue;
|
|
10334
10507
|
name = entry.name;
|
|
10335
|
-
filePath =
|
|
10508
|
+
filePath = path30.relative(cwd, path30.join(entryPath, indexFile));
|
|
10336
10509
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
10337
10510
|
name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
|
|
10338
|
-
filePath =
|
|
10511
|
+
filePath = path30.relative(cwd, entryPath);
|
|
10339
10512
|
} else {
|
|
10340
10513
|
continue;
|
|
10341
10514
|
}
|
|
@@ -10343,7 +10516,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
10343
10516
|
if (collections) {
|
|
10344
10517
|
for (const col of collections) {
|
|
10345
10518
|
try {
|
|
10346
|
-
const colContent =
|
|
10519
|
+
const colContent = fs31.readFileSync(path30.join(cwd, col.filePath), "utf-8");
|
|
10347
10520
|
if (colContent.includes(name)) {
|
|
10348
10521
|
usedInCollection = col.slug;
|
|
10349
10522
|
break;
|
|
@@ -10361,8 +10534,8 @@ function scanApiRoutes(cwd) {
|
|
|
10361
10534
|
const out = [];
|
|
10362
10535
|
const appDirs = ["src/app", "app"];
|
|
10363
10536
|
for (const appDir of appDirs) {
|
|
10364
|
-
const apiDir =
|
|
10365
|
-
if (!
|
|
10537
|
+
const apiDir = path30.join(cwd, appDir, "api");
|
|
10538
|
+
if (!fs31.existsSync(apiDir)) continue;
|
|
10366
10539
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
10367
10540
|
break;
|
|
10368
10541
|
}
|
|
@@ -10371,14 +10544,14 @@ function scanApiRoutes(cwd) {
|
|
|
10371
10544
|
function walkApiRoutes(dir, prefix, cwd, out) {
|
|
10372
10545
|
let entries;
|
|
10373
10546
|
try {
|
|
10374
|
-
entries =
|
|
10547
|
+
entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
10375
10548
|
} catch {
|
|
10376
10549
|
return;
|
|
10377
10550
|
}
|
|
10378
10551
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
10379
10552
|
if (routeFile) {
|
|
10380
10553
|
try {
|
|
10381
|
-
const content =
|
|
10554
|
+
const content = fs31.readFileSync(path30.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
10382
10555
|
const methods = HTTP_METHODS.filter(
|
|
10383
10556
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
10384
10557
|
);
|
|
@@ -10386,7 +10559,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
10386
10559
|
out.push({
|
|
10387
10560
|
path: prefix,
|
|
10388
10561
|
methods,
|
|
10389
|
-
filePath:
|
|
10562
|
+
filePath: path30.relative(cwd, path30.join(dir, routeFile.name))
|
|
10390
10563
|
});
|
|
10391
10564
|
}
|
|
10392
10565
|
} catch {
|
|
@@ -10397,7 +10570,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
10397
10570
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
10398
10571
|
let segment = entry.name;
|
|
10399
10572
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
10400
|
-
walkApiRoutes(
|
|
10573
|
+
walkApiRoutes(path30.join(dir, entry.name), prefix, cwd, out);
|
|
10401
10574
|
continue;
|
|
10402
10575
|
}
|
|
10403
10576
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -10405,16 +10578,16 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
10405
10578
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
10406
10579
|
segment = `:${segment.slice(1, -1)}`;
|
|
10407
10580
|
}
|
|
10408
|
-
walkApiRoutes(
|
|
10581
|
+
walkApiRoutes(path30.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
|
|
10409
10582
|
}
|
|
10410
10583
|
}
|
|
10411
10584
|
function scanEnvVars(cwd) {
|
|
10412
10585
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
10413
10586
|
for (const envFile of candidates) {
|
|
10414
|
-
const envPath =
|
|
10415
|
-
if (!
|
|
10587
|
+
const envPath = path30.join(cwd, envFile);
|
|
10588
|
+
if (!fs31.existsSync(envPath)) continue;
|
|
10416
10589
|
try {
|
|
10417
|
-
const content =
|
|
10590
|
+
const content = fs31.readFileSync(envPath, "utf-8");
|
|
10418
10591
|
const vars = [];
|
|
10419
10592
|
for (const line of content.split("\n")) {
|
|
10420
10593
|
const trimmed = line.trim();
|
|
@@ -10459,8 +10632,8 @@ var init_frameworkDetectors = __esm({
|
|
|
10459
10632
|
});
|
|
10460
10633
|
|
|
10461
10634
|
// src/scripts/discoverQaContext.ts
|
|
10462
|
-
import * as
|
|
10463
|
-
import * as
|
|
10635
|
+
import * as fs32 from "fs";
|
|
10636
|
+
import * as path31 from "path";
|
|
10464
10637
|
function runQaDiscovery(cwd) {
|
|
10465
10638
|
const out = {
|
|
10466
10639
|
routes: [],
|
|
@@ -10491,9 +10664,9 @@ function runQaDiscovery(cwd) {
|
|
|
10491
10664
|
}
|
|
10492
10665
|
function detectDevServer(cwd, out) {
|
|
10493
10666
|
try {
|
|
10494
|
-
const pkg = JSON.parse(
|
|
10667
|
+
const pkg = JSON.parse(fs32.readFileSync(path31.join(cwd, "package.json"), "utf-8"));
|
|
10495
10668
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
10496
|
-
const pm =
|
|
10669
|
+
const pm = fs32.existsSync(path31.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs32.existsSync(path31.join(cwd, "yarn.lock")) ? "yarn" : fs32.existsSync(path31.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
10497
10670
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
10498
10671
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
10499
10672
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -10503,8 +10676,8 @@ function detectDevServer(cwd, out) {
|
|
|
10503
10676
|
function scanFrontendRoutes(cwd, out) {
|
|
10504
10677
|
const appDirs = ["src/app", "app"];
|
|
10505
10678
|
for (const appDir of appDirs) {
|
|
10506
|
-
const full =
|
|
10507
|
-
if (!
|
|
10679
|
+
const full = path31.join(cwd, appDir);
|
|
10680
|
+
if (!fs32.existsSync(full)) continue;
|
|
10508
10681
|
walkFrontendRoutes(full, "", out);
|
|
10509
10682
|
break;
|
|
10510
10683
|
}
|
|
@@ -10512,7 +10685,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
10512
10685
|
function walkFrontendRoutes(dir, prefix, out) {
|
|
10513
10686
|
let entries;
|
|
10514
10687
|
try {
|
|
10515
|
-
entries =
|
|
10688
|
+
entries = fs32.readdirSync(dir, { withFileTypes: true });
|
|
10516
10689
|
} catch {
|
|
10517
10690
|
return;
|
|
10518
10691
|
}
|
|
@@ -10529,7 +10702,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
10529
10702
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
10530
10703
|
let segment = entry.name;
|
|
10531
10704
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
10532
|
-
walkFrontendRoutes(
|
|
10705
|
+
walkFrontendRoutes(path31.join(dir, entry.name), prefix, out);
|
|
10533
10706
|
continue;
|
|
10534
10707
|
}
|
|
10535
10708
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -10537,7 +10710,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
10537
10710
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
10538
10711
|
segment = `:${segment.slice(1, -1)}`;
|
|
10539
10712
|
}
|
|
10540
|
-
walkFrontendRoutes(
|
|
10713
|
+
walkFrontendRoutes(path31.join(dir, entry.name), `${prefix}/${segment}`, out);
|
|
10541
10714
|
}
|
|
10542
10715
|
}
|
|
10543
10716
|
function detectAuthFiles(cwd, out) {
|
|
@@ -10554,23 +10727,23 @@ function detectAuthFiles(cwd, out) {
|
|
|
10554
10727
|
"src/app/api/oauth"
|
|
10555
10728
|
];
|
|
10556
10729
|
for (const c of candidates) {
|
|
10557
|
-
if (
|
|
10730
|
+
if (fs32.existsSync(path31.join(cwd, c))) out.authFiles.push(c);
|
|
10558
10731
|
}
|
|
10559
10732
|
}
|
|
10560
10733
|
function detectRoles(cwd, out) {
|
|
10561
10734
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
10562
10735
|
for (const rp of rolePaths) {
|
|
10563
|
-
const dir =
|
|
10564
|
-
if (!
|
|
10736
|
+
const dir = path31.join(cwd, rp);
|
|
10737
|
+
if (!fs32.existsSync(dir)) continue;
|
|
10565
10738
|
let files;
|
|
10566
10739
|
try {
|
|
10567
|
-
files =
|
|
10740
|
+
files = fs32.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
10568
10741
|
} catch {
|
|
10569
10742
|
continue;
|
|
10570
10743
|
}
|
|
10571
10744
|
for (const f of files) {
|
|
10572
10745
|
try {
|
|
10573
|
-
const content =
|
|
10746
|
+
const content = fs32.readFileSync(path31.join(dir, f), "utf-8").slice(0, 5e3);
|
|
10574
10747
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
10575
10748
|
if (roleMatches) {
|
|
10576
10749
|
for (const m of roleMatches) {
|
|
@@ -11789,12 +11962,12 @@ var init_fixFlow = __esm({
|
|
|
11789
11962
|
|
|
11790
11963
|
// src/scripts/initFlow.ts
|
|
11791
11964
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
11792
|
-
import * as
|
|
11793
|
-
import * as
|
|
11965
|
+
import * as fs33 from "fs";
|
|
11966
|
+
import * as path32 from "path";
|
|
11794
11967
|
function detectPackageManager(cwd) {
|
|
11795
|
-
if (
|
|
11796
|
-
if (
|
|
11797
|
-
if (
|
|
11968
|
+
if (fs33.existsSync(path32.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
11969
|
+
if (fs33.existsSync(path32.join(cwd, "yarn.lock"))) return "yarn";
|
|
11970
|
+
if (fs33.existsSync(path32.join(cwd, "bun.lockb"))) return "bun";
|
|
11798
11971
|
return "npm";
|
|
11799
11972
|
}
|
|
11800
11973
|
function qualityCommandsFor(pm) {
|
|
@@ -11866,22 +12039,22 @@ function performInit(cwd, force) {
|
|
|
11866
12039
|
const pm = detectPackageManager(cwd);
|
|
11867
12040
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
11868
12041
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
11869
|
-
const configPath =
|
|
11870
|
-
if (
|
|
12042
|
+
const configPath = path32.join(cwd, "kody.config.json");
|
|
12043
|
+
if (fs33.existsSync(configPath) && !force) {
|
|
11871
12044
|
skipped.push("kody.config.json");
|
|
11872
12045
|
} else {
|
|
11873
12046
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
11874
|
-
|
|
12047
|
+
fs33.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
11875
12048
|
`);
|
|
11876
12049
|
wrote.push("kody.config.json");
|
|
11877
12050
|
}
|
|
11878
|
-
const workflowDir =
|
|
11879
|
-
const workflowPath =
|
|
11880
|
-
if (
|
|
12051
|
+
const workflowDir = path32.join(cwd, ".github", "workflows");
|
|
12052
|
+
const workflowPath = path32.join(workflowDir, "kody.yml");
|
|
12053
|
+
if (fs33.existsSync(workflowPath) && !force) {
|
|
11881
12054
|
skipped.push(".github/workflows/kody.yml");
|
|
11882
12055
|
} else {
|
|
11883
|
-
|
|
11884
|
-
|
|
12056
|
+
fs33.mkdirSync(workflowDir, { recursive: true });
|
|
12057
|
+
fs33.writeFileSync(workflowPath, WORKFLOW_TEMPLATE);
|
|
11885
12058
|
wrote.push(".github/workflows/kody.yml");
|
|
11886
12059
|
}
|
|
11887
12060
|
for (const exe of listExecutables()) {
|
|
@@ -11892,12 +12065,12 @@ function performInit(cwd, force) {
|
|
|
11892
12065
|
continue;
|
|
11893
12066
|
}
|
|
11894
12067
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
11895
|
-
const target =
|
|
11896
|
-
if (
|
|
12068
|
+
const target = path32.join(workflowDir, `kody-${exe.name}.yml`);
|
|
12069
|
+
if (fs33.existsSync(target) && !force) {
|
|
11897
12070
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
11898
12071
|
continue;
|
|
11899
12072
|
}
|
|
11900
|
-
|
|
12073
|
+
fs33.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
11901
12074
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
11902
12075
|
}
|
|
11903
12076
|
let labels;
|
|
@@ -12050,7 +12223,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
12050
12223
|
});
|
|
12051
12224
|
|
|
12052
12225
|
// src/scripts/loadAgentAdhoc.ts
|
|
12053
|
-
import * as
|
|
12226
|
+
import * as fs34 from "fs";
|
|
12054
12227
|
function resolveMessage(messageArg) {
|
|
12055
12228
|
const fromComment = readCommentBody();
|
|
12056
12229
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -12058,9 +12231,9 @@ function resolveMessage(messageArg) {
|
|
|
12058
12231
|
}
|
|
12059
12232
|
function readCommentBody() {
|
|
12060
12233
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
12061
|
-
if (!eventPath || !
|
|
12234
|
+
if (!eventPath || !fs34.existsSync(eventPath)) return "";
|
|
12062
12235
|
try {
|
|
12063
|
-
const event = JSON.parse(
|
|
12236
|
+
const event = JSON.parse(fs34.readFileSync(eventPath, "utf-8"));
|
|
12064
12237
|
return String(event.comment?.body ?? "");
|
|
12065
12238
|
} catch {
|
|
12066
12239
|
return "";
|
|
@@ -12113,10 +12286,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
12113
12286
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
12114
12287
|
}
|
|
12115
12288
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
12116
|
-
if (!
|
|
12289
|
+
if (!fs34.existsSync(agentPath)) {
|
|
12117
12290
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
12118
12291
|
}
|
|
12119
|
-
const { title, body } = parseAgentFile(
|
|
12292
|
+
const { title, body } = parseAgentFile(fs34.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
12120
12293
|
const message = resolveMessage(ctx.args.message);
|
|
12121
12294
|
if (!message) {
|
|
12122
12295
|
throw new Error(
|
|
@@ -12354,8 +12527,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
12354
12527
|
});
|
|
12355
12528
|
|
|
12356
12529
|
// src/scripts/loadJobFromFile.ts
|
|
12357
|
-
import * as
|
|
12358
|
-
import * as
|
|
12530
|
+
import * as fs35 from "fs";
|
|
12531
|
+
import * as path33 from "path";
|
|
12359
12532
|
function parseJobFile(raw, slug2) {
|
|
12360
12533
|
let stripped = raw;
|
|
12361
12534
|
if (stripped.startsWith("---\n")) {
|
|
@@ -12393,10 +12566,10 @@ var init_loadJobFromFile = __esm({
|
|
|
12393
12566
|
if (!slug2) {
|
|
12394
12567
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
12395
12568
|
}
|
|
12396
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
12569
|
+
const capability = resolveCapabilityFolder(slug2, path33.join(ctx.cwd, jobsDir));
|
|
12397
12570
|
if (!capability) {
|
|
12398
12571
|
throw new Error(
|
|
12399
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
12572
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path33.join(ctx.cwd, jobsDir, slug2)}`
|
|
12400
12573
|
);
|
|
12401
12574
|
}
|
|
12402
12575
|
const { title, body, config } = capability;
|
|
@@ -12406,12 +12579,12 @@ var init_loadJobFromFile = __esm({
|
|
|
12406
12579
|
let agentIdentity = "";
|
|
12407
12580
|
if (agentSlug) {
|
|
12408
12581
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
12409
|
-
if (!
|
|
12582
|
+
if (!fs35.existsSync(agentPath)) {
|
|
12410
12583
|
throw new Error(
|
|
12411
12584
|
`loadJobFromFile: capability '${slug2}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
12412
12585
|
);
|
|
12413
12586
|
}
|
|
12414
|
-
const agentRaw =
|
|
12587
|
+
const agentRaw = fs35.readFileSync(agentPath, "utf-8");
|
|
12415
12588
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
12416
12589
|
agentTitle = parsed.title;
|
|
12417
12590
|
agentIdentity = parsed.body;
|
|
@@ -12485,13 +12658,13 @@ ${truncate(issue.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
12485
12658
|
});
|
|
12486
12659
|
|
|
12487
12660
|
// src/scripts/kodyVariables.ts
|
|
12488
|
-
import * as
|
|
12489
|
-
import * as
|
|
12661
|
+
import * as fs36 from "fs";
|
|
12662
|
+
import * as path34 from "path";
|
|
12490
12663
|
function readKodyVariables(cwd) {
|
|
12491
|
-
const full =
|
|
12664
|
+
const full = path34.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
12492
12665
|
let raw;
|
|
12493
12666
|
try {
|
|
12494
|
-
raw =
|
|
12667
|
+
raw = fs36.readFileSync(full, "utf-8");
|
|
12495
12668
|
} catch {
|
|
12496
12669
|
return {};
|
|
12497
12670
|
}
|
|
@@ -12516,8 +12689,8 @@ var init_kodyVariables = __esm({
|
|
|
12516
12689
|
});
|
|
12517
12690
|
|
|
12518
12691
|
// src/scripts/loadQaContext.ts
|
|
12519
|
-
import * as
|
|
12520
|
-
import * as
|
|
12692
|
+
import * as fs37 from "fs";
|
|
12693
|
+
import * as path35 from "path";
|
|
12521
12694
|
function parseSlugList(value) {
|
|
12522
12695
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
12523
12696
|
return inner.split(",").map(
|
|
@@ -12546,18 +12719,18 @@ function readProfileAgents(raw) {
|
|
|
12546
12719
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
12547
12720
|
}
|
|
12548
12721
|
function readProfile(cwd) {
|
|
12549
|
-
const dir =
|
|
12550
|
-
if (!
|
|
12722
|
+
const dir = path35.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
12723
|
+
if (!fs37.existsSync(dir)) return "";
|
|
12551
12724
|
let entries;
|
|
12552
12725
|
try {
|
|
12553
|
-
entries =
|
|
12726
|
+
entries = fs37.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
12554
12727
|
} catch {
|
|
12555
12728
|
return "";
|
|
12556
12729
|
}
|
|
12557
12730
|
const blocks = [];
|
|
12558
12731
|
for (const file of entries) {
|
|
12559
12732
|
try {
|
|
12560
|
-
const raw =
|
|
12733
|
+
const raw = fs37.readFileSync(path35.join(dir, file), "utf-8");
|
|
12561
12734
|
const { agent, body } = readProfileAgents(raw);
|
|
12562
12735
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
12563
12736
|
blocks.push(`## ${file}
|
|
@@ -12603,8 +12776,8 @@ var init_loadQaContext = __esm({
|
|
|
12603
12776
|
});
|
|
12604
12777
|
|
|
12605
12778
|
// src/taskContext.ts
|
|
12606
|
-
import * as
|
|
12607
|
-
import * as
|
|
12779
|
+
import * as fs38 from "fs";
|
|
12780
|
+
import * as path36 from "path";
|
|
12608
12781
|
function buildTaskContext(args) {
|
|
12609
12782
|
return {
|
|
12610
12783
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -12620,9 +12793,9 @@ function buildTaskContext(args) {
|
|
|
12620
12793
|
function persistTaskContext(cwd, ctx) {
|
|
12621
12794
|
try {
|
|
12622
12795
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
12623
|
-
|
|
12624
|
-
const file =
|
|
12625
|
-
|
|
12796
|
+
fs38.mkdirSync(dir, { recursive: true });
|
|
12797
|
+
const file = path36.join(dir, "task-context.json");
|
|
12798
|
+
fs38.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
12626
12799
|
`);
|
|
12627
12800
|
return file;
|
|
12628
12801
|
} catch (err) {
|
|
@@ -14967,8 +15140,8 @@ fi
|
|
|
14967
15140
|
});
|
|
14968
15141
|
|
|
14969
15142
|
// src/stateRepoGithub.ts
|
|
14970
|
-
import * as
|
|
14971
|
-
import * as
|
|
15143
|
+
import * as fs39 from "fs";
|
|
15144
|
+
import * as path37 from "path";
|
|
14972
15145
|
function recordValue3(value) {
|
|
14973
15146
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14974
15147
|
}
|
|
@@ -15108,15 +15281,15 @@ function mergeJsonl(localText, remoteText) {
|
|
|
15108
15281
|
async function syncJsonlFileFromGithubState(opts) {
|
|
15109
15282
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
15110
15283
|
if (!remote) return;
|
|
15111
|
-
const local =
|
|
15284
|
+
const local = fs39.existsSync(opts.localPath) ? fs39.readFileSync(opts.localPath, "utf-8") : "";
|
|
15112
15285
|
const next = mergeJsonl(local, remote.content);
|
|
15113
15286
|
if (next === local) return;
|
|
15114
|
-
|
|
15115
|
-
|
|
15287
|
+
fs39.mkdirSync(path37.dirname(opts.localPath), { recursive: true });
|
|
15288
|
+
fs39.writeFileSync(opts.localPath, next);
|
|
15116
15289
|
}
|
|
15117
15290
|
async function persistJsonlFileToGithubState(opts) {
|
|
15118
|
-
if (!
|
|
15119
|
-
const localText =
|
|
15291
|
+
if (!fs39.existsSync(opts.localPath)) return;
|
|
15292
|
+
const localText = fs39.readFileSync(opts.localPath, "utf-8");
|
|
15120
15293
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
15121
15294
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
15122
15295
|
const body = mergeJsonl(localText, remote?.content ?? "");
|
|
@@ -15150,12 +15323,12 @@ var init_stateRepoGithub = __esm({
|
|
|
15150
15323
|
|
|
15151
15324
|
// src/scripts/runPreviewBuild.ts
|
|
15152
15325
|
import { copyFile, writeFile } from "fs/promises";
|
|
15153
|
-
import * as
|
|
15326
|
+
import * as path38 from "path";
|
|
15154
15327
|
import { fileURLToPath } from "url";
|
|
15155
15328
|
function bundledDockerfilePath(mode) {
|
|
15156
|
-
const here =
|
|
15329
|
+
const here = path38.dirname(fileURLToPath(import.meta.url));
|
|
15157
15330
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
15158
|
-
return
|
|
15331
|
+
return path38.join(here, "preview-build-templates", file);
|
|
15159
15332
|
}
|
|
15160
15333
|
function required(name) {
|
|
15161
15334
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -15406,10 +15579,10 @@ var init_runPreviewBuild = __esm({
|
|
|
15406
15579
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
15407
15580
|
if (Object.keys(buildEnv).length > 0) {
|
|
15408
15581
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
15409
|
-
await writeFile(
|
|
15582
|
+
await writeFile(path38.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
15410
15583
|
`, "utf8");
|
|
15411
15584
|
}
|
|
15412
|
-
const consumerDockerfile =
|
|
15585
|
+
const consumerDockerfile = path38.join(ctx.cwd, "Dockerfile.preview");
|
|
15413
15586
|
const { stat } = await import("fs/promises");
|
|
15414
15587
|
let hasConsumerDockerfile = false;
|
|
15415
15588
|
try {
|
|
@@ -15593,8 +15766,8 @@ var init_tickShellRunner = __esm({
|
|
|
15593
15766
|
});
|
|
15594
15767
|
|
|
15595
15768
|
// src/scripts/runScheduledExecutableTick.ts
|
|
15596
|
-
import * as
|
|
15597
|
-
import * as
|
|
15769
|
+
import * as fs40 from "fs";
|
|
15770
|
+
import * as path39 from "path";
|
|
15598
15771
|
var runScheduledExecutableTick;
|
|
15599
15772
|
var init_runScheduledExecutableTick = __esm({
|
|
15600
15773
|
"src/scripts/runScheduledExecutableTick.ts"() {
|
|
@@ -15614,14 +15787,14 @@ var init_runScheduledExecutableTick = __esm({
|
|
|
15614
15787
|
ctx.output.reason = `runScheduledExecutableTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
15615
15788
|
return;
|
|
15616
15789
|
}
|
|
15617
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
15790
|
+
const capability = resolveCapabilityFolder(slug2, path39.join(ctx.cwd, jobsDir));
|
|
15618
15791
|
if (!capability) {
|
|
15619
15792
|
ctx.output.exitCode = 99;
|
|
15620
15793
|
ctx.output.reason = `runScheduledExecutableTick: capability folder not found or incomplete: ${slug2} (searched ${jobsDir} and company store)`;
|
|
15621
15794
|
return;
|
|
15622
15795
|
}
|
|
15623
|
-
const shellPath =
|
|
15624
|
-
if (!
|
|
15796
|
+
const shellPath = path39.join(profile.dir, shell);
|
|
15797
|
+
if (!fs40.existsSync(shellPath)) {
|
|
15625
15798
|
ctx.output.exitCode = 99;
|
|
15626
15799
|
ctx.output.reason = `runScheduledExecutableTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
15627
15800
|
return;
|
|
@@ -15652,8 +15825,8 @@ var init_runScheduledExecutableTick = __esm({
|
|
|
15652
15825
|
});
|
|
15653
15826
|
|
|
15654
15827
|
// src/scripts/runTickScript.ts
|
|
15655
|
-
import * as
|
|
15656
|
-
import * as
|
|
15828
|
+
import * as fs41 from "fs";
|
|
15829
|
+
import * as path40 from "path";
|
|
15657
15830
|
var runTickScript;
|
|
15658
15831
|
var init_runTickScript = __esm({
|
|
15659
15832
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -15672,10 +15845,10 @@ var init_runTickScript = __esm({
|
|
|
15672
15845
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
15673
15846
|
return;
|
|
15674
15847
|
}
|
|
15675
|
-
const capability = readCapabilityFolder(
|
|
15848
|
+
const capability = readCapabilityFolder(path40.join(ctx.cwd, jobsDir), slug2);
|
|
15676
15849
|
if (!capability) {
|
|
15677
15850
|
ctx.output.exitCode = 99;
|
|
15678
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
15851
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path40.join(ctx.cwd, jobsDir, slug2)}`;
|
|
15679
15852
|
return;
|
|
15680
15853
|
}
|
|
15681
15854
|
const tickScript = capability.config.tickScript;
|
|
@@ -15684,8 +15857,8 @@ var init_runTickScript = __esm({
|
|
|
15684
15857
|
ctx.output.reason = `runTickScript: capability ${slug2} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
15685
15858
|
return;
|
|
15686
15859
|
}
|
|
15687
|
-
const scriptPath =
|
|
15688
|
-
if (!
|
|
15860
|
+
const scriptPath = path40.isAbsolute(tickScript) ? tickScript : path40.join(ctx.cwd, tickScript);
|
|
15861
|
+
if (!fs41.existsSync(scriptPath)) {
|
|
15689
15862
|
ctx.output.exitCode = 99;
|
|
15690
15863
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
15691
15864
|
return;
|
|
@@ -16507,7 +16680,7 @@ var init_warmupMcp = __esm({
|
|
|
16507
16680
|
});
|
|
16508
16681
|
|
|
16509
16682
|
// src/scripts/writeAgentRunSummary.ts
|
|
16510
|
-
import * as
|
|
16683
|
+
import * as fs42 from "fs";
|
|
16511
16684
|
var writeAgentRunSummary;
|
|
16512
16685
|
var init_writeAgentRunSummary = __esm({
|
|
16513
16686
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -16533,7 +16706,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
16533
16706
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
16534
16707
|
lines.push("");
|
|
16535
16708
|
try {
|
|
16536
|
-
|
|
16709
|
+
fs42.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
16537
16710
|
`);
|
|
16538
16711
|
} catch {
|
|
16539
16712
|
}
|
|
@@ -16853,22 +17026,22 @@ var init_scripts = __esm({
|
|
|
16853
17026
|
});
|
|
16854
17027
|
|
|
16855
17028
|
// src/stateWorkspace.ts
|
|
16856
|
-
import * as
|
|
16857
|
-
import * as
|
|
17029
|
+
import * as fs43 from "fs";
|
|
17030
|
+
import * as path41 from "path";
|
|
16858
17031
|
function writeLocalFile(cwd, relativePath, content) {
|
|
16859
|
-
const fullPath =
|
|
16860
|
-
|
|
16861
|
-
|
|
17032
|
+
const fullPath = path41.join(cwd, relativePath);
|
|
17033
|
+
fs43.mkdirSync(path41.dirname(fullPath), { recursive: true });
|
|
17034
|
+
fs43.writeFileSync(fullPath, content);
|
|
16862
17035
|
}
|
|
16863
17036
|
function hydrateDirectory(config, cwd, stateDir, localDir) {
|
|
16864
17037
|
const entries = listStateDirectory(config, cwd, stateDir);
|
|
16865
17038
|
if (entries.length === 0) return;
|
|
16866
17039
|
for (const entry of entries) {
|
|
16867
17040
|
if (!entry.name || !entry.type) continue;
|
|
16868
|
-
const childState =
|
|
16869
|
-
const childLocal =
|
|
17041
|
+
const childState = path41.posix.join(stateDir, entry.name);
|
|
17042
|
+
const childLocal = path41.join(localDir, entry.name);
|
|
16870
17043
|
if (entry.type === "dir") {
|
|
16871
|
-
|
|
17044
|
+
fs43.rmSync(path41.join(cwd, childLocal), { recursive: true, force: true });
|
|
16872
17045
|
hydrateDirectory(config, cwd, childState, childLocal);
|
|
16873
17046
|
} else if (entry.type === "file") {
|
|
16874
17047
|
const file = readStateText(config, cwd, childState);
|
|
@@ -16891,16 +17064,16 @@ var init_stateWorkspace = __esm({
|
|
|
16891
17064
|
"use strict";
|
|
16892
17065
|
init_stateRepo();
|
|
16893
17066
|
DIR_MAPPINGS = [
|
|
16894
|
-
{ stateDir: "executables", localDir:
|
|
16895
|
-
{ stateDir: "capabilities", localDir:
|
|
16896
|
-
{ stateDir: "agents", localDir:
|
|
16897
|
-
{ stateDir: "context", localDir:
|
|
16898
|
-
{ stateDir: "memory", localDir:
|
|
17067
|
+
{ stateDir: "executables", localDir: path41.join(".kody", "executables") },
|
|
17068
|
+
{ stateDir: "capabilities", localDir: path41.join(".kody", "capabilities") },
|
|
17069
|
+
{ stateDir: "agents", localDir: path41.join(".kody", "agents") },
|
|
17070
|
+
{ stateDir: "context", localDir: path41.join(".kody", "context") },
|
|
17071
|
+
{ stateDir: "memory", localDir: path41.join(".kody", "memory") }
|
|
16899
17072
|
];
|
|
16900
17073
|
FILE_MAPPINGS = [
|
|
16901
|
-
{ statePath: "instructions.md", localPath:
|
|
16902
|
-
{ statePath: "variables.json", localPath:
|
|
16903
|
-
{ statePath: "secrets.enc", localPath:
|
|
17074
|
+
{ statePath: "instructions.md", localPath: path41.join(".kody", "instructions.md") },
|
|
17075
|
+
{ statePath: "variables.json", localPath: path41.join(".kody", "variables.json") },
|
|
17076
|
+
{ statePath: "secrets.enc", localPath: path41.join(".kody", "secrets.enc") }
|
|
16904
17077
|
];
|
|
16905
17078
|
}
|
|
16906
17079
|
});
|
|
@@ -16971,8 +17144,8 @@ var init_tools = __esm({
|
|
|
16971
17144
|
|
|
16972
17145
|
// src/executor.ts
|
|
16973
17146
|
import { spawn as spawn7 } from "child_process";
|
|
16974
|
-
import * as
|
|
16975
|
-
import * as
|
|
17147
|
+
import * as fs44 from "fs";
|
|
17148
|
+
import * as path42 from "path";
|
|
16976
17149
|
function isMutatingPostflight(scriptName) {
|
|
16977
17150
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
16978
17151
|
}
|
|
@@ -17150,7 +17323,7 @@ async function runExecutable(profileName, input) {
|
|
|
17150
17323
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
17151
17324
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
17152
17325
|
const invokeAgent = async (prompt) => {
|
|
17153
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
17326
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path42.isAbsolute(p) ? p : path42.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
17154
17327
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
17155
17328
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
17156
17329
|
const agents = loadSubagents(profile);
|
|
@@ -17542,17 +17715,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
17542
17715
|
function resolveProfilePath(profileName) {
|
|
17543
17716
|
const found = resolveExecutable(profileName);
|
|
17544
17717
|
if (found) return found;
|
|
17545
|
-
const here =
|
|
17718
|
+
const here = path42.dirname(new URL(import.meta.url).pathname);
|
|
17546
17719
|
const candidates = [
|
|
17547
|
-
|
|
17720
|
+
path42.join(here, "executables", profileName, "profile.json"),
|
|
17548
17721
|
// same-dir sibling (dev)
|
|
17549
|
-
|
|
17722
|
+
path42.join(here, "..", "executables", profileName, "profile.json"),
|
|
17550
17723
|
// up one (prod: dist/bin → dist/executables)
|
|
17551
|
-
|
|
17724
|
+
path42.join(here, "..", "src", "executables", profileName, "profile.json")
|
|
17552
17725
|
// fallback
|
|
17553
17726
|
];
|
|
17554
17727
|
for (const c of candidates) {
|
|
17555
|
-
if (
|
|
17728
|
+
if (fs44.existsSync(c)) return c;
|
|
17556
17729
|
}
|
|
17557
17730
|
return candidates[0];
|
|
17558
17731
|
}
|
|
@@ -17650,8 +17823,8 @@ function resolveShellTimeoutMs(entry) {
|
|
|
17650
17823
|
}
|
|
17651
17824
|
async function runShellEntry(entry, ctx, profile) {
|
|
17652
17825
|
const shellName = entry.shell;
|
|
17653
|
-
const shellPath =
|
|
17654
|
-
if (!
|
|
17826
|
+
const shellPath = path42.join(profile.dir, shellName);
|
|
17827
|
+
if (!fs44.existsSync(shellPath)) {
|
|
17655
17828
|
ctx.skipAgent = true;
|
|
17656
17829
|
ctx.output.exitCode = 99;
|
|
17657
17830
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -17801,8 +17974,8 @@ var init_executor = __esm({
|
|
|
17801
17974
|
});
|
|
17802
17975
|
|
|
17803
17976
|
// src/workflowDefinitions.ts
|
|
17804
|
-
import * as
|
|
17805
|
-
import * as
|
|
17977
|
+
import * as fs45 from "fs";
|
|
17978
|
+
import * as path43 from "path";
|
|
17806
17979
|
function isWorkflowDefinitionId(value) {
|
|
17807
17980
|
return WORKFLOW_ID_PATTERN.test(value);
|
|
17808
17981
|
}
|
|
@@ -17836,7 +18009,7 @@ function readWorkflowDefinition(config, cwd, id) {
|
|
|
17836
18009
|
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
17837
18010
|
return {
|
|
17838
18011
|
slug: id,
|
|
17839
|
-
dir:
|
|
18012
|
+
dir: path43.dirname(source),
|
|
17840
18013
|
profilePath: source,
|
|
17841
18014
|
bodyPath: source,
|
|
17842
18015
|
title: workflow.name,
|
|
@@ -17871,9 +18044,9 @@ function workflowDefinitionToConfig(workflow) {
|
|
|
17871
18044
|
function readCompanyStoreWorkflowDefinition(id) {
|
|
17872
18045
|
const root = getCompanyStoreAssetRoot("workflows");
|
|
17873
18046
|
if (!root) return null;
|
|
17874
|
-
const filePath =
|
|
17875
|
-
if (!
|
|
17876
|
-
return parseWorkflowDefinition(
|
|
18047
|
+
const filePath = path43.join(root, id, "workflow.json");
|
|
18048
|
+
if (!fs45.existsSync(filePath)) return null;
|
|
18049
|
+
return parseWorkflowDefinition(fs45.readFileSync(filePath, "utf8"));
|
|
17877
18050
|
}
|
|
17878
18051
|
function parseWorkflowDefinition(content) {
|
|
17879
18052
|
try {
|
|
@@ -17905,7 +18078,7 @@ __export(job_exports, {
|
|
|
17905
18078
|
stableJobKey: () => stableJobKey,
|
|
17906
18079
|
validateJob: () => validateJob
|
|
17907
18080
|
});
|
|
17908
|
-
import * as
|
|
18081
|
+
import * as path44 from "path";
|
|
17909
18082
|
function newJobId(flavor) {
|
|
17910
18083
|
localJobSeq += 1;
|
|
17911
18084
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -17944,7 +18117,7 @@ function validateJob(input) {
|
|
|
17944
18117
|
async function runJob(job, base) {
|
|
17945
18118
|
const valid = validateJob(job);
|
|
17946
18119
|
const action = valid.action ?? valid.capability;
|
|
17947
|
-
const projectCapabilitiesRoot =
|
|
18120
|
+
const projectCapabilitiesRoot = path44.join(base.cwd, ".kody", "capabilities");
|
|
17948
18121
|
const resolvedCapability = !valid.workflow && action ? resolveCapabilityAction(action, projectCapabilitiesRoot) : null;
|
|
17949
18122
|
const capabilityIdentity = valid.capability ?? resolvedCapability?.capability;
|
|
17950
18123
|
const capabilityContext = valid.workflow ? null : loadCapabilityContext(capabilityIdentity, base.cwd);
|
|
@@ -18127,7 +18300,7 @@ function shouldRunWorkflowStep(step, data) {
|
|
|
18127
18300
|
if (!step.runWhen) return true;
|
|
18128
18301
|
const context = workflowConditionContext(data);
|
|
18129
18302
|
return Object.entries(step.runWhen).every(
|
|
18130
|
-
([
|
|
18303
|
+
([path50, expected]) => valueMatches(resolveDottedPath2(context, path50), expected)
|
|
18131
18304
|
);
|
|
18132
18305
|
}
|
|
18133
18306
|
function canContinueWorkflow(step, outcome) {
|
|
@@ -18197,7 +18370,7 @@ function composeStepWhy(parentWhy, step) {
|
|
|
18197
18370
|
}
|
|
18198
18371
|
function loadCapabilityContext(slug2, cwd) {
|
|
18199
18372
|
if (!slug2) return null;
|
|
18200
|
-
return resolveCapabilityFolder(slug2,
|
|
18373
|
+
return resolveCapabilityFolder(slug2, path44.join(cwd, ".kody", "capabilities"));
|
|
18201
18374
|
}
|
|
18202
18375
|
function loadWorkflowContext(slug2, base) {
|
|
18203
18376
|
if (!slug2 || !base.config || !isWorkflowDefinitionId(slug2)) return null;
|
|
@@ -18355,9 +18528,9 @@ function translateOpenAISseToBrain(opts) {
|
|
|
18355
18528
|
}
|
|
18356
18529
|
|
|
18357
18530
|
// src/servers/brain-serve.ts
|
|
18358
|
-
import * as
|
|
18531
|
+
import * as fs48 from "fs";
|
|
18359
18532
|
import { createServer } from "http";
|
|
18360
|
-
import * as
|
|
18533
|
+
import * as path47 from "path";
|
|
18361
18534
|
|
|
18362
18535
|
// src/chat/loop.ts
|
|
18363
18536
|
init_agent();
|
|
@@ -18917,8 +19090,8 @@ init_config();
|
|
|
18917
19090
|
|
|
18918
19091
|
// src/kody-cli.ts
|
|
18919
19092
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
18920
|
-
import * as
|
|
18921
|
-
import * as
|
|
19093
|
+
import * as fs46 from "fs";
|
|
19094
|
+
import * as path45 from "path";
|
|
18922
19095
|
|
|
18923
19096
|
// src/app-auth.ts
|
|
18924
19097
|
import { createSign } from "crypto";
|
|
@@ -19539,9 +19712,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
19539
19712
|
return void 0;
|
|
19540
19713
|
}
|
|
19541
19714
|
function detectPackageManager2(cwd) {
|
|
19542
|
-
if (
|
|
19543
|
-
if (
|
|
19544
|
-
if (
|
|
19715
|
+
if (fs46.existsSync(path45.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
19716
|
+
if (fs46.existsSync(path45.join(cwd, "yarn.lock"))) return "yarn";
|
|
19717
|
+
if (fs46.existsSync(path45.join(cwd, "bun.lockb"))) return "bun";
|
|
19545
19718
|
return "npm";
|
|
19546
19719
|
}
|
|
19547
19720
|
function shouldChainScheduledWatch(match) {
|
|
@@ -19634,8 +19807,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
19634
19807
|
const logPath = lastRunLogPath(cwd);
|
|
19635
19808
|
let tail = "";
|
|
19636
19809
|
try {
|
|
19637
|
-
if (
|
|
19638
|
-
const content =
|
|
19810
|
+
if (fs46.existsSync(logPath)) {
|
|
19811
|
+
const content = fs46.readFileSync(logPath, "utf-8");
|
|
19639
19812
|
tail = content.slice(-3e3);
|
|
19640
19813
|
}
|
|
19641
19814
|
} catch {
|
|
@@ -19660,7 +19833,7 @@ async function runCi(argv) {
|
|
|
19660
19833
|
return 0;
|
|
19661
19834
|
}
|
|
19662
19835
|
const args = parseCiArgs(argv);
|
|
19663
|
-
const cwd = args.cwd ?
|
|
19836
|
+
const cwd = args.cwd ? path45.resolve(args.cwd) : process.cwd();
|
|
19664
19837
|
let earlyConfig;
|
|
19665
19838
|
let earlyConfigError;
|
|
19666
19839
|
try {
|
|
@@ -19683,9 +19856,9 @@ async function runCi(argv) {
|
|
|
19683
19856
|
forceRunCliArgs = { goal: envForceMessage };
|
|
19684
19857
|
}
|
|
19685
19858
|
}
|
|
19686
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
19859
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && eventName === "workflow_dispatch" && dispatchEventPath && fs46.existsSync(dispatchEventPath)) {
|
|
19687
19860
|
try {
|
|
19688
|
-
const evt = JSON.parse(
|
|
19861
|
+
const evt = JSON.parse(fs46.readFileSync(dispatchEventPath, "utf-8"));
|
|
19689
19862
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
19690
19863
|
const sessionInput = String(evt?.inputs?.sessionId ?? "");
|
|
19691
19864
|
const dutyInput = String(evt?.inputs?.capability ?? evt?.inputs?.executable ?? "").trim();
|
|
@@ -20017,8 +20190,8 @@ init_repoWorkspace();
|
|
|
20017
20190
|
|
|
20018
20191
|
// src/scripts/brainTurnLog.ts
|
|
20019
20192
|
init_runtimePaths();
|
|
20020
|
-
import * as
|
|
20021
|
-
import * as
|
|
20193
|
+
import * as fs47 from "fs";
|
|
20194
|
+
import * as path46 from "path";
|
|
20022
20195
|
import posixPath4 from "path/posix";
|
|
20023
20196
|
var live = /* @__PURE__ */ new Map();
|
|
20024
20197
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -20029,8 +20202,8 @@ function brainEventsStatePath(chatId) {
|
|
|
20029
20202
|
}
|
|
20030
20203
|
function lastPersistedSeq(dir, chatId) {
|
|
20031
20204
|
const p = brainEventsFilePath(dir, chatId);
|
|
20032
|
-
if (!
|
|
20033
|
-
const lines =
|
|
20205
|
+
if (!fs47.existsSync(p)) return 0;
|
|
20206
|
+
const lines = fs47.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
20034
20207
|
if (lines.length === 0) return 0;
|
|
20035
20208
|
try {
|
|
20036
20209
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -20040,9 +20213,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
20040
20213
|
}
|
|
20041
20214
|
function readSince(dir, chatId, since) {
|
|
20042
20215
|
const p = brainEventsFilePath(dir, chatId);
|
|
20043
|
-
if (!
|
|
20216
|
+
if (!fs47.existsSync(p)) return [];
|
|
20044
20217
|
const out = [];
|
|
20045
|
-
for (const line of
|
|
20218
|
+
for (const line of fs47.readFileSync(p, "utf-8").split("\n")) {
|
|
20046
20219
|
if (!line) continue;
|
|
20047
20220
|
try {
|
|
20048
20221
|
const rec = JSON.parse(line);
|
|
@@ -20068,12 +20241,12 @@ function beginTurn(dir, chatId) {
|
|
|
20068
20241
|
};
|
|
20069
20242
|
live.set(chatId, state);
|
|
20070
20243
|
const p = brainEventsFilePath(dir, chatId);
|
|
20071
|
-
|
|
20244
|
+
fs47.mkdirSync(path46.dirname(p), { recursive: true });
|
|
20072
20245
|
return (event) => {
|
|
20073
20246
|
state.seq += 1;
|
|
20074
20247
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
20075
20248
|
try {
|
|
20076
|
-
|
|
20249
|
+
fs47.appendFileSync(p, `${JSON.stringify(rec)}
|
|
20077
20250
|
`);
|
|
20078
20251
|
} catch (err) {
|
|
20079
20252
|
process.stderr.write(
|
|
@@ -20112,7 +20285,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
20112
20285
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
20113
20286
|
};
|
|
20114
20287
|
try {
|
|
20115
|
-
|
|
20288
|
+
fs47.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
20116
20289
|
`);
|
|
20117
20290
|
} catch {
|
|
20118
20291
|
}
|
|
@@ -20418,7 +20591,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
20418
20591
|
);
|
|
20419
20592
|
}
|
|
20420
20593
|
}
|
|
20421
|
-
|
|
20594
|
+
fs48.mkdirSync(path47.dirname(sessionFile), { recursive: true });
|
|
20422
20595
|
appendTurn(sessionFile, {
|
|
20423
20596
|
role: "user",
|
|
20424
20597
|
content: message,
|
|
@@ -20483,7 +20656,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
20483
20656
|
function buildServer(opts) {
|
|
20484
20657
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
20485
20658
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
20486
|
-
const reposRoot = opts.reposRoot ??
|
|
20659
|
+
const reposRoot = opts.reposRoot ?? path47.join(path47.dirname(path47.resolve(opts.cwd)), "repos");
|
|
20487
20660
|
return createServer(async (req, res) => {
|
|
20488
20661
|
if (!req.method || !req.url) {
|
|
20489
20662
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -21078,8 +21251,8 @@ async function loadConfigSafe() {
|
|
|
21078
21251
|
}
|
|
21079
21252
|
|
|
21080
21253
|
// src/chat-cli.ts
|
|
21081
|
-
import * as
|
|
21082
|
-
import * as
|
|
21254
|
+
import * as fs50 from "fs";
|
|
21255
|
+
import * as path49 from "path";
|
|
21083
21256
|
|
|
21084
21257
|
// src/chat/inbox.ts
|
|
21085
21258
|
import { execFileSync as execFileSync26 } from "child_process";
|
|
@@ -21151,8 +21324,8 @@ function currentBranch(cwd) {
|
|
|
21151
21324
|
|
|
21152
21325
|
// src/chat/state-sync.ts
|
|
21153
21326
|
init_stateRepo();
|
|
21154
|
-
import * as
|
|
21155
|
-
import * as
|
|
21327
|
+
import * as fs49 from "fs";
|
|
21328
|
+
import * as path48 from "path";
|
|
21156
21329
|
function jsonlLines2(text) {
|
|
21157
21330
|
return text.split("\n").filter((line) => line.length > 0);
|
|
21158
21331
|
}
|
|
@@ -21169,15 +21342,15 @@ function mergeJsonl2(localText, remoteText) {
|
|
|
21169
21342
|
function syncJsonlFileFromState(opts) {
|
|
21170
21343
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
21171
21344
|
if (!remote) return;
|
|
21172
|
-
const local =
|
|
21345
|
+
const local = fs49.existsSync(opts.localPath) ? fs49.readFileSync(opts.localPath, "utf-8") : "";
|
|
21173
21346
|
const next = mergeJsonl2(local, remote.content);
|
|
21174
21347
|
if (next === local) return;
|
|
21175
|
-
|
|
21176
|
-
|
|
21348
|
+
fs49.mkdirSync(path48.dirname(opts.localPath), { recursive: true });
|
|
21349
|
+
fs49.writeFileSync(opts.localPath, next);
|
|
21177
21350
|
}
|
|
21178
21351
|
function persistJsonlFileToState(opts) {
|
|
21179
|
-
if (!
|
|
21180
|
-
const localText =
|
|
21352
|
+
if (!fs49.existsSync(opts.localPath)) return;
|
|
21353
|
+
const localText = fs49.readFileSync(opts.localPath, "utf-8");
|
|
21181
21354
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
21182
21355
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
21183
21356
|
const body = mergeJsonl2(localText, remote?.content ?? "");
|
|
@@ -21437,7 +21610,7 @@ async function runChat(argv) {
|
|
|
21437
21610
|
${CHAT_HELP}`);
|
|
21438
21611
|
return 64;
|
|
21439
21612
|
}
|
|
21440
|
-
const cwd = args.cwd ?
|
|
21613
|
+
const cwd = args.cwd ? path49.resolve(args.cwd) : process.cwd();
|
|
21441
21614
|
const sessionId = args.sessionId;
|
|
21442
21615
|
const unpackedSecrets = unpackAllSecrets();
|
|
21443
21616
|
if (unpackedSecrets > 0) {
|
|
@@ -21498,7 +21671,7 @@ ${CHAT_HELP}`);
|
|
|
21498
21671
|
const sink = buildSink(cwd, sessionId, args.dashboardUrl);
|
|
21499
21672
|
const meta = readMeta(sessionFile);
|
|
21500
21673
|
process.stdout.write(
|
|
21501
|
-
`\u2192 kody:chat: session file=${sessionFile} exists=${
|
|
21674
|
+
`\u2192 kody:chat: session file=${sessionFile} exists=${fs50.existsSync(sessionFile)} meta=${meta ? meta.mode : "none"}
|
|
21502
21675
|
`
|
|
21503
21676
|
);
|
|
21504
21677
|
try {
|
|
@@ -21658,8 +21831,8 @@ var FlyClient = class {
|
|
|
21658
21831
|
get fetch() {
|
|
21659
21832
|
return this.opts.fetchImpl ?? fetch;
|
|
21660
21833
|
}
|
|
21661
|
-
async call(
|
|
21662
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
21834
|
+
async call(path50, init = {}) {
|
|
21835
|
+
const res = await this.fetch(`${FLY_API_BASE}${path50}`, {
|
|
21663
21836
|
method: init.method ?? "GET",
|
|
21664
21837
|
headers: {
|
|
21665
21838
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -21670,7 +21843,7 @@ var FlyClient = class {
|
|
|
21670
21843
|
if (res.status === 404 && init.allow404) return null;
|
|
21671
21844
|
if (!res.ok) {
|
|
21672
21845
|
const text = await res.text().catch(() => "");
|
|
21673
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
21846
|
+
throw new Error(`Fly API ${res.status} on ${path50}: ${text.slice(0, 200) || res.statusText}`);
|
|
21674
21847
|
}
|
|
21675
21848
|
if (res.status === 204) return null;
|
|
21676
21849
|
const raw = await res.text();
|
|
@@ -22385,7 +22558,7 @@ async function poolServe() {
|
|
|
22385
22558
|
|
|
22386
22559
|
// src/servers/runner-serve.ts
|
|
22387
22560
|
import { spawn as spawn8 } from "child_process";
|
|
22388
|
-
import * as
|
|
22561
|
+
import * as fs51 from "fs";
|
|
22389
22562
|
import { createServer as createServer5 } from "http";
|
|
22390
22563
|
var DEFAULT_PORT2 = 8080;
|
|
22391
22564
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -22468,8 +22641,8 @@ async function defaultRunJob(job) {
|
|
|
22468
22641
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
22469
22642
|
const branch = job.ref ?? "main";
|
|
22470
22643
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
22471
|
-
|
|
22472
|
-
|
|
22644
|
+
fs51.rmSync(workdir, { recursive: true, force: true });
|
|
22645
|
+
fs51.mkdirSync(workdir, { recursive: true });
|
|
22473
22646
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
22474
22647
|
const interactive = job.mode === "interactive";
|
|
22475
22648
|
const scheduled = job.mode === "scheduled";
|