@open-tomato/rafa 0.15.0 → 0.17.0
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/README.md +20 -1
- package/dist/SKILL.md +8 -5
- package/dist/cli.js +9772 -6445
- package/dist/describe-wbn759vf.js +13 -0
- package/dist/effort/store/index.js +4 -2
- package/dist/index-4qd537z6.js +13332 -0
- package/dist/{index-p572cxex.js → index-64wec0k7.js} +24 -9
- package/dist/{index-1x5t4t9r.js → index-7t0qz29r.js} +33 -28
- package/dist/index-n3rw8rhr.js +397 -0
- package/dist/index-p901zs2p.js +124 -0
- package/dist/{index-2256nwj0.js → index-ps5sac9p.js} +43 -396
- package/dist/index-qzhpqmfy.js +234 -0
- package/dist/index-r7cnr44m.js +19857 -0
- package/dist/index.js +40 -11660
- package/dist/plan/index.js +5 -3
- package/dist/plan-prompt.md +3 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
activeOutput,
|
|
4
|
-
messageOf,
|
|
5
|
-
parseTaskDeclaration,
|
|
6
4
|
readRafaBlocks
|
|
7
|
-
} from "./index-
|
|
5
|
+
} from "./index-ps5sac9p.js";
|
|
6
|
+
import {
|
|
7
|
+
messageOf,
|
|
8
|
+
parseTaskDeclaration
|
|
9
|
+
} from "./index-n3rw8rhr.js";
|
|
8
10
|
// src/preflight/prerequisites-md.ts
|
|
9
11
|
import { basename, dirname, join } from "path";
|
|
10
12
|
var SECTION_AUTO_RE = /\[auto\]/i;
|
|
@@ -14,7 +16,7 @@ var ITEM_RE = /^-\s+\[\s*\]\s+/;
|
|
|
14
16
|
var INLINE_AUTO_RE = /^-\s+\[\s*\]\s+\[auto\]\s+/i;
|
|
15
17
|
var INLINE_HUMAN_RE = /^-\s+\[\s*\]\s+\[human\]\s+/i;
|
|
16
18
|
var INLINE_START_RE = /^-\s+\[\s*\]\s+\[start\]\s+/i;
|
|
17
|
-
var
|
|
19
|
+
var PROBE_RE = /:\s+`([^`]+)`\s*$/;
|
|
18
20
|
var HEADING_MARKS_RE = /^#+/;
|
|
19
21
|
var FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
|
|
20
22
|
var NESTED_LIST_ITEM_RE = /^\s+(?:[-*+]|\d+[.)])\s/;
|
|
@@ -76,7 +78,7 @@ function isProbedTag(tag) {
|
|
|
76
78
|
return tag === "auto" || tag === "start";
|
|
77
79
|
}
|
|
78
80
|
function extractProbe(description) {
|
|
79
|
-
const probe =
|
|
81
|
+
const probe = PROBE_RE.exec(description)?.[1]?.trim();
|
|
80
82
|
return probe || null;
|
|
81
83
|
}
|
|
82
84
|
function readItem(lines, lineIndex, inherited) {
|
|
@@ -123,24 +125,37 @@ function requiredItemsTagged(items, tag) {
|
|
|
123
125
|
const probed = items.filter(isProbed).filter((item) => item.tag === tag);
|
|
124
126
|
return Object.freeze(probed.map(requiredItem));
|
|
125
127
|
}
|
|
126
|
-
function
|
|
128
|
+
function namedItemOf(item) {
|
|
127
129
|
return Object.freeze({ description: item.description, tag: item.tag, line: item.lineIndex + 1 });
|
|
128
130
|
}
|
|
131
|
+
function isMalformed(item) {
|
|
132
|
+
return isProbedTag(item.tag) && item.probe === null;
|
|
133
|
+
}
|
|
129
134
|
function planPrerequisites(content) {
|
|
130
135
|
const items = parsePrerequisites(content);
|
|
131
136
|
return Object.freeze({
|
|
132
137
|
required: requiredItemsTagged(items, "auto"),
|
|
133
138
|
startRequired: requiredItemsTagged(items, "start"),
|
|
134
|
-
reminders: Object.freeze(items.filter((item) => !
|
|
139
|
+
reminders: Object.freeze(items.filter((item) => !isProbedTag(item.tag)).map(namedItemOf)),
|
|
140
|
+
malformed: Object.freeze(items.filter(isMalformed).map(namedItemOf))
|
|
135
141
|
});
|
|
136
142
|
}
|
|
143
|
+
var PROBE_ITEM_EXAMPLE = "- [ ] uv installed: `uvx --version`";
|
|
144
|
+
function malformedPrerequisiteLines(file, malformed) {
|
|
145
|
+
return [
|
|
146
|
+
`${file} holds ${malformed.length} malformed [auto] or [start] item(s): no command ends the item after a final ": ".`,
|
|
147
|
+
...malformed.map((item) => ` line ${item.line} [${item.tag}]: ${item.description}`),
|
|
148
|
+
`Write each as ${PROBE_ITEM_EXAMPLE}, its one backticked span a complete command run as written;` + " prove a tool is there with `<tool> --version`, `<tool> --help` or `which <tool>`."
|
|
149
|
+
];
|
|
150
|
+
}
|
|
137
151
|
function mergePlanPrerequisites(settings, content) {
|
|
138
152
|
const plan = planPrerequisites(content ?? "");
|
|
139
153
|
return Object.freeze({
|
|
140
154
|
required: Object.freeze([...settings.prerequisitesRequired, ...plan.required]),
|
|
141
155
|
startRequired: plan.startRequired,
|
|
142
156
|
optional: Object.freeze([...settings.prerequisitesOptional]),
|
|
143
|
-
reminders: plan.reminders
|
|
157
|
+
reminders: plan.reminders,
|
|
158
|
+
malformed: plan.malformed
|
|
144
159
|
});
|
|
145
160
|
}
|
|
146
161
|
function prerequisitesPathForPlan(planPath) {
|
|
@@ -1098,4 +1113,4 @@ function renderInjection(request) {
|
|
|
1098
1113
|
}
|
|
1099
1114
|
return { requested: mode, mode, text: RENDERERS[mode](model, location.task), fallback: null };
|
|
1100
1115
|
}
|
|
1101
|
-
export { isStampableStub, planStubFromPrompt, stampPrompt, planStubFromPath, REPORT_STATUSES, FINDING_KINDS, FINDING_SIGNALS, CHANGE_LEVELS, parseReport, escapeBlockerText, findNextTask, updateTrackerLine, writeTrackerBlocker, trackerPathFor, PLAN_BLOCK_KINDS, PLAN_HEADER_FIELDS, parsePlan, parsePrerequisites, planPrerequisites, mergePlanPrerequisites, prerequisitesPathForPlan, loadPlanPrerequisites, PROBE_TIMEOUT_MS, runShellProbe, runPreflight, renderInjection };
|
|
1116
|
+
export { isStampableStub, planStubFromPrompt, stampPrompt, planStubFromPath, REPORT_STATUSES, FINDING_KINDS, FINDING_SIGNALS, CHANGE_LEVELS, parseReport, escapeBlockerText, splitBlockerComment, findNextTask, updateTrackerLine, writeTrackerBlocker, trackerPathFor, PLAN_BLOCK_KINDS, PLAN_HEADER_FIELDS, parsePlan, parsePrerequisites, planPrerequisites, malformedPrerequisiteLines, mergePlanPrerequisites, prerequisitesPathForPlan, loadPlanPrerequisites, PROBE_TIMEOUT_MS, runShellProbe, runPreflight, renderInjection };
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
STORE_BACKENDS,
|
|
4
3
|
activeOutput,
|
|
5
4
|
activeOutputMode,
|
|
6
5
|
createTextOutput,
|
|
6
|
+
readRafaBlocks
|
|
7
|
+
} from "./index-ps5sac9p.js";
|
|
8
|
+
import {
|
|
9
|
+
commandSpelling
|
|
10
|
+
} from "./index-p901zs2p.js";
|
|
11
|
+
import {
|
|
12
|
+
STORE_BACKENDS,
|
|
7
13
|
describeValue,
|
|
8
14
|
isMapping,
|
|
9
|
-
messageOf
|
|
10
|
-
|
|
11
|
-
} from "./index-2256nwj0.js";
|
|
15
|
+
messageOf
|
|
16
|
+
} from "./index-n3rw8rhr.js";
|
|
12
17
|
|
|
13
18
|
// src/effort/store.ts
|
|
14
19
|
import {
|
|
@@ -840,27 +845,6 @@ function parseSpecReview(output) {
|
|
|
840
845
|
return judged(verdict, readGaps(document, issues), block, issues);
|
|
841
846
|
}
|
|
842
847
|
|
|
843
|
-
// src/cli/command.ts
|
|
844
|
-
var MAX_EXIT_CODE = 255;
|
|
845
|
-
|
|
846
|
-
class CommandExit extends Error {
|
|
847
|
-
exitCode;
|
|
848
|
-
constructor(exitCode, message = "") {
|
|
849
|
-
super(message);
|
|
850
|
-
if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > MAX_EXIT_CODE) {
|
|
851
|
-
throw new TypeError(`CommandExit: exit code is ${describeValue(exitCode)}, expected a whole number from 0 to ${MAX_EXIT_CODE}`);
|
|
852
|
-
}
|
|
853
|
-
this.name = "CommandExit";
|
|
854
|
-
this.exitCode = exitCode;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
function isTopLevel(command) {
|
|
858
|
-
return command.subject === command.action;
|
|
859
|
-
}
|
|
860
|
-
function commandSpelling(command) {
|
|
861
|
-
return isTopLevel(command) ? command.subject : `${command.subject} ${command.action}`;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
848
|
// src/cli/running.ts
|
|
865
849
|
var running = null;
|
|
866
850
|
function runningCommand() {
|
|
@@ -1133,7 +1117,7 @@ var REST_STATES = {
|
|
|
1133
1117
|
cancelled: "closed"
|
|
1134
1118
|
};
|
|
1135
1119
|
function createGhRunner(options) {
|
|
1136
|
-
const { cwd, command = "gh", env } = options;
|
|
1120
|
+
const { cwd, command = "gh", env, timeoutMs } = options;
|
|
1137
1121
|
return async (args) => {
|
|
1138
1122
|
const executable = env === undefined ? command : Bun.which(command, { PATH: env.PATH ?? "", cwd });
|
|
1139
1123
|
if (executable === null) {
|
|
@@ -1147,17 +1131,38 @@ function createGhRunner(options) {
|
|
|
1147
1131
|
stdout: "pipe",
|
|
1148
1132
|
stderr: "pipe"
|
|
1149
1133
|
});
|
|
1150
|
-
const
|
|
1134
|
+
const finished = Promise.all([
|
|
1151
1135
|
new Response(proc.stdout).text(),
|
|
1152
1136
|
new Response(proc.stderr).text(),
|
|
1153
1137
|
proc.exited
|
|
1154
1138
|
]);
|
|
1139
|
+
const outcome = await withDeadline(finished, timeoutMs);
|
|
1140
|
+
if (outcome === TIMED_OUT) {
|
|
1141
|
+
proc.kill("SIGKILL");
|
|
1142
|
+
await proc.exited;
|
|
1143
|
+
return { ok: false, stdout: "", stderr: `${command} in ${cwd} timed out after ${timeoutMs}ms and was killed` };
|
|
1144
|
+
}
|
|
1145
|
+
const [stdout, stderr, exitCode] = outcome;
|
|
1155
1146
|
return { ok: exitCode === 0, stdout, stderr };
|
|
1156
1147
|
} catch (error) {
|
|
1157
1148
|
return { ok: false, stdout: "", stderr: `could not run ${command} in ${cwd}: ${messageOf(error)}` };
|
|
1158
1149
|
}
|
|
1159
1150
|
};
|
|
1160
1151
|
}
|
|
1152
|
+
var TIMED_OUT = Symbol("timed out");
|
|
1153
|
+
async function withDeadline(work, timeoutMs) {
|
|
1154
|
+
if (timeoutMs === undefined)
|
|
1155
|
+
return work;
|
|
1156
|
+
let timer;
|
|
1157
|
+
const deadline = new Promise((resolve2) => {
|
|
1158
|
+
timer = setTimeout(() => resolve2(TIMED_OUT), timeoutMs);
|
|
1159
|
+
});
|
|
1160
|
+
try {
|
|
1161
|
+
return await Promise.race([work, deadline]);
|
|
1162
|
+
} finally {
|
|
1163
|
+
clearTimeout(timer);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1161
1166
|
function notOnPath(command, cwd, path) {
|
|
1162
1167
|
const searched = path === undefined ? "an environment with no PATH" : `PATH ${JSON.stringify(path)}`;
|
|
1163
1168
|
return `could not run ${command} in ${cwd}: not found on ${searched} (ENOENT)`;
|
|
@@ -1855,4 +1860,4 @@ function selectEffortStore(repoRoot, config) {
|
|
|
1855
1860
|
return adapter.create({ repoRoot });
|
|
1856
1861
|
}
|
|
1857
1862
|
|
|
1858
|
-
export { EFFORT_KEY_PROJECTIONS, openNdjsonStore, sqliteStorePath, LONE_SURROGATE, withSqliteStore, writeSqliteStore, openSqliteStore,
|
|
1863
|
+
export { EFFORT_STORE_DIR, effortStorePath, EFFORT_KEY_PROJECTIONS, openNdjsonStore, sqliteStorePath, LONE_SURROGATE, withSqliteStore, writeSqliteStore, openSqliteStore, sessionSpawnEnv, getClaudeUsagePercent, checkUsage, claudeArgs, interruptClaudeSessions, runClaude, spawnClaudeCaptured, runClaudeCaptured, planFilePath, ClaudePlannerError, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_STATES, GITHUB_LABELS, createGhRunner, typeOfLabels, moduleOfLabels, createLocalTracker, PORT_VERSIONS, createAdapterRegistry, CORE_ADAPTER_REGISTRY, selectEffortStore };
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __require = import.meta.require;
|
|
3
|
+
|
|
4
|
+
// src/pr/types.ts
|
|
5
|
+
var MERGE_METHODS = Object.freeze([
|
|
6
|
+
"squash",
|
|
7
|
+
"merge",
|
|
8
|
+
"rebase"
|
|
9
|
+
]);
|
|
10
|
+
function isMergeMethod(value) {
|
|
11
|
+
return typeof value === "string" && MERGE_METHODS.includes(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/utils/declaration.ts
|
|
15
|
+
var DECLARATION_KEYS = [
|
|
16
|
+
"agent",
|
|
17
|
+
"model",
|
|
18
|
+
"effort",
|
|
19
|
+
"budget",
|
|
20
|
+
"tools",
|
|
21
|
+
"skills"
|
|
22
|
+
];
|
|
23
|
+
var GRANULAR_KEYS = ["model", "effort", "tools"];
|
|
24
|
+
var AGENT_OWNED_KEYS = ["model", "tools"];
|
|
25
|
+
var MODEL_ALIASES = ["opus", "sonnet", "haiku", "fable"];
|
|
26
|
+
var EFFORT_LEVELS = [
|
|
27
|
+
"low",
|
|
28
|
+
"medium",
|
|
29
|
+
"high",
|
|
30
|
+
"xhigh",
|
|
31
|
+
"max"
|
|
32
|
+
];
|
|
33
|
+
var DECLARATION_BLOCK = /\{([^{}]*)\}$/;
|
|
34
|
+
var ENTRY_TOKEN = /^([A-Za-z_][A-Za-z0-9_-]*)=(.*)$/;
|
|
35
|
+
var FULL_MODEL_NAME = /^claude-[a-z0-9][a-z0-9.-]*$/;
|
|
36
|
+
var AGENT_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
37
|
+
function isAgentName(value) {
|
|
38
|
+
return AGENT_NAME.test(value);
|
|
39
|
+
}
|
|
40
|
+
var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
41
|
+
var SKILL_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
42
|
+
var BUDGET_FLAG = "--max-budget-usd";
|
|
43
|
+
var BUDGET_VALUE = /^(?:0|[1-9]\d{0,5})(?:\.\d{1,6})?$/;
|
|
44
|
+
function parseBudgetUsd(value) {
|
|
45
|
+
if (!BUDGET_VALUE.test(value))
|
|
46
|
+
return null;
|
|
47
|
+
const usd = Number(value);
|
|
48
|
+
return usd > 0 ? usd : null;
|
|
49
|
+
}
|
|
50
|
+
function isEffortLevel(value) {
|
|
51
|
+
return EFFORT_LEVELS.includes(value);
|
|
52
|
+
}
|
|
53
|
+
function isModelValue(value) {
|
|
54
|
+
if (MODEL_ALIASES.includes(value))
|
|
55
|
+
return true;
|
|
56
|
+
return FULL_MODEL_NAME.test(value);
|
|
57
|
+
}
|
|
58
|
+
function parseToolList(value) {
|
|
59
|
+
const parts = value.split(",");
|
|
60
|
+
if (parts.length === 0)
|
|
61
|
+
return null;
|
|
62
|
+
const tools = [];
|
|
63
|
+
for (const part of parts) {
|
|
64
|
+
if (!TOOL_NAME.test(part))
|
|
65
|
+
return null;
|
|
66
|
+
if (!tools.includes(part))
|
|
67
|
+
tools.push(part);
|
|
68
|
+
}
|
|
69
|
+
return tools;
|
|
70
|
+
}
|
|
71
|
+
function parseSkillList(value) {
|
|
72
|
+
const parts = value.split(",");
|
|
73
|
+
if (parts.length === 0)
|
|
74
|
+
return null;
|
|
75
|
+
const skills = [];
|
|
76
|
+
for (const part of parts) {
|
|
77
|
+
if (!SKILL_NAME.test(part))
|
|
78
|
+
return null;
|
|
79
|
+
if (!skills.includes(part))
|
|
80
|
+
skills.push(part);
|
|
81
|
+
}
|
|
82
|
+
return skills;
|
|
83
|
+
}
|
|
84
|
+
function unusableValue(key, token) {
|
|
85
|
+
return { reason: "unusable-value", key, text: token };
|
|
86
|
+
}
|
|
87
|
+
function isDeclarationKey(key) {
|
|
88
|
+
return DECLARATION_KEYS.includes(key);
|
|
89
|
+
}
|
|
90
|
+
function tokenise(body) {
|
|
91
|
+
const trimmed = body.trim();
|
|
92
|
+
if (trimmed.length === 0)
|
|
93
|
+
return [];
|
|
94
|
+
return trimmed.split(/\s+/);
|
|
95
|
+
}
|
|
96
|
+
function readBlock(raw, body) {
|
|
97
|
+
const entries = [];
|
|
98
|
+
const extras = [];
|
|
99
|
+
const issues = [];
|
|
100
|
+
const seen = new Set;
|
|
101
|
+
let agent = null;
|
|
102
|
+
let model = null;
|
|
103
|
+
let effort = null;
|
|
104
|
+
let budget = null;
|
|
105
|
+
let tools = null;
|
|
106
|
+
let skills = null;
|
|
107
|
+
for (const token of tokenise(body)) {
|
|
108
|
+
const match = token.match(ENTRY_TOKEN);
|
|
109
|
+
const key = match?.[1];
|
|
110
|
+
const value = match?.[2];
|
|
111
|
+
if (key === undefined || value === undefined) {
|
|
112
|
+
issues.push({ reason: "stray-token", key: "", text: token });
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const entry = { key, value };
|
|
116
|
+
entries.push(entry);
|
|
117
|
+
if (!isDeclarationKey(key)) {
|
|
118
|
+
extras.push(entry);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (seen.has(key)) {
|
|
122
|
+
issues.push({ reason: "duplicate-key", key, text: token });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
seen.add(key);
|
|
126
|
+
if (key === "agent") {
|
|
127
|
+
if (AGENT_NAME.test(value))
|
|
128
|
+
agent = value;
|
|
129
|
+
else
|
|
130
|
+
issues.push(unusableValue(key, token));
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (key === "model") {
|
|
134
|
+
if (isModelValue(value))
|
|
135
|
+
model = value;
|
|
136
|
+
else
|
|
137
|
+
issues.push(unusableValue(key, token));
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (key === "effort") {
|
|
141
|
+
if (isEffortLevel(value))
|
|
142
|
+
effort = value;
|
|
143
|
+
else
|
|
144
|
+
issues.push(unusableValue(key, token));
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (key === "budget") {
|
|
148
|
+
const usd = parseBudgetUsd(value);
|
|
149
|
+
if (usd === null)
|
|
150
|
+
issues.push(unusableValue(key, token));
|
|
151
|
+
else
|
|
152
|
+
budget = usd;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (key === "tools") {
|
|
156
|
+
const parsed = parseToolList(value);
|
|
157
|
+
if (parsed === null)
|
|
158
|
+
issues.push(unusableValue(key, token));
|
|
159
|
+
else
|
|
160
|
+
tools = parsed;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const named = parseSkillList(value);
|
|
164
|
+
if (named === null)
|
|
165
|
+
issues.push(unusableValue(key, token));
|
|
166
|
+
else
|
|
167
|
+
skills = named;
|
|
168
|
+
}
|
|
169
|
+
if (seen.size === 0)
|
|
170
|
+
return null;
|
|
171
|
+
return {
|
|
172
|
+
raw,
|
|
173
|
+
entries,
|
|
174
|
+
extras,
|
|
175
|
+
issues,
|
|
176
|
+
agent,
|
|
177
|
+
model,
|
|
178
|
+
effort,
|
|
179
|
+
budget,
|
|
180
|
+
tools,
|
|
181
|
+
skills
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function parseTaskDeclaration(taskText) {
|
|
185
|
+
const trimmed = taskText.trimEnd();
|
|
186
|
+
const match = trimmed.match(DECLARATION_BLOCK);
|
|
187
|
+
const raw = match?.[0];
|
|
188
|
+
const body = match?.[1];
|
|
189
|
+
if (raw === undefined || body === undefined) {
|
|
190
|
+
return { text: taskText, declaration: null };
|
|
191
|
+
}
|
|
192
|
+
const before = trimmed.slice(0, trimmed.length - raw.length).trimEnd();
|
|
193
|
+
if (before.length === 0)
|
|
194
|
+
return { text: taskText, declaration: null };
|
|
195
|
+
const declaration = readBlock(raw, body);
|
|
196
|
+
if (declaration === null)
|
|
197
|
+
return { text: taskText, declaration: null };
|
|
198
|
+
return { text: before, declaration };
|
|
199
|
+
}
|
|
200
|
+
function stripTaskDeclaration(taskText) {
|
|
201
|
+
return parseTaskDeclaration(taskText).text;
|
|
202
|
+
}
|
|
203
|
+
function budgetArgs(budget) {
|
|
204
|
+
return budget === null ? [] : [BUDGET_FLAG, String(budget)];
|
|
205
|
+
}
|
|
206
|
+
function resolveDeclarationFlags(declaration, agentDeclaresEffort) {
|
|
207
|
+
if (declaration === null)
|
|
208
|
+
return { args: [], suppressed: [] };
|
|
209
|
+
const { agent, effort } = declaration;
|
|
210
|
+
const isPresent = (key) => declaration[key] !== null;
|
|
211
|
+
const budget = budgetArgs(declaration.budget);
|
|
212
|
+
if (agent !== null) {
|
|
213
|
+
if (effort === null || agentDeclaresEffort(agent)) {
|
|
214
|
+
return { args: ["--agent", agent, ...budget], suppressed: GRANULAR_KEYS.filter(isPresent) };
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
args: ["--agent", agent, "--effort", effort, ...budget],
|
|
218
|
+
suppressed: AGENT_OWNED_KEYS.filter(isPresent)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const args = [];
|
|
222
|
+
if (declaration.model !== null)
|
|
223
|
+
args.push("--model", declaration.model);
|
|
224
|
+
if (declaration.effort !== null)
|
|
225
|
+
args.push("--effort", declaration.effort);
|
|
226
|
+
args.push(...budget);
|
|
227
|
+
if (declaration.tools !== null) {
|
|
228
|
+
args.push("--tools", declaration.tools.join(","));
|
|
229
|
+
}
|
|
230
|
+
return { args, suppressed: [] };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// src/config-sections.ts
|
|
234
|
+
function isMapping(value) {
|
|
235
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
236
|
+
}
|
|
237
|
+
function describeValue(value) {
|
|
238
|
+
if (typeof value === "string")
|
|
239
|
+
return JSON.stringify(value);
|
|
240
|
+
if (value === null)
|
|
241
|
+
return "null";
|
|
242
|
+
if (Array.isArray(value))
|
|
243
|
+
return "a list";
|
|
244
|
+
if (typeof value === "object")
|
|
245
|
+
return "a mapping";
|
|
246
|
+
return String(value);
|
|
247
|
+
}
|
|
248
|
+
function messageOf(error) {
|
|
249
|
+
return error instanceof Error ? error.message : String(error);
|
|
250
|
+
}
|
|
251
|
+
var CONFIG_VERSIONS = [1];
|
|
252
|
+
var STORE_BACKENDS = ["sqlite", "ndjson"];
|
|
253
|
+
var INJECT_MODES = ["full", "stage", "task"];
|
|
254
|
+
var OUTPUT_MODES = ["text", "json"];
|
|
255
|
+
var CLAUDE_SETTING_SOURCES = ["user", "project", "local"];
|
|
256
|
+
var PR_PROVIDERS = ["gh", "none"];
|
|
257
|
+
var RELEASE_AUTO = "auto";
|
|
258
|
+
function accepted(value) {
|
|
259
|
+
return { value, problems: [], extras: [] };
|
|
260
|
+
}
|
|
261
|
+
function refused(at, raw, expected) {
|
|
262
|
+
const problem = `${at.label} is ${describeValue(raw)}, expected ${expected}`;
|
|
263
|
+
return { value: undefined, problems: [problem], extras: [] };
|
|
264
|
+
}
|
|
265
|
+
function refusedWith(problems) {
|
|
266
|
+
return { value: undefined, problems, extras: [] };
|
|
267
|
+
}
|
|
268
|
+
function mapReading(reading, map) {
|
|
269
|
+
return reading.value === undefined ? { ...reading, value: undefined } : { ...reading, value: map(reading.value) };
|
|
270
|
+
}
|
|
271
|
+
function below(at, step) {
|
|
272
|
+
return { label: `${at.label}${step}`, key: `${at.key}${step}` };
|
|
273
|
+
}
|
|
274
|
+
function oneOf(values) {
|
|
275
|
+
const expected = `one of: ${values.join(", ")}`;
|
|
276
|
+
return (raw, at) => {
|
|
277
|
+
const hit = values.find((value) => value === raw);
|
|
278
|
+
return hit === undefined ? refused(at, raw, expected) : accepted(hit);
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function text(expected) {
|
|
282
|
+
return (raw, at) => typeof raw === "string" && raw.trim() !== "" ? accepted(raw) : refused(at, raw, expected);
|
|
283
|
+
}
|
|
284
|
+
var flag = (raw, at) => typeof raw === "boolean" ? accepted(raw) : refused(at, raw, "true or false");
|
|
285
|
+
var mergeMethod = oneOf(MERGE_METHODS);
|
|
286
|
+
var usdAmount = (raw, at) => {
|
|
287
|
+
const usd = typeof raw === "number" ? parseBudgetUsd(String(raw)) : null;
|
|
288
|
+
return usd === null ? refused(at, raw, "a number of US dollars above zero, at most six digits either side of the point") : accepted(usd);
|
|
289
|
+
};
|
|
290
|
+
var issueNumber = (raw, at) => typeof raw === "number" && Number.isSafeInteger(raw) && raw > 0 ? accepted(raw) : refused(at, raw, "an issue number, a whole number above zero");
|
|
291
|
+
var dayCount = (raw, at) => typeof raw === "number" && Number.isSafeInteger(raw) && raw > 0 ? accepted(raw) : refused(at, raw, "a number of days, a whole number above zero");
|
|
292
|
+
var releaseEnabled = (raw, at) => typeof raw === "boolean" || raw === RELEASE_AUTO ? accepted(raw) : refused(at, raw, `true, false or ${RELEASE_AUTO}`);
|
|
293
|
+
var GITHUB_LOGIN = /^[A-Za-z0-9][A-Za-z0-9-]*(?:\[bot\])?$/;
|
|
294
|
+
function isGitHubLogin(value) {
|
|
295
|
+
return typeof value === "string" && GITHUB_LOGIN.test(value);
|
|
296
|
+
}
|
|
297
|
+
var githubLogin = (raw, at) => isGitHubLogin(raw) ? accepted(raw) : refused(at, raw, "a GitHub login");
|
|
298
|
+
function listOf(item, expected) {
|
|
299
|
+
return (raw, at) => {
|
|
300
|
+
if (!Array.isArray(raw))
|
|
301
|
+
return refused(at, raw, `a list of ${expected}`);
|
|
302
|
+
const readings = raw.map((entry, index) => item(entry, below(at, `[${index}]`)));
|
|
303
|
+
const problems = readings.flatMap((reading) => reading.problems);
|
|
304
|
+
const extras = readings.flatMap((reading) => reading.extras);
|
|
305
|
+
if (problems.length > 0)
|
|
306
|
+
return { value: undefined, problems, extras };
|
|
307
|
+
const values = readings.flatMap((reading) => reading.value === undefined ? [] : [reading.value]);
|
|
308
|
+
return { value: Object.freeze(values), problems, extras };
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function subsetOf(values) {
|
|
312
|
+
const expected = `a comma-separated subset of: ${values.join(", ")}`;
|
|
313
|
+
return (raw, at) => {
|
|
314
|
+
if (typeof raw !== "string")
|
|
315
|
+
return refused(at, raw, expected);
|
|
316
|
+
const named = [];
|
|
317
|
+
for (const entry of raw.split(",")) {
|
|
318
|
+
const hit = values.find((value) => value === entry.trim());
|
|
319
|
+
if (hit === undefined || named.includes(hit))
|
|
320
|
+
return refused(at, raw, expected);
|
|
321
|
+
named.push(hit);
|
|
322
|
+
}
|
|
323
|
+
return accepted(Object.freeze(named));
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
var itemText = text("a non-empty string");
|
|
327
|
+
function readKeyedItem(shape, raw, at) {
|
|
328
|
+
const choices = shape.kinds.join(", ");
|
|
329
|
+
if (!isMapping(raw))
|
|
330
|
+
return refused(at, raw, `a mapping naming one of: ${choices}`);
|
|
331
|
+
const entries = Object.entries(raw);
|
|
332
|
+
const kinds = shape.kinds.filter((kind2) => entries.some(([name]) => name === kind2));
|
|
333
|
+
const [kind] = kinds;
|
|
334
|
+
if (kind === undefined)
|
|
335
|
+
return refusedWith([`${at.label} names none of: ${choices}`]);
|
|
336
|
+
if (kinds.length > 1) {
|
|
337
|
+
const named2 = kinds.join(" and ");
|
|
338
|
+
return refusedWith([`${at.label} names ${named2}, expected exactly one of: ${choices}`]);
|
|
339
|
+
}
|
|
340
|
+
const optionalKeys = shape.optionalFor(kind);
|
|
341
|
+
const problems = [];
|
|
342
|
+
const extras = [];
|
|
343
|
+
const optional = new Map;
|
|
344
|
+
let named;
|
|
345
|
+
for (const [name, value] of entries) {
|
|
346
|
+
if (name !== kind && !optionalKeys.includes(name)) {
|
|
347
|
+
extras.push({ key: `${at.key}.${name}`, value });
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (name !== kind && value === null)
|
|
351
|
+
continue;
|
|
352
|
+
const reading = itemText(value, below(at, `.${name}`));
|
|
353
|
+
problems.push(...reading.problems);
|
|
354
|
+
if (reading.value === undefined)
|
|
355
|
+
continue;
|
|
356
|
+
if (name === kind)
|
|
357
|
+
named = reading.value;
|
|
358
|
+
else
|
|
359
|
+
optional.set(name, reading.value);
|
|
360
|
+
}
|
|
361
|
+
return problems.length > 0 || named === undefined ? { value: undefined, problems, extras } : { value: { kind, named, optional }, problems, extras };
|
|
362
|
+
}
|
|
363
|
+
var PREREQUISITE_KINDS = ["tool", "env", "service", "lsp"];
|
|
364
|
+
var REQUIRED_ITEM_KEYS = [...PREREQUISITE_KINDS, "probe"];
|
|
365
|
+
var OPTIONAL_ITEM_KEYS = [...REQUIRED_ITEM_KEYS, "reason"];
|
|
366
|
+
var requiredPrerequisite = (raw, at) => {
|
|
367
|
+
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe"] };
|
|
368
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
369
|
+
kind: item.kind,
|
|
370
|
+
name: item.named,
|
|
371
|
+
probe: item.optional.get("probe") ?? null
|
|
372
|
+
}));
|
|
373
|
+
};
|
|
374
|
+
var optionalPrerequisite = (raw, at) => {
|
|
375
|
+
const shape = { kinds: PREREQUISITE_KINDS, optionalFor: () => ["probe", "reason"] };
|
|
376
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
377
|
+
kind: item.kind,
|
|
378
|
+
name: item.named,
|
|
379
|
+
probe: item.optional.get("probe") ?? null,
|
|
380
|
+
reason: item.optional.get("reason") ?? null
|
|
381
|
+
}));
|
|
382
|
+
};
|
|
383
|
+
var MODULE_SOURCE_KINDS = ["npm", "github", "path"];
|
|
384
|
+
var MODULE_SOURCE_KEYS = [...MODULE_SOURCE_KINDS, "ref"];
|
|
385
|
+
var moduleSource = (raw, at) => {
|
|
386
|
+
const shape = {
|
|
387
|
+
kinds: MODULE_SOURCE_KINDS,
|
|
388
|
+
optionalFor: (kind) => kind === "github" ? ["ref"] : []
|
|
389
|
+
};
|
|
390
|
+
return mapReading(readKeyedItem(shape, raw, at), (item) => Object.freeze({
|
|
391
|
+
kind: item.kind,
|
|
392
|
+
location: item.named,
|
|
393
|
+
ref: item.optional.get("ref") ?? null
|
|
394
|
+
}));
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
export { __require, MERGE_METHODS, isMergeMethod, isAgentName, BUDGET_FLAG, parseBudgetUsd, parseTaskDeclaration, stripTaskDeclaration, resolveDeclarationFlags, isMapping, describeValue, messageOf, CONFIG_VERSIONS, STORE_BACKENDS, INJECT_MODES, OUTPUT_MODES, CLAUDE_SETTING_SOURCES, PR_PROVIDERS, RELEASE_AUTO, oneOf, text, flag, mergeMethod, usdAmount, issueNumber, dayCount, releaseEnabled, isGitHubLogin, githubLogin, listOf, subsetOf, PREREQUISITE_KINDS, REQUIRED_ITEM_KEYS, OPTIONAL_ITEM_KEYS, requiredPrerequisite, optionalPrerequisite, MODULE_SOURCE_KINDS, MODULE_SOURCE_KEYS, moduleSource };
|