@kody-ade/kody-engine 0.4.255 → 0.4.257
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 +782 -246
- 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.257",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative agentAction profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -3069,9 +3069,9 @@ function parseAgentResponsibilityReportsFromText(text) {
|
|
|
3069
3069
|
function parseAgentResponsibilityReport(raw) {
|
|
3070
3070
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
3071
3071
|
const obj = raw;
|
|
3072
|
-
const target =
|
|
3072
|
+
const target = parseAgentResponsibilityReportTarget(obj.target);
|
|
3073
3073
|
if (!target) return null;
|
|
3074
|
-
const evidence =
|
|
3074
|
+
const evidence = parseAgentResponsibilityReportEvidence(obj.evidence);
|
|
3075
3075
|
const facts = parseFacts(obj.facts);
|
|
3076
3076
|
if (!evidence && !facts) return null;
|
|
3077
3077
|
return {
|
|
@@ -3080,36 +3080,14 @@ function parseAgentResponsibilityReport(raw) {
|
|
|
3080
3080
|
...facts ? { facts } : {}
|
|
3081
3081
|
};
|
|
3082
3082
|
}
|
|
3083
|
-
function
|
|
3084
|
-
const priorFacts = parseFacts(state.extra.facts) ?? {};
|
|
3085
|
-
const nextFacts = { ...priorFacts };
|
|
3086
|
-
for (const [key, value] of Object.entries(report.facts ?? {})) {
|
|
3087
|
-
if (CONTROL_FACT_KEYS.has(key)) continue;
|
|
3088
|
-
nextFacts[key] = value;
|
|
3089
|
-
}
|
|
3090
|
-
for (const [key, value] of Object.entries(report.evidence ?? {})) {
|
|
3091
|
-
nextFacts[key] = value;
|
|
3092
|
-
}
|
|
3093
|
-
const pending = nextFacts.pendingEvidence;
|
|
3094
|
-
if (typeof pending === "string" && Object.hasOwn(report.evidence ?? {}, pending)) {
|
|
3095
|
-
delete nextFacts.pendingEvidence;
|
|
3096
|
-
}
|
|
3097
|
-
return {
|
|
3098
|
-
...state,
|
|
3099
|
-
extra: {
|
|
3100
|
-
...state.extra,
|
|
3101
|
-
facts: nextFacts
|
|
3102
|
-
}
|
|
3103
|
-
};
|
|
3104
|
-
}
|
|
3105
|
-
function parseTarget(raw) {
|
|
3083
|
+
function parseAgentResponsibilityReportTarget(raw) {
|
|
3106
3084
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
3107
3085
|
const target = raw;
|
|
3108
3086
|
if (target.type !== "goal" && target.type !== "task" && target.type !== "agentResponsibility") return null;
|
|
3109
3087
|
if (typeof target.id !== "string" || target.id.trim().length === 0) return null;
|
|
3110
3088
|
return { type: target.type, id: target.id.trim() };
|
|
3111
3089
|
}
|
|
3112
|
-
function
|
|
3090
|
+
function parseAgentResponsibilityReportEvidence(raw) {
|
|
3113
3091
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
3114
3092
|
const out = {};
|
|
3115
3093
|
for (const [key, value] of Object.entries(raw)) {
|
|
@@ -3158,50 +3136,28 @@ function parseAgentResponsibilityResult(raw) {
|
|
|
3158
3136
|
if (!isAgentResponsibilityResultStatus(obj.status)) return null;
|
|
3159
3137
|
const summary = typeof obj.summary === "string" ? obj.summary.trim() : "";
|
|
3160
3138
|
if (!summary) return null;
|
|
3139
|
+
const target = obj.target === void 0 ? void 0 : parseAgentResponsibilityReportTarget(obj.target);
|
|
3140
|
+
if (obj.target !== void 0 && !target) return null;
|
|
3141
|
+
const evidence = obj.evidence === void 0 ? void 0 : parseAgentResponsibilityReportEvidence(obj.evidence);
|
|
3142
|
+
if (obj.evidence !== void 0 && !evidence) return null;
|
|
3161
3143
|
const facts = parseFacts2(obj.facts);
|
|
3162
3144
|
if (!facts) return null;
|
|
3163
3145
|
const artifacts = parseArtifacts(obj.artifacts);
|
|
3164
3146
|
if (!artifacts) return null;
|
|
3147
|
+
const missingEvidence = parseOptionalStringArray(obj.missingEvidence);
|
|
3148
|
+
if (!missingEvidence) return null;
|
|
3149
|
+
const blockers = parseOptionalStringArray(obj.blockers);
|
|
3150
|
+
if (!blockers) return null;
|
|
3165
3151
|
return {
|
|
3166
3152
|
version: 1,
|
|
3153
|
+
...target ? { target } : {},
|
|
3167
3154
|
status: obj.status,
|
|
3168
3155
|
summary,
|
|
3156
|
+
...evidence ? { evidence } : {},
|
|
3169
3157
|
facts,
|
|
3170
|
-
artifacts
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
function applyAgentResponsibilityResultToObjectiveState(state, result, evidenceOverride) {
|
|
3174
|
-
const priorFacts = parseFacts2(state.extra.facts) ?? {};
|
|
3175
|
-
const nextFacts = { ...priorFacts };
|
|
3176
|
-
for (const [key, value] of Object.entries(result.facts)) {
|
|
3177
|
-
if (CONTROL_FACT_KEYS2.has(key)) continue;
|
|
3178
|
-
nextFacts[key] = value;
|
|
3179
|
-
}
|
|
3180
|
-
const evidence = evidenceOverride || (typeof nextFacts.pendingEvidence === "string" ? nextFacts.pendingEvidence : "");
|
|
3181
|
-
if (evidence) {
|
|
3182
|
-
if (result.status === "pass") nextFacts[evidence] = true;
|
|
3183
|
-
if (result.status === "fail" || result.status === "blocked") nextFacts[evidence] = false;
|
|
3184
|
-
if ((result.status === "pass" || result.status === "fail" || result.status === "blocked") && nextFacts.pendingEvidence === evidence) {
|
|
3185
|
-
delete nextFacts.pendingEvidence;
|
|
3186
|
-
}
|
|
3187
|
-
}
|
|
3188
|
-
const blockers = parseStringArray(state.extra.blockers) ?? [];
|
|
3189
|
-
if ((result.status === "fail" || result.status === "blocked") && !blockers.includes(result.summary)) {
|
|
3190
|
-
blockers.push(result.summary);
|
|
3191
|
-
}
|
|
3192
|
-
return {
|
|
3193
|
-
...state,
|
|
3194
|
-
extra: {
|
|
3195
|
-
...state.extra,
|
|
3196
|
-
facts: nextFacts,
|
|
3197
|
-
blockers,
|
|
3198
|
-
lastAgentResponsibilityResult: {
|
|
3199
|
-
status: result.status,
|
|
3200
|
-
summary: result.summary,
|
|
3201
|
-
facts: result.facts,
|
|
3202
|
-
artifacts: result.artifacts
|
|
3203
|
-
}
|
|
3204
|
-
}
|
|
3158
|
+
artifacts,
|
|
3159
|
+
missingEvidence,
|
|
3160
|
+
blockers
|
|
3205
3161
|
};
|
|
3206
3162
|
}
|
|
3207
3163
|
function isAgentResponsibilityResultStatus(value) {
|
|
@@ -3227,6 +3183,10 @@ function parseStringArray(raw) {
|
|
|
3227
3183
|
}
|
|
3228
3184
|
return out;
|
|
3229
3185
|
}
|
|
3186
|
+
function parseOptionalStringArray(raw) {
|
|
3187
|
+
if (raw === void 0) return [];
|
|
3188
|
+
return parseStringArray(raw);
|
|
3189
|
+
}
|
|
3230
3190
|
function parseArtifacts(raw) {
|
|
3231
3191
|
if (raw === void 0) return [];
|
|
3232
3192
|
if (!Array.isArray(raw)) return null;
|
|
@@ -3250,6 +3210,7 @@ var RESULT_LINE, STATUSES, CONTROL_FACT_KEYS2;
|
|
|
3250
3210
|
var init_agent_responsibilityResult = __esm({
|
|
3251
3211
|
"src/agent-responsibilityResult.ts"() {
|
|
3252
3212
|
"use strict";
|
|
3213
|
+
init_agent_responsibilityReport();
|
|
3253
3214
|
RESULT_LINE = /^KODY_AGENT_RESPONSIBILITY_RESULT=(.+)$/gm;
|
|
3254
3215
|
STATUSES = /* @__PURE__ */ new Set(["pass", "fail", "blocked", "changed", "noop"]);
|
|
3255
3216
|
CONTROL_FACT_KEYS2 = /* @__PURE__ */ new Set(["blockers", "destination", "agent-responsibilities", "route", "stage", "state"]);
|
|
@@ -6180,6 +6141,7 @@ var init_state2 = __esm({
|
|
|
6180
6141
|
});
|
|
6181
6142
|
|
|
6182
6143
|
// src/goal/runLog.ts
|
|
6144
|
+
import * as fs25 from "fs";
|
|
6183
6145
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
6184
6146
|
const logs = goalRunLogs(data);
|
|
6185
6147
|
const existing = logs[goalId];
|
|
@@ -6201,7 +6163,7 @@ function flushGoalRunLogEvents(config, cwd, data) {
|
|
|
6201
6163
|
const logs = goalRunLogs(data);
|
|
6202
6164
|
for (const [goalId, log2] of Object.entries(logs)) {
|
|
6203
6165
|
if (log2.events.length === 0) continue;
|
|
6204
|
-
const lines = `${log2.events.map((event) => JSON.stringify(event)).join("\n")}
|
|
6166
|
+
const lines = `${log2.events.map((event) => JSON.stringify(enrichGoalRunLogEvent(config, data, log2.path, event))).join("\n")}
|
|
6205
6167
|
`;
|
|
6206
6168
|
appendStateLine(config, cwd, log2.path, lines, `chore(goal-logs): append ${goalId}`);
|
|
6207
6169
|
log2.events = [];
|
|
@@ -6212,6 +6174,55 @@ function goalRunLogPath(goalId, data) {
|
|
|
6212
6174
|
const runId = goalRunId(data);
|
|
6213
6175
|
return `logs/goals/${safePathSegment(goalId)}/runs/${startedAt}-${runId}.jsonl`;
|
|
6214
6176
|
}
|
|
6177
|
+
function goalStateLogPath(goalId) {
|
|
6178
|
+
return `goals/instances/${safePathSegment(goalId)}/state.json`;
|
|
6179
|
+
}
|
|
6180
|
+
function goalRunLogSnapshot(goalId, goalState, goal) {
|
|
6181
|
+
const requiredEvidence = [...goal.destination.evidence];
|
|
6182
|
+
const pendingEvidence = typeof goal.facts.pendingEvidence === "string" ? goal.facts.pendingEvidence : void 0;
|
|
6183
|
+
return {
|
|
6184
|
+
id: goalId,
|
|
6185
|
+
type: goal.type,
|
|
6186
|
+
state: goalState,
|
|
6187
|
+
stage: goal.stage,
|
|
6188
|
+
outcome: goal.destination.outcome,
|
|
6189
|
+
requiredEvidence,
|
|
6190
|
+
satisfiedEvidence: requiredEvidence.filter((evidence) => goal.facts[evidence] === true),
|
|
6191
|
+
failedEvidence: requiredEvidence.filter((evidence) => goal.facts[evidence] === false),
|
|
6192
|
+
missingEvidence: requiredEvidence.filter((evidence) => goal.facts[evidence] !== true),
|
|
6193
|
+
pendingEvidence,
|
|
6194
|
+
agentResponsibilities: [...goal.agentResponsibilities],
|
|
6195
|
+
route: goal.route.map(routeStepForLog),
|
|
6196
|
+
schedule: goal.schedule,
|
|
6197
|
+
preferredRunTime: goal.preferredRunTime,
|
|
6198
|
+
loopTarget: goal.loopTarget,
|
|
6199
|
+
blockers: [...goal.blockers],
|
|
6200
|
+
facts: { ...goal.facts }
|
|
6201
|
+
};
|
|
6202
|
+
}
|
|
6203
|
+
function goalRunLogChange(before, after) {
|
|
6204
|
+
if (!before || !after) return void 0;
|
|
6205
|
+
const change = {};
|
|
6206
|
+
addScalarChange(change, "state", before.state, after.state);
|
|
6207
|
+
addScalarChange(change, "stage", before.stage, after.stage);
|
|
6208
|
+
addScalarChange(change, "pendingEvidence", before.pendingEvidence, after.pendingEvidence);
|
|
6209
|
+
const beforeFacts = recordValue2(before.facts);
|
|
6210
|
+
const afterFacts = recordValue2(after.facts);
|
|
6211
|
+
if (beforeFacts || afterFacts) change.facts = diffRecordKeys(beforeFacts ?? {}, afterFacts ?? {});
|
|
6212
|
+
const beforeBlockers = stringArrayValue(before.blockers);
|
|
6213
|
+
const afterBlockers = stringArrayValue(after.blockers);
|
|
6214
|
+
if (beforeBlockers || afterBlockers) {
|
|
6215
|
+
const blockers = diffStringArrays(beforeBlockers ?? [], afterBlockers ?? []);
|
|
6216
|
+
if (blockers.added.length > 0 || blockers.removed.length > 0) change.blockers = blockers;
|
|
6217
|
+
}
|
|
6218
|
+
const beforeSatisfied = stringArrayValue(before.satisfiedEvidence);
|
|
6219
|
+
const afterSatisfied = stringArrayValue(after.satisfiedEvidence);
|
|
6220
|
+
if (beforeSatisfied || afterSatisfied) {
|
|
6221
|
+
const evidence = diffStringArrays(beforeSatisfied ?? [], afterSatisfied ?? []);
|
|
6222
|
+
if (evidence.added.length > 0 || evidence.removed.length > 0) change.satisfiedEvidence = evidence;
|
|
6223
|
+
}
|
|
6224
|
+
return Object.keys(change).length > 0 ? change : void 0;
|
|
6225
|
+
}
|
|
6215
6226
|
function goalRunLogs(data) {
|
|
6216
6227
|
const existing = data[LOGS_KEY];
|
|
6217
6228
|
if (existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
@@ -6242,6 +6253,176 @@ function githubRunId() {
|
|
|
6242
6253
|
const attempt = process.env.GITHUB_RUN_ATTEMPT?.trim();
|
|
6243
6254
|
return attempt ? `gh-${runId}-${attempt}` : `gh-${runId}`;
|
|
6244
6255
|
}
|
|
6256
|
+
function enrichGoalRunLogEvent(config, data, logPath, event) {
|
|
6257
|
+
const stateRepo = stateRepoContext(config, event.goalId, logPath);
|
|
6258
|
+
return pruneUndefined({
|
|
6259
|
+
...event,
|
|
6260
|
+
run: event.run ?? runContext(data),
|
|
6261
|
+
repo: event.repo ?? repoContext(config),
|
|
6262
|
+
stateRepo: event.stateRepo ?? stateRepo,
|
|
6263
|
+
trigger: event.trigger ?? triggerContext(),
|
|
6264
|
+
job: event.job ?? jobContext(data),
|
|
6265
|
+
links: event.links ?? linkContext(stateRepo)
|
|
6266
|
+
});
|
|
6267
|
+
}
|
|
6268
|
+
function runContext(data) {
|
|
6269
|
+
const runId = process.env.GITHUB_RUN_ID?.trim();
|
|
6270
|
+
const attempt = process.env.GITHUB_RUN_ATTEMPT?.trim();
|
|
6271
|
+
const repository = process.env.GITHUB_REPOSITORY?.trim();
|
|
6272
|
+
const server = process.env.GITHUB_SERVER_URL?.trim() || "https://github.com";
|
|
6273
|
+
return pruneUndefined({
|
|
6274
|
+
id: goalRunId(data),
|
|
6275
|
+
provider: runId ? "github-actions" : "local",
|
|
6276
|
+
githubRunId: runId || void 0,
|
|
6277
|
+
githubRunAttempt: attempt || void 0,
|
|
6278
|
+
workflow: process.env.GITHUB_WORKFLOW?.trim() || void 0,
|
|
6279
|
+
job: process.env.GITHUB_JOB?.trim() || void 0,
|
|
6280
|
+
url: runId && repository ? `${server}/${repository}/actions/runs/${runId}` : void 0,
|
|
6281
|
+
startedAt: data[LOG_STARTED_KEY]
|
|
6282
|
+
});
|
|
6283
|
+
}
|
|
6284
|
+
function repoContext(config) {
|
|
6285
|
+
const owner = config.github?.owner;
|
|
6286
|
+
const repo = config.github?.repo;
|
|
6287
|
+
return pruneUndefined({
|
|
6288
|
+
owner,
|
|
6289
|
+
repo,
|
|
6290
|
+
fullName: owner && repo ? `${owner}/${repo}` : process.env.GITHUB_REPOSITORY?.trim() || void 0,
|
|
6291
|
+
ref: process.env.GITHUB_REF?.trim() || void 0,
|
|
6292
|
+
sha: process.env.GITHUB_SHA?.trim() || void 0
|
|
6293
|
+
});
|
|
6294
|
+
}
|
|
6295
|
+
function stateRepoContext(config, goalId, logPath) {
|
|
6296
|
+
try {
|
|
6297
|
+
const state = resolveStateRepoConfig(config);
|
|
6298
|
+
return {
|
|
6299
|
+
repo: state.repo,
|
|
6300
|
+
path: state.path,
|
|
6301
|
+
goalStatePath: `${state.path}/${goalStateLogPath(goalId)}`,
|
|
6302
|
+
logPath: `${state.path}/${logPath}`
|
|
6303
|
+
};
|
|
6304
|
+
} catch {
|
|
6305
|
+
return void 0;
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
function triggerContext() {
|
|
6309
|
+
const event = readGithubEvent();
|
|
6310
|
+
const inputs = recordValue2(event?.inputs);
|
|
6311
|
+
return pruneUndefined({
|
|
6312
|
+
eventName: process.env.GITHUB_EVENT_NAME?.trim() || void 0,
|
|
6313
|
+
actor: process.env.GITHUB_ACTOR?.trim() || void 0,
|
|
6314
|
+
eventPath: process.env.GITHUB_EVENT_PATH?.trim() || void 0,
|
|
6315
|
+
issue: numberValue(recordValue2(event?.issue)?.number),
|
|
6316
|
+
pullRequest: numberValue(recordValue2(event?.pull_request)?.number),
|
|
6317
|
+
comment: numberValue(recordValue2(event?.comment)?.id),
|
|
6318
|
+
schedule: stringValue(event?.schedule),
|
|
6319
|
+
inputs: inputs ? pickRecord(inputs, ["issue_number", "sessionId", "message", "model", "title", "agentAction", "base"]) : void 0
|
|
6320
|
+
});
|
|
6321
|
+
}
|
|
6322
|
+
function jobContext(data) {
|
|
6323
|
+
const job = pruneUndefined({
|
|
6324
|
+
id: stringValue(data.jobId),
|
|
6325
|
+
key: stringValue(data.jobKey),
|
|
6326
|
+
flavor: stringValue(data.jobFlavor),
|
|
6327
|
+
action: stringValue(data.jobAction),
|
|
6328
|
+
agentResponsibility: stringValue(data.jobAgentResponsibility),
|
|
6329
|
+
agentAction: stringValue(data.jobAgentAction),
|
|
6330
|
+
agent: stringValue(data.jobAgent),
|
|
6331
|
+
schedule: stringValue(data.jobSchedule),
|
|
6332
|
+
target: data.jobTarget,
|
|
6333
|
+
why: truncateString(stringValue(data.jobWhy), 1e3),
|
|
6334
|
+
saveReport: data.jobSaveReport === true ? true : void 0
|
|
6335
|
+
});
|
|
6336
|
+
return Object.keys(job).length > 0 ? job : void 0;
|
|
6337
|
+
}
|
|
6338
|
+
function linkContext(stateRepo) {
|
|
6339
|
+
const links = {};
|
|
6340
|
+
const runId = process.env.GITHUB_RUN_ID?.trim();
|
|
6341
|
+
const repository = process.env.GITHUB_REPOSITORY?.trim();
|
|
6342
|
+
const server = process.env.GITHUB_SERVER_URL?.trim() || "https://github.com";
|
|
6343
|
+
if (runId && repository) links.workflowRun = `${server}/${repository}/actions/runs/${runId}`;
|
|
6344
|
+
const repo = stringValue(stateRepo?.repo);
|
|
6345
|
+
const goalStatePath = stringValue(stateRepo?.goalStatePath);
|
|
6346
|
+
const logPath = stringValue(stateRepo?.logPath);
|
|
6347
|
+
if (repo && goalStatePath) links.goalState = githubBlobUrl(repo, goalStatePath);
|
|
6348
|
+
if (repo && logPath) links.log = githubBlobUrl(repo, logPath);
|
|
6349
|
+
return Object.keys(links).length > 0 ? links : void 0;
|
|
6350
|
+
}
|
|
6351
|
+
function githubBlobUrl(repo, filePath) {
|
|
6352
|
+
try {
|
|
6353
|
+
const parsed = parseStateRepoSlug(repo);
|
|
6354
|
+
return `https://github.com/${parsed.owner}/${parsed.repo}/blob/main/${filePath}`;
|
|
6355
|
+
} catch {
|
|
6356
|
+
return void 0;
|
|
6357
|
+
}
|
|
6358
|
+
}
|
|
6359
|
+
function routeStepForLog(step) {
|
|
6360
|
+
return pruneUndefined({
|
|
6361
|
+
evidence: step.evidence,
|
|
6362
|
+
stage: step.stage,
|
|
6363
|
+
agentResponsibility: step.agentResponsibility,
|
|
6364
|
+
agentAction: step.agentAction,
|
|
6365
|
+
args: step.args,
|
|
6366
|
+
saveReport: step.saveReport === true ? true : void 0
|
|
6367
|
+
});
|
|
6368
|
+
}
|
|
6369
|
+
function readGithubEvent() {
|
|
6370
|
+
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
6371
|
+
if (!eventPath) return null;
|
|
6372
|
+
try {
|
|
6373
|
+
if (!fs25.existsSync(eventPath)) return null;
|
|
6374
|
+
const parsed = JSON.parse(fs25.readFileSync(eventPath, "utf-8"));
|
|
6375
|
+
return recordValue2(parsed);
|
|
6376
|
+
} catch {
|
|
6377
|
+
return null;
|
|
6378
|
+
}
|
|
6379
|
+
}
|
|
6380
|
+
function addScalarChange(change, field, before, after) {
|
|
6381
|
+
if (before === after) return;
|
|
6382
|
+
change[field] = pruneUndefined({ from: before, to: after });
|
|
6383
|
+
}
|
|
6384
|
+
function diffRecordKeys(before, after) {
|
|
6385
|
+
const beforeKeys = new Set(Object.keys(before));
|
|
6386
|
+
const afterKeys = new Set(Object.keys(after));
|
|
6387
|
+
const added = [...afterKeys].filter((key) => !beforeKeys.has(key)).sort();
|
|
6388
|
+
const removed = [...beforeKeys].filter((key) => !afterKeys.has(key)).sort();
|
|
6389
|
+
const changed = [...afterKeys].filter((key) => beforeKeys.has(key) && JSON.stringify(before[key]) !== JSON.stringify(after[key])).sort();
|
|
6390
|
+
return { added, removed, changed };
|
|
6391
|
+
}
|
|
6392
|
+
function diffStringArrays(before, after) {
|
|
6393
|
+
const beforeSet = new Set(before);
|
|
6394
|
+
const afterSet = new Set(after);
|
|
6395
|
+
return {
|
|
6396
|
+
added: after.filter((item) => !beforeSet.has(item)).sort(),
|
|
6397
|
+
removed: before.filter((item) => !afterSet.has(item)).sort()
|
|
6398
|
+
};
|
|
6399
|
+
}
|
|
6400
|
+
function recordValue2(value) {
|
|
6401
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
6402
|
+
}
|
|
6403
|
+
function stringArrayValue(value) {
|
|
6404
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? [...value] : null;
|
|
6405
|
+
}
|
|
6406
|
+
function numberValue(value) {
|
|
6407
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
6408
|
+
}
|
|
6409
|
+
function pickRecord(input, keys) {
|
|
6410
|
+
const out = {};
|
|
6411
|
+
for (const key of keys) {
|
|
6412
|
+
if (input[key] !== void 0 && input[key] !== "") out[key] = input[key];
|
|
6413
|
+
}
|
|
6414
|
+
return out;
|
|
6415
|
+
}
|
|
6416
|
+
function pruneUndefined(input) {
|
|
6417
|
+
for (const key of Object.keys(input)) {
|
|
6418
|
+
if (input[key] === void 0) delete input[key];
|
|
6419
|
+
}
|
|
6420
|
+
return input;
|
|
6421
|
+
}
|
|
6422
|
+
function truncateString(value, max) {
|
|
6423
|
+
if (!value) return void 0;
|
|
6424
|
+
return value.length > max ? `${value.slice(0, max)}...` : value;
|
|
6425
|
+
}
|
|
6245
6426
|
function stringValue(value) {
|
|
6246
6427
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
6247
6428
|
}
|
|
@@ -6587,7 +6768,7 @@ var init_contentsApiBackend = __esm({
|
|
|
6587
6768
|
});
|
|
6588
6769
|
|
|
6589
6770
|
// src/scripts/jobState/localFileBackend.ts
|
|
6590
|
-
import * as
|
|
6771
|
+
import * as fs26 from "fs";
|
|
6591
6772
|
import * as path24 from "path";
|
|
6592
6773
|
function sanitizeKey(s) {
|
|
6593
6774
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
@@ -6659,7 +6840,7 @@ var init_localFileBackend = __esm({
|
|
|
6659
6840
|
`);
|
|
6660
6841
|
return;
|
|
6661
6842
|
}
|
|
6662
|
-
|
|
6843
|
+
fs26.mkdirSync(this.absDir, { recursive: true });
|
|
6663
6844
|
const prefix = this.cacheKeyPrefix();
|
|
6664
6845
|
const probeKey = `${prefix}probe-${Date.now()}`;
|
|
6665
6846
|
try {
|
|
@@ -6688,7 +6869,7 @@ var init_localFileBackend = __esm({
|
|
|
6688
6869
|
`);
|
|
6689
6870
|
return;
|
|
6690
6871
|
}
|
|
6691
|
-
if (!
|
|
6872
|
+
if (!fs26.existsSync(this.absDir)) {
|
|
6692
6873
|
return;
|
|
6693
6874
|
}
|
|
6694
6875
|
const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
|
|
@@ -6705,10 +6886,10 @@ var init_localFileBackend = __esm({
|
|
|
6705
6886
|
load(slug2) {
|
|
6706
6887
|
const relPath = stateFilePath(this.jobsDir, slug2);
|
|
6707
6888
|
const absPath = path24.join(this.cwd, relPath);
|
|
6708
|
-
if (!
|
|
6889
|
+
if (!fs26.existsSync(absPath)) {
|
|
6709
6890
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
6710
6891
|
}
|
|
6711
|
-
const raw =
|
|
6892
|
+
const raw = fs26.readFileSync(absPath, "utf-8");
|
|
6712
6893
|
let parsed;
|
|
6713
6894
|
try {
|
|
6714
6895
|
parsed = JSON.parse(raw);
|
|
@@ -6726,12 +6907,12 @@ var init_localFileBackend = __esm({
|
|
|
6726
6907
|
return false;
|
|
6727
6908
|
}
|
|
6728
6909
|
const absPath = path24.join(this.cwd, loaded.path);
|
|
6729
|
-
|
|
6910
|
+
fs26.mkdirSync(path24.dirname(absPath), { recursive: true });
|
|
6730
6911
|
const body = `${JSON.stringify(next, null, 2)}
|
|
6731
6912
|
`;
|
|
6732
6913
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
6733
|
-
|
|
6734
|
-
|
|
6914
|
+
fs26.writeFileSync(tmpPath, body, "utf-8");
|
|
6915
|
+
fs26.renameSync(tmpPath, absPath);
|
|
6735
6916
|
return true;
|
|
6736
6917
|
}
|
|
6737
6918
|
cacheKeyPrefix() {
|
|
@@ -7000,7 +7181,7 @@ var init_goalAgentResponsibilityScheduling = __esm({
|
|
|
7000
7181
|
});
|
|
7001
7182
|
|
|
7002
7183
|
// src/scripts/advanceManagedGoal.ts
|
|
7003
|
-
function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
|
|
7184
|
+
function stageManagedGoalDecision(data, goalId, goal, goalState, decision, details) {
|
|
7004
7185
|
if (decision.kind === "dispatch") {
|
|
7005
7186
|
stageGoalRunLogEvent(data, goalId, {
|
|
7006
7187
|
source: "goal-manager",
|
|
@@ -7014,7 +7195,18 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
|
|
|
7014
7195
|
agentResponsibility: decision.agentResponsibility,
|
|
7015
7196
|
agentAction: decision.agentAction,
|
|
7016
7197
|
cliArgs: decision.cliArgs
|
|
7017
|
-
}
|
|
7198
|
+
},
|
|
7199
|
+
goal: details.goalSnapshot,
|
|
7200
|
+
inspection: details.inspection,
|
|
7201
|
+
decision: {
|
|
7202
|
+
kind: decision.kind,
|
|
7203
|
+
evidence: decision.evidence,
|
|
7204
|
+
stage: decision.stage,
|
|
7205
|
+
agentResponsibility: decision.agentResponsibility,
|
|
7206
|
+
agentAction: decision.agentAction,
|
|
7207
|
+
cliArgs: decision.cliArgs
|
|
7208
|
+
},
|
|
7209
|
+
change: details.change
|
|
7018
7210
|
});
|
|
7019
7211
|
return;
|
|
7020
7212
|
}
|
|
@@ -7026,7 +7218,11 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
|
|
|
7026
7218
|
goalState: "done",
|
|
7027
7219
|
stage: "done",
|
|
7028
7220
|
status: decision.kind,
|
|
7029
|
-
reason: "managed goal complete"
|
|
7221
|
+
reason: "managed goal complete",
|
|
7222
|
+
goal: details.goalSnapshot,
|
|
7223
|
+
inspection: details.inspection,
|
|
7224
|
+
decision: { kind: decision.kind, reason: "managed goal complete" },
|
|
7225
|
+
change: details.change
|
|
7030
7226
|
});
|
|
7031
7227
|
return;
|
|
7032
7228
|
}
|
|
@@ -7038,7 +7234,11 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
|
|
|
7038
7234
|
goalState,
|
|
7039
7235
|
stage: goal.stage,
|
|
7040
7236
|
status: decision.kind,
|
|
7041
|
-
reason: decision.reason
|
|
7237
|
+
reason: decision.reason,
|
|
7238
|
+
goal: details.goalSnapshot,
|
|
7239
|
+
inspection: details.inspection,
|
|
7240
|
+
decision: { kind: decision.kind, reason: decision.reason },
|
|
7241
|
+
change: details.change
|
|
7042
7242
|
});
|
|
7043
7243
|
return;
|
|
7044
7244
|
}
|
|
@@ -7050,7 +7250,16 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
|
|
|
7050
7250
|
stage: decision.stage,
|
|
7051
7251
|
evidence: decision.evidence,
|
|
7052
7252
|
status: decision.kind,
|
|
7053
|
-
reason: decision.reason
|
|
7253
|
+
reason: decision.reason,
|
|
7254
|
+
goal: details.goalSnapshot,
|
|
7255
|
+
inspection: details.inspection,
|
|
7256
|
+
decision: {
|
|
7257
|
+
kind: decision.kind,
|
|
7258
|
+
evidence: decision.evidence,
|
|
7259
|
+
stage: decision.stage,
|
|
7260
|
+
reason: decision.reason
|
|
7261
|
+
},
|
|
7262
|
+
change: details.change
|
|
7054
7263
|
});
|
|
7055
7264
|
}
|
|
7056
7265
|
function readSimpleGoalTaskSummary(goalId, cwd) {
|
|
@@ -7139,16 +7348,25 @@ var init_advanceManagedGoal = __esm({
|
|
|
7139
7348
|
ctx.output.reason = "goal has no managed-goal contract; nothing to advance";
|
|
7140
7349
|
return;
|
|
7141
7350
|
}
|
|
7351
|
+
const previousGoalIdFact = managed.facts.goalId;
|
|
7352
|
+
managed.facts.goalId = goal.id;
|
|
7353
|
+
const startSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7142
7354
|
stageGoalRunLogEvent(ctx.data, goal.id, {
|
|
7143
7355
|
source: "goal-manager",
|
|
7144
7356
|
event: "goal.tick.start",
|
|
7145
7357
|
goalType: managed.type,
|
|
7146
7358
|
goalState: goal.state,
|
|
7147
7359
|
stage: managed.stage,
|
|
7360
|
+
goal: startSnapshot,
|
|
7361
|
+
inspection: {
|
|
7362
|
+
requiredEvidence: startSnapshot.requiredEvidence,
|
|
7363
|
+
satisfiedEvidence: startSnapshot.satisfiedEvidence,
|
|
7364
|
+
missingEvidence: startSnapshot.missingEvidence,
|
|
7365
|
+
pendingEvidence: startSnapshot.pendingEvidence,
|
|
7366
|
+
blockers: startSnapshot.blockers
|
|
7367
|
+
},
|
|
7148
7368
|
facts: managed.facts
|
|
7149
7369
|
});
|
|
7150
|
-
const previousGoalIdFact = managed.facts.goalId;
|
|
7151
|
-
managed.facts.goalId = goal.id;
|
|
7152
7370
|
const restoreGoalIdFact = () => {
|
|
7153
7371
|
if (previousGoalIdFact === void 0) delete managed.facts.goalId;
|
|
7154
7372
|
else managed.facts.goalId = previousGoalIdFact;
|
|
@@ -7161,6 +7379,7 @@ var init_advanceManagedGoal = __esm({
|
|
|
7161
7379
|
if (!managed.blockers.includes(reason)) managed.blockers.push(reason);
|
|
7162
7380
|
restoreGoalIdFact();
|
|
7163
7381
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
7382
|
+
const blockedSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7164
7383
|
stageGoalRunLogEvent(ctx.data, goal.id, {
|
|
7165
7384
|
source: "goal-manager",
|
|
7166
7385
|
event: "goal.tick.blocked",
|
|
@@ -7168,12 +7387,20 @@ var init_advanceManagedGoal = __esm({
|
|
|
7168
7387
|
goalState: goal.state,
|
|
7169
7388
|
stage: managed.stage,
|
|
7170
7389
|
status: "blocked",
|
|
7171
|
-
reason
|
|
7390
|
+
reason,
|
|
7391
|
+
goal: blockedSnapshot,
|
|
7392
|
+
inspection: {
|
|
7393
|
+
purpose: "prepare goal issue fact before dispatch",
|
|
7394
|
+
routeNeedsIssueFact: true
|
|
7395
|
+
},
|
|
7396
|
+
decision: { kind: "blocked", reason },
|
|
7397
|
+
change: goalRunLogChange(startSnapshot, blockedSnapshot)
|
|
7172
7398
|
});
|
|
7173
7399
|
ctx.output.reason = reason;
|
|
7174
7400
|
return;
|
|
7175
7401
|
}
|
|
7176
7402
|
if (isGoalTargetLoop(managed)) {
|
|
7403
|
+
const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7177
7404
|
const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
|
|
7178
7405
|
const decision2 = planGoalTargetLoopSchedule({ goal: managed, previousScheduleState });
|
|
7179
7406
|
restoreGoalIdFact();
|
|
@@ -7196,12 +7423,32 @@ var init_advanceManagedGoal = __esm({
|
|
|
7196
7423
|
status: decision2.kind,
|
|
7197
7424
|
reason: decision2.reason,
|
|
7198
7425
|
target: decision2.dispatch?.cliArgs.goal && typeof decision2.dispatch.cliArgs.goal === "string" ? { type: "goal", id: decision2.dispatch.cliArgs.goal } : managed.loopTarget,
|
|
7199
|
-
dispatch: decision2.dispatch
|
|
7426
|
+
dispatch: decision2.dispatch,
|
|
7427
|
+
goal: goalRunLogSnapshot(goal.id, goal.state, managed),
|
|
7428
|
+
inspection: {
|
|
7429
|
+
loopTarget: managed.loopTarget,
|
|
7430
|
+
preferredRunTime: managed.preferredRunTime,
|
|
7431
|
+
previousScheduleState,
|
|
7432
|
+
scheduleState: decision2.scheduleState
|
|
7433
|
+
},
|
|
7434
|
+
decision: {
|
|
7435
|
+
kind: decision2.kind,
|
|
7436
|
+
reason: decision2.reason,
|
|
7437
|
+
dispatch: decision2.dispatch
|
|
7438
|
+
},
|
|
7439
|
+
change: {
|
|
7440
|
+
...goalRunLogChange(beforeSnapshot, goalRunLogSnapshot(goal.id, goal.state, managed)) ?? {},
|
|
7441
|
+
scheduleState: {
|
|
7442
|
+
previousDecision: previousScheduleState?.lastDecision,
|
|
7443
|
+
nextDecision: decision2.scheduleState.lastDecision
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7200
7446
|
});
|
|
7201
7447
|
ctx.output.reason = decision2.reason;
|
|
7202
7448
|
return;
|
|
7203
7449
|
}
|
|
7204
7450
|
if (isAgentResponsibilityCadenceGoal(managed, goal.raw.extra)) {
|
|
7451
|
+
const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7205
7452
|
const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
|
|
7206
7453
|
const decision2 = await planGoalAgentResponsibilitySchedule({
|
|
7207
7454
|
goal: managed,
|
|
@@ -7229,22 +7476,55 @@ var init_advanceManagedGoal = __esm({
|
|
|
7229
7476
|
stage: managed.stage,
|
|
7230
7477
|
status: decision2.kind,
|
|
7231
7478
|
reason: decision2.reason,
|
|
7232
|
-
dispatch: decision2.dispatch
|
|
7479
|
+
dispatch: decision2.dispatch,
|
|
7480
|
+
goal: goalRunLogSnapshot(goal.id, goal.state, managed),
|
|
7481
|
+
inspection: {
|
|
7482
|
+
agentResponsibilities: decision2.scheduleState.agentResponsibilities,
|
|
7483
|
+
previousScheduleState,
|
|
7484
|
+
scheduleState: decision2.scheduleState
|
|
7485
|
+
},
|
|
7486
|
+
decision: {
|
|
7487
|
+
kind: decision2.kind,
|
|
7488
|
+
reason: decision2.reason,
|
|
7489
|
+
dispatch: decision2.dispatch
|
|
7490
|
+
},
|
|
7491
|
+
change: {
|
|
7492
|
+
...goalRunLogChange(beforeSnapshot, goalRunLogSnapshot(goal.id, goal.state, managed)) ?? {},
|
|
7493
|
+
scheduleState: {
|
|
7494
|
+
previousDecision: previousScheduleState?.lastDecision,
|
|
7495
|
+
nextDecision: decision2.scheduleState.lastDecision
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7233
7498
|
});
|
|
7234
7499
|
ctx.output.reason = decision2.reason;
|
|
7235
7500
|
return;
|
|
7236
7501
|
}
|
|
7502
|
+
let simpleTaskSummary;
|
|
7237
7503
|
if (isSimpleGoal(managed)) {
|
|
7238
|
-
|
|
7504
|
+
simpleTaskSummary = readSimpleGoalTaskSummary(goal.id, ctx.cwd);
|
|
7505
|
+
applySimpleGoalTaskSummary(managed, simpleTaskSummary);
|
|
7239
7506
|
}
|
|
7507
|
+
const beforeDecisionSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7240
7508
|
const decision = planManagedGoalTick(managed);
|
|
7241
7509
|
restoreGoalIdFact();
|
|
7242
7510
|
ctx.data.managedGoalDecision = decision;
|
|
7243
|
-
stageManagedGoalDecision(ctx.data, goal.id, managed, goal.state, decision);
|
|
7244
7511
|
if (decision.kind === "done") {
|
|
7245
7512
|
goal.state = "done";
|
|
7246
7513
|
}
|
|
7247
7514
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
7515
|
+
const afterDecisionSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7516
|
+
stageManagedGoalDecision(ctx.data, goal.id, managed, goal.state, decision, {
|
|
7517
|
+
goalSnapshot: afterDecisionSnapshot,
|
|
7518
|
+
inspection: {
|
|
7519
|
+
requiredEvidence: beforeDecisionSnapshot.requiredEvidence,
|
|
7520
|
+
satisfiedEvidence: beforeDecisionSnapshot.satisfiedEvidence,
|
|
7521
|
+
missingEvidence: beforeDecisionSnapshot.missingEvidence,
|
|
7522
|
+
pendingEvidence: beforeDecisionSnapshot.pendingEvidence,
|
|
7523
|
+
route: beforeDecisionSnapshot.route,
|
|
7524
|
+
simpleTaskSummary
|
|
7525
|
+
},
|
|
7526
|
+
change: goalRunLogChange(beforeDecisionSnapshot, afterDecisionSnapshot)
|
|
7527
|
+
});
|
|
7248
7528
|
if (decision.kind === "blocked" || decision.kind === "wait" || decision.kind === "idle" || decision.kind === "done") {
|
|
7249
7529
|
ctx.output.reason = decision.kind === "done" ? "managed goal complete" : decision.reason;
|
|
7250
7530
|
return;
|
|
@@ -7790,6 +8070,174 @@ var init_appendCompanyIntentDecision = __esm({
|
|
|
7790
8070
|
}
|
|
7791
8071
|
});
|
|
7792
8072
|
|
|
8073
|
+
// src/agent-responsibilityEvidence.ts
|
|
8074
|
+
function agentResponsibilityReportToEvidence(report) {
|
|
8075
|
+
if (report.target.type !== "goal") return null;
|
|
8076
|
+
const evidence = report.evidence ?? {};
|
|
8077
|
+
const values = Object.values(evidence);
|
|
8078
|
+
const status = values.some((value) => value === false) ? "fail" : values.length > 0 || report.facts ? "changed" : "noop";
|
|
8079
|
+
return {
|
|
8080
|
+
version: 1,
|
|
8081
|
+
target: { type: "goal", id: report.target.id },
|
|
8082
|
+
status,
|
|
8083
|
+
summary: "responsibility reported goal evidence",
|
|
8084
|
+
evidence,
|
|
8085
|
+
facts: report.facts ?? {},
|
|
8086
|
+
artifacts: [],
|
|
8087
|
+
missingEvidence: [],
|
|
8088
|
+
blockers: [],
|
|
8089
|
+
sources: ["report"]
|
|
8090
|
+
};
|
|
8091
|
+
}
|
|
8092
|
+
function agentResponsibilityResultToEvidence(result, fallbackGoalId, explicitEvidence) {
|
|
8093
|
+
const targetId = result.target?.type === "goal" ? result.target.id : fallbackGoalId;
|
|
8094
|
+
if (!targetId) return null;
|
|
8095
|
+
return {
|
|
8096
|
+
version: 1,
|
|
8097
|
+
target: { type: "goal", id: targetId },
|
|
8098
|
+
status: result.status,
|
|
8099
|
+
summary: result.summary,
|
|
8100
|
+
evidence: result.evidence,
|
|
8101
|
+
explicitEvidence,
|
|
8102
|
+
facts: result.facts,
|
|
8103
|
+
artifacts: result.artifacts,
|
|
8104
|
+
missingEvidence: result.missingEvidence,
|
|
8105
|
+
blockers: result.blockers,
|
|
8106
|
+
sources: ["result"]
|
|
8107
|
+
};
|
|
8108
|
+
}
|
|
8109
|
+
function mergeResponsibilityEvidence(items) {
|
|
8110
|
+
const reports = items.filter((item) => item.sources.includes("report") && !item.sources.includes("result"));
|
|
8111
|
+
const results = items.filter((item) => item.sources.includes("result"));
|
|
8112
|
+
const usedReports = /* @__PURE__ */ new Set();
|
|
8113
|
+
const merged = [];
|
|
8114
|
+
for (const result of results) {
|
|
8115
|
+
const reportIndex = reports.findIndex(
|
|
8116
|
+
(report, index) => !usedReports.has(index) && evidenceMatches(report, result, reports)
|
|
8117
|
+
);
|
|
8118
|
+
if (reportIndex >= 0) {
|
|
8119
|
+
usedReports.add(reportIndex);
|
|
8120
|
+
merged.push(mergeReportAndResult(reports[reportIndex], result));
|
|
8121
|
+
} else {
|
|
8122
|
+
merged.push(result);
|
|
8123
|
+
}
|
|
8124
|
+
}
|
|
8125
|
+
for (let i = 0; i < reports.length; i += 1) {
|
|
8126
|
+
if (!usedReports.has(i)) merged.push(reports[i]);
|
|
8127
|
+
}
|
|
8128
|
+
return merged;
|
|
8129
|
+
}
|
|
8130
|
+
function applyAgentResponsibilityEvidenceToGoalState(state, evidence) {
|
|
8131
|
+
const priorFacts = parseFacts3(state.extra.facts) ?? {};
|
|
8132
|
+
const nextFacts = { ...priorFacts };
|
|
8133
|
+
for (const [key, value] of Object.entries(evidence.facts)) {
|
|
8134
|
+
if (CONTROL_FACT_KEYS3.has(key)) continue;
|
|
8135
|
+
nextFacts[key] = value;
|
|
8136
|
+
}
|
|
8137
|
+
for (const [key, value] of Object.entries(evidence.evidence ?? {})) {
|
|
8138
|
+
nextFacts[key] = value;
|
|
8139
|
+
}
|
|
8140
|
+
const pending = typeof nextFacts.pendingEvidence === "string" ? nextFacts.pendingEvidence : "";
|
|
8141
|
+
const statusEvidence = evidence.explicitEvidence || pending;
|
|
8142
|
+
const hasPendingEvidenceValue = pending ? Object.hasOwn(evidence.evidence ?? {}, pending) : false;
|
|
8143
|
+
const terminalStatus = evidence.status === "pass" || evidence.status === "fail" || evidence.status === "blocked";
|
|
8144
|
+
if (statusEvidence && !Object.hasOwn(evidence.evidence ?? {}, statusEvidence)) {
|
|
8145
|
+
if (evidence.status === "pass") nextFacts[statusEvidence] = true;
|
|
8146
|
+
if (evidence.status === "fail" || evidence.status === "blocked") nextFacts[statusEvidence] = false;
|
|
8147
|
+
}
|
|
8148
|
+
if (pending && (hasPendingEvidenceValue || statusEvidence === pending && terminalStatus)) {
|
|
8149
|
+
delete nextFacts.pendingEvidence;
|
|
8150
|
+
}
|
|
8151
|
+
const blockers = parseStringArray3(state.extra.blockers) ?? [];
|
|
8152
|
+
const evidenceBlockers = evidence.blockers.length > 0 || evidence.status !== "fail" && evidence.status !== "blocked" ? evidence.blockers : [evidence.summary];
|
|
8153
|
+
for (const blocker of evidenceBlockers) {
|
|
8154
|
+
if (!blockers.includes(blocker)) blockers.push(blocker);
|
|
8155
|
+
}
|
|
8156
|
+
const nextExtra = {
|
|
8157
|
+
...state.extra,
|
|
8158
|
+
facts: nextFacts
|
|
8159
|
+
};
|
|
8160
|
+
if (blockers.length > 0 || Array.isArray(state.extra.blockers)) {
|
|
8161
|
+
nextExtra.blockers = blockers;
|
|
8162
|
+
}
|
|
8163
|
+
return {
|
|
8164
|
+
...state,
|
|
8165
|
+
extra: nextExtra
|
|
8166
|
+
};
|
|
8167
|
+
}
|
|
8168
|
+
function evidenceMatches(report, result, allReports) {
|
|
8169
|
+
if (report.target.id !== result.target.id) return false;
|
|
8170
|
+
if (result.explicitEvidence && Object.hasOwn(report.evidence ?? {}, result.explicitEvidence)) return true;
|
|
8171
|
+
const resultEvidenceKeys = Object.keys(result.evidence ?? {});
|
|
8172
|
+
if (resultEvidenceKeys.length > 0 && resultEvidenceKeys.some((key) => Object.hasOwn(report.evidence ?? {}, key))) {
|
|
8173
|
+
return true;
|
|
8174
|
+
}
|
|
8175
|
+
return !result.explicitEvidence && resultEvidenceKeys.length === 0 && allReports.filter((item) => item.target.id === result.target.id).length === 1;
|
|
8176
|
+
}
|
|
8177
|
+
function mergeReportAndResult(report, result) {
|
|
8178
|
+
return {
|
|
8179
|
+
...result,
|
|
8180
|
+
evidence: mergeOptionalRecords(report.evidence, result.evidence),
|
|
8181
|
+
facts: { ...report.facts, ...result.facts },
|
|
8182
|
+
artifacts: uniqueArtifacts([...report.artifacts, ...result.artifacts]),
|
|
8183
|
+
missingEvidence: uniqueStrings([...report.missingEvidence, ...result.missingEvidence]),
|
|
8184
|
+
blockers: uniqueStrings([...report.blockers, ...result.blockers]),
|
|
8185
|
+
sources: uniqueSources([...report.sources, ...result.sources])
|
|
8186
|
+
};
|
|
8187
|
+
}
|
|
8188
|
+
function mergeOptionalRecords(left, right) {
|
|
8189
|
+
const merged = { ...left ?? {}, ...right ?? {} };
|
|
8190
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
8191
|
+
}
|
|
8192
|
+
function uniqueStrings(values) {
|
|
8193
|
+
return [...new Set(values)].sort();
|
|
8194
|
+
}
|
|
8195
|
+
function uniqueSources(values) {
|
|
8196
|
+
const order = ["report", "result"];
|
|
8197
|
+
const set = new Set(values);
|
|
8198
|
+
return order.filter((source) => set.has(source));
|
|
8199
|
+
}
|
|
8200
|
+
function uniqueArtifacts(artifacts) {
|
|
8201
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8202
|
+
const out = [];
|
|
8203
|
+
for (const artifact of artifacts) {
|
|
8204
|
+
const key = `${artifact.label}
|
|
8205
|
+
${artifact.url ?? ""}
|
|
8206
|
+
${artifact.path ?? ""}`;
|
|
8207
|
+
if (seen.has(key)) continue;
|
|
8208
|
+
seen.add(key);
|
|
8209
|
+
out.push(artifact);
|
|
8210
|
+
}
|
|
8211
|
+
return out;
|
|
8212
|
+
}
|
|
8213
|
+
function parseFacts3(raw) {
|
|
8214
|
+
if (raw === void 0) return {};
|
|
8215
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
8216
|
+
const facts = {};
|
|
8217
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
8218
|
+
if (!key.trim()) return null;
|
|
8219
|
+
if (CONTROL_FACT_KEYS3.has(key)) continue;
|
|
8220
|
+
facts[key] = value;
|
|
8221
|
+
}
|
|
8222
|
+
return facts;
|
|
8223
|
+
}
|
|
8224
|
+
function parseStringArray3(raw) {
|
|
8225
|
+
if (!Array.isArray(raw)) return null;
|
|
8226
|
+
const out = [];
|
|
8227
|
+
for (const item of raw) {
|
|
8228
|
+
if (typeof item !== "string") return null;
|
|
8229
|
+
out.push(item);
|
|
8230
|
+
}
|
|
8231
|
+
return out;
|
|
8232
|
+
}
|
|
8233
|
+
var CONTROL_FACT_KEYS3;
|
|
8234
|
+
var init_agent_responsibilityEvidence = __esm({
|
|
8235
|
+
"src/agent-responsibilityEvidence.ts"() {
|
|
8236
|
+
"use strict";
|
|
8237
|
+
CONTROL_FACT_KEYS3 = /* @__PURE__ */ new Set(["blockers", "destination", "agent-responsibilities", "route", "stage", "state"]);
|
|
8238
|
+
}
|
|
8239
|
+
});
|
|
8240
|
+
|
|
7793
8241
|
// src/scripts/applyAgentResponsibilityReports.ts
|
|
7794
8242
|
function flushLogs(ctx) {
|
|
7795
8243
|
try {
|
|
@@ -7823,13 +8271,24 @@ function collectResults(raw, agentResult) {
|
|
|
7823
8271
|
if (agentResult?.finalText) out.push(...parseAgentResponsibilityResultsFromText(agentResult.finalText));
|
|
7824
8272
|
return out;
|
|
7825
8273
|
}
|
|
7826
|
-
function
|
|
7827
|
-
const
|
|
8274
|
+
function collectGoalResponsibilityEvidence(reports, results, fallbackGoalId, explicitEvidence) {
|
|
8275
|
+
const items = [];
|
|
7828
8276
|
for (const report of reports) {
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
8277
|
+
const evidence = agentResponsibilityReportToEvidence(report);
|
|
8278
|
+
if (evidence) items.push(evidence);
|
|
8279
|
+
}
|
|
8280
|
+
for (const result of results) {
|
|
8281
|
+
const evidence = agentResponsibilityResultToEvidence(result, fallbackGoalId, explicitEvidence);
|
|
8282
|
+
if (evidence) items.push(evidence);
|
|
8283
|
+
}
|
|
8284
|
+
return mergeResponsibilityEvidence(items);
|
|
8285
|
+
}
|
|
8286
|
+
function groupGoalEvidence(evidenceItems) {
|
|
8287
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
8288
|
+
for (const evidence of evidenceItems) {
|
|
8289
|
+
const list = grouped.get(evidence.target.id) ?? [];
|
|
8290
|
+
list.push(evidence);
|
|
8291
|
+
grouped.set(evidence.target.id, list);
|
|
7833
8292
|
}
|
|
7834
8293
|
return grouped;
|
|
7835
8294
|
}
|
|
@@ -7842,16 +8301,72 @@ function completeSatisfiedManagedGoal(state) {
|
|
|
7842
8301
|
if (decision.kind !== "done") return state;
|
|
7843
8302
|
return writeManagedGoalToState({ ...state, state: "done" }, managed);
|
|
7844
8303
|
}
|
|
7845
|
-
function
|
|
7846
|
-
const
|
|
7847
|
-
|
|
7848
|
-
|
|
8304
|
+
function snapshotFromState(goalId, state) {
|
|
8305
|
+
const managed = managedGoalFromState(state);
|
|
8306
|
+
return managed ? goalRunLogSnapshot(goalId, state.state, managed) : null;
|
|
8307
|
+
}
|
|
8308
|
+
function responsibilityEvidenceOutput(evidence) {
|
|
8309
|
+
return {
|
|
8310
|
+
kind: "responsibility-evidence",
|
|
8311
|
+
sources: evidence.sources,
|
|
8312
|
+
status: evidence.status,
|
|
8313
|
+
summary: evidence.summary,
|
|
8314
|
+
evidence: evidence.evidence ?? {},
|
|
8315
|
+
facts: evidence.facts,
|
|
8316
|
+
artifacts: evidence.artifacts,
|
|
8317
|
+
missingEvidence: evidence.missingEvidence,
|
|
8318
|
+
blockers: evidence.blockers
|
|
8319
|
+
};
|
|
8320
|
+
}
|
|
8321
|
+
function evidenceInspection(goalBefore, goalAfter, responsibilityOutput, explicitEvidence) {
|
|
8322
|
+
return {
|
|
8323
|
+
expectedEvidence: {
|
|
8324
|
+
required: goalBefore?.requiredEvidence,
|
|
8325
|
+
missingBefore: goalBefore?.missingEvidence,
|
|
8326
|
+
pendingBefore: goalBefore?.pendingEvidence,
|
|
8327
|
+
explicit: explicitEvidence
|
|
8328
|
+
},
|
|
8329
|
+
responsibilityOutput,
|
|
8330
|
+
actualGoalState: {
|
|
8331
|
+
satisfiedEvidence: goalAfter?.satisfiedEvidence,
|
|
8332
|
+
missingEvidence: goalAfter?.missingEvidence,
|
|
8333
|
+
pendingEvidence: goalAfter?.pendingEvidence,
|
|
8334
|
+
blockers: goalAfter?.blockers
|
|
8335
|
+
}
|
|
8336
|
+
};
|
|
8337
|
+
}
|
|
8338
|
+
function evidenceDecision(change, goalAfter, responsibilityOutput) {
|
|
8339
|
+
return {
|
|
8340
|
+
kind: change ? "accept-evidence" : "no-state-change",
|
|
8341
|
+
status: responsibilityOutput.status,
|
|
8342
|
+
nextStep: nextStepFromEvidence(goalAfter, responsibilityOutput),
|
|
8343
|
+
reason: responsibilityOutput.summary
|
|
8344
|
+
};
|
|
8345
|
+
}
|
|
8346
|
+
function nextStepFromEvidence(goalAfter, responsibilityOutput) {
|
|
8347
|
+
const status = typeof responsibilityOutput.status === "string" ? responsibilityOutput.status : "";
|
|
8348
|
+
const outputBlockers = stringArrayField(responsibilityOutput, "blockers");
|
|
8349
|
+
const goalBlockers = stringArrayField(goalAfter, "blockers");
|
|
8350
|
+
const missingEvidence = stringArrayField(goalAfter, "missingEvidence");
|
|
8351
|
+
if (goalAfter && missingEvidence.length === 0) return "done";
|
|
8352
|
+
if (status === "fail" || status === "blocked" || outputBlockers.length > 0) return "rescue";
|
|
8353
|
+
if (goalBlockers.length > 0) return "block";
|
|
8354
|
+
if (missingEvidence.length > 0 && status !== "noop") return "dispatch";
|
|
8355
|
+
return "wait";
|
|
8356
|
+
}
|
|
8357
|
+
function stringArrayField(record2, key) {
|
|
8358
|
+
const value = record2?.[key];
|
|
8359
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
8360
|
+
}
|
|
8361
|
+
function describeMessage(goalId, evidenceItems) {
|
|
8362
|
+
const pieces = evidenceItems.map((evidence) => `${evidence.sources.join("+")}:${evidence.status}`);
|
|
7849
8363
|
return `Apply agentResponsibility output to ${goalId}${pieces.length > 0 ? ` (${pieces.join("; ")})` : ""}`;
|
|
7850
8364
|
}
|
|
7851
8365
|
var applyAgentResponsibilityReports;
|
|
7852
8366
|
var init_applyAgentResponsibilityReports = __esm({
|
|
7853
8367
|
"src/scripts/applyAgentResponsibilityReports.ts"() {
|
|
7854
8368
|
"use strict";
|
|
8369
|
+
init_agent_responsibilityEvidence();
|
|
7855
8370
|
init_agent_responsibilityReport();
|
|
7856
8371
|
init_agent_responsibilityResult();
|
|
7857
8372
|
init_manager();
|
|
@@ -7862,65 +8377,86 @@ var init_applyAgentResponsibilityReports = __esm({
|
|
|
7862
8377
|
const reports = collectReports(ctx.data.agentResponsibilityReports, agentResult);
|
|
7863
8378
|
const results = collectResults(ctx.data.dutyResults, agentResult);
|
|
7864
8379
|
const resultGoalId = typeof ctx.args.goal === "string" && ctx.args.goal.length > 0 ? ctx.args.goal : null;
|
|
7865
|
-
|
|
7866
|
-
const
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
for (const goalId of
|
|
8380
|
+
const explicitEvidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
|
|
8381
|
+
const evidenceItems = collectGoalResponsibilityEvidence(reports, results, resultGoalId, explicitEvidence);
|
|
8382
|
+
if (evidenceItems.length === 0) return;
|
|
8383
|
+
const evidenceByGoal = groupGoalEvidence(evidenceItems);
|
|
8384
|
+
for (const [goalId, goalEvidence] of evidenceByGoal) {
|
|
7870
8385
|
const prior = fetchGoalState(ctx.config, goalId, ctx.cwd);
|
|
7871
8386
|
if (!prior) {
|
|
8387
|
+
stageGoalRunLogEvent(ctx.data, goalId, {
|
|
8388
|
+
source: "goal-loop",
|
|
8389
|
+
event: "goal.evidence.rejected",
|
|
8390
|
+
status: "rejected",
|
|
8391
|
+
reason: "goal missing in state repo",
|
|
8392
|
+
inspection: {
|
|
8393
|
+
responsibilityOutput: {
|
|
8394
|
+
kind: "responsibility-evidence",
|
|
8395
|
+
count: goalEvidence.length,
|
|
8396
|
+
items: goalEvidence.map(responsibilityEvidenceOutput)
|
|
8397
|
+
},
|
|
8398
|
+
missingEvidence: [],
|
|
8399
|
+
blockers: ["goal missing in state repo"]
|
|
8400
|
+
},
|
|
8401
|
+
decision: { kind: "reject-evidence", nextStep: "block", reason: "goal missing in state repo" }
|
|
8402
|
+
});
|
|
8403
|
+
flushLogs(ctx);
|
|
7872
8404
|
process.stderr.write(`[kody agentResponsibility-report] goal ${goalId} missing in state repo; report skipped
|
|
7873
8405
|
`);
|
|
7874
8406
|
continue;
|
|
7875
8407
|
}
|
|
7876
8408
|
let next = prior;
|
|
7877
|
-
for (const
|
|
8409
|
+
for (const evidence of goalEvidence) {
|
|
8410
|
+
const beforeSnapshot = snapshotFromState(goalId, next);
|
|
8411
|
+
next = applyAgentResponsibilityEvidenceToGoalState(next, evidence);
|
|
8412
|
+
const afterSnapshot = snapshotFromState(goalId, next);
|
|
8413
|
+
const change = goalRunLogChange(beforeSnapshot, afterSnapshot);
|
|
8414
|
+
const output = responsibilityEvidenceOutput(evidence);
|
|
7878
8415
|
stageGoalRunLogEvent(ctx.data, goalId, {
|
|
7879
|
-
source: "goal-
|
|
7880
|
-
event: "goal.evidence.
|
|
7881
|
-
goalState:
|
|
7882
|
-
|
|
7883
|
-
|
|
8416
|
+
source: "goal-loop",
|
|
8417
|
+
event: change ? "goal.evidence.applied" : "goal.evidence.unchanged",
|
|
8418
|
+
goalState: next.state,
|
|
8419
|
+
evidence: evidence.explicitEvidence,
|
|
8420
|
+
evidenceValues: evidence.evidence,
|
|
8421
|
+
status: evidence.status,
|
|
8422
|
+
reason: evidence.summary,
|
|
8423
|
+
facts: evidence.facts,
|
|
8424
|
+
artifacts: evidence.artifacts,
|
|
8425
|
+
goal: afterSnapshot ?? void 0,
|
|
8426
|
+
inspection: evidenceInspection(beforeSnapshot, afterSnapshot, output, evidence.explicitEvidence),
|
|
8427
|
+
decision: {
|
|
8428
|
+
...evidenceDecision(change, afterSnapshot, output),
|
|
8429
|
+
evidence: evidence.explicitEvidence,
|
|
8430
|
+
evidenceValues: evidence.evidence
|
|
8431
|
+
},
|
|
8432
|
+
change
|
|
7884
8433
|
});
|
|
7885
|
-
next = applyAgentResponsibilityReportToGoalState(next, report);
|
|
7886
|
-
}
|
|
7887
|
-
if (goalId === resultGoalId) {
|
|
7888
|
-
const evidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
|
|
7889
|
-
for (const result of results) {
|
|
7890
|
-
stageGoalRunLogEvent(ctx.data, goalId, {
|
|
7891
|
-
source: "goal-report",
|
|
7892
|
-
event: "goal.result.applied",
|
|
7893
|
-
goalState: prior.state,
|
|
7894
|
-
evidence,
|
|
7895
|
-
status: result.status,
|
|
7896
|
-
reason: result.summary,
|
|
7897
|
-
facts: result.facts,
|
|
7898
|
-
artifacts: result.artifacts
|
|
7899
|
-
});
|
|
7900
|
-
next = applyAgentResponsibilityResultToObjectiveState(next, result, evidence);
|
|
7901
|
-
}
|
|
7902
8434
|
}
|
|
8435
|
+
const beforeCompletionSnapshot = snapshotFromState(goalId, next);
|
|
7903
8436
|
next = completeSatisfiedManagedGoal(next);
|
|
8437
|
+
const afterCompletionSnapshot = snapshotFromState(goalId, next);
|
|
7904
8438
|
if (prior.state !== "done" && next.state === "done") {
|
|
7905
8439
|
stageGoalRunLogEvent(ctx.data, goalId, {
|
|
7906
|
-
source: "goal-
|
|
7907
|
-
event: "goal.
|
|
8440
|
+
source: "goal-loop",
|
|
8441
|
+
event: "goal.decision.done",
|
|
7908
8442
|
goalState: "done",
|
|
7909
8443
|
status: "done",
|
|
7910
|
-
reason: "destination evidence satisfied"
|
|
8444
|
+
reason: "destination evidence satisfied",
|
|
8445
|
+
goal: afterCompletionSnapshot ?? void 0,
|
|
8446
|
+
inspection: {
|
|
8447
|
+
requiredEvidence: beforeCompletionSnapshot?.requiredEvidence,
|
|
8448
|
+
satisfiedEvidence: beforeCompletionSnapshot?.satisfiedEvidence,
|
|
8449
|
+
missingEvidence: beforeCompletionSnapshot?.missingEvidence
|
|
8450
|
+
},
|
|
8451
|
+
decision: { kind: "done", nextStep: "done", reason: "destination evidence satisfied" },
|
|
8452
|
+
change: goalRunLogChange(beforeCompletionSnapshot, afterCompletionSnapshot)
|
|
7911
8453
|
});
|
|
7912
8454
|
}
|
|
7913
8455
|
if (serializeGoalState(next) === serializeGoalState(prior)) {
|
|
7914
8456
|
flushLogs(ctx);
|
|
7915
8457
|
continue;
|
|
7916
8458
|
}
|
|
7917
|
-
putGoalState(
|
|
7918
|
-
ctx.config,
|
|
7919
|
-
goalId,
|
|
7920
|
-
{ ...next, updatedAt: nowIso() },
|
|
7921
|
-
describeMessage(goalId, reportsByGoal.get(goalId), results),
|
|
7922
|
-
ctx.cwd
|
|
7923
|
-
);
|
|
8459
|
+
putGoalState(ctx.config, goalId, { ...next, updatedAt: nowIso() }, describeMessage(goalId, goalEvidence), ctx.cwd);
|
|
7924
8460
|
flushLogs(ctx);
|
|
7925
8461
|
}
|
|
7926
8462
|
};
|
|
@@ -8093,7 +8629,7 @@ var init_classifyByLabel = __esm({
|
|
|
8093
8629
|
});
|
|
8094
8630
|
|
|
8095
8631
|
// src/scripts/commitAndPush.ts
|
|
8096
|
-
import * as
|
|
8632
|
+
import * as fs27 from "fs";
|
|
8097
8633
|
import * as path26 from "path";
|
|
8098
8634
|
function sentinelPathForStage(cwd, profileName) {
|
|
8099
8635
|
const runId = resolveRunId();
|
|
@@ -8115,9 +8651,9 @@ var init_commitAndPush = __esm({
|
|
|
8115
8651
|
}
|
|
8116
8652
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
8117
8653
|
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
8118
|
-
if (sentinel &&
|
|
8654
|
+
if (sentinel && fs27.existsSync(sentinel)) {
|
|
8119
8655
|
try {
|
|
8120
|
-
const replay = JSON.parse(
|
|
8656
|
+
const replay = JSON.parse(fs27.readFileSync(sentinel, "utf-8"));
|
|
8121
8657
|
ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
|
|
8122
8658
|
if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
|
|
8123
8659
|
if (typeof replay.hasCommitsAhead === "boolean") ctx.data.hasCommitsAhead = replay.hasCommitsAhead;
|
|
@@ -8170,8 +8706,8 @@ var init_commitAndPush = __esm({
|
|
|
8170
8706
|
const result = ctx.data.commitResult;
|
|
8171
8707
|
if (sentinel && result?.committed) {
|
|
8172
8708
|
try {
|
|
8173
|
-
|
|
8174
|
-
|
|
8709
|
+
fs27.mkdirSync(path26.dirname(sentinel), { recursive: true });
|
|
8710
|
+
fs27.writeFileSync(
|
|
8175
8711
|
sentinel,
|
|
8176
8712
|
JSON.stringify(
|
|
8177
8713
|
{
|
|
@@ -8243,7 +8779,7 @@ var init_commitGoalState = __esm({
|
|
|
8243
8779
|
});
|
|
8244
8780
|
|
|
8245
8781
|
// src/scripts/composePrompt.ts
|
|
8246
|
-
import * as
|
|
8782
|
+
import * as fs28 from "fs";
|
|
8247
8783
|
import * as path27 from "path";
|
|
8248
8784
|
function fenceUntrusted(value) {
|
|
8249
8785
|
if (value.trim().length === 0) return value;
|
|
@@ -8383,7 +8919,7 @@ var init_composePrompt = __esm({
|
|
|
8383
8919
|
break;
|
|
8384
8920
|
}
|
|
8385
8921
|
try {
|
|
8386
|
-
template =
|
|
8922
|
+
template = fs28.readFileSync(c, "utf-8");
|
|
8387
8923
|
templatePath = c;
|
|
8388
8924
|
break;
|
|
8389
8925
|
} catch (err) {
|
|
@@ -8394,7 +8930,7 @@ var init_composePrompt = __esm({
|
|
|
8394
8930
|
if (!templatePath) {
|
|
8395
8931
|
let dirState;
|
|
8396
8932
|
try {
|
|
8397
|
-
dirState = `dir contents: [${
|
|
8933
|
+
dirState = `dir contents: [${fs28.readdirSync(profile.dir).join(", ")}]`;
|
|
8398
8934
|
} catch (err) {
|
|
8399
8935
|
dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
|
|
8400
8936
|
}
|
|
@@ -8966,7 +9502,7 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
8966
9502
|
|
|
8967
9503
|
// src/scripts/diagMcp.ts
|
|
8968
9504
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
8969
|
-
import * as
|
|
9505
|
+
import * as fs29 from "fs";
|
|
8970
9506
|
import * as os6 from "os";
|
|
8971
9507
|
import * as path28 from "path";
|
|
8972
9508
|
var diagMcp;
|
|
@@ -8978,7 +9514,7 @@ var init_diagMcp = __esm({
|
|
|
8978
9514
|
const cacheDir = path28.join(home, ".cache", "ms-playwright");
|
|
8979
9515
|
let entries = [];
|
|
8980
9516
|
try {
|
|
8981
|
-
entries =
|
|
9517
|
+
entries = fs29.readdirSync(cacheDir);
|
|
8982
9518
|
} catch {
|
|
8983
9519
|
}
|
|
8984
9520
|
const hasChromium = entries.some((e) => e.startsWith("chromium"));
|
|
@@ -9006,13 +9542,13 @@ var init_diagMcp = __esm({
|
|
|
9006
9542
|
});
|
|
9007
9543
|
|
|
9008
9544
|
// src/scripts/frameworkDetectors.ts
|
|
9009
|
-
import * as
|
|
9545
|
+
import * as fs30 from "fs";
|
|
9010
9546
|
import * as path29 from "path";
|
|
9011
9547
|
function detectFrameworks(cwd) {
|
|
9012
9548
|
const out = [];
|
|
9013
9549
|
let deps = {};
|
|
9014
9550
|
try {
|
|
9015
|
-
const pkg = JSON.parse(
|
|
9551
|
+
const pkg = JSON.parse(fs30.readFileSync(path29.join(cwd, "package.json"), "utf-8"));
|
|
9016
9552
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
9017
9553
|
} catch {
|
|
9018
9554
|
return out;
|
|
@@ -9049,7 +9585,7 @@ function detectFrameworks(cwd) {
|
|
|
9049
9585
|
}
|
|
9050
9586
|
function findFile(cwd, candidates) {
|
|
9051
9587
|
for (const c of candidates) {
|
|
9052
|
-
if (
|
|
9588
|
+
if (fs30.existsSync(path29.join(cwd, c))) return c;
|
|
9053
9589
|
}
|
|
9054
9590
|
return null;
|
|
9055
9591
|
}
|
|
@@ -9057,17 +9593,17 @@ function discoverPayloadCollections(cwd) {
|
|
|
9057
9593
|
const out = [];
|
|
9058
9594
|
for (const dir of COLLECTION_DIRS) {
|
|
9059
9595
|
const full = path29.join(cwd, dir);
|
|
9060
|
-
if (!
|
|
9596
|
+
if (!fs30.existsSync(full)) continue;
|
|
9061
9597
|
let files;
|
|
9062
9598
|
try {
|
|
9063
|
-
files =
|
|
9599
|
+
files = fs30.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
9064
9600
|
} catch {
|
|
9065
9601
|
continue;
|
|
9066
9602
|
}
|
|
9067
9603
|
for (const file of files) {
|
|
9068
9604
|
try {
|
|
9069
9605
|
const filePath = path29.join(full, file);
|
|
9070
|
-
const content =
|
|
9606
|
+
const content = fs30.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
9071
9607
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
9072
9608
|
if (!slugMatch) continue;
|
|
9073
9609
|
const slug2 = slugMatch[1];
|
|
@@ -9095,10 +9631,10 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
9095
9631
|
const out = [];
|
|
9096
9632
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
9097
9633
|
const full = path29.join(cwd, dir);
|
|
9098
|
-
if (!
|
|
9634
|
+
if (!fs30.existsSync(full)) continue;
|
|
9099
9635
|
let entries;
|
|
9100
9636
|
try {
|
|
9101
|
-
entries =
|
|
9637
|
+
entries = fs30.readdirSync(full, { withFileTypes: true });
|
|
9102
9638
|
} catch {
|
|
9103
9639
|
continue;
|
|
9104
9640
|
}
|
|
@@ -9108,7 +9644,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
9108
9644
|
let filePath;
|
|
9109
9645
|
if (entry.isDirectory()) {
|
|
9110
9646
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
9111
|
-
(f) =>
|
|
9647
|
+
(f) => fs30.existsSync(path29.join(entryPath, f))
|
|
9112
9648
|
);
|
|
9113
9649
|
if (!indexFile) continue;
|
|
9114
9650
|
name = entry.name;
|
|
@@ -9123,7 +9659,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
9123
9659
|
if (collections) {
|
|
9124
9660
|
for (const col of collections) {
|
|
9125
9661
|
try {
|
|
9126
|
-
const colContent =
|
|
9662
|
+
const colContent = fs30.readFileSync(path29.join(cwd, col.filePath), "utf-8");
|
|
9127
9663
|
if (colContent.includes(name)) {
|
|
9128
9664
|
usedInCollection = col.slug;
|
|
9129
9665
|
break;
|
|
@@ -9142,7 +9678,7 @@ function scanApiRoutes(cwd) {
|
|
|
9142
9678
|
const appDirs = ["src/app", "app"];
|
|
9143
9679
|
for (const appDir of appDirs) {
|
|
9144
9680
|
const apiDir = path29.join(cwd, appDir, "api");
|
|
9145
|
-
if (!
|
|
9681
|
+
if (!fs30.existsSync(apiDir)) continue;
|
|
9146
9682
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
9147
9683
|
break;
|
|
9148
9684
|
}
|
|
@@ -9151,14 +9687,14 @@ function scanApiRoutes(cwd) {
|
|
|
9151
9687
|
function walkApiRoutes(dir, prefix, cwd, out) {
|
|
9152
9688
|
let entries;
|
|
9153
9689
|
try {
|
|
9154
|
-
entries =
|
|
9690
|
+
entries = fs30.readdirSync(dir, { withFileTypes: true });
|
|
9155
9691
|
} catch {
|
|
9156
9692
|
return;
|
|
9157
9693
|
}
|
|
9158
9694
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
9159
9695
|
if (routeFile) {
|
|
9160
9696
|
try {
|
|
9161
|
-
const content =
|
|
9697
|
+
const content = fs30.readFileSync(path29.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
9162
9698
|
const methods = HTTP_METHODS.filter(
|
|
9163
9699
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
9164
9700
|
);
|
|
@@ -9192,9 +9728,9 @@ function scanEnvVars(cwd) {
|
|
|
9192
9728
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
9193
9729
|
for (const envFile of candidates) {
|
|
9194
9730
|
const envPath = path29.join(cwd, envFile);
|
|
9195
|
-
if (!
|
|
9731
|
+
if (!fs30.existsSync(envPath)) continue;
|
|
9196
9732
|
try {
|
|
9197
|
-
const content =
|
|
9733
|
+
const content = fs30.readFileSync(envPath, "utf-8");
|
|
9198
9734
|
const vars = [];
|
|
9199
9735
|
for (const line of content.split("\n")) {
|
|
9200
9736
|
const trimmed = line.trim();
|
|
@@ -9239,7 +9775,7 @@ var init_frameworkDetectors = __esm({
|
|
|
9239
9775
|
});
|
|
9240
9776
|
|
|
9241
9777
|
// src/scripts/discoverQaContext.ts
|
|
9242
|
-
import * as
|
|
9778
|
+
import * as fs31 from "fs";
|
|
9243
9779
|
import * as path30 from "path";
|
|
9244
9780
|
function runQaDiscovery(cwd) {
|
|
9245
9781
|
const out = {
|
|
@@ -9271,9 +9807,9 @@ function runQaDiscovery(cwd) {
|
|
|
9271
9807
|
}
|
|
9272
9808
|
function detectDevServer(cwd, out) {
|
|
9273
9809
|
try {
|
|
9274
|
-
const pkg = JSON.parse(
|
|
9810
|
+
const pkg = JSON.parse(fs31.readFileSync(path30.join(cwd, "package.json"), "utf-8"));
|
|
9275
9811
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
9276
|
-
const pm =
|
|
9812
|
+
const pm = fs31.existsSync(path30.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs31.existsSync(path30.join(cwd, "yarn.lock")) ? "yarn" : fs31.existsSync(path30.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
9277
9813
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
9278
9814
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
9279
9815
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -9284,7 +9820,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
9284
9820
|
const appDirs = ["src/app", "app"];
|
|
9285
9821
|
for (const appDir of appDirs) {
|
|
9286
9822
|
const full = path30.join(cwd, appDir);
|
|
9287
|
-
if (!
|
|
9823
|
+
if (!fs31.existsSync(full)) continue;
|
|
9288
9824
|
walkFrontendRoutes(full, "", out);
|
|
9289
9825
|
break;
|
|
9290
9826
|
}
|
|
@@ -9292,7 +9828,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
9292
9828
|
function walkFrontendRoutes(dir, prefix, out) {
|
|
9293
9829
|
let entries;
|
|
9294
9830
|
try {
|
|
9295
|
-
entries =
|
|
9831
|
+
entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
9296
9832
|
} catch {
|
|
9297
9833
|
return;
|
|
9298
9834
|
}
|
|
@@ -9334,23 +9870,23 @@ function detectAuthFiles(cwd, out) {
|
|
|
9334
9870
|
"src/app/api/oauth"
|
|
9335
9871
|
];
|
|
9336
9872
|
for (const c of candidates) {
|
|
9337
|
-
if (
|
|
9873
|
+
if (fs31.existsSync(path30.join(cwd, c))) out.authFiles.push(c);
|
|
9338
9874
|
}
|
|
9339
9875
|
}
|
|
9340
9876
|
function detectRoles(cwd, out) {
|
|
9341
9877
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
9342
9878
|
for (const rp of rolePaths) {
|
|
9343
9879
|
const dir = path30.join(cwd, rp);
|
|
9344
|
-
if (!
|
|
9880
|
+
if (!fs31.existsSync(dir)) continue;
|
|
9345
9881
|
let files;
|
|
9346
9882
|
try {
|
|
9347
|
-
files =
|
|
9883
|
+
files = fs31.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
9348
9884
|
} catch {
|
|
9349
9885
|
continue;
|
|
9350
9886
|
}
|
|
9351
9887
|
for (const f of files) {
|
|
9352
9888
|
try {
|
|
9353
|
-
const content =
|
|
9889
|
+
const content = fs31.readFileSync(path30.join(dir, f), "utf-8").slice(0, 5e3);
|
|
9354
9890
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
9355
9891
|
if (roleMatches) {
|
|
9356
9892
|
for (const m of roleMatches) {
|
|
@@ -10564,12 +11100,12 @@ var init_fixFlow = __esm({
|
|
|
10564
11100
|
|
|
10565
11101
|
// src/scripts/initFlow.ts
|
|
10566
11102
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
10567
|
-
import * as
|
|
11103
|
+
import * as fs32 from "fs";
|
|
10568
11104
|
import * as path31 from "path";
|
|
10569
11105
|
function detectPackageManager(cwd) {
|
|
10570
|
-
if (
|
|
10571
|
-
if (
|
|
10572
|
-
if (
|
|
11106
|
+
if (fs32.existsSync(path31.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
11107
|
+
if (fs32.existsSync(path31.join(cwd, "yarn.lock"))) return "yarn";
|
|
11108
|
+
if (fs32.existsSync(path31.join(cwd, "bun.lockb"))) return "bun";
|
|
10573
11109
|
return "npm";
|
|
10574
11110
|
}
|
|
10575
11111
|
function qualityCommandsFor(pm) {
|
|
@@ -10642,21 +11178,21 @@ function performInit(cwd, force) {
|
|
|
10642
11178
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
10643
11179
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
10644
11180
|
const configPath = path31.join(cwd, "kody.config.json");
|
|
10645
|
-
if (
|
|
11181
|
+
if (fs32.existsSync(configPath) && !force) {
|
|
10646
11182
|
skipped.push("kody.config.json");
|
|
10647
11183
|
} else {
|
|
10648
11184
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
10649
|
-
|
|
11185
|
+
fs32.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
10650
11186
|
`);
|
|
10651
11187
|
wrote.push("kody.config.json");
|
|
10652
11188
|
}
|
|
10653
11189
|
const workflowDir = path31.join(cwd, ".github", "workflows");
|
|
10654
11190
|
const workflowPath = path31.join(workflowDir, "kody.yml");
|
|
10655
|
-
if (
|
|
11191
|
+
if (fs32.existsSync(workflowPath) && !force) {
|
|
10656
11192
|
skipped.push(".github/workflows/kody.yml");
|
|
10657
11193
|
} else {
|
|
10658
|
-
|
|
10659
|
-
|
|
11194
|
+
fs32.mkdirSync(workflowDir, { recursive: true });
|
|
11195
|
+
fs32.writeFileSync(workflowPath, WORKFLOW_TEMPLATE);
|
|
10660
11196
|
wrote.push(".github/workflows/kody.yml");
|
|
10661
11197
|
}
|
|
10662
11198
|
for (const exe of listAgentActions()) {
|
|
@@ -10668,11 +11204,11 @@ function performInit(cwd, force) {
|
|
|
10668
11204
|
}
|
|
10669
11205
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
10670
11206
|
const target = path31.join(workflowDir, `kody-${exe.name}.yml`);
|
|
10671
|
-
if (
|
|
11207
|
+
if (fs32.existsSync(target) && !force) {
|
|
10672
11208
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
10673
11209
|
continue;
|
|
10674
11210
|
}
|
|
10675
|
-
|
|
11211
|
+
fs32.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
10676
11212
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
10677
11213
|
}
|
|
10678
11214
|
let labels;
|
|
@@ -10825,7 +11361,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
10825
11361
|
});
|
|
10826
11362
|
|
|
10827
11363
|
// src/scripts/loadAgentAdhoc.ts
|
|
10828
|
-
import * as
|
|
11364
|
+
import * as fs33 from "fs";
|
|
10829
11365
|
function resolveMessage(messageArg) {
|
|
10830
11366
|
const fromComment = readCommentBody();
|
|
10831
11367
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -10833,9 +11369,9 @@ function resolveMessage(messageArg) {
|
|
|
10833
11369
|
}
|
|
10834
11370
|
function readCommentBody() {
|
|
10835
11371
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
10836
|
-
if (!eventPath || !
|
|
11372
|
+
if (!eventPath || !fs33.existsSync(eventPath)) return "";
|
|
10837
11373
|
try {
|
|
10838
|
-
const event = JSON.parse(
|
|
11374
|
+
const event = JSON.parse(fs33.readFileSync(eventPath, "utf-8"));
|
|
10839
11375
|
return String(event.comment?.body ?? "");
|
|
10840
11376
|
} catch {
|
|
10841
11377
|
return "";
|
|
@@ -10888,10 +11424,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
10888
11424
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
10889
11425
|
}
|
|
10890
11426
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
10891
|
-
if (!
|
|
11427
|
+
if (!fs33.existsSync(agentPath)) {
|
|
10892
11428
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
10893
11429
|
}
|
|
10894
|
-
const { title, body } = parseAgentFile(
|
|
11430
|
+
const { title, body } = parseAgentFile(fs33.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
10895
11431
|
const message = resolveMessage(ctx.args.message);
|
|
10896
11432
|
if (!message) {
|
|
10897
11433
|
throw new Error(
|
|
@@ -11129,7 +11665,7 @@ var init_loadIssueStateComment = __esm({
|
|
|
11129
11665
|
});
|
|
11130
11666
|
|
|
11131
11667
|
// src/scripts/loadJobFromFile.ts
|
|
11132
|
-
import * as
|
|
11668
|
+
import * as fs34 from "fs";
|
|
11133
11669
|
import * as path32 from "path";
|
|
11134
11670
|
function parseJobFile(raw, slug2) {
|
|
11135
11671
|
let stripped = raw;
|
|
@@ -11181,12 +11717,12 @@ var init_loadJobFromFile = __esm({
|
|
|
11181
11717
|
let agentIdentity = "";
|
|
11182
11718
|
if (agentSlug) {
|
|
11183
11719
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
11184
|
-
if (!
|
|
11720
|
+
if (!fs34.existsSync(agentPath)) {
|
|
11185
11721
|
throw new Error(
|
|
11186
11722
|
`loadJobFromFile: agentResponsibility '${slug2}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
11187
11723
|
);
|
|
11188
11724
|
}
|
|
11189
|
-
const agentRaw =
|
|
11725
|
+
const agentRaw = fs34.readFileSync(agentPath, "utf-8");
|
|
11190
11726
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
11191
11727
|
agentTitle = parsed.title;
|
|
11192
11728
|
agentIdentity = parsed.body;
|
|
@@ -11260,13 +11796,13 @@ ${truncate(issue.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
11260
11796
|
});
|
|
11261
11797
|
|
|
11262
11798
|
// src/scripts/kodyVariables.ts
|
|
11263
|
-
import * as
|
|
11799
|
+
import * as fs35 from "fs";
|
|
11264
11800
|
import * as path33 from "path";
|
|
11265
11801
|
function readKodyVariables(cwd) {
|
|
11266
11802
|
const full = path33.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
11267
11803
|
let raw;
|
|
11268
11804
|
try {
|
|
11269
|
-
raw =
|
|
11805
|
+
raw = fs35.readFileSync(full, "utf-8");
|
|
11270
11806
|
} catch {
|
|
11271
11807
|
return {};
|
|
11272
11808
|
}
|
|
@@ -11291,7 +11827,7 @@ var init_kodyVariables = __esm({
|
|
|
11291
11827
|
});
|
|
11292
11828
|
|
|
11293
11829
|
// src/scripts/loadQaContext.ts
|
|
11294
|
-
import * as
|
|
11830
|
+
import * as fs36 from "fs";
|
|
11295
11831
|
import * as path34 from "path";
|
|
11296
11832
|
function parseSlugList(value) {
|
|
11297
11833
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
@@ -11322,17 +11858,17 @@ function readProfileAgents(raw) {
|
|
|
11322
11858
|
}
|
|
11323
11859
|
function readProfile(cwd) {
|
|
11324
11860
|
const dir = path34.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
11325
|
-
if (!
|
|
11861
|
+
if (!fs36.existsSync(dir)) return "";
|
|
11326
11862
|
let entries;
|
|
11327
11863
|
try {
|
|
11328
|
-
entries =
|
|
11864
|
+
entries = fs36.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
11329
11865
|
} catch {
|
|
11330
11866
|
return "";
|
|
11331
11867
|
}
|
|
11332
11868
|
const blocks = [];
|
|
11333
11869
|
for (const file of entries) {
|
|
11334
11870
|
try {
|
|
11335
|
-
const raw =
|
|
11871
|
+
const raw = fs36.readFileSync(path34.join(dir, file), "utf-8");
|
|
11336
11872
|
const { agent, body } = readProfileAgents(raw);
|
|
11337
11873
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
11338
11874
|
blocks.push(`## ${file}
|
|
@@ -11378,7 +11914,7 @@ var init_loadQaContext = __esm({
|
|
|
11378
11914
|
});
|
|
11379
11915
|
|
|
11380
11916
|
// src/taskContext.ts
|
|
11381
|
-
import * as
|
|
11917
|
+
import * as fs37 from "fs";
|
|
11382
11918
|
import * as path35 from "path";
|
|
11383
11919
|
function buildTaskContext(args) {
|
|
11384
11920
|
return {
|
|
@@ -11395,9 +11931,9 @@ function buildTaskContext(args) {
|
|
|
11395
11931
|
function persistTaskContext(cwd, ctx) {
|
|
11396
11932
|
try {
|
|
11397
11933
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
11398
|
-
|
|
11934
|
+
fs37.mkdirSync(dir, { recursive: true });
|
|
11399
11935
|
const file = path35.join(dir, "task-context.json");
|
|
11400
|
-
|
|
11936
|
+
fs37.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
11401
11937
|
`);
|
|
11402
11938
|
return file;
|
|
11403
11939
|
} catch (err) {
|
|
@@ -13742,9 +14278,9 @@ fi
|
|
|
13742
14278
|
});
|
|
13743
14279
|
|
|
13744
14280
|
// src/stateRepoGithub.ts
|
|
13745
|
-
import * as
|
|
14281
|
+
import * as fs38 from "fs";
|
|
13746
14282
|
import * as path36 from "path";
|
|
13747
|
-
function
|
|
14283
|
+
function recordValue3(value) {
|
|
13748
14284
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
13749
14285
|
}
|
|
13750
14286
|
function contentsUrl(owner, repo, filePath) {
|
|
@@ -13800,12 +14336,12 @@ async function loadGithubStateConfig(opts) {
|
|
|
13800
14336
|
throw new Error(`kody.config.json is invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
13801
14337
|
}
|
|
13802
14338
|
}
|
|
13803
|
-
const githubRaw =
|
|
14339
|
+
const githubRaw = recordValue3(raw.github) ?? {};
|
|
13804
14340
|
const github = {
|
|
13805
14341
|
owner: typeof githubRaw.owner === "string" && githubRaw.owner.trim() ? githubRaw.owner.trim() : opts.owner,
|
|
13806
14342
|
repo: typeof githubRaw.repo === "string" && githubRaw.repo.trim() ? githubRaw.repo.trim() : opts.repo
|
|
13807
14343
|
};
|
|
13808
|
-
const nestedState =
|
|
14344
|
+
const nestedState = recordValue3(raw.state) ?? {};
|
|
13809
14345
|
const repoRaw = typeof raw.stateRepo === "string" ? raw.stateRepo : nestedState.repo;
|
|
13810
14346
|
const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nestedState.path;
|
|
13811
14347
|
const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${github.owner}/kody-state`;
|
|
@@ -13883,15 +14419,15 @@ function mergeJsonl(localText, remoteText) {
|
|
|
13883
14419
|
async function syncJsonlFileFromGithubState(opts) {
|
|
13884
14420
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
13885
14421
|
if (!remote) return;
|
|
13886
|
-
const local =
|
|
14422
|
+
const local = fs38.existsSync(opts.localPath) ? fs38.readFileSync(opts.localPath, "utf-8") : "";
|
|
13887
14423
|
const next = mergeJsonl(local, remote.content);
|
|
13888
14424
|
if (next === local) return;
|
|
13889
|
-
|
|
13890
|
-
|
|
14425
|
+
fs38.mkdirSync(path36.dirname(opts.localPath), { recursive: true });
|
|
14426
|
+
fs38.writeFileSync(opts.localPath, next);
|
|
13891
14427
|
}
|
|
13892
14428
|
async function persistJsonlFileToGithubState(opts) {
|
|
13893
|
-
if (!
|
|
13894
|
-
const localText =
|
|
14429
|
+
if (!fs38.existsSync(opts.localPath)) return;
|
|
14430
|
+
const localText = fs38.readFileSync(opts.localPath, "utf-8");
|
|
13895
14431
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
13896
14432
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
13897
14433
|
const body = mergeJsonl(localText, remote?.content ?? "");
|
|
@@ -14368,7 +14904,7 @@ var init_tickShellRunner = __esm({
|
|
|
14368
14904
|
});
|
|
14369
14905
|
|
|
14370
14906
|
// src/scripts/runScheduledAgentActionTick.ts
|
|
14371
|
-
import * as
|
|
14907
|
+
import * as fs39 from "fs";
|
|
14372
14908
|
import * as path38 from "path";
|
|
14373
14909
|
var runScheduledAgentActionTick;
|
|
14374
14910
|
var init_runScheduledAgentActionTick = __esm({
|
|
@@ -14396,7 +14932,7 @@ var init_runScheduledAgentActionTick = __esm({
|
|
|
14396
14932
|
return;
|
|
14397
14933
|
}
|
|
14398
14934
|
const shellPath = path38.join(profile.dir, shell);
|
|
14399
|
-
if (!
|
|
14935
|
+
if (!fs39.existsSync(shellPath)) {
|
|
14400
14936
|
ctx.output.exitCode = 99;
|
|
14401
14937
|
ctx.output.reason = `runScheduledAgentActionTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
14402
14938
|
return;
|
|
@@ -14427,7 +14963,7 @@ var init_runScheduledAgentActionTick = __esm({
|
|
|
14427
14963
|
});
|
|
14428
14964
|
|
|
14429
14965
|
// src/scripts/runTickScript.ts
|
|
14430
|
-
import * as
|
|
14966
|
+
import * as fs40 from "fs";
|
|
14431
14967
|
import * as path39 from "path";
|
|
14432
14968
|
var runTickScript;
|
|
14433
14969
|
var init_runTickScript = __esm({
|
|
@@ -14460,7 +14996,7 @@ var init_runTickScript = __esm({
|
|
|
14460
14996
|
return;
|
|
14461
14997
|
}
|
|
14462
14998
|
const scriptPath = path39.isAbsolute(tickScript) ? tickScript : path39.join(ctx.cwd, tickScript);
|
|
14463
|
-
if (!
|
|
14999
|
+
if (!fs40.existsSync(scriptPath)) {
|
|
14464
15000
|
ctx.output.exitCode = 99;
|
|
14465
15001
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
14466
15002
|
return;
|
|
@@ -15282,7 +15818,7 @@ var init_warmupMcp = __esm({
|
|
|
15282
15818
|
});
|
|
15283
15819
|
|
|
15284
15820
|
// src/scripts/writeAgentRunSummary.ts
|
|
15285
|
-
import * as
|
|
15821
|
+
import * as fs41 from "fs";
|
|
15286
15822
|
var writeAgentRunSummary;
|
|
15287
15823
|
var init_writeAgentRunSummary = __esm({
|
|
15288
15824
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -15308,7 +15844,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
15308
15844
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
15309
15845
|
lines.push("");
|
|
15310
15846
|
try {
|
|
15311
|
-
|
|
15847
|
+
fs41.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
15312
15848
|
`);
|
|
15313
15849
|
} catch {
|
|
15314
15850
|
}
|
|
@@ -15710,17 +16246,17 @@ var init_scripts = __esm({
|
|
|
15710
16246
|
});
|
|
15711
16247
|
|
|
15712
16248
|
// src/stateWorkspace.ts
|
|
15713
|
-
import * as
|
|
16249
|
+
import * as fs42 from "fs";
|
|
15714
16250
|
import * as path40 from "path";
|
|
15715
16251
|
function writeLocalFile(cwd, relativePath, content) {
|
|
15716
16252
|
const fullPath = path40.join(cwd, relativePath);
|
|
15717
|
-
|
|
15718
|
-
|
|
16253
|
+
fs42.mkdirSync(path40.dirname(fullPath), { recursive: true });
|
|
16254
|
+
fs42.writeFileSync(fullPath, content);
|
|
15719
16255
|
}
|
|
15720
16256
|
function hydrateDirectory(config, cwd, stateDir, localDir) {
|
|
15721
16257
|
const entries = listStateDirectory(config, cwd, stateDir);
|
|
15722
16258
|
if (entries.length === 0) return;
|
|
15723
|
-
|
|
16259
|
+
fs42.rmSync(path40.join(cwd, localDir), { recursive: true, force: true });
|
|
15724
16260
|
for (const entry of entries) {
|
|
15725
16261
|
if (!entry.name || !entry.type) continue;
|
|
15726
16262
|
const childState = path40.posix.join(stateDir, entry.name);
|
|
@@ -15828,7 +16364,7 @@ var init_tools = __esm({
|
|
|
15828
16364
|
|
|
15829
16365
|
// src/executor.ts
|
|
15830
16366
|
import { spawn as spawn7 } from "child_process";
|
|
15831
|
-
import * as
|
|
16367
|
+
import * as fs43 from "fs";
|
|
15832
16368
|
import * as path41 from "path";
|
|
15833
16369
|
function isMutatingPostflight(scriptName) {
|
|
15834
16370
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
@@ -16405,7 +16941,7 @@ function resolveProfilePath(profileName) {
|
|
|
16405
16941
|
// fallback
|
|
16406
16942
|
];
|
|
16407
16943
|
for (const c of candidates) {
|
|
16408
|
-
if (
|
|
16944
|
+
if (fs43.existsSync(c)) return c;
|
|
16409
16945
|
}
|
|
16410
16946
|
return candidates[0];
|
|
16411
16947
|
}
|
|
@@ -16504,7 +17040,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
16504
17040
|
async function runShellEntry(entry, ctx, profile) {
|
|
16505
17041
|
const shellName = entry.shell;
|
|
16506
17042
|
const shellPath = path41.join(profile.dir, shellName);
|
|
16507
|
-
if (!
|
|
17043
|
+
if (!fs43.existsSync(shellPath)) {
|
|
16508
17044
|
ctx.skipAgent = true;
|
|
16509
17045
|
ctx.output.exitCode = 99;
|
|
16510
17046
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -16916,7 +17452,7 @@ function translateOpenAISseToBrain(opts) {
|
|
|
16916
17452
|
}
|
|
16917
17453
|
|
|
16918
17454
|
// src/servers/brain-serve.ts
|
|
16919
|
-
import * as
|
|
17455
|
+
import * as fs46 from "fs";
|
|
16920
17456
|
import { createServer } from "http";
|
|
16921
17457
|
import * as path45 from "path";
|
|
16922
17458
|
|
|
@@ -17478,7 +18014,7 @@ init_config();
|
|
|
17478
18014
|
|
|
17479
18015
|
// src/kody-cli.ts
|
|
17480
18016
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
17481
|
-
import * as
|
|
18017
|
+
import * as fs44 from "fs";
|
|
17482
18018
|
import * as path43 from "path";
|
|
17483
18019
|
|
|
17484
18020
|
// src/app-auth.ts
|
|
@@ -18100,9 +18636,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
18100
18636
|
return void 0;
|
|
18101
18637
|
}
|
|
18102
18638
|
function detectPackageManager2(cwd) {
|
|
18103
|
-
if (
|
|
18104
|
-
if (
|
|
18105
|
-
if (
|
|
18639
|
+
if (fs44.existsSync(path43.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
18640
|
+
if (fs44.existsSync(path43.join(cwd, "yarn.lock"))) return "yarn";
|
|
18641
|
+
if (fs44.existsSync(path43.join(cwd, "bun.lockb"))) return "bun";
|
|
18106
18642
|
return "npm";
|
|
18107
18643
|
}
|
|
18108
18644
|
function shouldChainScheduledWatch(match) {
|
|
@@ -18195,8 +18731,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
18195
18731
|
const logPath = lastRunLogPath(cwd);
|
|
18196
18732
|
let tail = "";
|
|
18197
18733
|
try {
|
|
18198
|
-
if (
|
|
18199
|
-
const content =
|
|
18734
|
+
if (fs44.existsSync(logPath)) {
|
|
18735
|
+
const content = fs44.readFileSync(logPath, "utf-8");
|
|
18200
18736
|
tail = content.slice(-3e3);
|
|
18201
18737
|
}
|
|
18202
18738
|
} catch {
|
|
@@ -18236,9 +18772,9 @@ async function runCi(argv) {
|
|
|
18236
18772
|
let manualWorkflowDispatch = false;
|
|
18237
18773
|
let forceRunAction = null;
|
|
18238
18774
|
let forceRunCliArgs = {};
|
|
18239
|
-
if (!args.issueNumber && !autoFallback && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
18775
|
+
if (!args.issueNumber && !autoFallback && eventName === "workflow_dispatch" && dispatchEventPath && fs44.existsSync(dispatchEventPath)) {
|
|
18240
18776
|
try {
|
|
18241
|
-
const evt = JSON.parse(
|
|
18777
|
+
const evt = JSON.parse(fs44.readFileSync(dispatchEventPath, "utf-8"));
|
|
18242
18778
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
18243
18779
|
const sessionInput = String(evt?.inputs?.sessionId ?? "");
|
|
18244
18780
|
const dutyInput = String(evt?.inputs?.agentResponsibility ?? evt?.inputs?.agentAction ?? "").trim();
|
|
@@ -18570,7 +19106,7 @@ init_repoWorkspace();
|
|
|
18570
19106
|
|
|
18571
19107
|
// src/scripts/brainTurnLog.ts
|
|
18572
19108
|
init_runtimePaths();
|
|
18573
|
-
import * as
|
|
19109
|
+
import * as fs45 from "fs";
|
|
18574
19110
|
import * as path44 from "path";
|
|
18575
19111
|
import posixPath4 from "path/posix";
|
|
18576
19112
|
var live = /* @__PURE__ */ new Map();
|
|
@@ -18582,8 +19118,8 @@ function brainEventsStatePath(chatId) {
|
|
|
18582
19118
|
}
|
|
18583
19119
|
function lastPersistedSeq(dir, chatId) {
|
|
18584
19120
|
const p = brainEventsFilePath(dir, chatId);
|
|
18585
|
-
if (!
|
|
18586
|
-
const lines =
|
|
19121
|
+
if (!fs45.existsSync(p)) return 0;
|
|
19122
|
+
const lines = fs45.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
18587
19123
|
if (lines.length === 0) return 0;
|
|
18588
19124
|
try {
|
|
18589
19125
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -18593,9 +19129,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
18593
19129
|
}
|
|
18594
19130
|
function readSince(dir, chatId, since) {
|
|
18595
19131
|
const p = brainEventsFilePath(dir, chatId);
|
|
18596
|
-
if (!
|
|
19132
|
+
if (!fs45.existsSync(p)) return [];
|
|
18597
19133
|
const out = [];
|
|
18598
|
-
for (const line of
|
|
19134
|
+
for (const line of fs45.readFileSync(p, "utf-8").split("\n")) {
|
|
18599
19135
|
if (!line) continue;
|
|
18600
19136
|
try {
|
|
18601
19137
|
const rec = JSON.parse(line);
|
|
@@ -18621,12 +19157,12 @@ function beginTurn(dir, chatId) {
|
|
|
18621
19157
|
};
|
|
18622
19158
|
live.set(chatId, state);
|
|
18623
19159
|
const p = brainEventsFilePath(dir, chatId);
|
|
18624
|
-
|
|
19160
|
+
fs45.mkdirSync(path44.dirname(p), { recursive: true });
|
|
18625
19161
|
return (event) => {
|
|
18626
19162
|
state.seq += 1;
|
|
18627
19163
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
18628
19164
|
try {
|
|
18629
|
-
|
|
19165
|
+
fs45.appendFileSync(p, `${JSON.stringify(rec)}
|
|
18630
19166
|
`);
|
|
18631
19167
|
} catch (err) {
|
|
18632
19168
|
process.stderr.write(
|
|
@@ -18665,7 +19201,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
18665
19201
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
18666
19202
|
};
|
|
18667
19203
|
try {
|
|
18668
|
-
|
|
19204
|
+
fs45.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
18669
19205
|
`);
|
|
18670
19206
|
} catch {
|
|
18671
19207
|
}
|
|
@@ -18971,7 +19507,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
18971
19507
|
);
|
|
18972
19508
|
}
|
|
18973
19509
|
}
|
|
18974
|
-
|
|
19510
|
+
fs46.mkdirSync(path45.dirname(sessionFile), { recursive: true });
|
|
18975
19511
|
appendTurn(sessionFile, {
|
|
18976
19512
|
role: "user",
|
|
18977
19513
|
content: message,
|
|
@@ -19631,7 +20167,7 @@ async function loadConfigSafe() {
|
|
|
19631
20167
|
}
|
|
19632
20168
|
|
|
19633
20169
|
// src/chat-cli.ts
|
|
19634
|
-
import * as
|
|
20170
|
+
import * as fs48 from "fs";
|
|
19635
20171
|
import * as path47 from "path";
|
|
19636
20172
|
|
|
19637
20173
|
// src/chat/inbox.ts
|
|
@@ -19704,7 +20240,7 @@ function currentBranch(cwd) {
|
|
|
19704
20240
|
|
|
19705
20241
|
// src/chat/state-sync.ts
|
|
19706
20242
|
init_stateRepo();
|
|
19707
|
-
import * as
|
|
20243
|
+
import * as fs47 from "fs";
|
|
19708
20244
|
import * as path46 from "path";
|
|
19709
20245
|
function jsonlLines2(text) {
|
|
19710
20246
|
return text.split("\n").filter((line) => line.length > 0);
|
|
@@ -19722,15 +20258,15 @@ function mergeJsonl2(localText, remoteText) {
|
|
|
19722
20258
|
function syncJsonlFileFromState(opts) {
|
|
19723
20259
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
19724
20260
|
if (!remote) return;
|
|
19725
|
-
const local =
|
|
20261
|
+
const local = fs47.existsSync(opts.localPath) ? fs47.readFileSync(opts.localPath, "utf-8") : "";
|
|
19726
20262
|
const next = mergeJsonl2(local, remote.content);
|
|
19727
20263
|
if (next === local) return;
|
|
19728
|
-
|
|
19729
|
-
|
|
20264
|
+
fs47.mkdirSync(path46.dirname(opts.localPath), { recursive: true });
|
|
20265
|
+
fs47.writeFileSync(opts.localPath, next);
|
|
19730
20266
|
}
|
|
19731
20267
|
function persistJsonlFileToState(opts) {
|
|
19732
|
-
if (!
|
|
19733
|
-
const localText =
|
|
20268
|
+
if (!fs47.existsSync(opts.localPath)) return;
|
|
20269
|
+
const localText = fs47.readFileSync(opts.localPath, "utf-8");
|
|
19734
20270
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
19735
20271
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
19736
20272
|
const body = mergeJsonl2(localText, remote?.content ?? "");
|
|
@@ -20051,7 +20587,7 @@ ${CHAT_HELP}`);
|
|
|
20051
20587
|
const sink = buildSink(cwd, sessionId, args.dashboardUrl);
|
|
20052
20588
|
const meta = readMeta(sessionFile);
|
|
20053
20589
|
process.stdout.write(
|
|
20054
|
-
`\u2192 kody:chat: session file=${sessionFile} exists=${
|
|
20590
|
+
`\u2192 kody:chat: session file=${sessionFile} exists=${fs48.existsSync(sessionFile)} meta=${meta ? meta.mode : "none"}
|
|
20055
20591
|
`
|
|
20056
20592
|
);
|
|
20057
20593
|
try {
|
|
@@ -20938,7 +21474,7 @@ async function poolServe() {
|
|
|
20938
21474
|
|
|
20939
21475
|
// src/servers/runner-serve.ts
|
|
20940
21476
|
import { spawn as spawn8 } from "child_process";
|
|
20941
|
-
import * as
|
|
21477
|
+
import * as fs49 from "fs";
|
|
20942
21478
|
import { createServer as createServer5 } from "http";
|
|
20943
21479
|
var DEFAULT_PORT2 = 8080;
|
|
20944
21480
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -21018,8 +21554,8 @@ async function defaultRunJob(job) {
|
|
|
21018
21554
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
21019
21555
|
const branch = job.ref ?? "main";
|
|
21020
21556
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
21021
|
-
|
|
21022
|
-
|
|
21557
|
+
fs49.rmSync(workdir, { recursive: true, force: true });
|
|
21558
|
+
fs49.mkdirSync(workdir, { recursive: true });
|
|
21023
21559
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
21024
21560
|
const interactive = job.mode === "interactive";
|
|
21025
21561
|
const scheduled = job.mode === "scheduled";
|
|
@@ -21154,7 +21690,7 @@ async function runnerServe() {
|
|
|
21154
21690
|
init_config();
|
|
21155
21691
|
init_litellm();
|
|
21156
21692
|
import { spawn as spawn9 } from "child_process";
|
|
21157
|
-
function
|
|
21693
|
+
function parseTarget(positional) {
|
|
21158
21694
|
if (!Array.isArray(positional) || positional.length === 0) return "none";
|
|
21159
21695
|
const first = String(positional[0]).toLowerCase();
|
|
21160
21696
|
if (first === "vscode" || first === "code") return "vscode";
|
|
@@ -21169,7 +21705,7 @@ function buildProxyEnv(url) {
|
|
|
21169
21705
|
};
|
|
21170
21706
|
}
|
|
21171
21707
|
async function serve(opts) {
|
|
21172
|
-
const target =
|
|
21708
|
+
const target = parseTarget(opts.args);
|
|
21173
21709
|
const model = parseProviderModel(opts.config.agent.model);
|
|
21174
21710
|
const usesProxy = needsLitellmProxy(model);
|
|
21175
21711
|
let handle = null;
|