@kody-ade/kody-engine 0.4.280 → 0.4.282
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 +327 -96
- package/package.json +23 -24
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.282",
|
|
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",
|
|
@@ -724,10 +724,10 @@ function parseStateConfig(raw, github) {
|
|
|
724
724
|
const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nested.path;
|
|
725
725
|
const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${String(github.owner)}/kody-state`;
|
|
726
726
|
parseStateRepoSlug(stateRepo);
|
|
727
|
-
const
|
|
727
|
+
const statePath = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : String(github.repo);
|
|
728
728
|
return {
|
|
729
729
|
repo: stateRepo,
|
|
730
|
-
path: normalizeStatePath(
|
|
730
|
+
path: normalizeStatePath(statePath)
|
|
731
731
|
};
|
|
732
732
|
}
|
|
733
733
|
function parseAccessConfig(raw) {
|
|
@@ -6305,6 +6305,28 @@ var init_abortUnfinishedGitOps = __esm({
|
|
|
6305
6305
|
}
|
|
6306
6306
|
});
|
|
6307
6307
|
|
|
6308
|
+
// src/scripts/deliveryOutcome.ts
|
|
6309
|
+
function isRecord(input) {
|
|
6310
|
+
return !!input && typeof input === "object" && !Array.isArray(input);
|
|
6311
|
+
}
|
|
6312
|
+
function setDeliveryNotRequired(data, reason) {
|
|
6313
|
+
data.deliveryOutcome = { kind: "not_required", reason };
|
|
6314
|
+
}
|
|
6315
|
+
function readDeliveryOutcome(data) {
|
|
6316
|
+
const raw = data.deliveryOutcome;
|
|
6317
|
+
if (!isRecord(raw)) return null;
|
|
6318
|
+
if (raw.kind !== "not_required" || typeof raw.reason !== "string" || raw.reason.length === 0) return null;
|
|
6319
|
+
return { kind: "not_required", reason: raw.reason };
|
|
6320
|
+
}
|
|
6321
|
+
function isDeliveryNotRequired(data) {
|
|
6322
|
+
return readDeliveryOutcome(data)?.kind === "not_required";
|
|
6323
|
+
}
|
|
6324
|
+
var init_deliveryOutcome = __esm({
|
|
6325
|
+
"src/scripts/deliveryOutcome.ts"() {
|
|
6326
|
+
"use strict";
|
|
6327
|
+
}
|
|
6328
|
+
});
|
|
6329
|
+
|
|
6308
6330
|
// src/scripts/saveTaskState.ts
|
|
6309
6331
|
function jobMetaFromData(data) {
|
|
6310
6332
|
return {
|
|
@@ -6322,7 +6344,7 @@ function jobMetaFromData(data) {
|
|
|
6322
6344
|
}
|
|
6323
6345
|
function applyStandaloneTerminalState(state, ctx, profile) {
|
|
6324
6346
|
if (profile.lifecycleConfig?.finalize !== true || state.flow?.issueNumber) return;
|
|
6325
|
-
const delivered = ctx.output.exitCode === 0 && !!state.core.prUrl;
|
|
6347
|
+
const delivered = ctx.output.exitCode === 0 && (!!state.core.prUrl || isDeliveryNotRequired(ctx.data));
|
|
6326
6348
|
state.core.phase = delivered ? "shipped" : "failed";
|
|
6327
6349
|
state.core.status = delivered ? "succeeded" : "failed";
|
|
6328
6350
|
state.core.currentExecutable = null;
|
|
@@ -6344,6 +6366,7 @@ var init_saveTaskState = __esm({
|
|
|
6344
6366
|
"src/scripts/saveTaskState.ts"() {
|
|
6345
6367
|
"use strict";
|
|
6346
6368
|
init_state();
|
|
6369
|
+
init_deliveryOutcome();
|
|
6347
6370
|
saveTaskState = async (ctx, profile) => {
|
|
6348
6371
|
const target = ctx.data.commentTargetType;
|
|
6349
6372
|
const number = ctx.data.commentTargetNumber;
|
|
@@ -6722,7 +6745,7 @@ function goalRunLogPath(goalId, data) {
|
|
|
6722
6745
|
return `logs/goals/${safePathSegment(goalId)}/runs/${startedAt}-${runId}.jsonl`;
|
|
6723
6746
|
}
|
|
6724
6747
|
function goalStateLogPath(goalId) {
|
|
6725
|
-
return `
|
|
6748
|
+
return `todos/${safePathSegment(goalId)}.md`;
|
|
6726
6749
|
}
|
|
6727
6750
|
function goalRunLogSnapshot(goalId, goalState, goal) {
|
|
6728
6751
|
const requiredEvidence = [...goal.destination.evidence];
|
|
@@ -6961,9 +6984,9 @@ function linkContext(stateRepo) {
|
|
|
6961
6984
|
const server = process.env.GITHUB_SERVER_URL?.trim() || "https://github.com";
|
|
6962
6985
|
if (runId && repository) links.workflowRun = `${server}/${repository}/actions/runs/${runId}`;
|
|
6963
6986
|
const repo = stringValue(stateRepo?.repo);
|
|
6964
|
-
const
|
|
6987
|
+
const goalStatePath2 = stringValue(stateRepo?.goalStatePath);
|
|
6965
6988
|
const logPath = stringValue(stateRepo?.logPath);
|
|
6966
|
-
if (repo &&
|
|
6989
|
+
if (repo && goalStatePath2) links.goalState = githubBlobUrl(repo, goalStatePath2);
|
|
6967
6990
|
if (repo && logPath) links.log = githubBlobUrl(repo, logPath);
|
|
6968
6991
|
return Object.keys(links).length > 0 ? links : void 0;
|
|
6969
6992
|
}
|
|
@@ -7061,24 +7084,227 @@ var init_runLog = __esm({
|
|
|
7061
7084
|
}
|
|
7062
7085
|
});
|
|
7063
7086
|
|
|
7087
|
+
// src/goal/managedTodoState.ts
|
|
7088
|
+
function parseTodoGoalState(goalId, filePath, raw) {
|
|
7089
|
+
const frontmatter = parseFrontmatter(raw);
|
|
7090
|
+
const description = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(itemsBlockRe(), "").trim();
|
|
7091
|
+
const items = parseItems(raw);
|
|
7092
|
+
const destination = recordField(frontmatter.destination);
|
|
7093
|
+
const evidence = stringArray(destination.evidence).length > 0 ? stringArray(destination.evidence) : stringArray(frontmatter.evidence).length > 0 ? stringArray(frontmatter.evidence) : items.map((item) => stringField2(recordField(item.meta).evidence) || item.id).filter(Boolean);
|
|
7094
|
+
const facts = {
|
|
7095
|
+
...recordField(frontmatter.facts),
|
|
7096
|
+
...Object.fromEntries(items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed]))
|
|
7097
|
+
};
|
|
7098
|
+
return parseGoalState(filePath, {
|
|
7099
|
+
...frontmatter,
|
|
7100
|
+
id: goalId,
|
|
7101
|
+
state: frontmatter.state ?? "active",
|
|
7102
|
+
destination: {
|
|
7103
|
+
...destination,
|
|
7104
|
+
outcome: description || stringField2(destination.outcome),
|
|
7105
|
+
evidence
|
|
7106
|
+
},
|
|
7107
|
+
capabilities: stringArray(frontmatter.capabilities).length > 0 ? stringArray(frontmatter.capabilities) : items.map((item) => stringField2(recordField(item.meta).capability)).filter(Boolean),
|
|
7108
|
+
route: Array.isArray(frontmatter.route) ? frontmatter.route : routeFromItems(items),
|
|
7109
|
+
facts,
|
|
7110
|
+
blockers: stringArray(frontmatter.blockers)
|
|
7111
|
+
});
|
|
7112
|
+
}
|
|
7113
|
+
function isManagedTodoRaw(raw) {
|
|
7114
|
+
return isManagedTodoFrontmatter(parseFrontmatter(raw));
|
|
7115
|
+
}
|
|
7116
|
+
function serializeTodoGoalState(goalId, state, previousRaw) {
|
|
7117
|
+
const raw = JSON.parse(serializeGoalState(state));
|
|
7118
|
+
const destination = recordField(raw.destination);
|
|
7119
|
+
const outcome = stringField2(destination.outcome);
|
|
7120
|
+
const evidence = stringArray(destination.evidence);
|
|
7121
|
+
const route = Array.isArray(raw.route) ? raw.route : [];
|
|
7122
|
+
const facts = recordField(raw.facts);
|
|
7123
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7124
|
+
const createdAt = stringField2(raw.createdAt) || stringField2(raw.startedAt) || now;
|
|
7125
|
+
const routeByEvidence = new Map(route.map((step) => [stringField2(step.evidence), step]));
|
|
7126
|
+
const previousItems = new Map(parseItems(previousRaw ?? "").map((item) => [item.id, item]));
|
|
7127
|
+
const items = evidence.length > 0 ? evidence.map((key) => itemFromEvidence(key, routeByEvidence.get(key), facts, createdAt, now, previousItems.get(key))) : stringArray(raw.capabilities).map(
|
|
7128
|
+
(capability) => itemFromCapability(capability, createdAt, previousItems.get(capability))
|
|
7129
|
+
);
|
|
7130
|
+
delete raw.destination;
|
|
7131
|
+
raw.id = goalId;
|
|
7132
|
+
raw.title = goalId;
|
|
7133
|
+
raw.createdAt = createdAt;
|
|
7134
|
+
raw.managed = true;
|
|
7135
|
+
raw.managedModel = raw.scheduleMode === "agentLoop" || raw.type === "agentLoop" ? "agentLoop" : "agentGoal";
|
|
7136
|
+
raw.evidence = evidence;
|
|
7137
|
+
return [
|
|
7138
|
+
"---",
|
|
7139
|
+
...Object.entries(raw).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}: ${serializeFrontmatterValue(value)}`),
|
|
7140
|
+
"---",
|
|
7141
|
+
"",
|
|
7142
|
+
outcome,
|
|
7143
|
+
"",
|
|
7144
|
+
"<!-- kody-todo-items-json",
|
|
7145
|
+
JSON.stringify(items, null, 2),
|
|
7146
|
+
"-->",
|
|
7147
|
+
""
|
|
7148
|
+
].join("\n");
|
|
7149
|
+
}
|
|
7150
|
+
function isManagedTodoFrontmatter(frontmatter) {
|
|
7151
|
+
return frontmatter.managed === true || frontmatter.managed === "true" || frontmatter.managedModel === "agentGoal" || frontmatter.managedModel === "agentLoop";
|
|
7152
|
+
}
|
|
7153
|
+
function itemFromEvidence(evidence, step, facts, createdAt, now, prior) {
|
|
7154
|
+
const completed = facts[evidence] === true;
|
|
7155
|
+
return {
|
|
7156
|
+
id: evidence,
|
|
7157
|
+
title: (prior?.title ?? stringField2(step?.stage)) || evidence,
|
|
7158
|
+
body: prior?.body ?? "",
|
|
7159
|
+
assignee: prior?.assignee ?? null,
|
|
7160
|
+
completed,
|
|
7161
|
+
createdAt: prior?.createdAt ?? createdAt,
|
|
7162
|
+
completedAt: completed ? prior?.completedAt ?? now : null,
|
|
7163
|
+
meta: {
|
|
7164
|
+
...prior?.meta ?? {},
|
|
7165
|
+
evidence,
|
|
7166
|
+
...step ? {
|
|
7167
|
+
stage: stringField2(step.stage),
|
|
7168
|
+
capability: stringField2(step.capability),
|
|
7169
|
+
...step.args && typeof step.args === "object" ? { args: step.args } : {},
|
|
7170
|
+
...step.saveReport === true ? { saveReport: true } : {}
|
|
7171
|
+
} : {}
|
|
7172
|
+
}
|
|
7173
|
+
};
|
|
7174
|
+
}
|
|
7175
|
+
function itemFromCapability(capability, createdAt, prior) {
|
|
7176
|
+
return {
|
|
7177
|
+
id: capability,
|
|
7178
|
+
title: prior?.title ?? capability,
|
|
7179
|
+
body: prior?.body ?? "",
|
|
7180
|
+
assignee: prior?.assignee ?? null,
|
|
7181
|
+
completed: prior?.completed ?? false,
|
|
7182
|
+
createdAt: prior?.createdAt ?? createdAt,
|
|
7183
|
+
completedAt: prior?.completedAt ?? null,
|
|
7184
|
+
meta: { ...prior?.meta ?? {}, capability }
|
|
7185
|
+
};
|
|
7186
|
+
}
|
|
7187
|
+
function routeFromItems(items) {
|
|
7188
|
+
return items.flatMap((item) => {
|
|
7189
|
+
const meta = recordField(item.meta);
|
|
7190
|
+
const evidence = stringField2(meta.evidence) || item.id;
|
|
7191
|
+
const stage = stringField2(meta.stage);
|
|
7192
|
+
const capability = stringField2(meta.capability);
|
|
7193
|
+
if (!evidence || !stage || !capability) return [];
|
|
7194
|
+
return [{ evidence, stage, capability, ...meta.args ? { args: meta.args } : {}, ...meta.saveReport === true ? { saveReport: true } : {} }];
|
|
7195
|
+
});
|
|
7196
|
+
}
|
|
7197
|
+
function parseFrontmatter(raw) {
|
|
7198
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
7199
|
+
if (!match) return {};
|
|
7200
|
+
const parsed = {};
|
|
7201
|
+
for (const rawLine of (match[1] ?? "").split(/\r?\n/)) {
|
|
7202
|
+
const line = rawLine.trim();
|
|
7203
|
+
if (!line || line.startsWith("#")) continue;
|
|
7204
|
+
const colon = line.indexOf(":");
|
|
7205
|
+
if (colon === -1) continue;
|
|
7206
|
+
parsed[line.slice(0, colon).trim()] = parseFrontmatterValue(line.slice(colon + 1).trim());
|
|
7207
|
+
}
|
|
7208
|
+
return parsed;
|
|
7209
|
+
}
|
|
7210
|
+
function parseFrontmatterValue(raw) {
|
|
7211
|
+
let value = raw;
|
|
7212
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
7213
|
+
value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
7214
|
+
}
|
|
7215
|
+
if (value === "true") return true;
|
|
7216
|
+
if (value === "false") return false;
|
|
7217
|
+
if (value === "null") return null;
|
|
7218
|
+
if (value.startsWith("{") || value.startsWith("[") || /^-?\d+(\.\d+)?$/.test(value)) {
|
|
7219
|
+
try {
|
|
7220
|
+
return JSON.parse(value);
|
|
7221
|
+
} catch {
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
return value;
|
|
7225
|
+
}
|
|
7226
|
+
function serializeFrontmatterValue(value) {
|
|
7227
|
+
if (typeof value === "string") return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
7228
|
+
return `"${JSON.stringify(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
7229
|
+
}
|
|
7230
|
+
function itemsBlockRe() {
|
|
7231
|
+
return /<!--\s*kody-todo-items-json\s*\r?\n([\s\S]*?)\r?\n-->/;
|
|
7232
|
+
}
|
|
7233
|
+
function parseItems(raw) {
|
|
7234
|
+
const match = itemsBlockRe().exec(raw);
|
|
7235
|
+
if (!match) return [];
|
|
7236
|
+
try {
|
|
7237
|
+
const parsed = JSON.parse(match[1] ?? "[]");
|
|
7238
|
+
return Array.isArray(parsed) ? parsed.filter((item) => item && typeof item === "object") : [];
|
|
7239
|
+
} catch {
|
|
7240
|
+
return [];
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
function recordField(value) {
|
|
7244
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
7245
|
+
}
|
|
7246
|
+
function stringField2(value) {
|
|
7247
|
+
return typeof value === "string" ? value : "";
|
|
7248
|
+
}
|
|
7249
|
+
function stringArray(value) {
|
|
7250
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
7251
|
+
}
|
|
7252
|
+
var init_managedTodoState = __esm({
|
|
7253
|
+
"src/goal/managedTodoState.ts"() {
|
|
7254
|
+
"use strict";
|
|
7255
|
+
init_state2();
|
|
7256
|
+
}
|
|
7257
|
+
});
|
|
7258
|
+
|
|
7064
7259
|
// src/goal/stateStore.ts
|
|
7065
|
-
function
|
|
7260
|
+
function goalStatePath(goalId) {
|
|
7261
|
+
return `todos/${goalId}.md`;
|
|
7262
|
+
}
|
|
7263
|
+
function legacyGoalStatePath(goalId) {
|
|
7066
7264
|
return `goals/instances/${goalId}/state.json`;
|
|
7067
7265
|
}
|
|
7068
7266
|
function fetchGoalState(config, goalId, cwd) {
|
|
7069
|
-
const filePath =
|
|
7267
|
+
const filePath = goalStatePath(goalId);
|
|
7070
7268
|
const loaded = readStateText(config, cwd, filePath);
|
|
7071
|
-
if (
|
|
7072
|
-
|
|
7269
|
+
if (loaded) {
|
|
7270
|
+
if (!isManagedTodoRaw(loaded.content)) return null;
|
|
7271
|
+
return parseTodoGoalState(goalId, loaded.path, loaded.content);
|
|
7272
|
+
}
|
|
7273
|
+
const legacyPath = legacyGoalStatePath(goalId);
|
|
7274
|
+
const legacy = readStateText(config, cwd, legacyPath);
|
|
7275
|
+
if (!legacy) return null;
|
|
7276
|
+
return parseGoalState(legacy.path, JSON.parse(legacy.content));
|
|
7073
7277
|
}
|
|
7074
7278
|
function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
|
|
7075
|
-
|
|
7279
|
+
const previous = readStateText(config, cwd, goalStatePath(goalId));
|
|
7280
|
+
if (previous && !isManagedTodoRaw(previous.content)) {
|
|
7281
|
+
throw new Error(`Cannot overwrite regular todo list ${goalId} as managed goal`);
|
|
7282
|
+
}
|
|
7283
|
+
upsertStateText(config, cwd, goalStatePath(goalId), serializeTodoGoalState(goalId, state, previous?.content), message);
|
|
7284
|
+
}
|
|
7285
|
+
function listGoalStateIds(config, cwd) {
|
|
7286
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7287
|
+
const todoFileIds = /* @__PURE__ */ new Set();
|
|
7288
|
+
for (const entry of listStateDirectory(config, cwd, "todos")) {
|
|
7289
|
+
if (entry.type !== "file" || !entry.name?.endsWith(".md")) continue;
|
|
7290
|
+
const id = entry.name.slice(0, -3);
|
|
7291
|
+
todoFileIds.add(id);
|
|
7292
|
+
const loaded = readStateText(config, cwd, goalStatePath(id));
|
|
7293
|
+
if (loaded && isManagedTodoRaw(loaded.content)) ids.add(id);
|
|
7294
|
+
}
|
|
7295
|
+
for (const entry of listStateDirectory(config, cwd, "goals/instances")) {
|
|
7296
|
+
if (entry.type !== "dir" || !entry.name) continue;
|
|
7297
|
+
if (todoFileIds.has(entry.name)) continue;
|
|
7298
|
+
ids.add(entry.name);
|
|
7299
|
+
}
|
|
7300
|
+
return [...ids].sort();
|
|
7076
7301
|
}
|
|
7077
7302
|
var init_stateStore = __esm({
|
|
7078
7303
|
"src/goal/stateStore.ts"() {
|
|
7079
7304
|
"use strict";
|
|
7080
7305
|
init_stateRepo();
|
|
7081
7306
|
init_state2();
|
|
7307
|
+
init_managedTodoState();
|
|
7082
7308
|
}
|
|
7083
7309
|
});
|
|
7084
7310
|
|
|
@@ -7133,10 +7359,9 @@ function hasExplicitStateRepo(config) {
|
|
|
7133
7359
|
return !!state && typeof state.repo === "string" && state.repo.trim().length > 0 && typeof state.path === "string" && state.path.trim().length > 0;
|
|
7134
7360
|
}
|
|
7135
7361
|
function findActiveTargetInstance(config, cwd, loopGoalId, targetId) {
|
|
7136
|
-
const entries = listStateDirectory(config, cwd, "goals/instances");
|
|
7137
7362
|
const candidates = [];
|
|
7138
|
-
for (const
|
|
7139
|
-
const id =
|
|
7363
|
+
for (const entryId of listGoalStateIds(config, cwd)) {
|
|
7364
|
+
const id = entryId.trim();
|
|
7140
7365
|
if (!id || id === loopGoalId || id === targetId || !id.startsWith(`${targetId}-`)) continue;
|
|
7141
7366
|
assertSafeGoalId(id, "goal instance");
|
|
7142
7367
|
const state = fetchGoalState(config, id, cwd);
|
|
@@ -7238,7 +7463,6 @@ var init_targetLoopResolution = __esm({
|
|
|
7238
7463
|
"src/goal/targetLoopResolution.ts"() {
|
|
7239
7464
|
"use strict";
|
|
7240
7465
|
init_companyStore();
|
|
7241
|
-
init_stateRepo();
|
|
7242
7466
|
init_stateStore();
|
|
7243
7467
|
}
|
|
7244
7468
|
});
|
|
@@ -7253,7 +7477,7 @@ function cloneRoute(route) {
|
|
|
7253
7477
|
...step.args ? { args: structuredClone(step.args) } : {}
|
|
7254
7478
|
}));
|
|
7255
7479
|
}
|
|
7256
|
-
function
|
|
7480
|
+
function stringArray2(value) {
|
|
7257
7481
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
|
|
7258
7482
|
}
|
|
7259
7483
|
function routeArray(value) {
|
|
@@ -7283,11 +7507,11 @@ function expandManagedGoalState(state) {
|
|
|
7283
7507
|
if (!definition) return state;
|
|
7284
7508
|
const destination = state.extra.destination && typeof state.extra.destination === "object" && !Array.isArray(state.extra.destination) ? { ...state.extra.destination } : {};
|
|
7285
7509
|
const outcome = typeof destination.outcome === "string" ? destination.outcome : "";
|
|
7286
|
-
const evidence =
|
|
7287
|
-
const capabilities =
|
|
7510
|
+
const evidence = stringArray2(destination.evidence);
|
|
7511
|
+
const capabilities = stringArray2(state.extra.capabilities);
|
|
7288
7512
|
const route = routeArray(state.extra.route);
|
|
7289
7513
|
const facts = state.extra.facts && typeof state.extra.facts === "object" && !Array.isArray(state.extra.facts) ? { ...state.extra.facts } : {};
|
|
7290
|
-
const blockers =
|
|
7514
|
+
const blockers = stringArray2(state.extra.blockers);
|
|
7291
7515
|
return {
|
|
7292
7516
|
...state,
|
|
7293
7517
|
extra: {
|
|
@@ -8494,7 +8718,7 @@ function parseAction(value) {
|
|
|
8494
8718
|
function parseCreateManagedGoal(input) {
|
|
8495
8719
|
const route = Array.isArray(input.route) ? input.route.map(parseRouteStep) : [];
|
|
8496
8720
|
if (route.length === 0) throw new Error("createManagedGoal requires route");
|
|
8497
|
-
const evidence =
|
|
8721
|
+
const evidence = stringArray3(input.evidence);
|
|
8498
8722
|
if (evidence.length === 0) throw new Error("createManagedGoal requires evidence");
|
|
8499
8723
|
return {
|
|
8500
8724
|
kind: "createManagedGoal",
|
|
@@ -8533,9 +8757,9 @@ function parseUpdateIntentPortfolio(input) {
|
|
|
8533
8757
|
return {
|
|
8534
8758
|
kind: "updateIntentPortfolio",
|
|
8535
8759
|
intentId: slug(input.intentId, "intentId"),
|
|
8536
|
-
goals:
|
|
8537
|
-
loops:
|
|
8538
|
-
capabilities:
|
|
8760
|
+
goals: stringArray3(input.goals).filter(isSlug),
|
|
8761
|
+
loops: stringArray3(input.loops).filter(isSlug),
|
|
8762
|
+
capabilities: stringArray3(input.capabilities).filter(isSlug),
|
|
8539
8763
|
reason: requiredString(input.reason, "reason")
|
|
8540
8764
|
};
|
|
8541
8765
|
}
|
|
@@ -8569,12 +8793,12 @@ function requiredString(value, field) {
|
|
|
8569
8793
|
if (typeof value !== "string" || !value.trim()) throw new Error(`${field} is required`);
|
|
8570
8794
|
return value.trim();
|
|
8571
8795
|
}
|
|
8572
|
-
function
|
|
8796
|
+
function stringArray3(value) {
|
|
8573
8797
|
if (!Array.isArray(value)) return [];
|
|
8574
8798
|
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
8575
8799
|
}
|
|
8576
8800
|
function nonEmptyStringArray(value, field) {
|
|
8577
|
-
const values =
|
|
8801
|
+
const values = stringArray3(value);
|
|
8578
8802
|
if (values.length === 0) throw new Error(`${field} must not be empty`);
|
|
8579
8803
|
return values;
|
|
8580
8804
|
}
|
|
@@ -8606,15 +8830,15 @@ function normalizeCompanyIntent(path50, raw) {
|
|
|
8606
8830
|
throw new Error(`${path50}: intent must be JSON object`);
|
|
8607
8831
|
}
|
|
8608
8832
|
const input = raw;
|
|
8609
|
-
const id =
|
|
8833
|
+
const id = stringField3(input.id);
|
|
8610
8834
|
if (!id || !isCompanyIntentId(id)) throw new Error(`${path50}: invalid intent id`);
|
|
8611
|
-
const createdAt =
|
|
8612
|
-
const updatedAt =
|
|
8835
|
+
const createdAt = stringField3(input.createdAt) || nowIso();
|
|
8836
|
+
const updatedAt = stringField3(input.updatedAt) || createdAt;
|
|
8613
8837
|
return {
|
|
8614
8838
|
version: 1,
|
|
8615
8839
|
id,
|
|
8616
8840
|
status: oneOf2(input.status, ["active", "paused", "archived"], "active"),
|
|
8617
|
-
for:
|
|
8841
|
+
for: stringField3(input.for),
|
|
8618
8842
|
priority: numberField(input.priority, 100),
|
|
8619
8843
|
posture: oneOf2(
|
|
8620
8844
|
input.posture,
|
|
@@ -8622,21 +8846,21 @@ function normalizeCompanyIntent(path50, raw) {
|
|
|
8622
8846
|
"balanced"
|
|
8623
8847
|
),
|
|
8624
8848
|
scope: {
|
|
8625
|
-
repos:
|
|
8626
|
-
areas:
|
|
8849
|
+
repos: stringArray4(recordField2(input.scope)?.repos),
|
|
8850
|
+
areas: stringArray4(recordField2(input.scope)?.areas)
|
|
8627
8851
|
},
|
|
8628
|
-
principles:
|
|
8629
|
-
metrics:
|
|
8852
|
+
principles: stringArray4(input.principles),
|
|
8853
|
+
metrics: stringArray4(input.metrics),
|
|
8630
8854
|
policy: {
|
|
8631
|
-
release: normalizeReleasePolicy(
|
|
8632
|
-
automation: normalizeAutomationPolicy(
|
|
8855
|
+
release: normalizeReleasePolicy(recordField2(recordField2(input.policy)?.release)),
|
|
8856
|
+
automation: normalizeAutomationPolicy(recordField2(recordField2(input.policy)?.automation))
|
|
8633
8857
|
},
|
|
8634
8858
|
portfolio: {
|
|
8635
|
-
goals:
|
|
8636
|
-
loops:
|
|
8637
|
-
capabilities:
|
|
8859
|
+
goals: stringArray4(recordField2(input.portfolio)?.goals).filter(isCompanyIntentId),
|
|
8860
|
+
loops: stringArray4(recordField2(input.portfolio)?.loops).filter(isCompanyIntentId),
|
|
8861
|
+
capabilities: stringArray4(recordField2(input.portfolio)?.capabilities).filter(isCompanyIntentId)
|
|
8638
8862
|
},
|
|
8639
|
-
manager: normalizeManager(
|
|
8863
|
+
manager: normalizeManager(recordField2(input.manager)),
|
|
8640
8864
|
createdAt,
|
|
8641
8865
|
updatedAt
|
|
8642
8866
|
};
|
|
@@ -8672,20 +8896,18 @@ function appendCompanyIntentDecision(config, cwd, intentId, entry) {
|
|
|
8672
8896
|
appendStateLine(config, cwd, `intents/${intentId}/decisions.jsonl`, JSON.stringify(entry), `chore(intents): log ${intentId} decision`);
|
|
8673
8897
|
}
|
|
8674
8898
|
function listCompanyPortfolio(config, cwd) {
|
|
8675
|
-
const entries = listStateDirectory(config, cwd, "goals/instances");
|
|
8676
8899
|
const goals = [];
|
|
8677
|
-
for (const
|
|
8678
|
-
if (
|
|
8679
|
-
const
|
|
8680
|
-
if (!
|
|
8681
|
-
const
|
|
8682
|
-
const destination = recordField(state.extra.destination);
|
|
8900
|
+
for (const id of listGoalStateIds(config, cwd)) {
|
|
8901
|
+
if (!isCompanyIntentId(id)) continue;
|
|
8902
|
+
const state = fetchGoalState(config, id, cwd);
|
|
8903
|
+
if (!state) continue;
|
|
8904
|
+
const destination = recordField2(state.extra.destination);
|
|
8683
8905
|
goals.push({
|
|
8684
|
-
id
|
|
8906
|
+
id,
|
|
8685
8907
|
state: state.state,
|
|
8686
|
-
type:
|
|
8687
|
-
outcome:
|
|
8688
|
-
capabilities:
|
|
8908
|
+
type: stringField3(state.extra.type) || void 0,
|
|
8909
|
+
outcome: stringField3(destination?.outcome) || void 0,
|
|
8910
|
+
capabilities: stringArray4(state.extra.capabilities),
|
|
8689
8911
|
isLoop: state.extra.scheduleMode === "agentLoop" || state.extra.type === "agentLoop",
|
|
8690
8912
|
updatedAt: state.updatedAt
|
|
8691
8913
|
});
|
|
@@ -8694,21 +8916,21 @@ function listCompanyPortfolio(config, cwd) {
|
|
|
8694
8916
|
}
|
|
8695
8917
|
function writeCompanyGoalState(config, cwd, id, state, message) {
|
|
8696
8918
|
assertIntentId(id);
|
|
8697
|
-
|
|
8919
|
+
putGoalState(config, id, state, message, cwd);
|
|
8698
8920
|
}
|
|
8699
8921
|
function assertIntentId(id) {
|
|
8700
8922
|
if (!isCompanyIntentId(id)) throw new Error(`invalid intent/portfolio id: ${id}`);
|
|
8701
8923
|
}
|
|
8702
|
-
function
|
|
8924
|
+
function stringField3(value) {
|
|
8703
8925
|
return typeof value === "string" ? value.trim() : "";
|
|
8704
8926
|
}
|
|
8705
8927
|
function numberField(value, fallback) {
|
|
8706
8928
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
8707
8929
|
}
|
|
8708
|
-
function
|
|
8930
|
+
function recordField2(value) {
|
|
8709
8931
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
8710
8932
|
}
|
|
8711
|
-
function
|
|
8933
|
+
function stringArray4(value) {
|
|
8712
8934
|
if (!Array.isArray(value)) return [];
|
|
8713
8935
|
return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
|
|
8714
8936
|
}
|
|
@@ -8729,7 +8951,7 @@ function normalizeAutomationPolicy(raw) {
|
|
|
8729
8951
|
authority: "full-auto",
|
|
8730
8952
|
maxConcurrentGoals: Math.max(1, Math.floor(numberField(raw?.maxConcurrentGoals, 1))),
|
|
8731
8953
|
maxDailyActions: Math.max(1, Math.floor(numberField(raw?.maxDailyActions, 6))),
|
|
8732
|
-
requiresHumanFor:
|
|
8954
|
+
requiresHumanFor: stringArray4(raw?.requiresHumanFor)
|
|
8733
8955
|
};
|
|
8734
8956
|
}
|
|
8735
8957
|
function normalizeManager(raw) {
|
|
@@ -8746,6 +8968,7 @@ var init_companyIntent = __esm({
|
|
|
8746
8968
|
"src/companyIntent.ts"() {
|
|
8747
8969
|
"use strict";
|
|
8748
8970
|
init_state2();
|
|
8971
|
+
init_stateStore();
|
|
8749
8972
|
init_stateRepo();
|
|
8750
8973
|
SLUG_RE2 = /^[a-z][a-z0-9-]{0,63}$/;
|
|
8751
8974
|
}
|
|
@@ -9092,7 +9315,7 @@ function capabilityEvidenceOutput(evidence) {
|
|
|
9092
9315
|
function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
9093
9316
|
const outputs = evidenceItems.map(capabilityEvidenceOutput);
|
|
9094
9317
|
const latestOutput = outputs.at(-1);
|
|
9095
|
-
const facts =
|
|
9318
|
+
const facts = recordField3(snapshot, "facts") ?? recordField3(state.extra, "facts") ?? {};
|
|
9096
9319
|
const blockers = uniqueStrings2([
|
|
9097
9320
|
...stringArrayField(snapshot, "blockers"),
|
|
9098
9321
|
...stringArrayField(latestEvent, "blockers"),
|
|
@@ -9111,12 +9334,12 @@ function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
|
9111
9334
|
"",
|
|
9112
9335
|
"## Status",
|
|
9113
9336
|
`- State: ${state.state}`,
|
|
9114
|
-
`- Stage: ${
|
|
9337
|
+
`- Stage: ${stringField4(snapshot, "stage") ?? stringField4(state.extra, "stage") ?? "unknown"}`,
|
|
9115
9338
|
`- Next step: ${nextStepFromEvent(state, snapshot, latestOutput, latestEvent)}`,
|
|
9116
9339
|
`- Updated: ${state.updatedAt ?? state.createdAt ?? state.startedAt ?? "unknown"}`,
|
|
9117
9340
|
"",
|
|
9118
9341
|
"## Decision",
|
|
9119
|
-
`- Event: ${
|
|
9342
|
+
`- Event: ${stringField4(latestEvent, "event") ?? "unknown"}`,
|
|
9120
9343
|
`- Reason: ${decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers)}`,
|
|
9121
9344
|
`- Required evidence: ${listOrNone(stringArrayField(snapshot, "requiredEvidence"))}`,
|
|
9122
9345
|
`- Satisfied evidence: ${listOrNone(stringArrayField(snapshot, "satisfiedEvidence"))}`,
|
|
@@ -9144,9 +9367,9 @@ function capabilityEvidenceMarkdown(outputs) {
|
|
|
9144
9367
|
function decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers) {
|
|
9145
9368
|
if (state.state === "done") return "destination evidence satisfied";
|
|
9146
9369
|
if (blockers.length > 0) return blockers[0] ?? "blocked";
|
|
9147
|
-
const eventReason =
|
|
9370
|
+
const eventReason = stringField4(latestEvent, "reason") ?? stringField4(recordField3(latestEvent, "decision"), "reason");
|
|
9148
9371
|
if (eventReason) return eventReason;
|
|
9149
|
-
const summary =
|
|
9372
|
+
const summary = stringField4(latestOutput, "summary");
|
|
9150
9373
|
if (summary) return summary;
|
|
9151
9374
|
if (missingEvidence.length > 0) return `waiting for ${missingEvidence[0]}`;
|
|
9152
9375
|
return "waiting for more evidence";
|
|
@@ -9154,33 +9377,33 @@ function decisionReason(state, latestEvent, latestOutput, missingEvidence, block
|
|
|
9154
9377
|
function evidenceOutputMarkdown(index, output) {
|
|
9155
9378
|
return [
|
|
9156
9379
|
`### Output ${index}`,
|
|
9157
|
-
`- Status: ${
|
|
9158
|
-
`- Summary: ${
|
|
9380
|
+
`- Status: ${stringField4(output, "status") ?? "unknown"}`,
|
|
9381
|
+
`- Summary: ${stringField4(output, "summary") ?? "no summary"}`,
|
|
9159
9382
|
`- Sources: ${listOrNone(stringArrayField(output, "sources"))}`,
|
|
9160
|
-
`- Evidence values: ${inlineJson(
|
|
9383
|
+
`- Evidence values: ${inlineJson(recordField3(output, "evidence") ?? {})}`,
|
|
9161
9384
|
`- Missing evidence: ${listOrNone(stringArrayField(output, "missingEvidence"))}`,
|
|
9162
9385
|
`- Blockers: ${listOrNone(stringArrayField(output, "blockers"))}`,
|
|
9163
9386
|
""
|
|
9164
9387
|
];
|
|
9165
9388
|
}
|
|
9166
9389
|
function dispatchContextMarkdown(latestEvent) {
|
|
9167
|
-
const context =
|
|
9390
|
+
const context = recordField3(latestEvent, "dispatchContext");
|
|
9168
9391
|
if (!context) return ["- none"];
|
|
9169
|
-
const githubActor =
|
|
9170
|
-
const githubActorRole =
|
|
9171
|
-
const target = dispatchTargetLabel(
|
|
9392
|
+
const githubActor = stringField4(context, "githubActor");
|
|
9393
|
+
const githubActorRole = stringField4(context, "githubActorRole");
|
|
9394
|
+
const target = dispatchTargetLabel(recordField3(context, "target"));
|
|
9172
9395
|
return [
|
|
9173
|
-
`- Triggered by: ${
|
|
9174
|
-
`- Mode: ${
|
|
9396
|
+
`- Triggered by: ${stringField4(context, "triggeredBy") ?? "unknown"}`,
|
|
9397
|
+
`- Mode: ${stringField4(context, "dispatchMode") ?? "unknown"}`,
|
|
9175
9398
|
`- GitHub actor: ${githubActor ? `${githubActor}${githubActorRole ? ` (${githubActorRole})` : ""}` : "none"}`,
|
|
9176
|
-
`- Decided by: ${
|
|
9177
|
-
`- Dispatched by: ${
|
|
9399
|
+
`- Decided by: ${stringField4(context, "decidedBy") ?? "unknown"}`,
|
|
9400
|
+
`- Dispatched by: ${stringField4(context, "dispatchedBy") ?? "unknown"}`,
|
|
9178
9401
|
`- Target: ${target ?? "none"}`
|
|
9179
9402
|
];
|
|
9180
9403
|
}
|
|
9181
9404
|
function dispatchTargetLabel(target) {
|
|
9182
|
-
const type =
|
|
9183
|
-
const id =
|
|
9405
|
+
const type = stringField4(target, "type");
|
|
9406
|
+
const id = stringField4(target, "id");
|
|
9184
9407
|
if (type && id) return `${type} ${id}`;
|
|
9185
9408
|
return id ?? type;
|
|
9186
9409
|
}
|
|
@@ -9203,11 +9426,11 @@ function listOrNone(values) {
|
|
|
9203
9426
|
function uniqueStrings2(values) {
|
|
9204
9427
|
return [...new Set(values)].sort();
|
|
9205
9428
|
}
|
|
9206
|
-
function
|
|
9429
|
+
function stringField4(record2, key) {
|
|
9207
9430
|
const value = record2?.[key];
|
|
9208
9431
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
9209
9432
|
}
|
|
9210
|
-
function
|
|
9433
|
+
function recordField3(record2, key) {
|
|
9211
9434
|
const value = record2?.[key];
|
|
9212
9435
|
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : void 0;
|
|
9213
9436
|
}
|
|
@@ -9240,7 +9463,7 @@ ${artifact.path ?? ""}`;
|
|
|
9240
9463
|
}
|
|
9241
9464
|
function nextStepFromEvent(state, goalAfter, capabilityOutput, latestEvent) {
|
|
9242
9465
|
if (state.state === "done") return "done";
|
|
9243
|
-
const decisionKind =
|
|
9466
|
+
const decisionKind = stringField4(recordField3(latestEvent, "decision"), "kind") ?? stringField4(latestEvent, "status");
|
|
9244
9467
|
if (decisionKind === "done") return "done";
|
|
9245
9468
|
if (decisionKind === "dispatch") return "dispatch";
|
|
9246
9469
|
if (decisionKind === "blocked" || decisionKind === "reject-evidence") return "block";
|
|
@@ -11670,6 +11893,7 @@ var init_finalizeTerminal = __esm({
|
|
|
11670
11893
|
init_issue();
|
|
11671
11894
|
init_lifecycleLabels();
|
|
11672
11895
|
init_state();
|
|
11896
|
+
init_deliveryOutcome();
|
|
11673
11897
|
DONE = {
|
|
11674
11898
|
label: "kody:done",
|
|
11675
11899
|
color: "0e8a16",
|
|
@@ -11690,7 +11914,7 @@ var init_finalizeTerminal = __esm({
|
|
|
11690
11914
|
const cachedState = ctx.data.taskState;
|
|
11691
11915
|
let state = cachedState;
|
|
11692
11916
|
const prUrl = cachedState?.core.prUrl ?? ctx.output.prUrl ?? ctx.data.prResult?.url;
|
|
11693
|
-
const delivered = ctx.output.exitCode === 0 && !!prUrl;
|
|
11917
|
+
const delivered = ctx.output.exitCode === 0 && (!!prUrl || isDeliveryNotRequired(ctx.data));
|
|
11694
11918
|
const spec = delivered ? DONE : FAILED;
|
|
11695
11919
|
const phase = delivered ? "shipped" : "failed";
|
|
11696
11920
|
const status = delivered ? "succeeded" : "failed";
|
|
@@ -14331,6 +14555,7 @@ var init_postIssueComment = __esm({
|
|
|
14331
14555
|
"use strict";
|
|
14332
14556
|
init_issue();
|
|
14333
14557
|
init_lifecycleLabels();
|
|
14558
|
+
init_deliveryOutcome();
|
|
14334
14559
|
init_prOutcome();
|
|
14335
14560
|
FAILED_LABEL_SPEC = {
|
|
14336
14561
|
label: "kody:failed",
|
|
@@ -14347,7 +14572,14 @@ var init_postIssueComment = __esm({
|
|
|
14347
14572
|
const prResult = readPrOutcome(ctx.data);
|
|
14348
14573
|
if (!commitResult?.committed && !hasCommits) {
|
|
14349
14574
|
const specific = computeFailureReason2(ctx);
|
|
14350
|
-
|
|
14575
|
+
if (specific.length === 0) {
|
|
14576
|
+
const reason2 = "work already satisfied; no PR needed";
|
|
14577
|
+
setDeliveryNotRequired(ctx.data, reason2);
|
|
14578
|
+
postWith(targetType, targetNumber, `\u2139\uFE0F kody made no changes \u2014 ${reason2}`, ctx.cwd);
|
|
14579
|
+
ctx.output.exitCode = 0;
|
|
14580
|
+
return;
|
|
14581
|
+
}
|
|
14582
|
+
const reason = specific;
|
|
14351
14583
|
const containerParent = process.env.KODY_CONTAINER_PARENT;
|
|
14352
14584
|
if (containerParent) {
|
|
14353
14585
|
postWith(
|
|
@@ -15472,12 +15704,12 @@ async function loadGithubStateConfig(opts) {
|
|
|
15472
15704
|
const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nestedState.path;
|
|
15473
15705
|
const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${github.owner}/kody-state`;
|
|
15474
15706
|
parseStateRepoSlug(stateRepo);
|
|
15475
|
-
const
|
|
15707
|
+
const statePath = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : github.repo;
|
|
15476
15708
|
return {
|
|
15477
15709
|
github,
|
|
15478
15710
|
state: {
|
|
15479
15711
|
repo: stateRepo,
|
|
15480
|
-
path: normalizeStatePath(
|
|
15712
|
+
path: normalizeStatePath(statePath)
|
|
15481
15713
|
}
|
|
15482
15714
|
};
|
|
15483
15715
|
}
|
|
@@ -19932,22 +20164,20 @@ init_gha();
|
|
|
19932
20164
|
init_issue();
|
|
19933
20165
|
init_job();
|
|
19934
20166
|
init_registry();
|
|
19935
|
-
init_runtimePaths();
|
|
19936
|
-
init_stateWorkspace();
|
|
19937
20167
|
|
|
19938
20168
|
// src/run-request.ts
|
|
19939
20169
|
var RUN_REQUEST_ENV = "KODY_RUN_REQUEST_JSON";
|
|
19940
20170
|
var INTENTS = /* @__PURE__ */ new Set(["continue", "manage", "run", "tick"]);
|
|
19941
20171
|
var SOURCES = /* @__PURE__ */ new Set(["dashboard", "github", "schedule"]);
|
|
19942
20172
|
var TARGET_TYPES = /* @__PURE__ */ new Set(["chat", "goal", "issue", "workflow"]);
|
|
19943
|
-
function
|
|
20173
|
+
function isRecord2(value) {
|
|
19944
20174
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19945
20175
|
}
|
|
19946
20176
|
function readString(value) {
|
|
19947
20177
|
return typeof value === "string" ? value.trim() : "";
|
|
19948
20178
|
}
|
|
19949
20179
|
function parseTarget(input) {
|
|
19950
|
-
if (!
|
|
20180
|
+
if (!isRecord2(input)) return { error: "runRequest.target must be an object" };
|
|
19951
20181
|
const type = readString(input.type);
|
|
19952
20182
|
if (!TARGET_TYPES.has(type)) return { error: "runRequest.target.type is invalid" };
|
|
19953
20183
|
if (type === "issue") {
|
|
@@ -19970,14 +20200,14 @@ function parseRunRequest(input) {
|
|
|
19970
20200
|
return { error: `${RUN_REQUEST_ENV} must be valid JSON` };
|
|
19971
20201
|
}
|
|
19972
20202
|
}
|
|
19973
|
-
if (!
|
|
20203
|
+
if (!isRecord2(body)) return { error: "runRequest must be an object" };
|
|
19974
20204
|
const parsedTarget = parseTarget(body.target);
|
|
19975
20205
|
if ("error" in parsedTarget) return parsedTarget;
|
|
19976
20206
|
const intent = readString(body.intent);
|
|
19977
20207
|
if (!INTENTS.has(intent)) return { error: "runRequest.intent is invalid" };
|
|
19978
20208
|
const source = readString(body.source);
|
|
19979
20209
|
if (!SOURCES.has(source)) return { error: "runRequest.source is invalid" };
|
|
19980
|
-
if (body.input !== void 0 && !
|
|
20210
|
+
if (body.input !== void 0 && !isRecord2(body.input)) {
|
|
19981
20211
|
return { error: "runRequest.input must be an object when provided" };
|
|
19982
20212
|
}
|
|
19983
20213
|
return {
|
|
@@ -19996,6 +20226,8 @@ function readRunRequestFromEnv(env = process.env) {
|
|
|
19996
20226
|
}
|
|
19997
20227
|
|
|
19998
20228
|
// src/kody-cli.ts
|
|
20229
|
+
init_runtimePaths();
|
|
20230
|
+
init_stateWorkspace();
|
|
19999
20231
|
var CI_HELP = `kody ci \u2014 minimal-YAML autonomous engineer (CI preflight + run)
|
|
20000
20232
|
|
|
20001
20233
|
Usage:
|
|
@@ -20268,6 +20500,9 @@ ${tail}
|
|
|
20268
20500
|
} catch {
|
|
20269
20501
|
}
|
|
20270
20502
|
}
|
|
20503
|
+
function shouldPostRunFailureTail(exitCode) {
|
|
20504
|
+
return exitCode !== 0 && exitCode !== 1 && exitCode !== 2 && exitCode !== 3;
|
|
20505
|
+
}
|
|
20271
20506
|
async function runCi(argv) {
|
|
20272
20507
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
20273
20508
|
process.stdout.write(CI_HELP);
|
|
@@ -20497,10 +20732,8 @@ ${CI_HELP}`);
|
|
|
20497
20732
|
`);
|
|
20498
20733
|
const buildOnly = dispatch2.executable === "preview-build";
|
|
20499
20734
|
if (args.skipInstall || buildOnly) {
|
|
20500
|
-
process.stdout.write(
|
|
20501
|
-
|
|
20502
|
-
`
|
|
20503
|
-
);
|
|
20735
|
+
process.stdout.write(`\u2192 kody: skipping dep install (${buildOnly ? "build-only executable" : "--skip-install"})
|
|
20736
|
+
`);
|
|
20504
20737
|
} else {
|
|
20505
20738
|
const code = installDeps(pm, cwd);
|
|
20506
20739
|
if (code !== 0) {
|
|
@@ -20539,7 +20772,7 @@ ${CI_HELP}`);
|
|
|
20539
20772
|
verbose: args.verbose,
|
|
20540
20773
|
quiet: args.quiet
|
|
20541
20774
|
});
|
|
20542
|
-
if (result.exitCode
|
|
20775
|
+
if (shouldPostRunFailureTail(result.exitCode)) {
|
|
20543
20776
|
postFailureTail(issueNumber, cwd, result.reason || `exit ${result.exitCode}`);
|
|
20544
20777
|
}
|
|
20545
20778
|
return result.exitCode;
|
|
@@ -20599,11 +20832,9 @@ async function runScheduledFanOut(cwd, args, opts) {
|
|
|
20599
20832
|
const config = loadConfig(cwd);
|
|
20600
20833
|
const serial = process.env.KODY_SERIAL_WATCHES === "1";
|
|
20601
20834
|
const runWatch = async (match) => {
|
|
20602
|
-
process.stdout.write(
|
|
20603
|
-
`
|
|
20835
|
+
process.stdout.write(`
|
|
20604
20836
|
\u2192 kody: running watch capability \`${match.capability}\` (${match.executable})
|
|
20605
|
-
`
|
|
20606
|
-
);
|
|
20837
|
+
`);
|
|
20607
20838
|
try {
|
|
20608
20839
|
const result = await runJob(
|
|
20609
20840
|
mintScheduledJob({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.282",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,27 +12,6 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"kody:run": "tsx bin/kody.ts",
|
|
17
|
-
"serve": "tsx bin/kody.ts serve",
|
|
18
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
19
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
20
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
21
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
22
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
23
|
-
"pretest": "pnpm check:modularity",
|
|
24
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
25
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
26
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
27
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
28
|
-
"test:all": "vitest run tests --no-coverage",
|
|
29
|
-
"typecheck": "tsc --noEmit",
|
|
30
|
-
"lint": "biome check",
|
|
31
|
-
"lint:fix": "biome check --write",
|
|
32
|
-
"format": "biome format --write",
|
|
33
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
34
|
-
"prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build"
|
|
35
|
-
},
|
|
36
15
|
"dependencies": {
|
|
37
16
|
"@actions/cache": "^6.0.0",
|
|
38
17
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -56,5 +35,25 @@
|
|
|
56
35
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
57
36
|
},
|
|
58
37
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
59
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
60
|
-
|
|
38
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"kody:run": "tsx bin/kody.ts",
|
|
41
|
+
"serve": "tsx bin/kody.ts serve",
|
|
42
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
43
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
44
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
45
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
46
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
47
|
+
"pretest": "pnpm check:modularity",
|
|
48
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
49
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
50
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
51
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
52
|
+
"test:all": "vitest run tests --no-coverage",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"lint": "biome check",
|
|
55
|
+
"lint:fix": "biome check --write",
|
|
56
|
+
"format": "biome format --write",
|
|
57
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
58
|
+
}
|
|
59
|
+
}
|