@ordewell/core 0.7.1 → 0.8.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 +5 -2
- package/dist/{IFileSystem-BnLh-_SK.d.mts → IFileSystem-D96mT-bm.d.ts} +1 -1
- package/dist/{IFileSystem-DofiRcCo.d.ts → IFileSystem-DXJCRw5x.d.mts} +1 -1
- package/dist/IRunner-CGCihlGQ.d.ts +1165 -0
- package/dist/IRunner-XVUddYVX.d.mts +1165 -0
- package/dist/{ModeResolver-DkMYf4uS.d.ts → ModeResolver-DE-o2lRF.d.mts} +2 -2
- package/dist/{ModeResolver-DZzJSdIU.d.mts → ModeResolver-EWlpmVAy.d.ts} +2 -2
- package/dist/Task-1Q19y7sZ.d.mts +1122 -0
- package/dist/Task-1Q19y7sZ.d.ts +1122 -0
- package/dist/{chunk-ZV5LDNCO.mjs → chunk-2M4X3VB7.mjs} +18 -6
- package/dist/chunk-2M4X3VB7.mjs.map +1 -0
- package/dist/{chunk-Y36NIASW.mjs → chunk-BLLIBCCS.mjs} +153 -264
- package/dist/chunk-BLLIBCCS.mjs.map +1 -0
- package/dist/chunk-H5O74L77.mjs +185 -0
- package/dist/chunk-H5O74L77.mjs.map +1 -0
- package/dist/{chunk-LGQNXPBX.mjs → chunk-UUU46PVQ.mjs} +72 -192
- package/dist/chunk-UUU46PVQ.mjs.map +1 -0
- package/dist/index.d.mts +1119 -930
- package/dist/index.d.ts +1119 -930
- package/dist/index.js +8361 -8849
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8197 -8614
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +1 -4
- package/dist/order-labels.d.ts +1 -4
- package/dist/{parsing-ddZXZFP4.d.ts → parsing-CZdp2p_n.d.ts} +5 -3
- package/dist/{parsing-B6ctfF80.d.mts → parsing-GgUJoYKs.d.mts} +5 -3
- package/dist/parsing.d.mts +3 -6
- package/dist/parsing.d.ts +3 -6
- package/dist/parsing.js +25 -4
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -2
- package/dist/{plan-utils-CKgNtDwQ.d.mts → plan-utils-BMayhGBj.d.mts} +89 -14
- package/dist/{plan-utils--kQRzSE-.d.ts → plan-utils-Cv48fe7r.d.ts} +89 -14
- package/dist/plan-utils.d.mts +4 -4
- package/dist/plan-utils.d.ts +4 -4
- package/dist/plan-utils.js +128 -65
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +10 -2
- package/dist/testing.d.mts +12 -24
- package/dist/testing.d.ts +12 -24
- package/dist/testing.js +29 -29
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +21 -27
- package/dist/testing.mjs.map +1 -1
- package/package.json +1 -1
- package/skills/tdd/SKILL.md +19 -0
- package/dist/Task-BnLxkVQF.d.mts +0 -2594
- package/dist/Task-BnLxkVQF.d.ts +0 -2594
- package/dist/chunk-LGQNXPBX.mjs.map +0 -1
- package/dist/chunk-Y36NIASW.mjs.map +0 -1
- package/dist/chunk-ZV5LDNCO.mjs.map +0 -1
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PlanParseError,
|
|
3
3
|
TASK_OPS_ENVELOPE_KEY,
|
|
4
|
-
addTaskToPlan,
|
|
5
|
-
createTask,
|
|
6
4
|
escapeControlCharsInStrings,
|
|
7
5
|
extractObjectsWithKey,
|
|
6
|
+
stripTrailingCommas
|
|
7
|
+
} from "./chunk-H5O74L77.mjs";
|
|
8
|
+
import {
|
|
9
|
+
addTaskToPlan,
|
|
10
|
+
createTask,
|
|
8
11
|
flattenTasks,
|
|
9
12
|
inheritedOps,
|
|
13
|
+
inheritedSkills,
|
|
10
14
|
opsFlag,
|
|
11
15
|
removeTaskFromPlan,
|
|
12
16
|
renumberTasks,
|
|
13
|
-
|
|
17
|
+
skillNames,
|
|
14
18
|
updateTaskInPlan
|
|
15
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-UUU46PVQ.mjs";
|
|
16
20
|
import {
|
|
17
21
|
taskOrderLabel,
|
|
18
22
|
taskRef,
|
|
@@ -118,183 +122,8 @@ function normalizeAgentArgs(tool, args) {
|
|
|
118
122
|
return out;
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
// src/services/terminalRender.ts
|
|
122
|
-
var ANSI_OR_CTRL_RE = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[()][AB012]|\x1b[=>]|[\x00-\x08\x0b-\x1f\x7f]/g;
|
|
123
|
-
function flattenTerminalOutput(raw) {
|
|
124
|
-
return raw.replace(ANSI_OR_CTRL_RE, "").replace(/[─-▟]/g, "").replace(/\s+/g, "");
|
|
125
|
-
}
|
|
126
|
-
function renderTerminalOutput(raw) {
|
|
127
|
-
const rows = /* @__PURE__ */ new Map();
|
|
128
|
-
let row = 1;
|
|
129
|
-
let col = 1;
|
|
130
|
-
let savedRow = 1;
|
|
131
|
-
let savedCol = 1;
|
|
132
|
-
const cells = (r) => {
|
|
133
|
-
let line = rows.get(r);
|
|
134
|
-
if (!line) {
|
|
135
|
-
line = [];
|
|
136
|
-
rows.set(r, line);
|
|
137
|
-
}
|
|
138
|
-
return line;
|
|
139
|
-
};
|
|
140
|
-
const firstParam = (params, fallback = 1) => params[0] || fallback;
|
|
141
|
-
const eraseLine = (mode) => {
|
|
142
|
-
const line = cells(row);
|
|
143
|
-
if (mode === 2) {
|
|
144
|
-
rows.set(row, []);
|
|
145
|
-
} else if (mode === 1) {
|
|
146
|
-
for (let c = 0; c < col; c++) line[c] = " ";
|
|
147
|
-
} else {
|
|
148
|
-
line.length = Math.max(0, col - 1);
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
for (let i = 0; i < raw.length; ) {
|
|
152
|
-
const ch = raw[i];
|
|
153
|
-
if (ch === "\x1B") {
|
|
154
|
-
const kind = raw[i + 1];
|
|
155
|
-
if (kind === "[") {
|
|
156
|
-
let end = i + 2;
|
|
157
|
-
while (end < raw.length) {
|
|
158
|
-
const code = raw.charCodeAt(end);
|
|
159
|
-
if (code >= 64 && code <= 126) break;
|
|
160
|
-
end++;
|
|
161
|
-
}
|
|
162
|
-
if (end >= raw.length) break;
|
|
163
|
-
const final = raw[end];
|
|
164
|
-
const body = raw.slice(i + 2, end).replace(/^[?<>=!]+/, "");
|
|
165
|
-
const params = body.split(";").map((p) => Number.parseInt(p, 10) || 0);
|
|
166
|
-
switch (final) {
|
|
167
|
-
case "H":
|
|
168
|
-
case "f":
|
|
169
|
-
row = params[0] || 1;
|
|
170
|
-
col = params[1] || 1;
|
|
171
|
-
break;
|
|
172
|
-
case "G":
|
|
173
|
-
col = firstParam(params);
|
|
174
|
-
break;
|
|
175
|
-
case "d":
|
|
176
|
-
row = firstParam(params);
|
|
177
|
-
break;
|
|
178
|
-
case "A":
|
|
179
|
-
row = Math.max(1, row - firstParam(params));
|
|
180
|
-
break;
|
|
181
|
-
case "B":
|
|
182
|
-
row += firstParam(params);
|
|
183
|
-
break;
|
|
184
|
-
case "C":
|
|
185
|
-
col += firstParam(params);
|
|
186
|
-
break;
|
|
187
|
-
case "D":
|
|
188
|
-
col = Math.max(1, col - firstParam(params));
|
|
189
|
-
break;
|
|
190
|
-
case "E":
|
|
191
|
-
row += firstParam(params);
|
|
192
|
-
col = 1;
|
|
193
|
-
break;
|
|
194
|
-
case "F":
|
|
195
|
-
row = Math.max(1, row - firstParam(params));
|
|
196
|
-
col = 1;
|
|
197
|
-
break;
|
|
198
|
-
case "s":
|
|
199
|
-
savedRow = row;
|
|
200
|
-
savedCol = col;
|
|
201
|
-
break;
|
|
202
|
-
case "u":
|
|
203
|
-
row = savedRow;
|
|
204
|
-
col = savedCol;
|
|
205
|
-
break;
|
|
206
|
-
case "K":
|
|
207
|
-
eraseLine(params[0] || 0);
|
|
208
|
-
break;
|
|
209
|
-
case "J":
|
|
210
|
-
if ((params[0] || 0) === 2 || (params[0] || 0) === 3) rows.clear();
|
|
211
|
-
break;
|
|
212
|
-
case "X": {
|
|
213
|
-
const line = cells(row);
|
|
214
|
-
for (let c = 0; c < firstParam(params); c++) line[col - 1 + c] = " ";
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
case "P": {
|
|
218
|
-
cells(row).splice(col - 1, firstParam(params));
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
case "@": {
|
|
222
|
-
cells(row).splice(col - 1, 0, ...Array(firstParam(params)).fill(" "));
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
default:
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
i = end + 1;
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
if (kind === "]" || kind === "P" || kind === "^" || kind === "_") {
|
|
232
|
-
let end = i + 2;
|
|
233
|
-
while (end < raw.length && raw[end] !== "\x07" && !(raw[end] === "\x1B" && raw[end + 1] === "\\")) end++;
|
|
234
|
-
if (end >= raw.length) break;
|
|
235
|
-
i = raw[end] === "\x07" ? end + 1 : end + 2;
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
if (kind === "7") {
|
|
239
|
-
savedRow = row;
|
|
240
|
-
savedCol = col;
|
|
241
|
-
} else if (kind === "8") {
|
|
242
|
-
row = savedRow;
|
|
243
|
-
col = savedCol;
|
|
244
|
-
} else if (kind === "c") {
|
|
245
|
-
rows.clear();
|
|
246
|
-
row = 1;
|
|
247
|
-
col = 1;
|
|
248
|
-
}
|
|
249
|
-
i += kind === "(" || kind === ")" ? 3 : 2;
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (ch === "\r") {
|
|
253
|
-
col = 1;
|
|
254
|
-
i++;
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (ch === "\n") {
|
|
258
|
-
row++;
|
|
259
|
-
i++;
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
if (ch === "\b") {
|
|
263
|
-
col = Math.max(1, col - 1);
|
|
264
|
-
i++;
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
if (ch === " ") {
|
|
268
|
-
col += 8 - (col - 1) % 8;
|
|
269
|
-
i++;
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
if (ch < " " || ch === "\x7F") {
|
|
273
|
-
i++;
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
cells(row)[col - 1] = ch;
|
|
277
|
-
col++;
|
|
278
|
-
i++;
|
|
279
|
-
}
|
|
280
|
-
const populated = [...rows.keys()].sort((a, b) => a - b);
|
|
281
|
-
return populated.map((r) => cells(r).join("")).join("\n");
|
|
282
|
-
}
|
|
283
|
-
function renderCleanCapture(raw, doneToken) {
|
|
284
|
-
const rendered = renderTerminalOutput(raw).replace(/[\s─-▟]+$/gm, "");
|
|
285
|
-
if (!doneToken) return rendered.trim();
|
|
286
|
-
const lines2 = rendered.split("\n");
|
|
287
|
-
const flat = (s) => flattenTerminalOutput(s);
|
|
288
|
-
for (let i = 0; i < lines2.length; i++) {
|
|
289
|
-
const own = flat(lines2[i]).includes(doneToken);
|
|
290
|
-
if (own) return lines2.slice(0, i).join("\n").trim();
|
|
291
|
-
const window = flat(lines2[i]) + (i + 1 < lines2.length ? flat(lines2[i + 1]) : "");
|
|
292
|
-
if (window.includes(doneToken)) return lines2.slice(0, i + 1).join("\n").trim();
|
|
293
|
-
}
|
|
294
|
-
return rendered.trim();
|
|
295
|
-
}
|
|
296
|
-
|
|
297
125
|
// src/conversation/format.ts
|
|
126
|
+
var ANSI_OR_CTRL_RE = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?|\x1b[()][AB012]|\x1b[=>]|[\x00-\x08\x0b-\x1f\x7f]/g;
|
|
298
127
|
var DISPLAY_NAMES = {
|
|
299
128
|
read_file: "Read",
|
|
300
129
|
read_files: "Read",
|
|
@@ -425,6 +254,31 @@ function diffSummary({ added, removed }) {
|
|
|
425
254
|
function settledMessage(id, role, text2, turnId) {
|
|
426
255
|
return { type: "message", id, role, text: text2, streaming: false, ...turnId ? { turnId } : {} };
|
|
427
256
|
}
|
|
257
|
+
function userMessage(id, text2, skills, turnId) {
|
|
258
|
+
const block = settledMessage(id, "user", text2, turnId);
|
|
259
|
+
return skills.length > 0 ? { ...block, skills: skills.map((s) => s.name) } : block;
|
|
260
|
+
}
|
|
261
|
+
function skillLoadNotice({ invokedBy, name, source, path, attaches }) {
|
|
262
|
+
return { invokedBy, name, source, path, ...attaches ? { attaches } : {} };
|
|
263
|
+
}
|
|
264
|
+
var LOAD_SKILL_TOOL = /(?:^|_)load_skill$/;
|
|
265
|
+
function surfaceStep(step) {
|
|
266
|
+
if (!step.success || !LOAD_SKILL_TOOL.test(step.toolLabel ?? step.tool)) return step;
|
|
267
|
+
const name = loadedSkillName(step.args);
|
|
268
|
+
return { ...step, result: name ? `Loaded skill ${name}.` : "Loaded a skill." };
|
|
269
|
+
}
|
|
270
|
+
function loadedSkillName(args) {
|
|
271
|
+
try {
|
|
272
|
+
const parsed = JSON.parse(args);
|
|
273
|
+
const name = typeof parsed === "object" && parsed !== null && "name" in parsed ? parsed.name : void 0;
|
|
274
|
+
return typeof name === "string" ? name : void 0;
|
|
275
|
+
} catch {
|
|
276
|
+
return void 0;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function skillLoadBlock(id, { invokedBy, name, source, path, attaches }, turnId) {
|
|
280
|
+
return { type: "skill_load", id, invokedBy, name, source, path, ...attaches ? { attaches } : {}, ...turnId ? { turnId } : {} };
|
|
281
|
+
}
|
|
428
282
|
function subagentBlock(id, { toolCallId, model, usage, turnId, ...fields }) {
|
|
429
283
|
return {
|
|
430
284
|
type: "subagent",
|
|
@@ -764,6 +618,8 @@ function unqueueMessage(view, { messageId }) {
|
|
|
764
618
|
}
|
|
765
619
|
function reduceTaskLog(view, event) {
|
|
766
620
|
switch (event.type) {
|
|
621
|
+
case "task_skills":
|
|
622
|
+
return append(view, (id) => settledMessage(id, "system", `Skills: ${event.skills.map((s) => `${s.name} (${s.path})`).join(", ")}`));
|
|
767
623
|
case "turn_start":
|
|
768
624
|
return startTurn(view, event);
|
|
769
625
|
case "turn_end":
|
|
@@ -1041,7 +897,8 @@ var UPDATABLE_FIELDS = [
|
|
|
1041
897
|
"userSteps",
|
|
1042
898
|
"autonomy",
|
|
1043
899
|
"sliceType",
|
|
1044
|
-
"ops"
|
|
900
|
+
"ops",
|
|
901
|
+
"skills"
|
|
1045
902
|
];
|
|
1046
903
|
function taskOpsProtocol(executionNote = "", tools = false) {
|
|
1047
904
|
const updateChanges = UPDATABLE_FIELDS.map((f) => f === "dependencies" ? '"dependencies"?:["<id or #order>"]' : `"${f}"?`).join(",");
|
|
@@ -1064,6 +921,7 @@ function taskOpsProtocol(executionNote = "", tools = false) {
|
|
|
1064
921
|
...tools ? ["edit_plan checks the batch when you call it and answers with what it will change, or with the error to fix \u2014 call it again in the same reply. The edit is applied when your reply ends; edits you make in one reply join one batch."] : [],
|
|
1065
922
|
'Just declare the dependencies you want \u2014 display order is repaired for you afterwards, so a rewire or a newly added prerequisite never needs a "reorder" op. Only a task that is running or completed cannot be shifted, so an edit that would need one to move is rejected.' + executionNote,
|
|
1066
923
|
'Flipping "type" between "ai" and "user" is a content change, not just a label: an update to "user" needs "userSteps" in the SAME op, and an update to "ai" needs "prompt" in the SAME op \u2014 the model/mode/effort/autonomy fields (flipping to "user") or the userSteps (flipping to "ai") are cleared automatically.',
|
|
924
|
+
`"skills" in "changes" REPLACES the task's whole skill list. To add one, send the names the plan block shows in its skills:[...] plus the new one; to drop one, send the rest; [] removes them all.`,
|
|
1067
925
|
'"rearm" puts a failed OR completed task back to pending \u2014 verdict and output summary are cleared, any dependents it had blocked are released, and it may carry field changes (e.g. a corrected "prompt") applied in the same op. A running task cannot be re-armed. Never rearm a task just to relabel it \u2014 only when it should actually run again.'
|
|
1068
926
|
];
|
|
1069
927
|
}
|
|
@@ -1159,8 +1017,22 @@ function updatableChanges(raw) {
|
|
|
1159
1017
|
if (raw && key in raw) changes[key] = raw[key];
|
|
1160
1018
|
}
|
|
1161
1019
|
if ("ops" in changes) changes.ops = opsFlag(changes.ops);
|
|
1020
|
+
if ("skills" in changes) changes.skills = skillNames(changes.skills);
|
|
1162
1021
|
return changes;
|
|
1163
1022
|
}
|
|
1023
|
+
function withSkillNames(subtasks) {
|
|
1024
|
+
if (!Array.isArray(subtasks)) return subtasks;
|
|
1025
|
+
return subtasks.map((sub) => {
|
|
1026
|
+
if (typeof sub !== "object" || sub === null) return sub;
|
|
1027
|
+
const { skills, ...rest } = sub;
|
|
1028
|
+
const names = skillNames(skills);
|
|
1029
|
+
return {
|
|
1030
|
+
...rest,
|
|
1031
|
+
...names ? { skills: names } : {},
|
|
1032
|
+
..."subtasks" in rest ? { subtasks: withSkillNames(rest.subtasks) } : {}
|
|
1033
|
+
};
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1164
1036
|
function findInTasks(tasks, id) {
|
|
1165
1037
|
return flattenTasks(tasks).find((t) => t.id === id);
|
|
1166
1038
|
}
|
|
@@ -1328,41 +1200,38 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1328
1200
|
}
|
|
1329
1201
|
return { ids, bad };
|
|
1330
1202
|
};
|
|
1203
|
+
const prepareEdit = (op, opIndex, label, audience, refuseRunning = false) => {
|
|
1204
|
+
const ref = resolveRef(op.taskId, originalFlatAll, flattenTasks(tasks), handleOwner, handleId, opIndex);
|
|
1205
|
+
if ("error" in ref) return { error: `${label}: ${ref.error}` };
|
|
1206
|
+
const target = findInTasks(tasks, ref.id);
|
|
1207
|
+
if (!target) return { error: `${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)` };
|
|
1208
|
+
if (refuseRunning && target.status === "in_progress") return { error: `${label}: "${target.title}" is running and cannot be re-armed` };
|
|
1209
|
+
const changes = updatableChanges(op.changes);
|
|
1210
|
+
if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
|
|
1211
|
+
return { error: `${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]` };
|
|
1212
|
+
}
|
|
1213
|
+
const changesForCheck = { ...changes };
|
|
1214
|
+
delete changesForCheck.dependencies;
|
|
1215
|
+
const check = validateTaskEdit(audience, flattenTasks(tasks), target.id, changesForCheck, catalog);
|
|
1216
|
+
if (!check.ok) return { error: `${label}: ${check.error}` };
|
|
1217
|
+
for (const field of check.clear ?? []) changes[field] = void 0;
|
|
1218
|
+
if ("dependencies" in changes) {
|
|
1219
|
+
const { ids, bad } = resolveDeps(changes.dependencies, opIndex);
|
|
1220
|
+
if (bad.length) return { error: `${label}: unknown dependencies: ${bad.join(", ")}` };
|
|
1221
|
+
changes.dependencies = ids.filter((id) => id !== target.id);
|
|
1222
|
+
}
|
|
1223
|
+
return { target, changes, check };
|
|
1224
|
+
};
|
|
1331
1225
|
for (const [i, op] of ops.entries()) {
|
|
1332
1226
|
const label = `op ${i + 1} (${op.op})`;
|
|
1333
1227
|
switch (op.op) {
|
|
1334
1228
|
case "update": {
|
|
1335
|
-
const
|
|
1336
|
-
if ("error" in
|
|
1337
|
-
errors.push(
|
|
1229
|
+
const prep = prepareEdit(op, i, label, "planner");
|
|
1230
|
+
if ("error" in prep) {
|
|
1231
|
+
errors.push(prep.error);
|
|
1338
1232
|
break;
|
|
1339
1233
|
}
|
|
1340
|
-
const target =
|
|
1341
|
-
if (!target) {
|
|
1342
|
-
errors.push(`${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)`);
|
|
1343
|
-
break;
|
|
1344
|
-
}
|
|
1345
|
-
const changes = updatableChanges(op.changes);
|
|
1346
|
-
if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
|
|
1347
|
-
errors.push(`${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]`);
|
|
1348
|
-
break;
|
|
1349
|
-
}
|
|
1350
|
-
const changesForCheck = { ...changes };
|
|
1351
|
-
delete changesForCheck.dependencies;
|
|
1352
|
-
const check = validateTaskEdit("planner", flattenTasks(tasks), target.id, changesForCheck, catalog);
|
|
1353
|
-
if (!check.ok) {
|
|
1354
|
-
errors.push(`${label}: ${check.error}`);
|
|
1355
|
-
break;
|
|
1356
|
-
}
|
|
1357
|
-
for (const field of check.clear ?? []) changes[field] = void 0;
|
|
1358
|
-
if ("dependencies" in changes) {
|
|
1359
|
-
const { ids, bad } = resolveDeps(changes.dependencies, i);
|
|
1360
|
-
if (bad.length) {
|
|
1361
|
-
errors.push(`${label}: unknown dependencies: ${bad.join(", ")}`);
|
|
1362
|
-
break;
|
|
1363
|
-
}
|
|
1364
|
-
changes.dependencies = ids.filter((id) => id !== target.id);
|
|
1365
|
-
}
|
|
1234
|
+
const { target, changes, check } = prep;
|
|
1366
1235
|
if (Object.keys(changes).length === 0) {
|
|
1367
1236
|
errors.push(`${label}: no valid changes provided`);
|
|
1368
1237
|
break;
|
|
@@ -1392,6 +1261,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1392
1261
|
const newId = uuidv4();
|
|
1393
1262
|
tasks = addTaskToPlan(tasks, {
|
|
1394
1263
|
...spec,
|
|
1264
|
+
subtasks: withSkillNames(spec.subtasks),
|
|
1395
1265
|
id: newId,
|
|
1396
1266
|
dependencies: ids,
|
|
1397
1267
|
assignedRunner: runner,
|
|
@@ -1459,7 +1329,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1459
1329
|
errors.push(`${label}: unknown task in merge list (already removed, merged, or split by an earlier op)`);
|
|
1460
1330
|
break;
|
|
1461
1331
|
}
|
|
1462
|
-
const toMerge = resolved.map((t) => t).sort((a, b) => a.order - b.order);
|
|
1332
|
+
const toMerge = [...new Map(resolved.map((t) => [t.id, t])).values()].sort((a, b) => a.order - b.order);
|
|
1463
1333
|
if (toMerge.length < 2) {
|
|
1464
1334
|
errors.push(`${label}: merge needs at least two tasks`);
|
|
1465
1335
|
break;
|
|
@@ -1495,6 +1365,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1495
1365
|
autonomy: spec.autonomy ?? toMerge.find((t) => t.autonomy)?.autonomy,
|
|
1496
1366
|
sliceType: spec.sliceType ?? toMerge.find((t) => t.sliceType)?.sliceType,
|
|
1497
1367
|
ops: inheritedOps(toMerge, spec.ops),
|
|
1368
|
+
skills: inheritedSkills(spec.skills, toMerge.flatMap((t) => t.skills ?? [])),
|
|
1498
1369
|
userStoriesCovered: spec.userStoriesCovered ?? (toMerge.flatMap((t) => t.userStoriesCovered ?? []).length ? [...new Set(toMerge.flatMap((t) => t.userStoriesCovered ?? []))] : void 0)
|
|
1499
1370
|
});
|
|
1500
1371
|
const mergedId = mergedTask.id;
|
|
@@ -1576,6 +1447,7 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1576
1447
|
autonomy: spec.autonomy ?? target.autonomy,
|
|
1577
1448
|
sliceType: spec.sliceType ?? target.sliceType,
|
|
1578
1449
|
ops: inheritedOps([target], spec.ops),
|
|
1450
|
+
skills: inheritedSkills(spec.skills, target.skills),
|
|
1579
1451
|
userStoriesCovered: spec.userStoriesCovered ?? target.userStoriesCovered
|
|
1580
1452
|
});
|
|
1581
1453
|
newTasks.push(nt);
|
|
@@ -1597,41 +1469,12 @@ function applyTaskOps(currentTasks, ops, runners, catalog) {
|
|
|
1597
1469
|
break;
|
|
1598
1470
|
}
|
|
1599
1471
|
case "rearm": {
|
|
1600
|
-
const
|
|
1601
|
-
if ("error" in
|
|
1602
|
-
errors.push(
|
|
1472
|
+
const prep = prepareEdit(op, i, label, "direct", true);
|
|
1473
|
+
if ("error" in prep) {
|
|
1474
|
+
errors.push(prep.error);
|
|
1603
1475
|
break;
|
|
1604
1476
|
}
|
|
1605
|
-
const target =
|
|
1606
|
-
if (!target) {
|
|
1607
|
-
errors.push(`${label}: task "${op.taskId}" no longer exists in this batch (removed, merged, or split by an earlier op)`);
|
|
1608
|
-
break;
|
|
1609
|
-
}
|
|
1610
|
-
if (target.status === "in_progress") {
|
|
1611
|
-
errors.push(`${label}: "${target.title}" is running and cannot be re-armed`);
|
|
1612
|
-
break;
|
|
1613
|
-
}
|
|
1614
|
-
const changes = updatableChanges(op.changes);
|
|
1615
|
-
if (changes.assignedRunner && !runners.includes(changes.assignedRunner)) {
|
|
1616
|
-
errors.push(`${label}: runner "${changes.assignedRunner}" is not in this plan's runner set [${runners.join(", ")}]`);
|
|
1617
|
-
break;
|
|
1618
|
-
}
|
|
1619
|
-
const changesForCheck = { ...changes };
|
|
1620
|
-
delete changesForCheck.dependencies;
|
|
1621
|
-
const check = validateTaskEdit("direct", flattenTasks(tasks), target.id, changesForCheck, catalog);
|
|
1622
|
-
if (!check.ok) {
|
|
1623
|
-
errors.push(`${label}: ${check.error}`);
|
|
1624
|
-
break;
|
|
1625
|
-
}
|
|
1626
|
-
for (const field of check.clear ?? []) changes[field] = void 0;
|
|
1627
|
-
if ("dependencies" in changes) {
|
|
1628
|
-
const { ids, bad } = resolveDeps(changes.dependencies, i);
|
|
1629
|
-
if (bad.length) {
|
|
1630
|
-
errors.push(`${label}: unknown dependencies: ${bad.join(", ")}`);
|
|
1631
|
-
break;
|
|
1632
|
-
}
|
|
1633
|
-
changes.dependencies = ids.filter((id) => id !== target.id);
|
|
1634
|
-
}
|
|
1477
|
+
const { target, changes, check } = prep;
|
|
1635
1478
|
tasks = updateTaskInPlan(tasks, target.id, { ...changes, status: "pending", verdict: void 0, outputSummary: void 0, awaitingReason: void 0 });
|
|
1636
1479
|
for (const dep of flattenTasks(tasks)) {
|
|
1637
1480
|
if (dep.status === "blocked" && dep.dependencies.includes(target.id)) {
|
|
@@ -1749,9 +1592,8 @@ function continuability(task) {
|
|
|
1749
1592
|
return refuse("its work is waiting on a merge conflict. Resolve or repair the conflict instead.");
|
|
1750
1593
|
}
|
|
1751
1594
|
if (task.status !== "completed" && task.status !== "failed") return refuse("only a completed or failed task can be.");
|
|
1752
|
-
if (task.
|
|
1753
|
-
|
|
1754
|
-
return { ok: true, sessionId: task.transport.nativeSessionId };
|
|
1595
|
+
if (!task.runnerSessionId) return refuse("its runner left no saved session to resume. Use Retry instead.");
|
|
1596
|
+
return { ok: true, sessionId: task.runnerSessionId };
|
|
1755
1597
|
}
|
|
1756
1598
|
function canContinue(task) {
|
|
1757
1599
|
return continuability(task).ok;
|
|
@@ -1776,7 +1618,8 @@ function serializeTask(t) {
|
|
|
1776
1618
|
autonomy: t.autonomy || void 0,
|
|
1777
1619
|
sliceType: t.sliceType || void 0,
|
|
1778
1620
|
userStoriesCovered: t.userStoriesCovered || void 0,
|
|
1779
|
-
...t.ops ? { ops: true } : {}
|
|
1621
|
+
...t.ops ? { ops: true } : {},
|
|
1622
|
+
...t.skills?.length ? { skills: [...t.skills] } : {}
|
|
1780
1623
|
};
|
|
1781
1624
|
}
|
|
1782
1625
|
function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [], awaitingApproval = 0, mergeGate = [], checkpoint = "") {
|
|
@@ -1786,7 +1629,6 @@ function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [],
|
|
|
1786
1629
|
verdict: t.verdict ? { outcome: t.verdict.outcome, reason: t.verdict.reason, checks: t.verdict.checks || [] } : null,
|
|
1787
1630
|
idleSince,
|
|
1788
1631
|
...isolation ? { isolation } : {},
|
|
1789
|
-
...t.transport ? { transport: t.transport.fallback ? { kind: t.transport.kind, fallback: t.transport.fallback } : { kind: t.transport.kind } } : {},
|
|
1790
1632
|
...t.status === "awaiting_user" && t.awaitingReason ? { awaitingReason: t.awaitingReason } : {},
|
|
1791
1633
|
...t.status === "awaiting_user" && t.awaitingReason === "checkpoint" && checkpoint ? { checkpoint } : {},
|
|
1792
1634
|
...queued.length > 0 ? { queued: queued.map((m) => ({ ...m })) } : {},
|
|
@@ -1796,14 +1638,39 @@ function serializeTaskStatus(t, idleSince = null, isolation = null, queued = [],
|
|
|
1796
1638
|
...t.forcedPastGate?.length ? { forcedPastGate: [...t.forcedPastGate] } : {}
|
|
1797
1639
|
};
|
|
1798
1640
|
}
|
|
1641
|
+
function surfaceConversation(history) {
|
|
1642
|
+
return history?.map(({ skill, ...m }) => skill ? { ...m, skill: skillLoadNotice(skill) } : m);
|
|
1643
|
+
}
|
|
1644
|
+
function surfaceQueued(queued) {
|
|
1645
|
+
return queued?.map(({ skills, ...m }) => skills ? { ...m, skills: skills.map(skillLoadNotice) } : m);
|
|
1646
|
+
}
|
|
1647
|
+
function surfaceTask({ attemptSkills, subtasks, runnerSessionId: _runnerSessionId, ...task }) {
|
|
1648
|
+
return {
|
|
1649
|
+
...task,
|
|
1650
|
+
...attemptSkills ? { attemptSkills: attemptSkills.map(({ name, source, path }) => ({ name, source, path })) } : {},
|
|
1651
|
+
subtasks: (subtasks ?? []).map(surfaceTask)
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
function surfacePlan(plan) {
|
|
1655
|
+
return {
|
|
1656
|
+
...plan,
|
|
1657
|
+
tasks: plan.tasks.map(surfaceTask),
|
|
1658
|
+
conversationHistory: surfaceConversation(plan.conversationHistory),
|
|
1659
|
+
queuedMessages: surfaceQueued(plan.queuedMessages),
|
|
1660
|
+
researchLog: plan.researchLog?.map((e) => "type" in e ? e : surfaceStep(e))
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
function surfacePlanState(state) {
|
|
1664
|
+
return state.phase === "planning" ? { ...state, pendingTasks: state.pendingTasks.map(surfaceTask) } : { ...state, pendingTasks: state.pendingTasks.map(surfaceTask), executionLog: state.executionLog.map(surfaceTask) };
|
|
1665
|
+
}
|
|
1799
1666
|
function serializePlan(plan) {
|
|
1800
1667
|
return {
|
|
1801
1668
|
tasks: plan.tasks.map(serializeTask),
|
|
1802
1669
|
runners: plan.runners,
|
|
1803
1670
|
generatedAt: plan.generatedAt,
|
|
1804
|
-
conversationHistory: plan.conversationHistory,
|
|
1671
|
+
conversationHistory: surfaceConversation(plan.conversationHistory),
|
|
1805
1672
|
prdMarkdown: plan.prdMarkdown,
|
|
1806
|
-
queuedMessages: plan.queuedMessages
|
|
1673
|
+
queuedMessages: surfaceQueued(plan.queuedMessages)
|
|
1807
1674
|
};
|
|
1808
1675
|
}
|
|
1809
1676
|
function executionSummary(tasks) {
|
|
@@ -1837,13 +1704,15 @@ function finalSegmentIndex(blocks, turnId, pastPlan = false) {
|
|
|
1837
1704
|
}
|
|
1838
1705
|
return -1;
|
|
1839
1706
|
}
|
|
1840
|
-
function openTurn(view, turnId, prompt) {
|
|
1707
|
+
function openTurn(view, { turnId, prompt = "", skills = [] }) {
|
|
1841
1708
|
const i = findLastIndex(view.blocks, (b) => b.type === "message" && b.role === "user");
|
|
1842
1709
|
const sent = view.blocks[i];
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1710
|
+
const adopted = sent?.type === "message" && sent.turnId === void 0 && sent.text === prompt;
|
|
1711
|
+
const said = adopted ? { ...view, blocks: replaceAt(view.blocks, i, userMessage(sent.id, prompt, skills, turnId)) } : append(view, (id) => userMessage(id, prompt, skills, turnId));
|
|
1712
|
+
if (skills.length === 0) return said;
|
|
1713
|
+
const at = adopted ? i + 1 : findLastIndex(said.blocks, (b) => b.type === "message" && b.role === "user") + 1;
|
|
1714
|
+
const loads = skills.map((skill, n) => skillLoadBlock(`b${said.nextId + n}`, skill, turnId));
|
|
1715
|
+
return { ...said, blocks: [...said.blocks.slice(0, at), ...loads, ...said.blocks.slice(at)], nextId: said.nextId + loads.length };
|
|
1847
1716
|
}
|
|
1848
1717
|
function streamText(view, { turnId, segmentId, text: text2 }) {
|
|
1849
1718
|
const i = findLastIndex(view.blocks, (b) => isUnsettledSegment(b, turnId) && b.segmentId === segmentId);
|
|
@@ -1990,7 +1859,9 @@ function reduceConversation(view, input) {
|
|
|
1990
1859
|
case "local_entry":
|
|
1991
1860
|
return append(view, (id) => settledMessage(id, input.role, input.text));
|
|
1992
1861
|
case "planner_turn_started":
|
|
1993
|
-
return input.prompt === void 0 ? view : openTurn(view, input
|
|
1862
|
+
return input.prompt === void 0 ? view : openTurn(view, input);
|
|
1863
|
+
case "planner_skill_loaded":
|
|
1864
|
+
return append(sealLane(view, null, -1), (id) => skillLoadBlock(id, input.skill, input.turnId));
|
|
1994
1865
|
case "planner_text_delta":
|
|
1995
1866
|
return streamText(view, input);
|
|
1996
1867
|
case "planner_message":
|
|
@@ -2030,11 +1901,27 @@ function reduceConversation(view, input) {
|
|
|
2030
1901
|
var USER = 0;
|
|
2031
1902
|
var RESEARCH = 1;
|
|
2032
1903
|
var SETTLED = 2;
|
|
2033
|
-
function fromEntry(entry) {
|
|
1904
|
+
function fromEntry(entry, loaded = []) {
|
|
2034
1905
|
if (entry.kind === "plan_generated") return (id) => ({ type: "plan", id: id(), text: "", ...planMarker(entry.content) });
|
|
1906
|
+
if (entry.kind === "skill_load" && entry.skill) {
|
|
1907
|
+
const { skill } = entry;
|
|
1908
|
+
return (id) => skillLoadBlock(id(), skillLoadNotice(skill));
|
|
1909
|
+
}
|
|
1910
|
+
if (entry.role === "user" && !entry.kind) return (id) => userMessage(id(), entry.content, loaded.map(skillLoadNotice));
|
|
2035
1911
|
const role = entry.kind === "system" || entry.kind === "compaction" ? "system" : entry.role === "user" ? "user" : "planner";
|
|
2036
1912
|
return (id) => settledMessage(id(), role, entry.content);
|
|
2037
1913
|
}
|
|
1914
|
+
function loadsAfter(entries, index) {
|
|
1915
|
+
const loads = [];
|
|
1916
|
+
for (let i = index + 1; i < entries.length && entries[i].kind === "skill_load"; i++) {
|
|
1917
|
+
const { skill } = entries[i];
|
|
1918
|
+
if (skill?.invokedBy === "user") loads.push(skill);
|
|
1919
|
+
}
|
|
1920
|
+
return loads;
|
|
1921
|
+
}
|
|
1922
|
+
function rankOf(entry) {
|
|
1923
|
+
return entry.role === "user" && (!entry.kind || entry.kind === "skill_load") ? USER : SETTLED;
|
|
1924
|
+
}
|
|
2038
1925
|
function spawnBrief(step) {
|
|
2039
1926
|
try {
|
|
2040
1927
|
const args = JSON.parse(step.args);
|
|
@@ -2097,7 +1984,7 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage) {
|
|
|
2097
1984
|
const kept = compacted ? history.slice(1) : history;
|
|
2098
1985
|
const cutoff = compacted ? kept[0]?.timestamp ?? compacted.timestamp : "";
|
|
2099
1986
|
const placed = [
|
|
2100
|
-
...kept.map((entry) => ({ at: entry.timestamp, rank: entry
|
|
1987
|
+
...kept.map((entry, i) => ({ at: entry.timestamp, rank: rankOf(entry), build: fromEntry(entry, loadsAfter(kept, i)) })),
|
|
2101
1988
|
...research(researchLog ?? []).filter((item) => item.at >= cutoff)
|
|
2102
1989
|
];
|
|
2103
1990
|
placed.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : a.rank - b.rank);
|
|
@@ -2144,7 +2031,8 @@ var TURN_STREAM = /* @__PURE__ */ new Set([
|
|
|
2144
2031
|
"research_step_done",
|
|
2145
2032
|
"subagent_started",
|
|
2146
2033
|
"subagent_finished",
|
|
2147
|
-
"planner_turn_ended"
|
|
2034
|
+
"planner_turn_ended",
|
|
2035
|
+
"planner_skill_loaded"
|
|
2148
2036
|
]);
|
|
2149
2037
|
function cutOff(gate, input) {
|
|
2150
2038
|
if (gate.stopped === null || !TURN_STREAM.has(input.type)) return false;
|
|
@@ -2289,15 +2177,14 @@ export {
|
|
|
2289
2177
|
plannerContextFill,
|
|
2290
2178
|
mapAgentTool,
|
|
2291
2179
|
normalizeAgentArgs,
|
|
2292
|
-
flattenTerminalOutput,
|
|
2293
|
-
renderTerminalOutput,
|
|
2294
|
-
renderCleanCapture,
|
|
2295
2180
|
toolHeadline,
|
|
2296
2181
|
outputLines,
|
|
2297
2182
|
outputPreview,
|
|
2298
2183
|
diffStat,
|
|
2299
2184
|
diffRows,
|
|
2300
2185
|
diffSummary,
|
|
2186
|
+
skillLoadNotice,
|
|
2187
|
+
surfaceStep,
|
|
2301
2188
|
EMPTY_TASK_LOG,
|
|
2302
2189
|
runnerToolSubject,
|
|
2303
2190
|
reduceTaskLog,
|
|
@@ -2330,6 +2217,8 @@ export {
|
|
|
2330
2217
|
canContinue,
|
|
2331
2218
|
serializeTask,
|
|
2332
2219
|
serializeTaskStatus,
|
|
2220
|
+
surfacePlan,
|
|
2221
|
+
surfacePlanState,
|
|
2333
2222
|
serializePlan,
|
|
2334
2223
|
executionSummary,
|
|
2335
2224
|
CHECKPOINT_TRUNCATE_LENGTH,
|
|
@@ -2359,4 +2248,4 @@ export {
|
|
|
2359
2248
|
pastGateConfirmation,
|
|
2360
2249
|
newTaskFields
|
|
2361
2250
|
};
|
|
2362
|
-
//# sourceMappingURL=chunk-
|
|
2251
|
+
//# sourceMappingURL=chunk-BLLIBCCS.mjs.map
|