@kody-ade/kody-engine 0.4.455 → 0.4.457
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
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.457",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -1770,6 +1770,7 @@ function parseWorkflowStep(value) {
|
|
|
1770
1770
|
const evidence = stringField(raw.evidence);
|
|
1771
1771
|
const reason = stringField(raw.reason);
|
|
1772
1772
|
const target = stringField(raw.target);
|
|
1773
|
+
const delivery = stringField(raw.delivery);
|
|
1773
1774
|
const targetFact = stringField(raw.targetFact ?? raw.target_fact);
|
|
1774
1775
|
const hasInput = Object.hasOwn(raw, "input");
|
|
1775
1776
|
const next = parseWorkflowTransitions(raw.next);
|
|
@@ -1781,6 +1782,7 @@ function parseWorkflowStep(value) {
|
|
|
1781
1782
|
...action && isSafeSlug(action) ? { action } : {},
|
|
1782
1783
|
...evidence ? { evidence } : {},
|
|
1783
1784
|
...target === "issue" || target === "pr" ? { target } : {},
|
|
1785
|
+
...delivery === "pull-request" ? { delivery } : {},
|
|
1784
1786
|
...targetFact ? { targetFact } : {},
|
|
1785
1787
|
...reason ? { reason } : {},
|
|
1786
1788
|
...next ? { next } : {},
|
|
@@ -4212,6 +4214,24 @@ var init_agencyBoundaryEval = __esm({
|
|
|
4212
4214
|
}
|
|
4213
4215
|
});
|
|
4214
4216
|
|
|
4217
|
+
// src/capabilityDelivery.ts
|
|
4218
|
+
function capabilityDeliveryTarget(input) {
|
|
4219
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
4220
|
+
const value = input;
|
|
4221
|
+
const issue2 = positiveInteger(value.issue);
|
|
4222
|
+
const pr = positiveInteger(value.pr);
|
|
4223
|
+
if (issue2 === null === (pr === null)) return null;
|
|
4224
|
+
return issue2 === null ? { kind: "pr", number: pr } : { kind: "issue", number: issue2 };
|
|
4225
|
+
}
|
|
4226
|
+
function positiveInteger(value) {
|
|
4227
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
|
|
4228
|
+
}
|
|
4229
|
+
var init_capabilityDelivery = __esm({
|
|
4230
|
+
"src/capabilityDelivery.ts"() {
|
|
4231
|
+
"use strict";
|
|
4232
|
+
}
|
|
4233
|
+
});
|
|
4234
|
+
|
|
4215
4235
|
// src/agency/capability-contract-validation.ts
|
|
4216
4236
|
import Ajv from "ajv";
|
|
4217
4237
|
function validateCapabilityContractValue(boundary, schema, value) {
|
|
@@ -4350,7 +4370,7 @@ function parseGoalEvidenceProgress(value) {
|
|
|
4350
4370
|
...stringField2(raw.reason) ? { reason: stringField2(raw.reason) } : {},
|
|
4351
4371
|
...stringField2(raw.nextAction) ? { nextAction: stringField2(raw.nextAction) } : {},
|
|
4352
4372
|
...stringField2(raw.nextRetryAt) ? { nextRetryAt: stringField2(raw.nextRetryAt) } : {},
|
|
4353
|
-
...
|
|
4373
|
+
...positiveInteger2(raw.issue) ? { issue: positiveInteger2(raw.issue) } : {},
|
|
4354
4374
|
...stringField2(raw.updatedAt) ? { updatedAt: stringField2(raw.updatedAt) } : {}
|
|
4355
4375
|
};
|
|
4356
4376
|
}
|
|
@@ -4366,7 +4386,7 @@ function definedProgressFields(update) {
|
|
|
4366
4386
|
function stringField2(value) {
|
|
4367
4387
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
4368
4388
|
}
|
|
4369
|
-
function
|
|
4389
|
+
function positiveInteger2(value) {
|
|
4370
4390
|
if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
|
|
4371
4391
|
return void 0;
|
|
4372
4392
|
}
|
|
@@ -8904,6 +8924,9 @@ function validateWorkflow(value, options = {}) {
|
|
|
8904
8924
|
}
|
|
8905
8925
|
}
|
|
8906
8926
|
validateDataMatch(step.runWhen, `${base}.runWhen`, issues);
|
|
8927
|
+
if (step.delivery !== void 0 && step.delivery !== "pull-request") {
|
|
8928
|
+
issue(issues, "invalid_delivery", `${base}.delivery`, "workflow step delivery must be pull-request");
|
|
8929
|
+
}
|
|
8907
8930
|
if (step.input !== void 0 && !isJsonValue(step.input)) {
|
|
8908
8931
|
issue(issues, "invalid_input", `${base}.input`, "workflow step input must be one JSON value");
|
|
8909
8932
|
}
|
|
@@ -9118,6 +9141,7 @@ var init_workflowValidation = __esm({
|
|
|
9118
9141
|
"action",
|
|
9119
9142
|
"evidence",
|
|
9120
9143
|
"target",
|
|
9144
|
+
"delivery",
|
|
9121
9145
|
"targetFact",
|
|
9122
9146
|
"reason",
|
|
9123
9147
|
"next",
|
|
@@ -13033,124 +13057,6 @@ var init_dispatch = __esm({
|
|
|
13033
13057
|
}
|
|
13034
13058
|
});
|
|
13035
13059
|
|
|
13036
|
-
// src/scripts/dispatchCapabilityFileTicks.ts
|
|
13037
|
-
var dispatchCapabilityFileTicks;
|
|
13038
|
-
var init_dispatchCapabilityFileTicks = __esm({
|
|
13039
|
-
"src/scripts/dispatchCapabilityFileTicks.ts"() {
|
|
13040
|
-
"use strict";
|
|
13041
|
-
dispatchCapabilityFileTicks = async (ctx) => {
|
|
13042
|
-
ctx.skipAgent = true;
|
|
13043
|
-
ctx.data.jobTickResults = [];
|
|
13044
|
-
ctx.output.exitCode = 0;
|
|
13045
|
-
ctx.output.reason = "capability scheduling is owned by goals and loops";
|
|
13046
|
-
process.stdout.write("[jobs] no flat capability fan-out; goals and loops own scheduled capability decisions\n");
|
|
13047
|
-
};
|
|
13048
|
-
}
|
|
13049
|
-
});
|
|
13050
|
-
|
|
13051
|
-
// src/scripts/dispatchCapabilityTicks.ts
|
|
13052
|
-
function listIssuesByLabel(label, cwd) {
|
|
13053
|
-
let raw = "";
|
|
13054
|
-
try {
|
|
13055
|
-
raw = gh(["issue", "list", "--state", "open", "--label", label, "--limit", "100", "--json", "number,title"], {
|
|
13056
|
-
cwd
|
|
13057
|
-
});
|
|
13058
|
-
} catch {
|
|
13059
|
-
return [];
|
|
13060
|
-
}
|
|
13061
|
-
let list;
|
|
13062
|
-
try {
|
|
13063
|
-
list = JSON.parse(raw);
|
|
13064
|
-
} catch {
|
|
13065
|
-
return [];
|
|
13066
|
-
}
|
|
13067
|
-
if (!Array.isArray(list)) return [];
|
|
13068
|
-
return list.filter((x) => typeof x.number === "number" && typeof x.title === "string").map((x) => ({ number: x.number, title: x.title }));
|
|
13069
|
-
}
|
|
13070
|
-
var dispatchCapabilityTicks;
|
|
13071
|
-
var init_dispatchCapabilityTicks = __esm({
|
|
13072
|
-
"src/scripts/dispatchCapabilityTicks.ts"() {
|
|
13073
|
-
"use strict";
|
|
13074
|
-
init_issue();
|
|
13075
|
-
init_job();
|
|
13076
|
-
dispatchCapabilityTicks = async (ctx, _profile, args) => {
|
|
13077
|
-
ctx.skipAgent = true;
|
|
13078
|
-
const label = String(args?.label ?? "");
|
|
13079
|
-
const targetImplementation = String(args?.targetImplementation ?? "");
|
|
13080
|
-
if (!label) throw new Error("dispatchCapabilityTicks: `with.label` is required");
|
|
13081
|
-
if (!targetImplementation) throw new Error("dispatchCapabilityTicks: `with.targetImplementation` is required");
|
|
13082
|
-
const issueArg = String(args?.issueArg ?? "issue");
|
|
13083
|
-
const issues = listIssuesByLabel(label, ctx.cwd);
|
|
13084
|
-
ctx.data.jobIssueCount = issues.length;
|
|
13085
|
-
if (issues.length === 0) {
|
|
13086
|
-
process.stdout.write(`[jobs] no open issues with label "${label}"
|
|
13087
|
-
`);
|
|
13088
|
-
return;
|
|
13089
|
-
}
|
|
13090
|
-
process.stdout.write(`[jobs] ticking ${issues.length} issue(s) via ${targetImplementation}
|
|
13091
|
-
`);
|
|
13092
|
-
const results = [];
|
|
13093
|
-
for (const issue2 of issues) {
|
|
13094
|
-
process.stdout.write(`[jobs] \u2192 tick #${issue2.number}: ${issue2.title}
|
|
13095
|
-
`);
|
|
13096
|
-
try {
|
|
13097
|
-
const out = await runJob(
|
|
13098
|
-
mintScheduledJob({
|
|
13099
|
-
capability: targetImplementation,
|
|
13100
|
-
implementation: targetImplementation,
|
|
13101
|
-
cliArgs: { [issueArg]: issue2.number }
|
|
13102
|
-
}),
|
|
13103
|
-
{ cwd: ctx.cwd, config: ctx.config, verbose: ctx.verbose, quiet: ctx.quiet, chain: false }
|
|
13104
|
-
);
|
|
13105
|
-
results.push({ issue: issue2.number, exitCode: out.exitCode, reason: out.reason });
|
|
13106
|
-
if (out.exitCode !== 0) {
|
|
13107
|
-
process.stderr.write(`[jobs] tick #${issue2.number} failed (exit ${out.exitCode}): ${out.reason ?? ""}
|
|
13108
|
-
`);
|
|
13109
|
-
}
|
|
13110
|
-
} catch (err) {
|
|
13111
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
13112
|
-
process.stderr.write(`[jobs] tick #${issue2.number} crashed: ${msg}
|
|
13113
|
-
`);
|
|
13114
|
-
results.push({ issue: issue2.number, exitCode: 99, reason: msg });
|
|
13115
|
-
}
|
|
13116
|
-
}
|
|
13117
|
-
ctx.data.jobTickResults = results;
|
|
13118
|
-
ctx.output.exitCode = 0;
|
|
13119
|
-
};
|
|
13120
|
-
}
|
|
13121
|
-
});
|
|
13122
|
-
|
|
13123
|
-
// src/scripts/dispatchClassified.ts
|
|
13124
|
-
var VALID_CLASSES2, dispatchClassified;
|
|
13125
|
-
var init_dispatchClassified = __esm({
|
|
13126
|
-
"src/scripts/dispatchClassified.ts"() {
|
|
13127
|
-
"use strict";
|
|
13128
|
-
init_registry();
|
|
13129
|
-
init_state();
|
|
13130
|
-
init_saveTaskState();
|
|
13131
|
-
VALID_CLASSES2 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
|
|
13132
|
-
dispatchClassified = async (ctx, profile) => {
|
|
13133
|
-
const issueNumber = ctx.args.issue;
|
|
13134
|
-
if (!issueNumber) return;
|
|
13135
|
-
const classification = ctx.data.classification;
|
|
13136
|
-
if (!classification || !VALID_CLASSES2.has(classification)) return;
|
|
13137
|
-
const action = ctx.data.action;
|
|
13138
|
-
if (!action) return;
|
|
13139
|
-
const base = typeof ctx.args.base === "string" && ctx.args.base.length > 0 ? ctx.args.base : void 0;
|
|
13140
|
-
const state = ctx.data.taskState ?? emptyState();
|
|
13141
|
-
const nextState = reduce(state, "classify", action, void 0, profile.agent, jobMetaFromData(ctx.data));
|
|
13142
|
-
ctx.data.taskState = nextState;
|
|
13143
|
-
ctx.data.taskStateRendered = renderStateComment(nextState);
|
|
13144
|
-
await writeTaskState("issue", issueNumber, nextState, ctx.cwd, ctx.config);
|
|
13145
|
-
const cliArgs = { issue: issueNumber };
|
|
13146
|
-
if (base && getProfileInputs(classification)?.some((i) => i.name === "base")) {
|
|
13147
|
-
cliArgs.base = base;
|
|
13148
|
-
}
|
|
13149
|
-
ctx.output.nextDispatch = { action: classification, cliArgs };
|
|
13150
|
-
};
|
|
13151
|
-
}
|
|
13152
|
-
});
|
|
13153
|
-
|
|
13154
13060
|
// src/goal/agencyModelRepository.ts
|
|
13155
13061
|
import {
|
|
13156
13062
|
createAgentDefinition,
|
|
@@ -13826,107 +13732,291 @@ var init_dispatchAgencyLoops = __esm({
|
|
|
13826
13732
|
}
|
|
13827
13733
|
});
|
|
13828
13734
|
|
|
13829
|
-
// src/
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
if (targetKind !== "workflow" && targetKind !== "capability" || typeof targetId !== "string" || !ID.test(targetId)) {
|
|
13842
|
-
return null;
|
|
13843
|
-
}
|
|
13844
|
-
const trigger = normalizeTrigger(raw.trigger);
|
|
13845
|
-
if (!trigger) return null;
|
|
13846
|
-
return {
|
|
13847
|
-
id: raw.id,
|
|
13848
|
-
trigger,
|
|
13849
|
-
target: { kind: targetKind, id: targetId },
|
|
13850
|
-
input: raw.input,
|
|
13851
|
-
enabled: raw.enabled
|
|
13852
|
-
};
|
|
13853
|
-
}
|
|
13854
|
-
function readLoopDefinition(cwd, id) {
|
|
13855
|
-
if (!ID.test(id)) return null;
|
|
13856
|
-
const roots = loopRoots(cwd);
|
|
13857
|
-
for (const root of roots) {
|
|
13858
|
-
const filePath = path34.join(root, "loops", id, "loop.json");
|
|
13859
|
-
if (!fs36.existsSync(filePath)) continue;
|
|
13860
|
-
try {
|
|
13861
|
-
const loop = normalizeLoopDefinition(JSON.parse(fs36.readFileSync(filePath, "utf8")));
|
|
13862
|
-
if (loop?.id === id) return loop;
|
|
13863
|
-
process.stderr.write(`[kody] invalid simple Loop definition: ${filePath}
|
|
13864
|
-
`);
|
|
13865
|
-
} catch {
|
|
13866
|
-
process.stderr.write(`[kody] unreadable simple Loop definition: ${filePath}
|
|
13867
|
-
`);
|
|
13868
|
-
}
|
|
13869
|
-
}
|
|
13870
|
-
process.stderr.write(
|
|
13871
|
-
`[kody] simple Loop not found: ${id} (${roots.map((root) => path34.join(root, "loops", id, "loop.json")).join(", ")})
|
|
13872
|
-
`
|
|
13873
|
-
);
|
|
13874
|
-
return null;
|
|
13875
|
-
}
|
|
13876
|
-
function listLoopDefinitions(cwd) {
|
|
13877
|
-
const roots = loopRoots(cwd);
|
|
13878
|
-
const byId = /* @__PURE__ */ new Map();
|
|
13879
|
-
for (const root of roots.reverse()) {
|
|
13880
|
-
const loopsDir = path34.join(root, "loops");
|
|
13881
|
-
if (!fs36.existsSync(loopsDir)) continue;
|
|
13882
|
-
for (const id of fs36.readdirSync(loopsDir).sort()) {
|
|
13883
|
-
if (!ID.test(id)) continue;
|
|
13884
|
-
const filePath = path34.join(loopsDir, id, "loop.json");
|
|
13885
|
-
if (!fs36.existsSync(filePath)) continue;
|
|
13886
|
-
try {
|
|
13887
|
-
const loop = normalizeLoopDefinition(JSON.parse(fs36.readFileSync(filePath, "utf8")));
|
|
13888
|
-
if (loop?.id === id) byId.set(id, loop);
|
|
13889
|
-
} catch {
|
|
13890
|
-
process.stderr.write(`[kody] unreadable simple Loop definition: ${filePath}
|
|
13891
|
-
`);
|
|
13892
|
-
}
|
|
13893
|
-
}
|
|
13894
|
-
}
|
|
13895
|
-
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
13896
|
-
}
|
|
13897
|
-
function loopRoots(cwd) {
|
|
13898
|
-
return [
|
|
13899
|
-
path34.join(cwd, ".kody-engine", "runtime"),
|
|
13900
|
-
path34.join(cwd, ".kody-engine", "definitions"),
|
|
13901
|
-
definitionsRoot(cwd)
|
|
13902
|
-
].filter((root, index, roots) => roots.indexOf(root) === index);
|
|
13903
|
-
}
|
|
13904
|
-
function normalizeTrigger(raw) {
|
|
13905
|
-
if (raw.type === "manual" && Object.keys(raw).length === 1) return { type: "manual" };
|
|
13906
|
-
if (raw.type === "schedule" && typeof raw.every === "string" && /^\d+[mhd]$/.test(raw.every)) {
|
|
13907
|
-
if (raw.at === void 0 && Object.keys(raw).every((key) => key === "type" || key === "every")) {
|
|
13908
|
-
return { type: "schedule", every: raw.every };
|
|
13909
|
-
}
|
|
13910
|
-
if (isObject(raw.at) && typeof raw.at.time === "string" && typeof raw.at.timezone === "string" && Object.keys(raw.at).every((key) => key === "time" || key === "timezone") && Object.keys(raw).every((key) => key === "type" || key === "every" || key === "at")) {
|
|
13911
|
-
return { type: "schedule", every: raw.every, at: { time: raw.at.time, timezone: raw.at.timezone } };
|
|
13912
|
-
}
|
|
13735
|
+
// src/scripts/dispatchCapabilityFileTicks.ts
|
|
13736
|
+
var dispatchCapabilityFileTicks;
|
|
13737
|
+
var init_dispatchCapabilityFileTicks = __esm({
|
|
13738
|
+
"src/scripts/dispatchCapabilityFileTicks.ts"() {
|
|
13739
|
+
"use strict";
|
|
13740
|
+
dispatchCapabilityFileTicks = async (ctx) => {
|
|
13741
|
+
ctx.skipAgent = true;
|
|
13742
|
+
ctx.data.jobTickResults = [];
|
|
13743
|
+
ctx.output.exitCode = 0;
|
|
13744
|
+
ctx.output.reason = "capability scheduling is owned by goals and loops";
|
|
13745
|
+
process.stdout.write("[jobs] no flat capability fan-out; goals and loops own scheduled capability decisions\n");
|
|
13746
|
+
};
|
|
13913
13747
|
}
|
|
13914
|
-
|
|
13915
|
-
|
|
13748
|
+
});
|
|
13749
|
+
|
|
13750
|
+
// src/scripts/dispatchCapabilityTicks.ts
|
|
13751
|
+
function listIssuesByLabel(label, cwd) {
|
|
13752
|
+
let raw = "";
|
|
13753
|
+
try {
|
|
13754
|
+
raw = gh(["issue", "list", "--state", "open", "--label", label, "--limit", "100", "--json", "number,title"], {
|
|
13755
|
+
cwd
|
|
13756
|
+
});
|
|
13757
|
+
} catch {
|
|
13758
|
+
return [];
|
|
13916
13759
|
}
|
|
13917
|
-
|
|
13918
|
-
|
|
13760
|
+
let list;
|
|
13761
|
+
try {
|
|
13762
|
+
list = JSON.parse(raw);
|
|
13763
|
+
} catch {
|
|
13764
|
+
return [];
|
|
13919
13765
|
}
|
|
13920
|
-
return
|
|
13921
|
-
}
|
|
13922
|
-
function isObject(value) {
|
|
13923
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13766
|
+
if (!Array.isArray(list)) return [];
|
|
13767
|
+
return list.filter((x) => typeof x.number === "number" && typeof x.title === "string").map((x) => ({ number: x.number, title: x.title }));
|
|
13924
13768
|
}
|
|
13925
|
-
var
|
|
13926
|
-
var
|
|
13927
|
-
"src/
|
|
13769
|
+
var dispatchCapabilityTicks;
|
|
13770
|
+
var init_dispatchCapabilityTicks = __esm({
|
|
13771
|
+
"src/scripts/dispatchCapabilityTicks.ts"() {
|
|
13928
13772
|
"use strict";
|
|
13929
|
-
|
|
13773
|
+
init_issue();
|
|
13774
|
+
init_job();
|
|
13775
|
+
dispatchCapabilityTicks = async (ctx, _profile, args) => {
|
|
13776
|
+
ctx.skipAgent = true;
|
|
13777
|
+
const label = String(args?.label ?? "");
|
|
13778
|
+
const targetImplementation = String(args?.targetImplementation ?? "");
|
|
13779
|
+
if (!label) throw new Error("dispatchCapabilityTicks: `with.label` is required");
|
|
13780
|
+
if (!targetImplementation) throw new Error("dispatchCapabilityTicks: `with.targetImplementation` is required");
|
|
13781
|
+
const issueArg = String(args?.issueArg ?? "issue");
|
|
13782
|
+
const issues = listIssuesByLabel(label, ctx.cwd);
|
|
13783
|
+
ctx.data.jobIssueCount = issues.length;
|
|
13784
|
+
if (issues.length === 0) {
|
|
13785
|
+
process.stdout.write(`[jobs] no open issues with label "${label}"
|
|
13786
|
+
`);
|
|
13787
|
+
return;
|
|
13788
|
+
}
|
|
13789
|
+
process.stdout.write(`[jobs] ticking ${issues.length} issue(s) via ${targetImplementation}
|
|
13790
|
+
`);
|
|
13791
|
+
const results = [];
|
|
13792
|
+
for (const issue2 of issues) {
|
|
13793
|
+
process.stdout.write(`[jobs] \u2192 tick #${issue2.number}: ${issue2.title}
|
|
13794
|
+
`);
|
|
13795
|
+
try {
|
|
13796
|
+
const out = await runJob(
|
|
13797
|
+
mintScheduledJob({
|
|
13798
|
+
capability: targetImplementation,
|
|
13799
|
+
implementation: targetImplementation,
|
|
13800
|
+
cliArgs: { [issueArg]: issue2.number }
|
|
13801
|
+
}),
|
|
13802
|
+
{ cwd: ctx.cwd, config: ctx.config, verbose: ctx.verbose, quiet: ctx.quiet, chain: false }
|
|
13803
|
+
);
|
|
13804
|
+
results.push({ issue: issue2.number, exitCode: out.exitCode, reason: out.reason });
|
|
13805
|
+
if (out.exitCode !== 0) {
|
|
13806
|
+
process.stderr.write(`[jobs] tick #${issue2.number} failed (exit ${out.exitCode}): ${out.reason ?? ""}
|
|
13807
|
+
`);
|
|
13808
|
+
}
|
|
13809
|
+
} catch (err) {
|
|
13810
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
13811
|
+
process.stderr.write(`[jobs] tick #${issue2.number} crashed: ${msg}
|
|
13812
|
+
`);
|
|
13813
|
+
results.push({ issue: issue2.number, exitCode: 99, reason: msg });
|
|
13814
|
+
}
|
|
13815
|
+
}
|
|
13816
|
+
ctx.data.jobTickResults = results;
|
|
13817
|
+
ctx.output.exitCode = 0;
|
|
13818
|
+
};
|
|
13819
|
+
}
|
|
13820
|
+
});
|
|
13821
|
+
|
|
13822
|
+
// src/scripts/dispatchClassified.ts
|
|
13823
|
+
var VALID_CLASSES2, dispatchClassified;
|
|
13824
|
+
var init_dispatchClassified = __esm({
|
|
13825
|
+
"src/scripts/dispatchClassified.ts"() {
|
|
13826
|
+
"use strict";
|
|
13827
|
+
init_registry();
|
|
13828
|
+
init_state();
|
|
13829
|
+
init_saveTaskState();
|
|
13830
|
+
VALID_CLASSES2 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
|
|
13831
|
+
dispatchClassified = async (ctx, profile) => {
|
|
13832
|
+
const issueNumber = ctx.args.issue;
|
|
13833
|
+
if (!issueNumber) return;
|
|
13834
|
+
const classification = ctx.data.classification;
|
|
13835
|
+
if (!classification || !VALID_CLASSES2.has(classification)) return;
|
|
13836
|
+
const action = ctx.data.action;
|
|
13837
|
+
if (!action) return;
|
|
13838
|
+
const base = typeof ctx.args.base === "string" && ctx.args.base.length > 0 ? ctx.args.base : void 0;
|
|
13839
|
+
const state = ctx.data.taskState ?? emptyState();
|
|
13840
|
+
const nextState = reduce(state, "classify", action, void 0, profile.agent, jobMetaFromData(ctx.data));
|
|
13841
|
+
ctx.data.taskState = nextState;
|
|
13842
|
+
ctx.data.taskStateRendered = renderStateComment(nextState);
|
|
13843
|
+
await writeTaskState("issue", issueNumber, nextState, ctx.cwd, ctx.config);
|
|
13844
|
+
const cliArgs = { issue: issueNumber };
|
|
13845
|
+
if (base && getProfileInputs(classification)?.some((i) => i.name === "base")) {
|
|
13846
|
+
cliArgs.base = base;
|
|
13847
|
+
}
|
|
13848
|
+
ctx.output.nextDispatch = { action: classification, cliArgs };
|
|
13849
|
+
};
|
|
13850
|
+
}
|
|
13851
|
+
});
|
|
13852
|
+
|
|
13853
|
+
// src/jobIdentity.ts
|
|
13854
|
+
function stableJobKey(job) {
|
|
13855
|
+
const capability = job.workflow ?? job.capability ?? job.action;
|
|
13856
|
+
const implementation = job.implementation ?? capability ?? "unknown";
|
|
13857
|
+
if (job.flavor === "scheduled" && job.capability) return `scheduled:${job.capability}:${implementation}`;
|
|
13858
|
+
const target = typeof job.target === "number" ? job.target : targetFromCliArgs(job.cliArgs);
|
|
13859
|
+
const work = capability && implementation && implementation !== capability ? `${capability}:${implementation}` : capability ?? implementation;
|
|
13860
|
+
return target === void 0 ? `${job.flavor}:${work}` : `${job.flavor}:${work}:${target}`;
|
|
13861
|
+
}
|
|
13862
|
+
function targetFromCliArgs(cliArgs) {
|
|
13863
|
+
if (!cliArgs) return void 0;
|
|
13864
|
+
for (const key of ["issue", "pr", "target", "issue_number"]) {
|
|
13865
|
+
const value = cliArgs[key];
|
|
13866
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
13867
|
+
}
|
|
13868
|
+
return void 0;
|
|
13869
|
+
}
|
|
13870
|
+
var init_jobIdentity = __esm({
|
|
13871
|
+
"src/jobIdentity.ts"() {
|
|
13872
|
+
"use strict";
|
|
13873
|
+
}
|
|
13874
|
+
});
|
|
13875
|
+
|
|
13876
|
+
// src/scripts/dispatchNextTaskJob.ts
|
|
13877
|
+
function taskJobToJob(job, issueArg) {
|
|
13878
|
+
const target = typeof job.target === "number" ? job.target : typeof issueArg === "number" ? issueArg : void 0;
|
|
13879
|
+
return {
|
|
13880
|
+
capability: job.capability ?? job.implementation,
|
|
13881
|
+
implementation: job.implementation,
|
|
13882
|
+
...job.reason ? { why: job.reason } : {},
|
|
13883
|
+
...job.agent ? { agent: job.agent } : {},
|
|
13884
|
+
...job.schedule ? { schedule: job.schedule } : {},
|
|
13885
|
+
...typeof target === "number" ? { target, cliArgs: { issue: target } } : { cliArgs: {} },
|
|
13886
|
+
flavor: job.flavor ?? "instant"
|
|
13887
|
+
};
|
|
13888
|
+
}
|
|
13889
|
+
function isJob(input) {
|
|
13890
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return false;
|
|
13891
|
+
const job = input;
|
|
13892
|
+
return (typeof job.capability === "string" || typeof job.action === "string") && (job.flavor === "instant" || job.flavor === "scheduled") && (!job.cliArgs || typeof job.cliArgs === "object" && !Array.isArray(job.cliArgs));
|
|
13893
|
+
}
|
|
13894
|
+
var dispatchNextTaskJob;
|
|
13895
|
+
var init_dispatchNextTaskJob = __esm({
|
|
13896
|
+
"src/scripts/dispatchNextTaskJob.ts"() {
|
|
13897
|
+
"use strict";
|
|
13898
|
+
init_jobIdentity();
|
|
13899
|
+
init_state();
|
|
13900
|
+
dispatchNextTaskJob = async (ctx, profile) => {
|
|
13901
|
+
const state = ctx.data.taskState ?? emptyState();
|
|
13902
|
+
const ids = Array.isArray(ctx.data.plannedTaskJobIds) ? ctx.data.plannedTaskJobIds.filter((id) => typeof id === "string") : void 0;
|
|
13903
|
+
const next = nextPendingTaskJob(state, ids);
|
|
13904
|
+
ctx.skipAgent = true;
|
|
13905
|
+
if (!next) {
|
|
13906
|
+
ctx.output.exitCode = 0;
|
|
13907
|
+
ctx.output.reason = "all planned task jobs are complete";
|
|
13908
|
+
return;
|
|
13909
|
+
}
|
|
13910
|
+
const plannedJobs = Array.isArray(ctx.data.plannedTaskJobs) ? ctx.data.plannedTaskJobs.filter(isJob) : [];
|
|
13911
|
+
ctx.output.nextJob = plannedJobs.find((job) => stableJobKey(job) === next.id) ?? taskJobToJob(next, ctx.args.issue);
|
|
13912
|
+
if (typeof ctx.args.issue === "number") {
|
|
13913
|
+
ctx.output.afterNextJob = { action: profile.action ?? profile.name, cliArgs: { issue: ctx.args.issue } };
|
|
13914
|
+
}
|
|
13915
|
+
};
|
|
13916
|
+
}
|
|
13917
|
+
});
|
|
13918
|
+
|
|
13919
|
+
// src/loopDefinitions.ts
|
|
13920
|
+
import * as fs36 from "fs";
|
|
13921
|
+
import * as path34 from "path";
|
|
13922
|
+
function normalizeLoopDefinition(value) {
|
|
13923
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
13924
|
+
const raw = value;
|
|
13925
|
+
if (Object.keys(raw).some((key) => !["id", "trigger", "target", "input", "enabled"].includes(key))) return null;
|
|
13926
|
+
if (typeof raw.id !== "string" || !ID.test(raw.id)) return null;
|
|
13927
|
+
if (typeof raw.enabled !== "boolean") return null;
|
|
13928
|
+
if (!isObject(raw.input) || !isObject(raw.trigger) || !isObject(raw.target)) return null;
|
|
13929
|
+
const targetKind = raw.target.kind;
|
|
13930
|
+
const targetId = raw.target.id;
|
|
13931
|
+
if (targetKind !== "workflow" && targetKind !== "capability" || typeof targetId !== "string" || !ID.test(targetId)) {
|
|
13932
|
+
return null;
|
|
13933
|
+
}
|
|
13934
|
+
const trigger = normalizeTrigger(raw.trigger);
|
|
13935
|
+
if (!trigger) return null;
|
|
13936
|
+
return {
|
|
13937
|
+
id: raw.id,
|
|
13938
|
+
trigger,
|
|
13939
|
+
target: { kind: targetKind, id: targetId },
|
|
13940
|
+
input: raw.input,
|
|
13941
|
+
enabled: raw.enabled
|
|
13942
|
+
};
|
|
13943
|
+
}
|
|
13944
|
+
function readLoopDefinition(cwd, id) {
|
|
13945
|
+
if (!ID.test(id)) return null;
|
|
13946
|
+
const roots = loopRoots(cwd);
|
|
13947
|
+
for (const root of roots) {
|
|
13948
|
+
const filePath = path34.join(root, "loops", id, "loop.json");
|
|
13949
|
+
if (!fs36.existsSync(filePath)) continue;
|
|
13950
|
+
try {
|
|
13951
|
+
const loop = normalizeLoopDefinition(JSON.parse(fs36.readFileSync(filePath, "utf8")));
|
|
13952
|
+
if (loop?.id === id) return loop;
|
|
13953
|
+
process.stderr.write(`[kody] invalid simple Loop definition: ${filePath}
|
|
13954
|
+
`);
|
|
13955
|
+
} catch {
|
|
13956
|
+
process.stderr.write(`[kody] unreadable simple Loop definition: ${filePath}
|
|
13957
|
+
`);
|
|
13958
|
+
}
|
|
13959
|
+
}
|
|
13960
|
+
process.stderr.write(
|
|
13961
|
+
`[kody] simple Loop not found: ${id} (${roots.map((root) => path34.join(root, "loops", id, "loop.json")).join(", ")})
|
|
13962
|
+
`
|
|
13963
|
+
);
|
|
13964
|
+
return null;
|
|
13965
|
+
}
|
|
13966
|
+
function listLoopDefinitions(cwd) {
|
|
13967
|
+
const roots = loopRoots(cwd);
|
|
13968
|
+
const byId = /* @__PURE__ */ new Map();
|
|
13969
|
+
for (const root of roots.reverse()) {
|
|
13970
|
+
const loopsDir = path34.join(root, "loops");
|
|
13971
|
+
if (!fs36.existsSync(loopsDir)) continue;
|
|
13972
|
+
for (const id of fs36.readdirSync(loopsDir).sort()) {
|
|
13973
|
+
if (!ID.test(id)) continue;
|
|
13974
|
+
const filePath = path34.join(loopsDir, id, "loop.json");
|
|
13975
|
+
if (!fs36.existsSync(filePath)) continue;
|
|
13976
|
+
try {
|
|
13977
|
+
const loop = normalizeLoopDefinition(JSON.parse(fs36.readFileSync(filePath, "utf8")));
|
|
13978
|
+
if (loop?.id === id) byId.set(id, loop);
|
|
13979
|
+
} catch {
|
|
13980
|
+
process.stderr.write(`[kody] unreadable simple Loop definition: ${filePath}
|
|
13981
|
+
`);
|
|
13982
|
+
}
|
|
13983
|
+
}
|
|
13984
|
+
}
|
|
13985
|
+
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
13986
|
+
}
|
|
13987
|
+
function loopRoots(cwd) {
|
|
13988
|
+
return [
|
|
13989
|
+
path34.join(cwd, ".kody-engine", "runtime"),
|
|
13990
|
+
path34.join(cwd, ".kody-engine", "definitions"),
|
|
13991
|
+
definitionsRoot(cwd)
|
|
13992
|
+
].filter((root, index, roots) => roots.indexOf(root) === index);
|
|
13993
|
+
}
|
|
13994
|
+
function normalizeTrigger(raw) {
|
|
13995
|
+
if (raw.type === "manual" && Object.keys(raw).length === 1) return { type: "manual" };
|
|
13996
|
+
if (raw.type === "schedule" && typeof raw.every === "string" && /^\d+[mhd]$/.test(raw.every)) {
|
|
13997
|
+
if (raw.at === void 0 && Object.keys(raw).every((key) => key === "type" || key === "every")) {
|
|
13998
|
+
return { type: "schedule", every: raw.every };
|
|
13999
|
+
}
|
|
14000
|
+
if (isObject(raw.at) && typeof raw.at.time === "string" && typeof raw.at.timezone === "string" && Object.keys(raw.at).every((key) => key === "time" || key === "timezone") && Object.keys(raw).every((key) => key === "type" || key === "every" || key === "at")) {
|
|
14001
|
+
return { type: "schedule", every: raw.every, at: { time: raw.at.time, timezone: raw.at.timezone } };
|
|
14002
|
+
}
|
|
14003
|
+
}
|
|
14004
|
+
if ((raw.type === "event" || raw.type === "webhook") && typeof raw.event === "string" && raw.event.trim() && Object.keys(raw).every((key) => key === "type" || key === "event")) {
|
|
14005
|
+
return { type: raw.type, event: raw.event.trim() };
|
|
14006
|
+
}
|
|
14007
|
+
if (raw.type === "condition" && typeof raw.expression === "string" && raw.expression.trim() && Object.keys(raw).every((key) => key === "type" || key === "expression")) {
|
|
14008
|
+
return { type: "condition", expression: raw.expression.trim() };
|
|
14009
|
+
}
|
|
14010
|
+
return null;
|
|
14011
|
+
}
|
|
14012
|
+
function isObject(value) {
|
|
14013
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
14014
|
+
}
|
|
14015
|
+
var ID;
|
|
14016
|
+
var init_loopDefinitions = __esm({
|
|
14017
|
+
"src/loopDefinitions.ts"() {
|
|
14018
|
+
"use strict";
|
|
14019
|
+
init_definition_paths();
|
|
13930
14020
|
ID = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
13931
14021
|
}
|
|
13932
14022
|
});
|
|
@@ -14051,72 +14141,6 @@ var init_dispatchSimpleLoops = __esm({
|
|
|
14051
14141
|
}
|
|
14052
14142
|
});
|
|
14053
14143
|
|
|
14054
|
-
// src/jobIdentity.ts
|
|
14055
|
-
function stableJobKey(job) {
|
|
14056
|
-
const capability = job.workflow ?? job.capability ?? job.action;
|
|
14057
|
-
const implementation = job.implementation ?? capability ?? "unknown";
|
|
14058
|
-
if (job.flavor === "scheduled" && job.capability) return `scheduled:${job.capability}:${implementation}`;
|
|
14059
|
-
const target = typeof job.target === "number" ? job.target : targetFromCliArgs(job.cliArgs);
|
|
14060
|
-
const work = capability && implementation && implementation !== capability ? `${capability}:${implementation}` : capability ?? implementation;
|
|
14061
|
-
return target === void 0 ? `${job.flavor}:${work}` : `${job.flavor}:${work}:${target}`;
|
|
14062
|
-
}
|
|
14063
|
-
function targetFromCliArgs(cliArgs) {
|
|
14064
|
-
if (!cliArgs) return void 0;
|
|
14065
|
-
for (const key of ["issue", "pr", "target", "issue_number"]) {
|
|
14066
|
-
const value = cliArgs[key];
|
|
14067
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
14068
|
-
}
|
|
14069
|
-
return void 0;
|
|
14070
|
-
}
|
|
14071
|
-
var init_jobIdentity = __esm({
|
|
14072
|
-
"src/jobIdentity.ts"() {
|
|
14073
|
-
"use strict";
|
|
14074
|
-
}
|
|
14075
|
-
});
|
|
14076
|
-
|
|
14077
|
-
// src/scripts/dispatchNextTaskJob.ts
|
|
14078
|
-
function taskJobToJob(job, issueArg) {
|
|
14079
|
-
const target = typeof job.target === "number" ? job.target : typeof issueArg === "number" ? issueArg : void 0;
|
|
14080
|
-
return {
|
|
14081
|
-
capability: job.capability ?? job.implementation,
|
|
14082
|
-
implementation: job.implementation,
|
|
14083
|
-
...job.reason ? { why: job.reason } : {},
|
|
14084
|
-
...job.agent ? { agent: job.agent } : {},
|
|
14085
|
-
...job.schedule ? { schedule: job.schedule } : {},
|
|
14086
|
-
...typeof target === "number" ? { target, cliArgs: { issue: target } } : { cliArgs: {} },
|
|
14087
|
-
flavor: job.flavor ?? "instant"
|
|
14088
|
-
};
|
|
14089
|
-
}
|
|
14090
|
-
function isJob(input) {
|
|
14091
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return false;
|
|
14092
|
-
const job = input;
|
|
14093
|
-
return (typeof job.capability === "string" || typeof job.action === "string") && (job.flavor === "instant" || job.flavor === "scheduled") && (!job.cliArgs || typeof job.cliArgs === "object" && !Array.isArray(job.cliArgs));
|
|
14094
|
-
}
|
|
14095
|
-
var dispatchNextTaskJob;
|
|
14096
|
-
var init_dispatchNextTaskJob = __esm({
|
|
14097
|
-
"src/scripts/dispatchNextTaskJob.ts"() {
|
|
14098
|
-
"use strict";
|
|
14099
|
-
init_jobIdentity();
|
|
14100
|
-
init_state();
|
|
14101
|
-
dispatchNextTaskJob = async (ctx, profile) => {
|
|
14102
|
-
const state = ctx.data.taskState ?? emptyState();
|
|
14103
|
-
const ids = Array.isArray(ctx.data.plannedTaskJobIds) ? ctx.data.plannedTaskJobIds.filter((id) => typeof id === "string") : void 0;
|
|
14104
|
-
const next = nextPendingTaskJob(state, ids);
|
|
14105
|
-
ctx.skipAgent = true;
|
|
14106
|
-
if (!next) {
|
|
14107
|
-
ctx.output.exitCode = 0;
|
|
14108
|
-
ctx.output.reason = "all planned task jobs are complete";
|
|
14109
|
-
return;
|
|
14110
|
-
}
|
|
14111
|
-
const plannedJobs = Array.isArray(ctx.data.plannedTaskJobs) ? ctx.data.plannedTaskJobs.filter(isJob) : [];
|
|
14112
|
-
ctx.output.nextJob = plannedJobs.find((job) => stableJobKey(job) === next.id) ?? taskJobToJob(next, ctx.args.issue);
|
|
14113
|
-
if (typeof ctx.args.issue === "number") {
|
|
14114
|
-
ctx.output.afterNextJob = { action: profile.action ?? profile.name, cliArgs: { issue: ctx.args.issue } };
|
|
14115
|
-
}
|
|
14116
|
-
};
|
|
14117
|
-
}
|
|
14118
|
-
});
|
|
14119
|
-
|
|
14120
14144
|
// src/pr.ts
|
|
14121
14145
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
14122
14146
|
function prMergeStatus(prNumber, cwd) {
|
|
@@ -15384,158 +15408,40 @@ var init_loadCapabilityState = __esm({
|
|
|
15384
15408
|
const slug = profile.name;
|
|
15385
15409
|
const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
|
|
15386
15410
|
if (backend.hydrate) await backend.hydrate();
|
|
15387
|
-
const loaded = await backend.load(slug);
|
|
15388
|
-
ctx.data.jobSlug = slug;
|
|
15389
|
-
ctx.data.jobState = loaded;
|
|
15390
|
-
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
15391
|
-
ctx.data.capabilitySlug = slug;
|
|
15392
|
-
ctx.data.capabilityTitle = profile.describe;
|
|
15393
|
-
ctx.data.implementationSlug = profile.implementation ?? profile.name;
|
|
15394
|
-
ctx.data.agentSlug = profile.agent ?? "";
|
|
15395
|
-
ctx.data.agentTitle = "";
|
|
15396
|
-
ctx.data.capabilitySchedule = String(ctx.data.jobSchedule ?? "");
|
|
15397
|
-
const mentions = (profile.mentions ?? []).map((l) => `@${l}`).join(" ");
|
|
15398
|
-
ctx.data.mentions = mentions;
|
|
15399
|
-
const declaredTools = profile.capabilityTools ?? profile.capabilityTools ?? [];
|
|
15400
|
-
if (declaredTools.length > 0) {
|
|
15401
|
-
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE.has(name));
|
|
15402
|
-
if (unknown.length > 0) {
|
|
15403
|
-
throw new Error(
|
|
15404
|
-
`loadCapabilityState: capability '${slug}' declared capabilityTools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
15405
|
-
);
|
|
15406
|
-
}
|
|
15407
|
-
const mode = profile.capabilityToolMode ?? "lock";
|
|
15408
|
-
ctx.data.capabilityTools = declaredTools;
|
|
15409
|
-
ctx.data.capabilityToolMode = mode;
|
|
15410
|
-
ctx.data.capabilityToolsList = declaredTools.map((name) => `- \`${name}\``).join("\n");
|
|
15411
|
-
ctx.data.capabilityOperatorMention = mentions;
|
|
15412
|
-
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
15413
|
-
const submitStateTool = "mcp__kody-submit__submit_state";
|
|
15414
|
-
profile.claudeCode.enableSubmitTool = true;
|
|
15415
|
-
if (mode === "append") {
|
|
15416
|
-
profile.claudeCode.tools = [.../* @__PURE__ */ new Set([...profile.claudeCode.tools ?? [], ...mcpToolNames, submitStateTool])];
|
|
15417
|
-
return;
|
|
15418
|
-
}
|
|
15419
|
-
profile.claudeCode.tools = [...mcpToolNames, submitStateTool];
|
|
15420
|
-
}
|
|
15421
|
-
};
|
|
15422
|
-
}
|
|
15423
|
-
});
|
|
15424
|
-
|
|
15425
|
-
// src/scripts/loadSimpleCapability.ts
|
|
15426
|
-
import * as fs40 from "fs";
|
|
15427
|
-
import * as path37 from "path";
|
|
15428
|
-
function parseInput(supplied) {
|
|
15429
|
-
if (typeof supplied !== "string") return supplied;
|
|
15430
|
-
try {
|
|
15431
|
-
return JSON.parse(supplied);
|
|
15432
|
-
} catch {
|
|
15433
|
-
return parseFlagInput(supplied) ?? supplied;
|
|
15434
|
-
}
|
|
15435
|
-
}
|
|
15436
|
-
function parseFlagInput(value) {
|
|
15437
|
-
const tokens = value.trim().split(/\s+/).filter(Boolean);
|
|
15438
|
-
if (!tokens.some((token) => token.startsWith("--"))) return null;
|
|
15439
|
-
const input = {};
|
|
15440
|
-
const text2 = [];
|
|
15441
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
15442
|
-
const token = tokens[index];
|
|
15443
|
-
if (!token.startsWith("--") || token.length === 2) {
|
|
15444
|
-
text2.push(token);
|
|
15445
|
-
continue;
|
|
15446
|
-
}
|
|
15447
|
-
const equalAt = token.indexOf("=");
|
|
15448
|
-
const name = equalAt >= 0 ? token.slice(2, equalAt) : token.slice(2);
|
|
15449
|
-
const next = equalAt >= 0 ? token.slice(equalAt + 1) : tokens[index + 1];
|
|
15450
|
-
if (equalAt < 0 && next && !next.startsWith("--")) index += 1;
|
|
15451
|
-
input[name] = next && !next.startsWith("--") ? scalar(next) : true;
|
|
15452
|
-
}
|
|
15453
|
-
if (text2.length > 0) input.request = text2.join(" ");
|
|
15454
|
-
return input;
|
|
15455
|
-
}
|
|
15456
|
-
function scalar(value) {
|
|
15457
|
-
if (value === "true" || value === "false") return value === "true";
|
|
15458
|
-
if (/^-?\d+$/.test(value)) return Number(value);
|
|
15459
|
-
return value;
|
|
15460
|
-
}
|
|
15461
|
-
function capabilityEnvironment(input) {
|
|
15462
|
-
const environment = {
|
|
15463
|
-
KODY_CAPABILITY_INPUT: JSON.stringify(input ?? null)
|
|
15464
|
-
};
|
|
15465
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return environment;
|
|
15466
|
-
for (const [name, value] of Object.entries(input)) {
|
|
15467
|
-
if (value === void 0 || value === null) continue;
|
|
15468
|
-
const key = name.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
15469
|
-
environment[`KODY_ARG_${key}`] = typeof value === "string" ? value : JSON.stringify(value);
|
|
15470
|
-
}
|
|
15471
|
-
return environment;
|
|
15472
|
-
}
|
|
15473
|
-
function listFiles(root) {
|
|
15474
|
-
if (!fs40.existsSync(root)) return [];
|
|
15475
|
-
const files = [];
|
|
15476
|
-
const visit = (dir) => {
|
|
15477
|
-
for (const entry of fs40.readdirSync(dir, { withFileTypes: true })) {
|
|
15478
|
-
const absolute = path37.join(dir, entry.name);
|
|
15479
|
-
if (entry.isSymbolicLink()) continue;
|
|
15480
|
-
if (entry.isDirectory()) visit(absolute);
|
|
15481
|
-
else if (entry.isFile()) files.push(path37.relative(root, absolute));
|
|
15482
|
-
}
|
|
15483
|
-
};
|
|
15484
|
-
visit(root);
|
|
15485
|
-
return files.sort();
|
|
15486
|
-
}
|
|
15487
|
-
var loadSimpleCapability;
|
|
15488
|
-
var init_loadSimpleCapability = __esm({
|
|
15489
|
-
"src/scripts/loadSimpleCapability.ts"() {
|
|
15490
|
-
"use strict";
|
|
15491
|
-
init_capabilityFolders();
|
|
15492
|
-
init_definition_paths();
|
|
15493
|
-
loadSimpleCapability = async (ctx) => {
|
|
15494
|
-
const slug = typeof ctx.args.capability === "string" ? ctx.args.capability.trim() : "";
|
|
15495
|
-
if (!/^[a-z][a-z0-9-]*$/.test(slug)) {
|
|
15496
|
-
throw new Error("capability-run requires a valid capability slug");
|
|
15497
|
-
}
|
|
15498
|
-
const capability = readCapabilityFolder(capabilitiesRoot(ctx.cwd), slug);
|
|
15499
|
-
if (!capability) {
|
|
15500
|
-
throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
|
|
15411
|
+
const loaded = await backend.load(slug);
|
|
15412
|
+
ctx.data.jobSlug = slug;
|
|
15413
|
+
ctx.data.jobState = loaded;
|
|
15414
|
+
ctx.data.jobStateJson = JSON.stringify(loaded.state, null, 2);
|
|
15415
|
+
ctx.data.capabilitySlug = slug;
|
|
15416
|
+
ctx.data.capabilityTitle = profile.describe;
|
|
15417
|
+
ctx.data.implementationSlug = profile.implementation ?? profile.name;
|
|
15418
|
+
ctx.data.agentSlug = profile.agent ?? "";
|
|
15419
|
+
ctx.data.agentTitle = "";
|
|
15420
|
+
ctx.data.capabilitySchedule = String(ctx.data.jobSchedule ?? "");
|
|
15421
|
+
const mentions = (profile.mentions ?? []).map((l) => `@${l}`).join(" ");
|
|
15422
|
+
ctx.data.mentions = mentions;
|
|
15423
|
+
const declaredTools = profile.capabilityTools ?? profile.capabilityTools ?? [];
|
|
15424
|
+
if (declaredTools.length > 0) {
|
|
15425
|
+
const unknown = declaredTools.filter((name) => !CAPABILITY_TOOL_PALETTE.has(name));
|
|
15426
|
+
if (unknown.length > 0) {
|
|
15427
|
+
throw new Error(
|
|
15428
|
+
`loadCapabilityState: capability '${slug}' declared capabilityTools not in the kody-capability palette: ${unknown.join(", ")}. Available: ${[...CAPABILITY_MCP_TOOL_NAMES].join(", ")}`
|
|
15429
|
+
);
|
|
15430
|
+
}
|
|
15431
|
+
const mode = profile.capabilityToolMode ?? "lock";
|
|
15432
|
+
ctx.data.capabilityTools = declaredTools;
|
|
15433
|
+
ctx.data.capabilityToolMode = mode;
|
|
15434
|
+
ctx.data.capabilityToolsList = declaredTools.map((name) => `- \`${name}\``).join("\n");
|
|
15435
|
+
ctx.data.capabilityOperatorMention = mentions;
|
|
15436
|
+
const mcpToolNames = declaredTools.map((name) => `mcp__kody-capability__${name}`);
|
|
15437
|
+
const submitStateTool = "mcp__kody-submit__submit_state";
|
|
15438
|
+
profile.claudeCode.enableSubmitTool = true;
|
|
15439
|
+
if (mode === "append") {
|
|
15440
|
+
profile.claudeCode.tools = [.../* @__PURE__ */ new Set([...profile.claudeCode.tools ?? [], ...mcpToolNames, submitStateTool])];
|
|
15441
|
+
return;
|
|
15442
|
+
}
|
|
15443
|
+
profile.claudeCode.tools = [...mcpToolNames, submitStateTool];
|
|
15501
15444
|
}
|
|
15502
|
-
const toolRoot = path37.join(capability.dir, "tools");
|
|
15503
|
-
const skillRoot = path37.join(capability.dir, "skills");
|
|
15504
|
-
const toolFiles = listFiles(toolRoot);
|
|
15505
|
-
const skillFiles = listFiles(skillRoot);
|
|
15506
|
-
const input = parseInput(ctx.args.input);
|
|
15507
|
-
ctx.data.jobCapability = slug;
|
|
15508
|
-
ctx.data.capabilityInput = input;
|
|
15509
|
-
ctx.data.capabilityEnvironment = capabilityEnvironment(input);
|
|
15510
|
-
ctx.data.prompt = [
|
|
15511
|
-
capability.rawBody.trim(),
|
|
15512
|
-
"",
|
|
15513
|
-
"## Input",
|
|
15514
|
-
"",
|
|
15515
|
-
"```json",
|
|
15516
|
-
JSON.stringify(input ?? null, null, 2),
|
|
15517
|
-
"```",
|
|
15518
|
-
"",
|
|
15519
|
-
"Return one JSON value.",
|
|
15520
|
-
...skillFiles.length ? [
|
|
15521
|
-
"",
|
|
15522
|
-
"## Skills",
|
|
15523
|
-
"",
|
|
15524
|
-
...skillFiles.flatMap((file) => [
|
|
15525
|
-
`### ${file}`,
|
|
15526
|
-
"",
|
|
15527
|
-
fs40.readFileSync(path37.join(skillRoot, file), "utf-8"),
|
|
15528
|
-
""
|
|
15529
|
-
])
|
|
15530
|
-
] : [],
|
|
15531
|
-
...toolFiles.length ? [
|
|
15532
|
-
"",
|
|
15533
|
-
"## Tools",
|
|
15534
|
-
"",
|
|
15535
|
-
"Inspect or run these capability-owned files when needed:",
|
|
15536
|
-
...toolFiles.map((file) => `- ${path37.join(toolRoot, file)}`)
|
|
15537
|
-
] : []
|
|
15538
|
-
].join("\n");
|
|
15539
15445
|
};
|
|
15540
15446
|
}
|
|
15541
15447
|
});
|
|
@@ -15841,8 +15747,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
15841
15747
|
});
|
|
15842
15748
|
|
|
15843
15749
|
// src/scripts/loadJobFromFile.ts
|
|
15844
|
-
import * as
|
|
15845
|
-
import * as
|
|
15750
|
+
import * as fs40 from "fs";
|
|
15751
|
+
import * as path37 from "path";
|
|
15846
15752
|
function parseJobFile(raw, slug) {
|
|
15847
15753
|
let stripped = raw;
|
|
15848
15754
|
if (stripped.startsWith("---\n")) {
|
|
@@ -15881,10 +15787,10 @@ var init_loadJobFromFile = __esm({
|
|
|
15881
15787
|
if (!slug) {
|
|
15882
15788
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
15883
15789
|
}
|
|
15884
|
-
const capability = resolveCapabilityFolder(slug,
|
|
15790
|
+
const capability = resolveCapabilityFolder(slug, path37.resolve(ctx.cwd, jobsDir));
|
|
15885
15791
|
if (!capability) {
|
|
15886
15792
|
throw new Error(
|
|
15887
|
-
`loadJobFromFile: capability folder not found or incomplete: ${
|
|
15793
|
+
`loadJobFromFile: capability folder not found or incomplete: ${path37.resolve(ctx.cwd, jobsDir, slug)}`
|
|
15888
15794
|
);
|
|
15889
15795
|
}
|
|
15890
15796
|
const { title, body, config } = capability;
|
|
@@ -15894,12 +15800,12 @@ var init_loadJobFromFile = __esm({
|
|
|
15894
15800
|
let agentIdentity = "";
|
|
15895
15801
|
if (agentSlug) {
|
|
15896
15802
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
15897
|
-
if (!
|
|
15803
|
+
if (!fs40.existsSync(agentPath)) {
|
|
15898
15804
|
throw new Error(
|
|
15899
15805
|
`loadJobFromFile: capability '${slug}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
15900
15806
|
);
|
|
15901
15807
|
}
|
|
15902
|
-
const agentRaw =
|
|
15808
|
+
const agentRaw = fs40.readFileSync(agentPath, "utf-8");
|
|
15903
15809
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
15904
15810
|
agentTitle = parsed.title;
|
|
15905
15811
|
agentIdentity = parsed.body;
|
|
@@ -15979,13 +15885,13 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
15979
15885
|
});
|
|
15980
15886
|
|
|
15981
15887
|
// src/scripts/kodyVariables.ts
|
|
15982
|
-
import * as
|
|
15983
|
-
import * as
|
|
15888
|
+
import * as fs41 from "fs";
|
|
15889
|
+
import * as path38 from "path";
|
|
15984
15890
|
function readKodyVariables(cwd) {
|
|
15985
|
-
const full =
|
|
15891
|
+
const full = path38.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
15986
15892
|
let raw;
|
|
15987
15893
|
try {
|
|
15988
|
-
raw =
|
|
15894
|
+
raw = fs41.readFileSync(full, "utf-8");
|
|
15989
15895
|
} catch {
|
|
15990
15896
|
return {};
|
|
15991
15897
|
}
|
|
@@ -16161,8 +16067,8 @@ var init_runtimeSecrets = __esm({
|
|
|
16161
16067
|
});
|
|
16162
16068
|
|
|
16163
16069
|
// src/scripts/loadQaContext.ts
|
|
16164
|
-
import * as
|
|
16165
|
-
import * as
|
|
16070
|
+
import * as fs42 from "fs";
|
|
16071
|
+
import * as path39 from "path";
|
|
16166
16072
|
function parseSlugList(value) {
|
|
16167
16073
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
16168
16074
|
return inner.split(",").map(
|
|
@@ -16191,18 +16097,18 @@ function readProfileAgents(raw) {
|
|
|
16191
16097
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
16192
16098
|
}
|
|
16193
16099
|
function readProfile(cwd) {
|
|
16194
|
-
const dir =
|
|
16195
|
-
if (!
|
|
16100
|
+
const dir = path39.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
16101
|
+
if (!fs42.existsSync(dir)) return "";
|
|
16196
16102
|
let entries;
|
|
16197
16103
|
try {
|
|
16198
|
-
entries =
|
|
16104
|
+
entries = fs42.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
16199
16105
|
} catch {
|
|
16200
16106
|
return "";
|
|
16201
16107
|
}
|
|
16202
16108
|
const blocks = [];
|
|
16203
16109
|
for (const file of entries) {
|
|
16204
16110
|
try {
|
|
16205
|
-
const raw =
|
|
16111
|
+
const raw = fs42.readFileSync(path39.join(dir, file), "utf-8");
|
|
16206
16112
|
const { agent, body } = readProfileAgents(raw);
|
|
16207
16113
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
16208
16114
|
blocks.push(`## ${file}
|
|
@@ -16250,6 +16156,139 @@ var init_loadQaContext = __esm({
|
|
|
16250
16156
|
}
|
|
16251
16157
|
});
|
|
16252
16158
|
|
|
16159
|
+
// src/scripts/loadSimpleCapability.ts
|
|
16160
|
+
import * as fs43 from "fs";
|
|
16161
|
+
import * as path40 from "path";
|
|
16162
|
+
function parseInput(supplied) {
|
|
16163
|
+
if (typeof supplied !== "string") return supplied;
|
|
16164
|
+
try {
|
|
16165
|
+
return JSON.parse(supplied);
|
|
16166
|
+
} catch {
|
|
16167
|
+
return parseFlagInput(supplied) ?? supplied;
|
|
16168
|
+
}
|
|
16169
|
+
}
|
|
16170
|
+
function parseFlagInput(value) {
|
|
16171
|
+
const tokens = value.trim().split(/\s+/).filter(Boolean);
|
|
16172
|
+
if (!tokens.some((token) => token.startsWith("--"))) return null;
|
|
16173
|
+
const input = {};
|
|
16174
|
+
const text2 = [];
|
|
16175
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
16176
|
+
const token = tokens[index];
|
|
16177
|
+
if (!token.startsWith("--") || token.length === 2) {
|
|
16178
|
+
text2.push(token);
|
|
16179
|
+
continue;
|
|
16180
|
+
}
|
|
16181
|
+
const equalAt = token.indexOf("=");
|
|
16182
|
+
const name = equalAt >= 0 ? token.slice(2, equalAt) : token.slice(2);
|
|
16183
|
+
const next = equalAt >= 0 ? token.slice(equalAt + 1) : tokens[index + 1];
|
|
16184
|
+
if (equalAt < 0 && next && !next.startsWith("--")) index += 1;
|
|
16185
|
+
input[name] = next && !next.startsWith("--") ? scalar(next) : true;
|
|
16186
|
+
}
|
|
16187
|
+
if (text2.length > 0) input.request = text2.join(" ");
|
|
16188
|
+
return input;
|
|
16189
|
+
}
|
|
16190
|
+
function scalar(value) {
|
|
16191
|
+
if (value === "true" || value === "false") return value === "true";
|
|
16192
|
+
if (/^-?\d+$/.test(value)) return Number(value);
|
|
16193
|
+
return value;
|
|
16194
|
+
}
|
|
16195
|
+
function capabilityEnvironment(input) {
|
|
16196
|
+
const environment = {
|
|
16197
|
+
KODY_CAPABILITY_INPUT: JSON.stringify(input ?? null)
|
|
16198
|
+
};
|
|
16199
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return environment;
|
|
16200
|
+
for (const [name, value] of Object.entries(input)) {
|
|
16201
|
+
if (value === void 0 || value === null) continue;
|
|
16202
|
+
const key = name.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
16203
|
+
environment[`KODY_ARG_${key}`] = typeof value === "string" ? value : JSON.stringify(value);
|
|
16204
|
+
}
|
|
16205
|
+
return environment;
|
|
16206
|
+
}
|
|
16207
|
+
function listFiles(root) {
|
|
16208
|
+
if (!fs43.existsSync(root)) return [];
|
|
16209
|
+
const files = [];
|
|
16210
|
+
const visit = (dir) => {
|
|
16211
|
+
for (const entry of fs43.readdirSync(dir, { withFileTypes: true })) {
|
|
16212
|
+
const absolute = path40.join(dir, entry.name);
|
|
16213
|
+
if (entry.isSymbolicLink()) continue;
|
|
16214
|
+
if (entry.isDirectory()) visit(absolute);
|
|
16215
|
+
else if (entry.isFile()) files.push(path40.relative(root, absolute));
|
|
16216
|
+
}
|
|
16217
|
+
};
|
|
16218
|
+
visit(root);
|
|
16219
|
+
return files.sort();
|
|
16220
|
+
}
|
|
16221
|
+
var loadSimpleCapability;
|
|
16222
|
+
var init_loadSimpleCapability = __esm({
|
|
16223
|
+
"src/scripts/loadSimpleCapability.ts"() {
|
|
16224
|
+
"use strict";
|
|
16225
|
+
init_capabilityFolders();
|
|
16226
|
+
init_definition_paths();
|
|
16227
|
+
loadSimpleCapability = async (ctx) => {
|
|
16228
|
+
const slug = typeof ctx.args.capability === "string" ? ctx.args.capability.trim() : "";
|
|
16229
|
+
if (!/^[a-z][a-z0-9-]*$/.test(slug)) {
|
|
16230
|
+
throw new Error("capability-run requires a valid capability slug");
|
|
16231
|
+
}
|
|
16232
|
+
const capability = readCapabilityFolder(capabilitiesRoot(ctx.cwd), slug);
|
|
16233
|
+
if (!capability) {
|
|
16234
|
+
throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
|
|
16235
|
+
}
|
|
16236
|
+
const toolRoot = path40.join(capability.dir, "tools");
|
|
16237
|
+
const skillRoot = path40.join(capability.dir, "skills");
|
|
16238
|
+
const toolFiles = listFiles(toolRoot);
|
|
16239
|
+
const skillFiles = listFiles(skillRoot);
|
|
16240
|
+
const input = parseInput(ctx.args.input);
|
|
16241
|
+
const delivery = ctx.data.jobDelivery === "pull-request";
|
|
16242
|
+
ctx.data.jobCapability = slug;
|
|
16243
|
+
ctx.data.capabilityInput = input;
|
|
16244
|
+
ctx.data.capabilityEnvironment = capabilityEnvironment(input);
|
|
16245
|
+
ctx.data.prompt = [
|
|
16246
|
+
capability.rawBody.trim(),
|
|
16247
|
+
"",
|
|
16248
|
+
"## Input",
|
|
16249
|
+
"",
|
|
16250
|
+
"```json",
|
|
16251
|
+
JSON.stringify(input ?? null, null, 2),
|
|
16252
|
+
"```",
|
|
16253
|
+
"",
|
|
16254
|
+
...delivery ? [
|
|
16255
|
+
"## Delivery",
|
|
16256
|
+
"",
|
|
16257
|
+
"The wrapper owns git commits, pushes, and pull requests. Do not run git or gh write commands.",
|
|
16258
|
+
"Finish with exactly this structure:",
|
|
16259
|
+
"",
|
|
16260
|
+
"DONE",
|
|
16261
|
+
"PLAN_DEVIATIONS: none",
|
|
16262
|
+
"COMMIT_MSG: <conventional commit message>",
|
|
16263
|
+
"PR_SUMMARY:",
|
|
16264
|
+
"- <what changed>",
|
|
16265
|
+
"```json",
|
|
16266
|
+
'{"summary":"<result>","status":"changed"}',
|
|
16267
|
+
"```"
|
|
16268
|
+
] : ["Return one JSON value."],
|
|
16269
|
+
...skillFiles.length ? [
|
|
16270
|
+
"",
|
|
16271
|
+
"## Skills",
|
|
16272
|
+
"",
|
|
16273
|
+
...skillFiles.flatMap((file) => [
|
|
16274
|
+
`### ${file}`,
|
|
16275
|
+
"",
|
|
16276
|
+
fs43.readFileSync(path40.join(skillRoot, file), "utf-8"),
|
|
16277
|
+
""
|
|
16278
|
+
])
|
|
16279
|
+
] : [],
|
|
16280
|
+
...toolFiles.length ? [
|
|
16281
|
+
"",
|
|
16282
|
+
"## Tools",
|
|
16283
|
+
"",
|
|
16284
|
+
"Inspect or run these capability-owned files when needed:",
|
|
16285
|
+
...toolFiles.map((file) => `- ${path40.join(toolRoot, file)}`)
|
|
16286
|
+
] : []
|
|
16287
|
+
].join("\n");
|
|
16288
|
+
};
|
|
16289
|
+
}
|
|
16290
|
+
});
|
|
16291
|
+
|
|
16253
16292
|
// src/taskContext.ts
|
|
16254
16293
|
import * as fs44 from "fs";
|
|
16255
16294
|
import * as path41 from "path";
|
|
@@ -17074,95 +17113,11 @@ var init_parseJobStateFromAgentResult = __esm({
|
|
|
17074
17113
|
done: loaded.state.done
|
|
17075
17114
|
};
|
|
17076
17115
|
return;
|
|
17077
|
-
}
|
|
17078
|
-
ctx.data.nextStateParseError = result.error.startsWith("missing `") ? `agent did not emit a \`${fenceLabel}\` fenced block` : result.error;
|
|
17079
|
-
return;
|
|
17080
|
-
}
|
|
17081
|
-
ctx.data.nextJobState = result.envelope;
|
|
17082
|
-
};
|
|
17083
|
-
}
|
|
17084
|
-
});
|
|
17085
|
-
|
|
17086
|
-
// src/scripts/parseSimpleCapabilityOutput.ts
|
|
17087
|
-
function parseOutput(text2) {
|
|
17088
|
-
if (!text2) return void 0;
|
|
17089
|
-
try {
|
|
17090
|
-
return JSON.parse(text2);
|
|
17091
|
-
} catch {
|
|
17092
|
-
}
|
|
17093
|
-
const fences = [...text2.matchAll(/```([a-z0-9_-]+)?\s*([\s\S]*?)\s*```/gi)];
|
|
17094
|
-
const jsonFences = fences.filter((match) => match[1]?.toLowerCase() === "json");
|
|
17095
|
-
const labelledOutput = parseSingleJsonCandidate(jsonFences.map((match) => match[2]));
|
|
17096
|
-
if (labelledOutput.found) return labelledOutput.value;
|
|
17097
|
-
const plainOutput = parseSingleJsonCandidate(fences.filter((match) => !match[1]).map((match) => match[2]));
|
|
17098
|
-
if (plainOutput.found) return plainOutput.value;
|
|
17099
|
-
const legacyText = text2.trim();
|
|
17100
|
-
return legacyText ? { summary: legacyText, output: legacyText } : void 0;
|
|
17101
|
-
}
|
|
17102
|
-
function parseSingleJsonCandidate(candidates) {
|
|
17103
|
-
const parsed = [];
|
|
17104
|
-
for (const candidate of candidates) {
|
|
17105
|
-
if (!candidate) continue;
|
|
17106
|
-
try {
|
|
17107
|
-
parsed.push(JSON.parse(candidate));
|
|
17108
|
-
} catch {
|
|
17109
|
-
}
|
|
17110
|
-
}
|
|
17111
|
-
return parsed.length === 1 ? { found: true, value: parsed[0] } : { found: false };
|
|
17112
|
-
}
|
|
17113
|
-
function isObject2(value) {
|
|
17114
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17115
|
-
}
|
|
17116
|
-
function stringValue4(value) {
|
|
17117
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
17118
|
-
}
|
|
17119
|
-
var parseSimpleCapabilityOutput;
|
|
17120
|
-
var init_parseSimpleCapabilityOutput = __esm({
|
|
17121
|
-
"src/scripts/parseSimpleCapabilityOutput.ts"() {
|
|
17122
|
-
"use strict";
|
|
17123
|
-
parseSimpleCapabilityOutput = async (ctx, _profile, agentResult) => {
|
|
17124
|
-
const output = parseOutput(agentResult?.finalText);
|
|
17125
|
-
if (output === void 0) {
|
|
17126
|
-
const reason2 = agentResult?.outcomeKind === "out_of_turns" ? "Capability execution limit reached" : "Capability execution ended before returning a result";
|
|
17127
|
-
const blocked = {
|
|
17128
|
-
status: "blocked",
|
|
17129
|
-
reason: reason2,
|
|
17130
|
-
summary: reason2
|
|
17131
|
-
};
|
|
17132
|
-
ctx.output.reason = reason2;
|
|
17133
|
-
ctx.data.capabilityOutput = blocked;
|
|
17134
|
-
ctx.data.capabilityResults = [
|
|
17135
|
-
{
|
|
17136
|
-
version: 1,
|
|
17137
|
-
status: "blocked",
|
|
17138
|
-
summary: reason2,
|
|
17139
|
-
facts: blocked,
|
|
17140
|
-
artifacts: [],
|
|
17141
|
-
missingEvidence: [],
|
|
17142
|
-
blockers: [reason2]
|
|
17143
|
-
}
|
|
17144
|
-
];
|
|
17116
|
+
}
|
|
17117
|
+
ctx.data.nextStateParseError = result.error.startsWith("missing `") ? `agent did not emit a \`${fenceLabel}\` fenced block` : result.error;
|
|
17145
17118
|
return;
|
|
17146
17119
|
}
|
|
17147
|
-
ctx.data.
|
|
17148
|
-
const result = isObject2(output) ? output : {};
|
|
17149
|
-
const data = isObject2(result.data) ? result.data : isObject2(output) ? output : { output };
|
|
17150
|
-
const summary = typeof result.summary === "string" ? result.summary : "Capability completed";
|
|
17151
|
-
const reason = typeof result.reason === "string" ? result.reason : summary;
|
|
17152
|
-
const prUrl = stringValue4(data.pullRequestUrl) ?? stringValue4(data.prUrl) ?? stringValue4(result.pullRequestUrl) ?? stringValue4(result.prUrl);
|
|
17153
|
-
if (prUrl) ctx.output.prUrl = prUrl;
|
|
17154
|
-
ctx.output.reason = reason;
|
|
17155
|
-
ctx.data.capabilityResults = [
|
|
17156
|
-
{
|
|
17157
|
-
version: 1,
|
|
17158
|
-
status: "changed",
|
|
17159
|
-
summary,
|
|
17160
|
-
facts: data,
|
|
17161
|
-
artifacts: prUrl ? [{ label: "Pull request", url: prUrl }] : [],
|
|
17162
|
-
missingEvidence: [],
|
|
17163
|
-
blockers: []
|
|
17164
|
-
}
|
|
17165
|
-
];
|
|
17120
|
+
ctx.data.nextJobState = result.envelope;
|
|
17166
17121
|
};
|
|
17167
17122
|
}
|
|
17168
17123
|
});
|
|
@@ -17274,6 +17229,90 @@ var init_parseReproOutput = __esm({
|
|
|
17274
17229
|
}
|
|
17275
17230
|
});
|
|
17276
17231
|
|
|
17232
|
+
// src/scripts/parseSimpleCapabilityOutput.ts
|
|
17233
|
+
function parseOutput(text2) {
|
|
17234
|
+
if (!text2) return void 0;
|
|
17235
|
+
try {
|
|
17236
|
+
return JSON.parse(text2);
|
|
17237
|
+
} catch {
|
|
17238
|
+
}
|
|
17239
|
+
const fences = [...text2.matchAll(/```([a-z0-9_-]+)?\s*([\s\S]*?)\s*```/gi)];
|
|
17240
|
+
const jsonFences = fences.filter((match) => match[1]?.toLowerCase() === "json");
|
|
17241
|
+
const labelledOutput = parseSingleJsonCandidate(jsonFences.map((match) => match[2]));
|
|
17242
|
+
if (labelledOutput.found) return labelledOutput.value;
|
|
17243
|
+
const plainOutput = parseSingleJsonCandidate(fences.filter((match) => !match[1]).map((match) => match[2]));
|
|
17244
|
+
if (plainOutput.found) return plainOutput.value;
|
|
17245
|
+
const legacyText = text2.trim();
|
|
17246
|
+
return legacyText ? { summary: legacyText, output: legacyText } : void 0;
|
|
17247
|
+
}
|
|
17248
|
+
function parseSingleJsonCandidate(candidates) {
|
|
17249
|
+
const parsed = [];
|
|
17250
|
+
for (const candidate of candidates) {
|
|
17251
|
+
if (!candidate) continue;
|
|
17252
|
+
try {
|
|
17253
|
+
parsed.push(JSON.parse(candidate));
|
|
17254
|
+
} catch {
|
|
17255
|
+
}
|
|
17256
|
+
}
|
|
17257
|
+
return parsed.length === 1 ? { found: true, value: parsed[0] } : { found: false };
|
|
17258
|
+
}
|
|
17259
|
+
function isObject2(value) {
|
|
17260
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17261
|
+
}
|
|
17262
|
+
function stringValue4(value) {
|
|
17263
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
17264
|
+
}
|
|
17265
|
+
var parseSimpleCapabilityOutput;
|
|
17266
|
+
var init_parseSimpleCapabilityOutput = __esm({
|
|
17267
|
+
"src/scripts/parseSimpleCapabilityOutput.ts"() {
|
|
17268
|
+
"use strict";
|
|
17269
|
+
parseSimpleCapabilityOutput = async (ctx, _profile, agentResult) => {
|
|
17270
|
+
const output = parseOutput(agentResult?.finalText);
|
|
17271
|
+
if (output === void 0) {
|
|
17272
|
+
const reason2 = agentResult?.outcomeKind === "out_of_turns" ? "Capability execution limit reached" : "Capability execution ended before returning a result";
|
|
17273
|
+
const blocked = {
|
|
17274
|
+
status: "blocked",
|
|
17275
|
+
reason: reason2,
|
|
17276
|
+
summary: reason2
|
|
17277
|
+
};
|
|
17278
|
+
ctx.output.reason = reason2;
|
|
17279
|
+
ctx.data.capabilityOutput = blocked;
|
|
17280
|
+
ctx.data.capabilityResults = [
|
|
17281
|
+
{
|
|
17282
|
+
version: 1,
|
|
17283
|
+
status: "blocked",
|
|
17284
|
+
summary: reason2,
|
|
17285
|
+
facts: blocked,
|
|
17286
|
+
artifacts: [],
|
|
17287
|
+
missingEvidence: [],
|
|
17288
|
+
blockers: [reason2]
|
|
17289
|
+
}
|
|
17290
|
+
];
|
|
17291
|
+
return;
|
|
17292
|
+
}
|
|
17293
|
+
ctx.data.capabilityOutput = output;
|
|
17294
|
+
const result = isObject2(output) ? output : {};
|
|
17295
|
+
const data = isObject2(result.data) ? result.data : isObject2(output) ? output : { output };
|
|
17296
|
+
const summary = typeof result.summary === "string" ? result.summary : "Capability completed";
|
|
17297
|
+
const reason = typeof result.reason === "string" ? result.reason : summary;
|
|
17298
|
+
const prUrl = stringValue4(data.pullRequestUrl) ?? stringValue4(data.prUrl) ?? stringValue4(result.pullRequestUrl) ?? stringValue4(result.prUrl);
|
|
17299
|
+
if (prUrl) ctx.output.prUrl = prUrl;
|
|
17300
|
+
ctx.output.reason = reason;
|
|
17301
|
+
ctx.data.capabilityResults = [
|
|
17302
|
+
{
|
|
17303
|
+
version: 1,
|
|
17304
|
+
status: "changed",
|
|
17305
|
+
summary,
|
|
17306
|
+
facts: data,
|
|
17307
|
+
artifacts: prUrl ? [{ label: "Pull request", url: prUrl }] : [],
|
|
17308
|
+
missingEvidence: [],
|
|
17309
|
+
blockers: []
|
|
17310
|
+
}
|
|
17311
|
+
];
|
|
17312
|
+
};
|
|
17313
|
+
}
|
|
17314
|
+
});
|
|
17315
|
+
|
|
17277
17316
|
// src/scripts/persistArtifacts.ts
|
|
17278
17317
|
function readDottedString(source, dotted) {
|
|
17279
17318
|
const parts = dotted.split(".");
|
|
@@ -17908,20 +17947,220 @@ async function prepareMethod(ctx, profile, method) {
|
|
|
17908
17947
|
);
|
|
17909
17948
|
return false;
|
|
17910
17949
|
}
|
|
17911
|
-
}
|
|
17912
|
-
var prepareBrowserAuth;
|
|
17913
|
-
var init_prepareBrowserAuth = __esm({
|
|
17914
|
-
"src/scripts/prepareBrowserAuth.ts"() {
|
|
17950
|
+
}
|
|
17951
|
+
var prepareBrowserAuth;
|
|
17952
|
+
var init_prepareBrowserAuth = __esm({
|
|
17953
|
+
"src/scripts/prepareBrowserAuth.ts"() {
|
|
17954
|
+
"use strict";
|
|
17955
|
+
init_runtimeCleanup();
|
|
17956
|
+
init_kodyVariables();
|
|
17957
|
+
init_runtimeSecrets();
|
|
17958
|
+
prepareBrowserAuth = async (ctx, profile) => {
|
|
17959
|
+
const methods = profile.auth?.methods ?? [];
|
|
17960
|
+
for (const method of methods) {
|
|
17961
|
+
if (method.strategy !== "browser-storage-state" || method.adapter !== "kody-repository") continue;
|
|
17962
|
+
if (await prepareMethod(ctx, profile, method)) return;
|
|
17963
|
+
}
|
|
17964
|
+
};
|
|
17965
|
+
}
|
|
17966
|
+
});
|
|
17967
|
+
|
|
17968
|
+
// src/scripts/runFlow.ts
|
|
17969
|
+
function tryPost(issueNumber, body, cwd) {
|
|
17970
|
+
try {
|
|
17971
|
+
postIssueComment(issueNumber, body, cwd);
|
|
17972
|
+
} catch {
|
|
17973
|
+
}
|
|
17974
|
+
}
|
|
17975
|
+
function resolveBaseOverride(value) {
|
|
17976
|
+
if (!value) return null;
|
|
17977
|
+
if (value.length > 200) return null;
|
|
17978
|
+
if (value.includes("..")) return null;
|
|
17979
|
+
if (!/^[a-z0-9][a-z0-9/._-]*$/.test(value)) return null;
|
|
17980
|
+
return value;
|
|
17981
|
+
}
|
|
17982
|
+
var runFlow;
|
|
17983
|
+
var init_runFlow = __esm({
|
|
17984
|
+
"src/scripts/runFlow.ts"() {
|
|
17985
|
+
"use strict";
|
|
17986
|
+
init_branch();
|
|
17987
|
+
init_gha();
|
|
17988
|
+
init_issue();
|
|
17989
|
+
runFlow = async (ctx) => {
|
|
17990
|
+
const issueNumber = ctx.args.issue;
|
|
17991
|
+
const issue2 = getIssue(issueNumber, ctx.cwd);
|
|
17992
|
+
const cfgCtx = ctx.config.issueContext ?? {};
|
|
17993
|
+
const commentsFormatted = formatIssueComments(
|
|
17994
|
+
issue2.comments,
|
|
17995
|
+
cfgCtx.commentLimit ?? DEFAULT_COMMENT_LIMIT,
|
|
17996
|
+
cfgCtx.commentMaxBytes ?? DEFAULT_COMMENT_MAX_BYTES
|
|
17997
|
+
);
|
|
17998
|
+
ctx.data.issue = { ...issue2, commentsFormatted };
|
|
17999
|
+
if (issue2.isPullRequest) {
|
|
18000
|
+
ctx.data.commentTargetType = "pr";
|
|
18001
|
+
ctx.data.commentTargetNumber = issueNumber;
|
|
18002
|
+
ctx.skipAgent = true;
|
|
18003
|
+
ctx.output.exitCode = 1;
|
|
18004
|
+
ctx.output.reason = `run target #${issueNumber} is a pull request; dispatch a PR action or the source issue instead`;
|
|
18005
|
+
return;
|
|
18006
|
+
}
|
|
18007
|
+
ctx.data.commentTargetType = "issue";
|
|
18008
|
+
ctx.data.commentTargetNumber = issueNumber;
|
|
18009
|
+
const argBase = resolveBaseOverride(ctx.args.base);
|
|
18010
|
+
const baseRaw = ctx.args.base;
|
|
18011
|
+
if (baseRaw && !argBase) {
|
|
18012
|
+
process.stderr.write(`[kody runFlow] ignoring --base "${baseRaw}" (must match kody-task or goal-branch pattern)
|
|
18013
|
+
`);
|
|
18014
|
+
}
|
|
18015
|
+
const base = argBase;
|
|
18016
|
+
if (base) {
|
|
18017
|
+
ctx.data.baseBranch = base;
|
|
18018
|
+
process.stderr.write(`[kody runFlow] resolved base branch: ${base} (from --base)
|
|
18019
|
+
`);
|
|
18020
|
+
}
|
|
18021
|
+
const branchInfo = ensureFeatureBranch(
|
|
18022
|
+
issueNumber,
|
|
18023
|
+
issue2.title,
|
|
18024
|
+
ctx.config.git.defaultBranch,
|
|
18025
|
+
ctx.cwd,
|
|
18026
|
+
base ?? void 0
|
|
18027
|
+
);
|
|
18028
|
+
ctx.data.branch = branchInfo.branch;
|
|
18029
|
+
const runUrl = getRunUrl();
|
|
18030
|
+
const startMsg = runUrl ? `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\`, run ${runUrl}` : `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\``;
|
|
18031
|
+
tryPost(issueNumber, startMsg, ctx.cwd);
|
|
18032
|
+
};
|
|
18033
|
+
}
|
|
18034
|
+
});
|
|
18035
|
+
|
|
18036
|
+
// src/scripts/syncFlow.ts
|
|
18037
|
+
import { execFileSync as execFileSync16 } from "child_process";
|
|
18038
|
+
function restoreDone(prNumber, cwd) {
|
|
18039
|
+
try {
|
|
18040
|
+
setKodyLabel(prNumber, DONE2, cwd);
|
|
18041
|
+
} catch {
|
|
18042
|
+
}
|
|
18043
|
+
}
|
|
18044
|
+
function bail2(ctx, prNumber, reason) {
|
|
18045
|
+
ctx.skipAgent = true;
|
|
18046
|
+
ctx.output.exitCode = 1;
|
|
18047
|
+
ctx.output.reason = reason;
|
|
18048
|
+
const runUrl = getRunUrl();
|
|
18049
|
+
const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
|
|
18050
|
+
tryPostPr3(prNumber, `\u274C kody sync could not complete${runSuffix}: ${reason}`, ctx.cwd);
|
|
18051
|
+
}
|
|
18052
|
+
function revParseHead(cwd) {
|
|
18053
|
+
try {
|
|
18054
|
+
return execFileSync16("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
18055
|
+
} catch {
|
|
18056
|
+
return "";
|
|
18057
|
+
}
|
|
18058
|
+
}
|
|
18059
|
+
function pushBranch(branch, cwd) {
|
|
18060
|
+
const result = pushWithRetry({ cwd: cwd ?? process.cwd(), branch, setUpstream: true });
|
|
18061
|
+
if (!result.ok) {
|
|
18062
|
+
throw new Error(result.reason);
|
|
18063
|
+
}
|
|
18064
|
+
}
|
|
18065
|
+
function tryPostPr3(prNumber, body, cwd) {
|
|
18066
|
+
try {
|
|
18067
|
+
postPrReviewComment(prNumber, body, cwd);
|
|
18068
|
+
} catch {
|
|
18069
|
+
}
|
|
18070
|
+
}
|
|
18071
|
+
var DONE2, syncFlow;
|
|
18072
|
+
var init_syncFlow = __esm({
|
|
18073
|
+
"src/scripts/syncFlow.ts"() {
|
|
18074
|
+
"use strict";
|
|
18075
|
+
init_branch();
|
|
18076
|
+
init_gha();
|
|
18077
|
+
init_issue();
|
|
18078
|
+
init_lifecycleLabels();
|
|
18079
|
+
init_pushWithRetry();
|
|
18080
|
+
DONE2 = {
|
|
18081
|
+
label: "kody:done",
|
|
18082
|
+
color: "0e8a16",
|
|
18083
|
+
description: "kody: PR ready for human review/merge"
|
|
18084
|
+
};
|
|
18085
|
+
syncFlow = async (ctx, _profile, args) => {
|
|
18086
|
+
const announceOnSuccess = Boolean(args?.announceOnSuccess);
|
|
18087
|
+
const prNumber = ctx.args.pr;
|
|
18088
|
+
const pr = getPr(prNumber, ctx.cwd);
|
|
18089
|
+
if (pr.state !== "OPEN") {
|
|
18090
|
+
bail2(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
|
|
18091
|
+
return;
|
|
18092
|
+
}
|
|
18093
|
+
ctx.data.pr = pr;
|
|
18094
|
+
if (announceOnSuccess) {
|
|
18095
|
+
ctx.data.commentTargetType = "pr";
|
|
18096
|
+
ctx.data.commentTargetNumber = prNumber;
|
|
18097
|
+
}
|
|
18098
|
+
checkoutPrBranch(prNumber, ctx.cwd);
|
|
18099
|
+
ctx.data.branch = getCurrentBranch(ctx.cwd);
|
|
18100
|
+
const baseBranch = pr.baseRefName || ctx.config.git.defaultBranch;
|
|
18101
|
+
ctx.data.baseBranch = baseBranch;
|
|
18102
|
+
const headBefore = revParseHead(ctx.cwd);
|
|
18103
|
+
const mergeStatus = mergeBase(baseBranch, ctx.cwd);
|
|
18104
|
+
if (mergeStatus === "error") {
|
|
18105
|
+
bail2(ctx, prNumber, `failed to merge origin/${baseBranch} (non-conflict error); see runner log`);
|
|
18106
|
+
return;
|
|
18107
|
+
}
|
|
18108
|
+
if (mergeStatus === "conflict") {
|
|
18109
|
+
bail2(
|
|
18110
|
+
ctx,
|
|
18111
|
+
prNumber,
|
|
18112
|
+
`merge from origin/${baseBranch} produced conflicts \u2014 run \`@kody resolve\` to let kody resolve them`
|
|
18113
|
+
);
|
|
18114
|
+
return;
|
|
18115
|
+
}
|
|
18116
|
+
const headAfter = revParseHead(ctx.cwd);
|
|
18117
|
+
if (headAfter === headBefore) {
|
|
18118
|
+
ctx.data.syncResult = "noop";
|
|
18119
|
+
if (announceOnSuccess) {
|
|
18120
|
+
ctx.output.exitCode = 0;
|
|
18121
|
+
ctx.output.reason = `already up to date with origin/${baseBranch}`;
|
|
18122
|
+
restoreDone(prNumber, ctx.cwd);
|
|
18123
|
+
}
|
|
18124
|
+
return;
|
|
18125
|
+
}
|
|
18126
|
+
try {
|
|
18127
|
+
pushBranch(ctx.data.branch, ctx.cwd);
|
|
18128
|
+
} catch (err) {
|
|
18129
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18130
|
+
bail2(ctx, prNumber, `merge succeeded but push failed: ${msg}`);
|
|
18131
|
+
return;
|
|
18132
|
+
}
|
|
18133
|
+
ctx.data.syncResult = "merged";
|
|
18134
|
+
if (announceOnSuccess) {
|
|
18135
|
+
ctx.output.exitCode = 0;
|
|
18136
|
+
ctx.output.reason = `merged origin/${baseBranch} into ${ctx.data.branch}`;
|
|
18137
|
+
restoreDone(prNumber, ctx.cwd);
|
|
18138
|
+
}
|
|
18139
|
+
};
|
|
18140
|
+
}
|
|
18141
|
+
});
|
|
18142
|
+
|
|
18143
|
+
// src/scripts/prepareCapabilityDelivery.ts
|
|
18144
|
+
var prepareCapabilityDelivery;
|
|
18145
|
+
var init_prepareCapabilityDelivery = __esm({
|
|
18146
|
+
"src/scripts/prepareCapabilityDelivery.ts"() {
|
|
17915
18147
|
"use strict";
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
const
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
|
|
18148
|
+
init_capabilityDelivery();
|
|
18149
|
+
init_runFlow();
|
|
18150
|
+
init_syncFlow();
|
|
18151
|
+
prepareCapabilityDelivery = async (ctx, profile) => {
|
|
18152
|
+
const target = capabilityDeliveryTarget(ctx.data.capabilityInput);
|
|
18153
|
+
if (!target) {
|
|
18154
|
+
throw new Error("pull-request delivery requires exactly one positive issue or pr input");
|
|
18155
|
+
}
|
|
18156
|
+
ctx.args[target.kind] = target.number;
|
|
18157
|
+
if (target.kind === "issue") {
|
|
18158
|
+
await runFlow(ctx, profile);
|
|
18159
|
+
return;
|
|
17924
18160
|
}
|
|
18161
|
+
ctx.data.commentTargetType = "pr";
|
|
18162
|
+
ctx.data.commentTargetNumber = target.number;
|
|
18163
|
+
await syncFlow(ctx, profile);
|
|
17925
18164
|
};
|
|
17926
18165
|
}
|
|
17927
18166
|
});
|
|
@@ -18081,7 +18320,7 @@ var init_publishReport = __esm({
|
|
|
18081
18320
|
});
|
|
18082
18321
|
|
|
18083
18322
|
// src/scripts/recordClassification.ts
|
|
18084
|
-
import { execFileSync as
|
|
18323
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
18085
18324
|
function parseClassification(prSummary) {
|
|
18086
18325
|
if (!prSummary) return null;
|
|
18087
18326
|
const classMatch = prSummary.match(/classification:\s*(feature|bug|spec|chore)\b/i);
|
|
@@ -18093,7 +18332,7 @@ function parseClassification(prSummary) {
|
|
|
18093
18332
|
}
|
|
18094
18333
|
function tryAuditComment(issueNumber, body, cwd) {
|
|
18095
18334
|
try {
|
|
18096
|
-
|
|
18335
|
+
execFileSync17("gh", ["issue", "comment", String(issueNumber), "--body", body], {
|
|
18097
18336
|
cwd,
|
|
18098
18337
|
timeout: API_TIMEOUT_MS5,
|
|
18099
18338
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18313,7 +18552,7 @@ var init_resolveArtifacts = __esm({
|
|
|
18313
18552
|
});
|
|
18314
18553
|
|
|
18315
18554
|
// src/scripts/resolveFlow.ts
|
|
18316
|
-
import { execFileSync as
|
|
18555
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
18317
18556
|
function buildPreferBlock(prefer, baseBranch) {
|
|
18318
18557
|
if (prefer !== "ours" && prefer !== "theirs") return "";
|
|
18319
18558
|
const keepSide = prefer === "ours" ? "HEAD (this PR branch)" : `origin/${baseBranch} (base branch)`;
|
|
@@ -18333,7 +18572,7 @@ function buildPreferBlock(prefer, baseBranch) {
|
|
|
18333
18572
|
}
|
|
18334
18573
|
function getConflictedFiles(cwd) {
|
|
18335
18574
|
try {
|
|
18336
|
-
const out =
|
|
18575
|
+
const out = execFileSync18("git", ["diff", "--name-only", "--diff-filter=U"], {
|
|
18337
18576
|
encoding: "utf-8",
|
|
18338
18577
|
cwd,
|
|
18339
18578
|
env: { ...process.env, HUSKY: "0" }
|
|
@@ -18348,7 +18587,7 @@ function getConflictMarkersPreview(files, cwd, maxBytes = CONFLICT_DIFF_MAX_BYTE
|
|
|
18348
18587
|
let total = 0;
|
|
18349
18588
|
for (const f of files) {
|
|
18350
18589
|
try {
|
|
18351
|
-
const content =
|
|
18590
|
+
const content = execFileSync18("cat", [f], { encoding: "utf-8", cwd }).toString();
|
|
18352
18591
|
const snippet = `### ${f}
|
|
18353
18592
|
|
|
18354
18593
|
\`\`\`
|
|
@@ -18363,7 +18602,7 @@ ${content.slice(0, 6e3)}
|
|
|
18363
18602
|
}
|
|
18364
18603
|
return chunks.join("\n");
|
|
18365
18604
|
}
|
|
18366
|
-
function
|
|
18605
|
+
function tryPostPr4(prNumber, body, cwd) {
|
|
18367
18606
|
try {
|
|
18368
18607
|
postPrReviewComment(prNumber, body, cwd);
|
|
18369
18608
|
} catch {
|
|
@@ -18372,12 +18611,12 @@ function tryPostPr3(prNumber, body, cwd) {
|
|
|
18372
18611
|
function pushEmptyCommit(branch, cwd) {
|
|
18373
18612
|
const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
|
|
18374
18613
|
try {
|
|
18375
|
-
|
|
18614
|
+
execFileSync18(
|
|
18376
18615
|
"git",
|
|
18377
18616
|
["commit", "--allow-empty", "-m", "chore: kody resolve refresh \u2014 empty commit to recompute mergeable status"],
|
|
18378
18617
|
{ cwd, env, stdio: ["ignore", "pipe", "pipe"] }
|
|
18379
18618
|
);
|
|
18380
|
-
|
|
18619
|
+
execFileSync18("git", ["push", "-u", "origin", branch], {
|
|
18381
18620
|
cwd,
|
|
18382
18621
|
env,
|
|
18383
18622
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18415,14 +18654,14 @@ var init_resolveFlow = __esm({
|
|
|
18415
18654
|
ctx.output.exitCode = 0;
|
|
18416
18655
|
ctx.output.reason = `PR #${prNumber} is mergeable (no conflicts) \u2014 nothing to resolve`;
|
|
18417
18656
|
ctx.skipAgent = true;
|
|
18418
|
-
|
|
18657
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18419
18658
|
return;
|
|
18420
18659
|
}
|
|
18421
18660
|
if (ghStatus.status === "BLOCKED") {
|
|
18422
18661
|
ctx.output.exitCode = 0;
|
|
18423
18662
|
ctx.output.reason = `PR #${prNumber} is mergeable but blocked by checks/reviews (mergeStateStatus=${ghStatus.mergeStateStatus}) \u2014 nothing for resolve to do`;
|
|
18424
18663
|
ctx.skipAgent = true;
|
|
18425
|
-
|
|
18664
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18426
18665
|
return;
|
|
18427
18666
|
}
|
|
18428
18667
|
checkoutPrBranch(prNumber, ctx.cwd);
|
|
@@ -18434,20 +18673,20 @@ var init_resolveFlow = __esm({
|
|
|
18434
18673
|
ctx.output.exitCode = 0;
|
|
18435
18674
|
ctx.output.reason = pushed ? `local merge clean despite GitHub reporting CONFLICTING \u2014 pushed empty commit to force re-evaluation` : `local merge clean despite GitHub reporting CONFLICTING \u2014 couldn't refresh GitHub cache (push failed)`;
|
|
18436
18675
|
ctx.skipAgent = true;
|
|
18437
|
-
|
|
18676
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18438
18677
|
return;
|
|
18439
18678
|
}
|
|
18440
18679
|
ctx.output.exitCode = 0;
|
|
18441
18680
|
ctx.output.reason = `already up to date with origin/${baseBranch} \u2014 nothing to resolve`;
|
|
18442
18681
|
ctx.skipAgent = true;
|
|
18443
|
-
|
|
18682
|
+
tryPostPr4(prNumber, `\u2139\uFE0F kody resolve: ${ctx.output.reason}`, ctx.cwd);
|
|
18444
18683
|
return;
|
|
18445
18684
|
}
|
|
18446
18685
|
if (mergeStatus === "error") {
|
|
18447
18686
|
ctx.output.exitCode = 99;
|
|
18448
18687
|
ctx.output.reason = `failed to merge origin/${baseBranch} (non-conflict error); see runner log`;
|
|
18449
18688
|
ctx.skipAgent = true;
|
|
18450
|
-
|
|
18689
|
+
tryPostPr4(prNumber, `\u26A0\uFE0F kody resolve FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18451
18690
|
return;
|
|
18452
18691
|
}
|
|
18453
18692
|
const conflictedFiles = getConflictedFiles(ctx.cwd);
|
|
@@ -18462,7 +18701,7 @@ var init_resolveFlow = __esm({
|
|
|
18462
18701
|
ctx.data.preferBlock = buildPreferBlock(ctx.args.prefer, baseBranch);
|
|
18463
18702
|
const runUrl = getRunUrl();
|
|
18464
18703
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18465
|
-
|
|
18704
|
+
tryPostPr4(
|
|
18466
18705
|
prNumber,
|
|
18467
18706
|
`\u2699\uFE0F kody resolve started on \`${ctx.data.branch}\`${runSuffix} \u2014 ${conflictedFiles.length} conflicted file(s)`,
|
|
18468
18707
|
ctx.cwd
|
|
@@ -18563,10 +18802,10 @@ var init_resolvePreviewUrl = __esm({
|
|
|
18563
18802
|
});
|
|
18564
18803
|
|
|
18565
18804
|
// src/scripts/resolveQaUrl.ts
|
|
18566
|
-
import { execFileSync as
|
|
18805
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
18567
18806
|
function ghQuery(args, cwd) {
|
|
18568
18807
|
try {
|
|
18569
|
-
const out =
|
|
18808
|
+
const out = execFileSync19("gh", args, {
|
|
18570
18809
|
cwd,
|
|
18571
18810
|
stdio: ["ignore", "pipe", "pipe"],
|
|
18572
18811
|
encoding: "utf-8",
|
|
@@ -18643,7 +18882,7 @@ var init_resolveQaUrl = __esm({
|
|
|
18643
18882
|
});
|
|
18644
18883
|
|
|
18645
18884
|
// src/scripts/revertFlow.ts
|
|
18646
|
-
import { execFileSync as
|
|
18885
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
18647
18886
|
function buildCommitMessage(resolved) {
|
|
18648
18887
|
if (resolved.length === 1) {
|
|
18649
18888
|
const { full, subject } = resolved[0];
|
|
@@ -18656,7 +18895,7 @@ function buildPrSummary(resolved) {
|
|
|
18656
18895
|
return resolved.map((r) => `- Reverted \`${r.full.slice(0, 7)}\`${r.subject ? ` \u2014 ${r.subject}` : ""}`).join("\n");
|
|
18657
18896
|
}
|
|
18658
18897
|
function git4(args, cwd) {
|
|
18659
|
-
return
|
|
18898
|
+
return execFileSync20("git", args, {
|
|
18660
18899
|
encoding: "utf-8",
|
|
18661
18900
|
timeout: 3e4,
|
|
18662
18901
|
cwd,
|
|
@@ -18666,7 +18905,7 @@ function git4(args, cwd) {
|
|
|
18666
18905
|
}
|
|
18667
18906
|
function isAncestorOfHead(sha, cwd) {
|
|
18668
18907
|
try {
|
|
18669
|
-
|
|
18908
|
+
execFileSync20("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
|
|
18670
18909
|
cwd,
|
|
18671
18910
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
18672
18911
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -18676,7 +18915,7 @@ function isAncestorOfHead(sha, cwd) {
|
|
|
18676
18915
|
return false;
|
|
18677
18916
|
}
|
|
18678
18917
|
}
|
|
18679
|
-
function
|
|
18918
|
+
function tryPostPr5(prNumber, body, cwd) {
|
|
18680
18919
|
try {
|
|
18681
18920
|
postPrReviewComment(prNumber, body, cwd);
|
|
18682
18921
|
} catch (err) {
|
|
@@ -18712,7 +18951,7 @@ var init_revertFlow = __esm({
|
|
|
18712
18951
|
ctx.output.exitCode = 64;
|
|
18713
18952
|
ctx.output.reason = "no commit SHAs provided \u2014 usage: @kody revert <sha> [<sha> \u2026]";
|
|
18714
18953
|
ctx.skipAgent = true;
|
|
18715
|
-
|
|
18954
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18716
18955
|
return;
|
|
18717
18956
|
}
|
|
18718
18957
|
const requested = shasArg.split(/\s+/).filter((s) => s.length > 0);
|
|
@@ -18721,7 +18960,7 @@ var init_revertFlow = __esm({
|
|
|
18721
18960
|
ctx.output.exitCode = 64;
|
|
18722
18961
|
ctx.output.reason = `not valid SHA-shaped tokens: ${bad.join(", ")}`;
|
|
18723
18962
|
ctx.skipAgent = true;
|
|
18724
|
-
|
|
18963
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18725
18964
|
return;
|
|
18726
18965
|
}
|
|
18727
18966
|
const resolved = [];
|
|
@@ -18749,7 +18988,7 @@ var init_revertFlow = __esm({
|
|
|
18749
18988
|
ctx.output.exitCode = 64;
|
|
18750
18989
|
ctx.output.reason = `commit(s) not found in this PR branch: ${unreachable.join(", ")}`;
|
|
18751
18990
|
ctx.skipAgent = true;
|
|
18752
|
-
|
|
18991
|
+
tryPostPr5(prNumber, `\u26A0\uFE0F kody revert FAILED: ${ctx.output.reason}`, ctx.cwd);
|
|
18753
18992
|
return;
|
|
18754
18993
|
}
|
|
18755
18994
|
ctx.args.shas = resolved.map((r) => r.full).join(" ");
|
|
@@ -18759,13 +18998,13 @@ var init_revertFlow = __esm({
|
|
|
18759
18998
|
const runUrl = getRunUrl();
|
|
18760
18999
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18761
19000
|
const shaList = resolved.map((r) => `\`${r.full.slice(0, 7)}\``).join(", ");
|
|
18762
|
-
|
|
19001
|
+
tryPostPr5(prNumber, `\u2699\uFE0F kody revert started on \`${ctx.data.branch}\`${runSuffix} \u2014 reverting ${shaList}`, ctx.cwd);
|
|
18763
19002
|
};
|
|
18764
19003
|
}
|
|
18765
19004
|
});
|
|
18766
19005
|
|
|
18767
19006
|
// src/scripts/reviewFlow.ts
|
|
18768
|
-
function
|
|
19007
|
+
function tryPostPr6(prNumber, body, cwd) {
|
|
18769
19008
|
try {
|
|
18770
19009
|
postPrReviewComment(prNumber, body, cwd);
|
|
18771
19010
|
} catch {
|
|
@@ -18795,75 +19034,7 @@ var init_reviewFlow = __esm({
|
|
|
18795
19034
|
ctx.data.prDiff = getPrDiff(prNumber, ctx.cwd);
|
|
18796
19035
|
const runUrl = getRunUrl();
|
|
18797
19036
|
const runSuffix = runUrl ? `, run ${runUrl}` : "";
|
|
18798
|
-
|
|
18799
|
-
};
|
|
18800
|
-
}
|
|
18801
|
-
});
|
|
18802
|
-
|
|
18803
|
-
// src/scripts/runFlow.ts
|
|
18804
|
-
function tryPost(issueNumber, body, cwd) {
|
|
18805
|
-
try {
|
|
18806
|
-
postIssueComment(issueNumber, body, cwd);
|
|
18807
|
-
} catch {
|
|
18808
|
-
}
|
|
18809
|
-
}
|
|
18810
|
-
function resolveBaseOverride(value) {
|
|
18811
|
-
if (!value) return null;
|
|
18812
|
-
if (value.length > 200) return null;
|
|
18813
|
-
if (value.includes("..")) return null;
|
|
18814
|
-
if (!/^[a-z0-9][a-z0-9/._-]*$/.test(value)) return null;
|
|
18815
|
-
return value;
|
|
18816
|
-
}
|
|
18817
|
-
var runFlow;
|
|
18818
|
-
var init_runFlow = __esm({
|
|
18819
|
-
"src/scripts/runFlow.ts"() {
|
|
18820
|
-
"use strict";
|
|
18821
|
-
init_branch();
|
|
18822
|
-
init_gha();
|
|
18823
|
-
init_issue();
|
|
18824
|
-
runFlow = async (ctx) => {
|
|
18825
|
-
const issueNumber = ctx.args.issue;
|
|
18826
|
-
const issue2 = getIssue(issueNumber, ctx.cwd);
|
|
18827
|
-
const cfgCtx = ctx.config.issueContext ?? {};
|
|
18828
|
-
const commentsFormatted = formatIssueComments(
|
|
18829
|
-
issue2.comments,
|
|
18830
|
-
cfgCtx.commentLimit ?? DEFAULT_COMMENT_LIMIT,
|
|
18831
|
-
cfgCtx.commentMaxBytes ?? DEFAULT_COMMENT_MAX_BYTES
|
|
18832
|
-
);
|
|
18833
|
-
ctx.data.issue = { ...issue2, commentsFormatted };
|
|
18834
|
-
if (issue2.isPullRequest) {
|
|
18835
|
-
ctx.data.commentTargetType = "pr";
|
|
18836
|
-
ctx.data.commentTargetNumber = issueNumber;
|
|
18837
|
-
ctx.skipAgent = true;
|
|
18838
|
-
ctx.output.exitCode = 1;
|
|
18839
|
-
ctx.output.reason = `run target #${issueNumber} is a pull request; dispatch a PR action or the source issue instead`;
|
|
18840
|
-
return;
|
|
18841
|
-
}
|
|
18842
|
-
ctx.data.commentTargetType = "issue";
|
|
18843
|
-
ctx.data.commentTargetNumber = issueNumber;
|
|
18844
|
-
const argBase = resolveBaseOverride(ctx.args.base);
|
|
18845
|
-
const baseRaw = ctx.args.base;
|
|
18846
|
-
if (baseRaw && !argBase) {
|
|
18847
|
-
process.stderr.write(`[kody runFlow] ignoring --base "${baseRaw}" (must match kody-task or goal-branch pattern)
|
|
18848
|
-
`);
|
|
18849
|
-
}
|
|
18850
|
-
const base = argBase;
|
|
18851
|
-
if (base) {
|
|
18852
|
-
ctx.data.baseBranch = base;
|
|
18853
|
-
process.stderr.write(`[kody runFlow] resolved base branch: ${base} (from --base)
|
|
18854
|
-
`);
|
|
18855
|
-
}
|
|
18856
|
-
const branchInfo = ensureFeatureBranch(
|
|
18857
|
-
issueNumber,
|
|
18858
|
-
issue2.title,
|
|
18859
|
-
ctx.config.git.defaultBranch,
|
|
18860
|
-
ctx.cwd,
|
|
18861
|
-
base ?? void 0
|
|
18862
|
-
);
|
|
18863
|
-
ctx.data.branch = branchInfo.branch;
|
|
18864
|
-
const runUrl = getRunUrl();
|
|
18865
|
-
const startMsg = runUrl ? `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\`, run ${runUrl}` : `\u2699\uFE0F kody started \u2014 branch \`${ctx.data.branch}\``;
|
|
18866
|
-
tryPost(issueNumber, startMsg, ctx.cwd);
|
|
19037
|
+
tryPostPr6(prNumber, `\u{1F440} kody review started on PR #${prNumber}${runSuffix}`, ctx.cwd);
|
|
18867
19038
|
};
|
|
18868
19039
|
}
|
|
18869
19040
|
});
|
|
@@ -19633,7 +19804,7 @@ var init_skipAgent = __esm({
|
|
|
19633
19804
|
});
|
|
19634
19805
|
|
|
19635
19806
|
// src/scripts/stageMergeConflicts.ts
|
|
19636
|
-
import { execFileSync as
|
|
19807
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
19637
19808
|
var stageMergeConflicts;
|
|
19638
19809
|
var init_stageMergeConflicts = __esm({
|
|
19639
19810
|
"src/scripts/stageMergeConflicts.ts"() {
|
|
@@ -19641,7 +19812,7 @@ var init_stageMergeConflicts = __esm({
|
|
|
19641
19812
|
stageMergeConflicts = async (ctx) => {
|
|
19642
19813
|
if (ctx.data.agentDone === false) return;
|
|
19643
19814
|
try {
|
|
19644
|
-
|
|
19815
|
+
execFileSync21("git", ["add", "-A"], {
|
|
19645
19816
|
cwd: ctx.cwd,
|
|
19646
19817
|
env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
|
|
19647
19818
|
stdio: "pipe"
|
|
@@ -19694,113 +19865,6 @@ var init_startFlow = __esm({
|
|
|
19694
19865
|
}
|
|
19695
19866
|
});
|
|
19696
19867
|
|
|
19697
|
-
// src/scripts/syncFlow.ts
|
|
19698
|
-
import { execFileSync as execFileSync21 } from "child_process";
|
|
19699
|
-
function restoreDone(prNumber, cwd) {
|
|
19700
|
-
try {
|
|
19701
|
-
setKodyLabel(prNumber, DONE2, cwd);
|
|
19702
|
-
} catch {
|
|
19703
|
-
}
|
|
19704
|
-
}
|
|
19705
|
-
function bail2(ctx, prNumber, reason) {
|
|
19706
|
-
ctx.skipAgent = true;
|
|
19707
|
-
ctx.output.exitCode = 1;
|
|
19708
|
-
ctx.output.reason = reason;
|
|
19709
|
-
const runUrl = getRunUrl();
|
|
19710
|
-
const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
|
|
19711
|
-
tryPostPr6(prNumber, `\u274C kody sync could not complete${runSuffix}: ${reason}`, ctx.cwd);
|
|
19712
|
-
}
|
|
19713
|
-
function revParseHead(cwd) {
|
|
19714
|
-
try {
|
|
19715
|
-
return execFileSync21("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
|
|
19716
|
-
} catch {
|
|
19717
|
-
return "";
|
|
19718
|
-
}
|
|
19719
|
-
}
|
|
19720
|
-
function pushBranch(branch, cwd) {
|
|
19721
|
-
const result = pushWithRetry({ cwd: cwd ?? process.cwd(), branch, setUpstream: true });
|
|
19722
|
-
if (!result.ok) {
|
|
19723
|
-
throw new Error(result.reason);
|
|
19724
|
-
}
|
|
19725
|
-
}
|
|
19726
|
-
function tryPostPr6(prNumber, body, cwd) {
|
|
19727
|
-
try {
|
|
19728
|
-
postPrReviewComment(prNumber, body, cwd);
|
|
19729
|
-
} catch {
|
|
19730
|
-
}
|
|
19731
|
-
}
|
|
19732
|
-
var DONE2, syncFlow;
|
|
19733
|
-
var init_syncFlow = __esm({
|
|
19734
|
-
"src/scripts/syncFlow.ts"() {
|
|
19735
|
-
"use strict";
|
|
19736
|
-
init_branch();
|
|
19737
|
-
init_gha();
|
|
19738
|
-
init_issue();
|
|
19739
|
-
init_lifecycleLabels();
|
|
19740
|
-
init_pushWithRetry();
|
|
19741
|
-
DONE2 = {
|
|
19742
|
-
label: "kody:done",
|
|
19743
|
-
color: "0e8a16",
|
|
19744
|
-
description: "kody: PR ready for human review/merge"
|
|
19745
|
-
};
|
|
19746
|
-
syncFlow = async (ctx, _profile, args) => {
|
|
19747
|
-
const announceOnSuccess = Boolean(args?.announceOnSuccess);
|
|
19748
|
-
const prNumber = ctx.args.pr;
|
|
19749
|
-
const pr = getPr(prNumber, ctx.cwd);
|
|
19750
|
-
if (pr.state !== "OPEN") {
|
|
19751
|
-
bail2(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
|
|
19752
|
-
return;
|
|
19753
|
-
}
|
|
19754
|
-
ctx.data.pr = pr;
|
|
19755
|
-
if (announceOnSuccess) {
|
|
19756
|
-
ctx.data.commentTargetType = "pr";
|
|
19757
|
-
ctx.data.commentTargetNumber = prNumber;
|
|
19758
|
-
}
|
|
19759
|
-
checkoutPrBranch(prNumber, ctx.cwd);
|
|
19760
|
-
ctx.data.branch = getCurrentBranch(ctx.cwd);
|
|
19761
|
-
const baseBranch = pr.baseRefName || ctx.config.git.defaultBranch;
|
|
19762
|
-
ctx.data.baseBranch = baseBranch;
|
|
19763
|
-
const headBefore = revParseHead(ctx.cwd);
|
|
19764
|
-
const mergeStatus = mergeBase(baseBranch, ctx.cwd);
|
|
19765
|
-
if (mergeStatus === "error") {
|
|
19766
|
-
bail2(ctx, prNumber, `failed to merge origin/${baseBranch} (non-conflict error); see runner log`);
|
|
19767
|
-
return;
|
|
19768
|
-
}
|
|
19769
|
-
if (mergeStatus === "conflict") {
|
|
19770
|
-
bail2(
|
|
19771
|
-
ctx,
|
|
19772
|
-
prNumber,
|
|
19773
|
-
`merge from origin/${baseBranch} produced conflicts \u2014 run \`@kody resolve\` to let kody resolve them`
|
|
19774
|
-
);
|
|
19775
|
-
return;
|
|
19776
|
-
}
|
|
19777
|
-
const headAfter = revParseHead(ctx.cwd);
|
|
19778
|
-
if (headAfter === headBefore) {
|
|
19779
|
-
ctx.data.syncResult = "noop";
|
|
19780
|
-
if (announceOnSuccess) {
|
|
19781
|
-
ctx.output.exitCode = 0;
|
|
19782
|
-
ctx.output.reason = `already up to date with origin/${baseBranch}`;
|
|
19783
|
-
restoreDone(prNumber, ctx.cwd);
|
|
19784
|
-
}
|
|
19785
|
-
return;
|
|
19786
|
-
}
|
|
19787
|
-
try {
|
|
19788
|
-
pushBranch(ctx.data.branch, ctx.cwd);
|
|
19789
|
-
} catch (err) {
|
|
19790
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
19791
|
-
bail2(ctx, prNumber, `merge succeeded but push failed: ${msg}`);
|
|
19792
|
-
return;
|
|
19793
|
-
}
|
|
19794
|
-
ctx.data.syncResult = "merged";
|
|
19795
|
-
if (announceOnSuccess) {
|
|
19796
|
-
ctx.output.exitCode = 0;
|
|
19797
|
-
ctx.output.reason = `merged origin/${baseBranch} into ${ctx.data.branch}`;
|
|
19798
|
-
restoreDone(prNumber, ctx.cwd);
|
|
19799
|
-
}
|
|
19800
|
-
};
|
|
19801
|
-
}
|
|
19802
|
-
});
|
|
19803
|
-
|
|
19804
19868
|
// src/scripts/validateAgencyModelProposal.ts
|
|
19805
19869
|
import * as path46 from "path";
|
|
19806
19870
|
function validateModelBundle(bundle, expectedKind, options = {}) {
|
|
@@ -20830,12 +20894,12 @@ var init_scripts = __esm({
|
|
|
20830
20894
|
init_diagMcp();
|
|
20831
20895
|
init_discoverQaContext();
|
|
20832
20896
|
init_dispatch();
|
|
20897
|
+
init_dispatchAgencyLoops();
|
|
20833
20898
|
init_dispatchCapabilityFileTicks();
|
|
20834
20899
|
init_dispatchCapabilityTicks();
|
|
20835
20900
|
init_dispatchClassified();
|
|
20836
|
-
init_dispatchAgencyLoops();
|
|
20837
|
-
init_dispatchSimpleLoops();
|
|
20838
20901
|
init_dispatchNextTaskJob();
|
|
20902
|
+
init_dispatchSimpleLoops();
|
|
20839
20903
|
init_ensurePr();
|
|
20840
20904
|
init_evaluateAgencyBoundaries();
|
|
20841
20905
|
init_failOnceTaskJob();
|
|
@@ -20846,7 +20910,6 @@ var init_scripts = __esm({
|
|
|
20846
20910
|
init_initFlow();
|
|
20847
20911
|
init_loadAgentAdhoc();
|
|
20848
20912
|
init_loadCapabilityState();
|
|
20849
|
-
init_loadSimpleCapability();
|
|
20850
20913
|
init_loadCompanyIntents();
|
|
20851
20914
|
init_loadCompanyPortfolio();
|
|
20852
20915
|
init_loadConventions();
|
|
@@ -20859,6 +20922,7 @@ var init_scripts = __esm({
|
|
|
20859
20922
|
init_loadMemoryContext();
|
|
20860
20923
|
init_loadPriorArt();
|
|
20861
20924
|
init_loadQaContext();
|
|
20925
|
+
init_loadSimpleCapability();
|
|
20862
20926
|
init_loadTaskContext();
|
|
20863
20927
|
init_loadTaskState();
|
|
20864
20928
|
init_markFlowSuccess();
|
|
@@ -20871,8 +20935,8 @@ var init_scripts = __esm({
|
|
|
20871
20935
|
init_parseAgentResult();
|
|
20872
20936
|
init_parseIssueStateFromAgentResult();
|
|
20873
20937
|
init_parseJobStateFromAgentResult();
|
|
20874
|
-
init_parseSimpleCapabilityOutput();
|
|
20875
20938
|
init_parseReproOutput();
|
|
20939
|
+
init_parseSimpleCapabilityOutput();
|
|
20876
20940
|
init_persistArtifacts();
|
|
20877
20941
|
init_persistFlowState();
|
|
20878
20942
|
init_planTaskJobs();
|
|
@@ -20882,6 +20946,7 @@ var init_scripts = __esm({
|
|
|
20882
20946
|
init_postResearchComment();
|
|
20883
20947
|
init_postReviewResult();
|
|
20884
20948
|
init_prepareBrowserAuth();
|
|
20949
|
+
init_prepareCapabilityDelivery();
|
|
20885
20950
|
init_promoteQaGoal();
|
|
20886
20951
|
init_publishReport();
|
|
20887
20952
|
init_recordClassification();
|
|
@@ -20943,6 +21008,7 @@ var init_scripts = __esm({
|
|
|
20943
21008
|
loadPriorArt,
|
|
20944
21009
|
loadQaContext,
|
|
20945
21010
|
prepareBrowserAuth,
|
|
21011
|
+
prepareCapabilityDelivery,
|
|
20946
21012
|
buildSyntheticPlugin,
|
|
20947
21013
|
resolveArtifacts,
|
|
20948
21014
|
discoverQaContext,
|
|
@@ -22303,6 +22369,9 @@ function validateJob(input) {
|
|
|
22303
22369
|
if (j.cliArgs !== void 0 && (typeof j.cliArgs !== "object" || j.cliArgs === null)) {
|
|
22304
22370
|
throw new InvalidJobError("job.cliArgs must be an object when present");
|
|
22305
22371
|
}
|
|
22372
|
+
if (j.delivery !== void 0 && j.delivery !== "pull-request") {
|
|
22373
|
+
throw new InvalidJobError(`job.delivery must be "pull-request" (got ${String(j.delivery)})`);
|
|
22374
|
+
}
|
|
22306
22375
|
return {
|
|
22307
22376
|
action: typeof j.action === "string" ? j.action : void 0,
|
|
22308
22377
|
implementation: typeof j.implementation === "string" ? j.implementation : void 0,
|
|
@@ -22312,6 +22381,7 @@ function validateJob(input) {
|
|
|
22312
22381
|
agent: typeof j.agent === "string" ? j.agent : void 0,
|
|
22313
22382
|
schedule: typeof j.schedule === "string" ? j.schedule : void 0,
|
|
22314
22383
|
target: typeof j.target === "number" ? j.target : void 0,
|
|
22384
|
+
delivery: j.delivery === "pull-request" ? j.delivery : void 0,
|
|
22315
22385
|
cliArgs: j.cliArgs ?? {},
|
|
22316
22386
|
workflowFacts: j.workflowFacts && typeof j.workflowFacts === "object" && !Array.isArray(j.workflowFacts) ? j.workflowFacts : void 0,
|
|
22317
22387
|
workflowState: parseWorkflowRunState(j.workflowState) ?? void 0,
|
|
@@ -22364,7 +22434,7 @@ async function runJob(job, base) {
|
|
|
22364
22434
|
}
|
|
22365
22435
|
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
22366
22436
|
const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
|
|
22367
|
-
const capabilitySelectedImplementation = resolvedCapability?.implementation ?? capabilityContext?.config.implementation ?? capabilityContext?.config.implementations?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
22437
|
+
const capabilitySelectedImplementation = valid.delivery === "pull-request" && resolvedCapability?.implementation === "capability-run" ? "capability-delivery" : resolvedCapability?.implementation ?? capabilityContext?.config.implementation ?? capabilityContext?.config.implementations?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
22368
22438
|
const profileName = explicitImplementation ?? capabilitySelectedImplementation;
|
|
22369
22439
|
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedImplementation, base)) {
|
|
22370
22440
|
const workflowCapability = capabilityContext ?? workflowContext;
|
|
@@ -22454,6 +22524,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
22454
22524
|
preloadedData.jobKey = stableJobKey(valid);
|
|
22455
22525
|
preloadedData.jobFlavor = valid.flavor;
|
|
22456
22526
|
if (valid.target !== void 0) preloadedData.jobTarget = valid.target;
|
|
22527
|
+
if (valid.delivery !== void 0) preloadedData.jobDelivery = valid.delivery;
|
|
22457
22528
|
if (valid.action !== void 0 && valid.action.length > 0) preloadedData.jobAction = valid.action;
|
|
22458
22529
|
if (capabilityIdentity !== void 0 && capabilityIdentity.length > 0)
|
|
22459
22530
|
preloadedData.jobCapability = capabilityIdentity;
|
|
@@ -22493,11 +22564,13 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
22493
22564
|
};
|
|
22494
22565
|
const shouldApplyResolvedCapabilityArgs = valid.implementation === void 0 && resolvedCapability && profileName === resolvedCapability.implementation;
|
|
22495
22566
|
input.cliArgs = shouldApplyResolvedCapabilityArgs ? { ...resolvedCapability.cliArgs, ...input.cliArgs } : input.cliArgs;
|
|
22496
|
-
if (profileName === "capability-run" && capabilityIdentity) {
|
|
22567
|
+
if ((profileName === "capability-run" || profileName === "capability-delivery") && capabilityIdentity) {
|
|
22497
22568
|
const capabilityInput = Object.keys(valid.cliArgs).length > 0 ? genericInputFromArgs(valid.cliArgs) : void 0;
|
|
22569
|
+
const deliveryTarget = profileName === "capability-delivery" && capabilityInput && typeof capabilityInput === "object" ? capabilityDeliveryArgs(capabilityInput) : {};
|
|
22498
22570
|
input.cliArgs = {
|
|
22499
22571
|
capability: capabilityIdentity,
|
|
22500
|
-
...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {}
|
|
22572
|
+
...capabilityInput !== void 0 ? { input: JSON.stringify(capabilityInput) } : {},
|
|
22573
|
+
...deliveryTarget
|
|
22501
22574
|
};
|
|
22502
22575
|
}
|
|
22503
22576
|
const run = base.chain === false ? runImplementation : runImplementationChain;
|
|
@@ -22854,6 +22927,7 @@ function workflowStepToJob(step, parent, chainData, cwd) {
|
|
|
22854
22927
|
...parent.agent ? { agent: parent.agent } : {},
|
|
22855
22928
|
...parent.schedule ? { schedule: parent.schedule } : {},
|
|
22856
22929
|
...typeof target === "number" ? { target } : {},
|
|
22930
|
+
...step.delivery ? { delivery: step.delivery } : {},
|
|
22857
22931
|
cliArgs,
|
|
22858
22932
|
...step.evidence ? { evidence: step.evidence } : parent.evidence ? { evidence: parent.evidence } : {},
|
|
22859
22933
|
flavor: parent.flavor,
|
|
@@ -22863,6 +22937,10 @@ function workflowStepToJob(step, parent, chainData, cwd) {
|
|
|
22863
22937
|
...parent.resultTarget ? { resultTarget: parent.resultTarget } : {}
|
|
22864
22938
|
};
|
|
22865
22939
|
}
|
|
22940
|
+
function capabilityDeliveryArgs(input) {
|
|
22941
|
+
const target = capabilityDeliveryTarget(input);
|
|
22942
|
+
return target ? { [target.kind]: target.number } : {};
|
|
22943
|
+
}
|
|
22866
22944
|
function usesGenericCapabilityInput(action, cwd) {
|
|
22867
22945
|
const inputs = getCapabilityActionInputs(action, hydratedCapabilitiesRoot(cwd));
|
|
22868
22946
|
return Boolean(inputs?.length === 1 && inputs[0]?.name === "input" && inputs[0]?.flag === "--input");
|
|
@@ -23027,6 +23105,7 @@ var init_job = __esm({
|
|
|
23027
23105
|
"src/job.ts"() {
|
|
23028
23106
|
"use strict";
|
|
23029
23107
|
init_agencyBoundaryEval();
|
|
23108
|
+
init_capabilityDelivery();
|
|
23030
23109
|
init_capabilityFolders();
|
|
23031
23110
|
init_definition_paths();
|
|
23032
23111
|
init_executor();
|