@ordewell/core 0.10.5 → 0.10.7
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/{IRunner-Crkt3tHD.d.ts → IFileSystem-C4_mpfze.d.ts} +97 -14
- package/dist/{IRunner-lMQIa5Wc.d.mts → IFileSystem-DUgeWWQN.d.mts} +97 -14
- package/dist/{ModeResolver-B4hhABNf.d.mts → ModeResolver-4qNjxcDs.d.mts} +1 -1
- package/dist/{ModeResolver-CUR5jCSU.d.ts → ModeResolver-DGK2rWHE.d.ts} +1 -1
- package/dist/{Task-D4QHjdGv.d.mts → Task-C0o4i3Nn.d.mts} +23 -4
- package/dist/{Task-D4QHjdGv.d.ts → Task-C0o4i3Nn.d.ts} +23 -4
- package/dist/{chunk-6LEA6WAM.mjs → chunk-DMG4ISUG.mjs} +923 -45
- package/dist/chunk-DMG4ISUG.mjs.map +1 -0
- package/dist/{chunk-RT4NQ2BZ.mjs → chunk-EEE2GBLG.mjs} +114 -27
- package/dist/chunk-EEE2GBLG.mjs.map +1 -0
- package/dist/chunk-H7QX32BH.mjs +647 -0
- package/dist/chunk-H7QX32BH.mjs.map +1 -0
- package/dist/{chunk-F3KIX7WR.mjs → chunk-LTHKFBKM.mjs} +4 -4
- package/dist/chunk-LTHKFBKM.mjs.map +1 -0
- package/dist/index.d.mts +278 -1701
- package/dist/index.d.ts +278 -1701
- package/dist/index.js +2744 -1915
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2186 -1535
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.d.mts +2 -2
- package/dist/parsing.d.ts +2 -2
- package/dist/parsing.js +231 -75
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -3
- package/dist/plan-utils.d.mts +20 -4
- package/dist/plan-utils.d.ts +20 -4
- package/dist/plan-utils.js +255 -97
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +33 -19
- package/dist/{plan-utils-wI8MuDBC.d.mts → runSettingsText-BgOmLxdw.d.mts} +1941 -108
- package/dist/{plan-utils-BVJCzNvm.d.ts → runSettingsText-BgXvajj2.d.ts} +1941 -108
- package/dist/testing.d.mts +2 -3
- package/dist/testing.d.ts +2 -3
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +1 -1
- package/dist/IFileSystem-ClBdp59f.d.ts +0 -78
- package/dist/IFileSystem-Db34maxC.d.mts +0 -78
- package/dist/chunk-4QLFM73A.mjs +0 -1407
- package/dist/chunk-4QLFM73A.mjs.map +0 -1
- package/dist/chunk-6LEA6WAM.mjs.map +0 -1
- package/dist/chunk-F3KIX7WR.mjs.map +0 -1
- package/dist/chunk-RT4NQ2BZ.mjs.map +0 -1
package/dist/plan-utils.js
CHANGED
|
@@ -36,6 +36,7 @@ __export(plan_utils_exports, {
|
|
|
36
36
|
EMPTY_HOLD: () => EMPTY_HOLD,
|
|
37
37
|
EMPTY_RUN: () => EMPTY_RUN,
|
|
38
38
|
EMPTY_TASK_LOG: () => EMPTY_TASK_LOG,
|
|
39
|
+
EMPTY_TASK_LOG_FOLLOW: () => EMPTY_TASK_LOG_FOLLOW,
|
|
39
40
|
NOT_STARTED: () => NOT_STARTED,
|
|
40
41
|
NO_TURN: () => NO_TURN,
|
|
41
42
|
SUPERVISOR_LEVEL_LABEL: () => SUPERVISOR_LEVEL_LABEL,
|
|
@@ -56,6 +57,7 @@ __export(plan_utils_exports, {
|
|
|
56
57
|
canSetDependencies: () => canSetDependencies,
|
|
57
58
|
canSplitTask: () => canSplitTask,
|
|
58
59
|
capConflictFiles: () => capConflictFiles,
|
|
60
|
+
clampThinkingEffort: () => clampThinkingEffort,
|
|
59
61
|
countedSessionCost: () => countedSessionCost,
|
|
60
62
|
dependencyCandidates: () => dependencyCandidates,
|
|
61
63
|
dependentsNotice: () => dependentsNotice,
|
|
@@ -65,6 +67,7 @@ __export(plan_utils_exports, {
|
|
|
65
67
|
diffSummary: () => diffSummary,
|
|
66
68
|
drainNext: () => drainNext,
|
|
67
69
|
endAttemptUsage: () => endAttemptUsage,
|
|
70
|
+
followTaskLog: () => followTaskLog,
|
|
68
71
|
followTurn: () => followTurn,
|
|
69
72
|
fromTranscript: () => fromTranscript,
|
|
70
73
|
hasHiddenDetail: () => hasHiddenDetail,
|
|
@@ -92,6 +95,7 @@ __export(plan_utils_exports, {
|
|
|
92
95
|
reduceTaskLog: () => reduceTaskLog,
|
|
93
96
|
replayTaskLog: () => replayTaskLog,
|
|
94
97
|
resolveTaskRef: () => resolveTaskRef,
|
|
98
|
+
resolveUserTaskRef: () => resolveUserTaskRef,
|
|
95
99
|
resumeLabel: () => resumeLabel,
|
|
96
100
|
resumeTime: () => resumeTime,
|
|
97
101
|
resumedSessionWindow: () => resumedSessionWindow,
|
|
@@ -100,9 +104,11 @@ __export(plan_utils_exports, {
|
|
|
100
104
|
skippedLabel: () => skippedLabel,
|
|
101
105
|
startAttemptUsage: () => startAttemptUsage,
|
|
102
106
|
stopTurn: () => stopTurn,
|
|
107
|
+
subtreeIds: () => subtreeIds,
|
|
103
108
|
summarizeToolCall: () => summarizeToolCall,
|
|
104
109
|
takeAt: () => takeAt,
|
|
105
110
|
taskOrderLabel: () => taskOrderLabel,
|
|
111
|
+
taskPlacement: () => taskPlacement,
|
|
106
112
|
taskRef: () => taskRef,
|
|
107
113
|
taskRefOf: () => taskRefOf,
|
|
108
114
|
taskRowActions: () => taskRowActions,
|
|
@@ -117,7 +123,8 @@ __export(plan_utils_exports, {
|
|
|
117
123
|
truncateCheckpointSummary: () => truncateCheckpointSummary,
|
|
118
124
|
unsendAll: () => unsendAll,
|
|
119
125
|
unsendLatest: () => unsendLatest,
|
|
120
|
-
usageLine: () => usageLine
|
|
126
|
+
usageLine: () => usageLine,
|
|
127
|
+
walkPlan: () => walkPlan
|
|
121
128
|
});
|
|
122
129
|
module.exports = __toCommonJS(plan_utils_exports);
|
|
123
130
|
|
|
@@ -143,6 +150,90 @@ function loadedSkillTokens(text2, loaded) {
|
|
|
143
150
|
return skillTokens(text2).filter((t) => loaded.includes(t.name));
|
|
144
151
|
}
|
|
145
152
|
|
|
153
|
+
// src/services/PlanTree.ts
|
|
154
|
+
function* walkPlan(tasks) {
|
|
155
|
+
function* walk(level, ancestors, parentLabel) {
|
|
156
|
+
for (const task of level) {
|
|
157
|
+
const label = parentLabel ? `${parentLabel}.${task.order}` : String(task.order);
|
|
158
|
+
yield { task, parent: ancestors.at(-1), ancestors, siblings: level, label };
|
|
159
|
+
yield* walk(task.subtasks ?? [], [...ancestors, task], label);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
yield* walk(tasks, []);
|
|
163
|
+
}
|
|
164
|
+
function taskPlacement(tasks, id) {
|
|
165
|
+
for (const row of walkPlan(tasks)) if (row.task.id === id) return row;
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
function subtreeIds(tasks, id) {
|
|
169
|
+
const found = taskPlacement(tasks, id);
|
|
170
|
+
return new Set(found ? [...walkPlan([found.task])].map(({ task }) => task.id) : []);
|
|
171
|
+
}
|
|
172
|
+
function dependencyCandidates(tasks, taskId) {
|
|
173
|
+
if (!taskId) return [...tasks];
|
|
174
|
+
const found = taskPlacement(tasks, taskId);
|
|
175
|
+
return found ? found.siblings.filter((t) => t.order < found.task.order) : [];
|
|
176
|
+
}
|
|
177
|
+
function dependentsOf(tasks, taskId) {
|
|
178
|
+
const removed = subtreeIds(tasks, taskId);
|
|
179
|
+
return [...walkPlan(tasks)].map(({ task }) => task).filter((t) => !removed.has(t.id) && t.dependencies.some((id) => removed.has(id)));
|
|
180
|
+
}
|
|
181
|
+
function dependencyTargetErrors(tasks, taskId, dependencies) {
|
|
182
|
+
const found = taskPlacement(tasks, taskId);
|
|
183
|
+
if (!found) return ["Task not found"];
|
|
184
|
+
const descendants = subtreeIds(tasks, taskId);
|
|
185
|
+
const errors = [];
|
|
186
|
+
for (const dep of dependencies) {
|
|
187
|
+
if (dep === taskId) {
|
|
188
|
+
errors.push(`"${found.task.title}" cannot depend on itself`);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const target = taskPlacement(tasks, dep)?.task;
|
|
192
|
+
if (!target) {
|
|
193
|
+
errors.push(`Unknown dependency "${dep}"`);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (found.ancestors.some((t) => t.id === dep) || descendants.has(dep)) {
|
|
197
|
+
errors.push(`"${found.task.title}" cannot depend on "${target.title}", its ancestor or descendant`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return errors;
|
|
201
|
+
}
|
|
202
|
+
function findDependencyCycle(tasks) {
|
|
203
|
+
const byId = new Map([...walkPlan(tasks)].map(({ task }) => [task.id, task]));
|
|
204
|
+
const path = [];
|
|
205
|
+
const done = /* @__PURE__ */ new Set();
|
|
206
|
+
const visit = (id) => {
|
|
207
|
+
if (done.has(id)) return null;
|
|
208
|
+
const at = path.indexOf(id);
|
|
209
|
+
if (at >= 0) return path.slice(at);
|
|
210
|
+
path.push(id);
|
|
211
|
+
for (const dep of byId.get(id)?.dependencies ?? []) {
|
|
212
|
+
const hit = visit(dep);
|
|
213
|
+
if (hit) return hit;
|
|
214
|
+
}
|
|
215
|
+
path.pop();
|
|
216
|
+
done.add(id);
|
|
217
|
+
return null;
|
|
218
|
+
};
|
|
219
|
+
for (const id of byId.keys()) {
|
|
220
|
+
const hit = visit(id);
|
|
221
|
+
if (hit) return hit.map((key) => byId.get(key));
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
function canSetDependencies(tasks, taskId, dependencies) {
|
|
226
|
+
const [error] = dependencyTargetErrors(tasks, taskId, dependencies);
|
|
227
|
+
if (error) return { ok: false, error };
|
|
228
|
+
const replace = (level) => level.map((t) => ({
|
|
229
|
+
...t,
|
|
230
|
+
dependencies: t.id === taskId ? dependencies : t.dependencies,
|
|
231
|
+
subtasks: replace(t.subtasks ?? [])
|
|
232
|
+
}));
|
|
233
|
+
const cycle = findDependencyCycle(replace(tasks));
|
|
234
|
+
return cycle ? { ok: false, error: `Dependency cycle detected: ${[...cycle, cycle[0]].map((t) => `"${t.title}"`).join(" \u2192 ")}` } : { ok: true };
|
|
235
|
+
}
|
|
236
|
+
|
|
146
237
|
// src/services/TaskRefs.ts
|
|
147
238
|
function taskOrderLabel(task, parent) {
|
|
148
239
|
return parent ? `${parent.label ?? parent.order}.${task.order}` : String(task.order);
|
|
@@ -153,16 +244,8 @@ function taskRef(task, parent) {
|
|
|
153
244
|
function titledTaskRef(task, parent) {
|
|
154
245
|
return `${taskRef(task, parent)} ${task.title}`;
|
|
155
246
|
}
|
|
156
|
-
function* depthFirst(tasks, parent, parentLabel) {
|
|
157
|
-
for (const task of tasks) {
|
|
158
|
-
const label = taskOrderLabel(task, parent ? { order: parent.order, label: parentLabel } : void 0);
|
|
159
|
-
yield { task, parent, label };
|
|
160
|
-
yield* depthFirst(task.subtasks ?? [], task, label);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
247
|
function findTaskRef(tasks, id) {
|
|
164
|
-
|
|
165
|
-
return void 0;
|
|
248
|
+
return taskPlacement(tasks, id);
|
|
166
249
|
}
|
|
167
250
|
function taskRefOf(tasks, id) {
|
|
168
251
|
const found = findTaskRef(tasks, id);
|
|
@@ -175,7 +258,7 @@ function titledTaskRefOf(tasks, id) {
|
|
|
175
258
|
function resolveTaskRef(tasks, ref) {
|
|
176
259
|
const s = String(ref).trim();
|
|
177
260
|
if (!s) return void 0;
|
|
178
|
-
for (const { task } of
|
|
261
|
+
for (const { task } of walkPlan(tasks)) if (task.id === s) return task;
|
|
179
262
|
const label = s.startsWith("#") ? s.slice(1) : s;
|
|
180
263
|
if (/^\d+(\.\d+)*$/.test(label)) {
|
|
181
264
|
let level = tasks;
|
|
@@ -186,9 +269,16 @@ function resolveTaskRef(tasks, ref) {
|
|
|
186
269
|
}
|
|
187
270
|
return found;
|
|
188
271
|
}
|
|
189
|
-
for (const { task } of
|
|
272
|
+
for (const { task } of walkPlan(tasks)) if (task.title === s) return task;
|
|
190
273
|
return void 0;
|
|
191
274
|
}
|
|
275
|
+
function resolveUserTaskRef(tasks, ref) {
|
|
276
|
+
const found = resolveTaskRef(tasks, ref);
|
|
277
|
+
if (found) return found;
|
|
278
|
+
const prefix = String(ref).trim();
|
|
279
|
+
const matches = prefix ? [...walkPlan(tasks)].filter(({ task }) => task.id.startsWith(prefix)) : [];
|
|
280
|
+
return matches.length === 1 ? matches[0].task : void 0;
|
|
281
|
+
}
|
|
192
282
|
|
|
193
283
|
// src/models/Task.ts
|
|
194
284
|
var SKILL_NAME = new RegExp(`^${SKILL_NAME_PATTERN}$`);
|
|
@@ -200,20 +290,6 @@ function pausedOnLimit(task) {
|
|
|
200
290
|
// src/services/TaskOps.ts
|
|
201
291
|
var import_uuid3 = require("uuid");
|
|
202
292
|
|
|
203
|
-
// src/services/ModelAllowlistResolver.ts
|
|
204
|
-
function effectiveAllowlist(allowlist, runner, modelsByRunner) {
|
|
205
|
-
if (!allowlist || allowlist.length === 0) return void 0;
|
|
206
|
-
if (!modelsByRunner) return allowlist;
|
|
207
|
-
const own = new Set((modelsByRunner[runner] ?? []).map((m) => m.modelId));
|
|
208
|
-
const elsewhere = /* @__PURE__ */ new Set();
|
|
209
|
-
for (const [other, models] of Object.entries(modelsByRunner)) {
|
|
210
|
-
if (other === runner) continue;
|
|
211
|
-
for (const m of models ?? []) elsewhere.add(m.modelId);
|
|
212
|
-
}
|
|
213
|
-
const kept = allowlist.filter((id) => own.has(id) || !elsewhere.has(id));
|
|
214
|
-
return kept.length > 0 ? kept : void 0;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
293
|
// src/taskRow/status.ts
|
|
218
294
|
var isTaskRunning = (task) => task.status === "in_progress" || task.status === "running";
|
|
219
295
|
var NOT_STARTED = /* @__PURE__ */ new Set(["pending", "approved", "blocked"]);
|
|
@@ -267,28 +343,43 @@ function resumeLabel(task, now = /* @__PURE__ */ new Date()) {
|
|
|
267
343
|
|
|
268
344
|
// src/services/PlannedTask.ts
|
|
269
345
|
var import_uuid2 = require("uuid");
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
for (const
|
|
280
|
-
const hit = visit(dep);
|
|
281
|
-
if (hit) return hit;
|
|
282
|
-
}
|
|
283
|
-
path.pop();
|
|
284
|
-
done.add(id);
|
|
285
|
-
return null;
|
|
286
|
-
};
|
|
287
|
-
for (const t of tasks) {
|
|
288
|
-
const hit = visit(t.id);
|
|
289
|
-
if (hit) return hit.map((id) => byId.get(id));
|
|
346
|
+
|
|
347
|
+
// src/services/ModelAllowlistResolver.ts
|
|
348
|
+
function effectiveAllowlist(allowlist, runner, modelsByRunner) {
|
|
349
|
+
if (!allowlist || allowlist.length === 0) return void 0;
|
|
350
|
+
if (!modelsByRunner) return allowlist;
|
|
351
|
+
const own = new Set((modelsByRunner[runner] ?? []).map((m) => m.modelId));
|
|
352
|
+
const elsewhere = /* @__PURE__ */ new Set();
|
|
353
|
+
for (const [other, models] of Object.entries(modelsByRunner)) {
|
|
354
|
+
if (other === runner) continue;
|
|
355
|
+
for (const m of models ?? []) elsewhere.add(m.modelId);
|
|
290
356
|
}
|
|
291
|
-
|
|
357
|
+
const kept = allowlist.filter((id) => own.has(id) || !elsewhere.has(id));
|
|
358
|
+
return kept.length > 0 ? kept : void 0;
|
|
359
|
+
}
|
|
360
|
+
var EFFORT_LADDER = ["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"];
|
|
361
|
+
var EFFORT_ALIASES = { disabled: "none", adaptive: "medium" };
|
|
362
|
+
function clampThinkingEffort(effort, variants) {
|
|
363
|
+
if (!effort) return void 0;
|
|
364
|
+
if (variants.length === 0) return void 0;
|
|
365
|
+
const ids = new Set(variants.map((v) => v.id));
|
|
366
|
+
if (ids.has(effort)) return effort;
|
|
367
|
+
const canon = EFFORT_ALIASES[effort] ?? effort;
|
|
368
|
+
if (ids.has(canon)) return canon;
|
|
369
|
+
const idx = EFFORT_LADDER.indexOf(canon);
|
|
370
|
+
if (idx < 0) return void 0;
|
|
371
|
+
for (let d = 1; d < EFFORT_LADDER.length; d++) {
|
|
372
|
+
const lower = EFFORT_LADDER[idx - d];
|
|
373
|
+
if (lower && ids.has(lower)) return lower;
|
|
374
|
+
const higher = EFFORT_LADDER[idx + d];
|
|
375
|
+
if (higher && ids.has(higher)) return higher;
|
|
376
|
+
}
|
|
377
|
+
return void 0;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/services/PlannedTask.ts
|
|
381
|
+
function findCycle(tasks) {
|
|
382
|
+
return findDependencyCycle(tasks);
|
|
292
383
|
}
|
|
293
384
|
function detectCycle(tasks) {
|
|
294
385
|
return findCycle(tasks)?.[0].title ?? null;
|
|
@@ -313,28 +404,6 @@ function canMergeTasks(tasks, selectedIds) {
|
|
|
313
404
|
if (cycle) return { ok: false, error: `Merging would create a dependency cycle involving "${cycle}"` };
|
|
314
405
|
return { ok: true };
|
|
315
406
|
}
|
|
316
|
-
function dependentsOf(tasks, taskId) {
|
|
317
|
-
return tasks.filter((t) => t.id !== taskId && t.dependencies.includes(taskId));
|
|
318
|
-
}
|
|
319
|
-
function dependencyCandidates(tasks, taskId) {
|
|
320
|
-
if (!taskId) return [...tasks];
|
|
321
|
-
const target = tasks.find((t) => t.id === taskId);
|
|
322
|
-
return target ? tasks.filter((t) => t.order < target.order) : [];
|
|
323
|
-
}
|
|
324
|
-
function canSetDependencies(tasks, taskId, dependencies) {
|
|
325
|
-
const target = tasks.find((t) => t.id === taskId);
|
|
326
|
-
if (!target) return { ok: false, error: "Task not found" };
|
|
327
|
-
const allowed = new Set(dependencyCandidates(tasks, taskId).map((t) => t.id));
|
|
328
|
-
for (const dep of dependencies) {
|
|
329
|
-
if (dep === taskId) return { ok: false, error: `"${target.title}" cannot depend on itself` };
|
|
330
|
-
const found = tasks.find((t) => t.id === dep);
|
|
331
|
-
if (!found) return { ok: false, error: `Unknown dependency "${dep}"` };
|
|
332
|
-
if (!allowed.has(dep)) {
|
|
333
|
-
return { ok: false, error: `"${target.title}" cannot depend on "${found.title}", which comes after it in the plan` };
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return { ok: true };
|
|
337
|
-
}
|
|
338
407
|
function canSplitTask(tasks, taskId) {
|
|
339
408
|
const target = tasks.find((t) => t.id === taskId);
|
|
340
409
|
if (!target) return { ok: false, error: "Task not found" };
|
|
@@ -657,7 +726,7 @@ function planMarker(content) {
|
|
|
657
726
|
}
|
|
658
727
|
|
|
659
728
|
// src/services/blocking.ts
|
|
660
|
-
var UNSTARTED = /* @__PURE__ */ new Set(["pending", "approved"
|
|
729
|
+
var UNSTARTED = /* @__PURE__ */ new Set(["pending", "approved"]);
|
|
661
730
|
function blockingFailures(tasks) {
|
|
662
731
|
const byId = /* @__PURE__ */ new Map();
|
|
663
732
|
const index = (list) => {
|
|
@@ -1032,8 +1101,9 @@ function dropBuildingPlan(view, turnId, segmentId) {
|
|
|
1032
1101
|
const blocks = view.blocks.filter((b) => !(isBuildingPlan(b, turnId) && (segmentId === void 0 || b.segmentId === segmentId)));
|
|
1033
1102
|
return blocks.length === view.blocks.length ? view : { ...view, blocks };
|
|
1034
1103
|
}
|
|
1035
|
-
function settleReply(view, { content, turnId, supervisor }) {
|
|
1104
|
+
function settleReply(view, { content, turnId, supervisor, runs }) {
|
|
1036
1105
|
const role = supervisor ? "supervisor" : "planner";
|
|
1106
|
+
if (runs) return settleRuns(view, runs, role, turnId);
|
|
1037
1107
|
if (turnId !== void 0) {
|
|
1038
1108
|
const i = finalSegmentIndex(view.blocks, turnId);
|
|
1039
1109
|
if (i >= 0) {
|
|
@@ -1042,6 +1112,25 @@ function settleReply(view, { content, turnId, supervisor }) {
|
|
|
1042
1112
|
}
|
|
1043
1113
|
return append(dropBuildingPlan(view, turnId), (id) => settledMessage(id, role, content, turnId));
|
|
1044
1114
|
}
|
|
1115
|
+
function settleRuns(view, runs, role, turnId) {
|
|
1116
|
+
const settled = /* @__PURE__ */ new Map();
|
|
1117
|
+
let turn = turnId;
|
|
1118
|
+
for (const run of runs) {
|
|
1119
|
+
const i = view.blocks.findIndex((b) => b.type === "message" && b.segmentId === run.segmentId && b.turnId !== void 0 && (turnId === void 0 || b.turnId === turnId));
|
|
1120
|
+
const segment = view.blocks[i];
|
|
1121
|
+
if (segment?.type !== "message") continue;
|
|
1122
|
+
settled.set(i, run);
|
|
1123
|
+
turn ??= segment.turnId;
|
|
1124
|
+
}
|
|
1125
|
+
const contained = new Set(runs.map((run) => run.segmentId));
|
|
1126
|
+
const blocks = view.blocks.flatMap((block, i) => {
|
|
1127
|
+
const run = settled.get(i);
|
|
1128
|
+
if (run) return [settledMessage(block.id, role, run.text, turn)];
|
|
1129
|
+
return turn !== void 0 && isUnsettledSegment(block, turn) && !contained.has(block.segmentId) ? [] : [block];
|
|
1130
|
+
});
|
|
1131
|
+
const streamed = new Set(settled.values());
|
|
1132
|
+
return runs.filter((run) => !streamed.has(run)).reduce((next, run) => append(next, (id) => settledMessage(id, role, run.text, turn)), dropBuildingPlan({ ...view, blocks }, turn));
|
|
1133
|
+
}
|
|
1045
1134
|
function retractText(view, { turnId, segmentId }) {
|
|
1046
1135
|
const blocks = view.blocks.filter((b) => !(isUnsettledSegment(b, turnId) && (segmentId === void 0 || b.segmentId === segmentId)));
|
|
1047
1136
|
return dropBuildingPlan(blocks.length === view.blocks.length ? view : { ...view, blocks }, turnId, segmentId);
|
|
@@ -1318,7 +1407,7 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage, pendingT
|
|
|
1318
1407
|
const kept = compacted ? history.slice(1) : history;
|
|
1319
1408
|
const cutoff = compacted ? kept[0]?.timestamp ?? compacted.timestamp : "";
|
|
1320
1409
|
const placed = [
|
|
1321
|
-
...kept.
|
|
1410
|
+
...kept.flatMap((entry, i) => entry.runs ? entry.runs.map((run) => ({ at: run.startedAt, rank: SETTLED, build: (id2) => settledMessage(id2(), roleOf(entry), run.text) })) : [{ at: entry.timestamp, rank: rankOf(entry), build: fromEntry(entry, loadsAfter(kept, i)) }]),
|
|
1322
1411
|
...research(researchLog ?? []).filter((item) => item.at >= cutoff)
|
|
1323
1412
|
];
|
|
1324
1413
|
placed.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : a.rank - b.rank);
|
|
@@ -1351,7 +1440,7 @@ function sameMessage(a, b) {
|
|
|
1351
1440
|
|
|
1352
1441
|
// src/conversation/taskLog.ts
|
|
1353
1442
|
var EMPTY_TASK_LOG = { blocks: [], nextId: 1, queued: [], working: false, streams: {} };
|
|
1354
|
-
var
|
|
1443
|
+
var textStream = (runId) => runId === void 0 ? "text" : `text:${runId}`;
|
|
1355
1444
|
var thinkingStream = (subagentId) => `thinking:${subagentId ?? ""}`;
|
|
1356
1445
|
function withoutStream(view, key) {
|
|
1357
1446
|
if (!(key in view.streams)) return view;
|
|
@@ -1368,35 +1457,43 @@ function openStream(view, lane, key) {
|
|
|
1368
1457
|
const block = blocks[i];
|
|
1369
1458
|
return block?.id === id && (block.type === "message" || block.type === "thinking") && block.streaming ? i : -1;
|
|
1370
1459
|
}
|
|
1371
|
-
function
|
|
1372
|
-
const
|
|
1460
|
+
function streamBlock(view, lane, key) {
|
|
1461
|
+
const id = view.streams[key];
|
|
1462
|
+
return id === void 0 ? -1 : findLastIndex(laneBlocks(view, lane), (b) => b.id === id);
|
|
1463
|
+
}
|
|
1464
|
+
function streamDelta(view, lane, key, text2, make, anywhere = false) {
|
|
1465
|
+
const i = anywhere ? streamBlock(view, lane, key) : openStream(view, lane, key);
|
|
1373
1466
|
const open = laneBlocks(view, lane)[i];
|
|
1374
1467
|
if (open?.type === "message" || open?.type === "thinking") return laneReplace(view, lane, i, { ...open, text: open.text + text2 });
|
|
1375
1468
|
const next = appendOutput(view, lane, (id) => make(id, blockText(text2)));
|
|
1376
1469
|
return { ...next, streams: { ...next.streams, [key]: `b${view.nextId}` } };
|
|
1377
1470
|
}
|
|
1378
1471
|
function streamWhole(view, lane, key, text2, make) {
|
|
1379
|
-
const
|
|
1380
|
-
const
|
|
1381
|
-
const i = id === void 0 ? -1 : findLastIndex(blocks, (b) => b.id === id);
|
|
1382
|
-
const streamed = blocks[i];
|
|
1472
|
+
const i = streamBlock(view, lane, key);
|
|
1473
|
+
const streamed = laneBlocks(view, lane)[i];
|
|
1383
1474
|
const next = withoutStream(view, key);
|
|
1384
1475
|
if (streamed?.type === "message" || streamed?.type === "thinking") {
|
|
1385
1476
|
return laneReplace(next, lane, i, { ...streamed, text: blockText(text2), streaming: false });
|
|
1386
1477
|
}
|
|
1387
1478
|
return appendOutput(next, lane, make);
|
|
1388
1479
|
}
|
|
1389
|
-
function
|
|
1390
|
-
|
|
1391
|
-
return { ...next, latestText: next.nextId > view.nextId ? `b${view.nextId}` : view.streams[TEXT_STREAM] };
|
|
1480
|
+
function openedText(view, next) {
|
|
1481
|
+
return next.nextId > view.nextId ? { ...next, latestText: `b${view.nextId}` } : next;
|
|
1392
1482
|
}
|
|
1393
|
-
function
|
|
1394
|
-
|
|
1395
|
-
|
|
1483
|
+
function agentText(view, { runId, text: text2 }) {
|
|
1484
|
+
return openedText(view, streamWhole(view, null, textStream(runId), text2, (id) => settledMessage(id, "agent", blockText(text2))));
|
|
1485
|
+
}
|
|
1486
|
+
function agentTextDelta(view, { runId, text: text2 }) {
|
|
1487
|
+
const make = (id, t) => ({ type: "message", id, role: "agent", text: t, streaming: true });
|
|
1488
|
+
return openedText(view, streamDelta(view, null, textStream(runId), text2, make, runId !== void 0));
|
|
1396
1489
|
}
|
|
1397
1490
|
function failTurn(view, message) {
|
|
1398
1491
|
const repeated = view.blocks.find((b) => b.id === view.latestText);
|
|
1399
|
-
const settled = repeated?.type === "message" && repeated.role === "agent" && sameMessage(repeated.text, message) ?
|
|
1492
|
+
const settled = repeated?.type === "message" && repeated.role === "agent" && sameMessage(repeated.text, message) ? {
|
|
1493
|
+
...view,
|
|
1494
|
+
blocks: view.blocks.filter((b) => b !== repeated),
|
|
1495
|
+
streams: Object.fromEntries(Object.entries(view.streams).filter(([, id]) => id !== repeated.id))
|
|
1496
|
+
} : view;
|
|
1400
1497
|
return appendOutput({ ...settled, latestText: void 0 }, null, (id) => settledMessage(id, "error", message));
|
|
1401
1498
|
}
|
|
1402
1499
|
function thinkingBlock(id, text2, streaming, subagentId) {
|
|
@@ -1577,7 +1674,7 @@ function endCall(block) {
|
|
|
1577
1674
|
function endOpenCalls(view) {
|
|
1578
1675
|
let changed = false;
|
|
1579
1676
|
const blocks = view.blocks.map((block) => {
|
|
1580
|
-
const ended = block.type === "subagent" ? block.children.some((c) => c.type === "tool" && c.status === "pending") ? { ...block, children: block.children.map(endCall) } : block : block.type === "tool" ? endCall(block) : block;
|
|
1677
|
+
const ended = block.type === "subagent" ? block.children.some((c) => c.type === "tool" && c.status === "pending") ? { ...block, children: block.children.map(endCall) } : block : block.type === "tool" ? endCall(block) : block.type === "command" && block.status === "running" ? { ...block, status: "stopped" } : block;
|
|
1581
1678
|
if (ended !== block) changed = true;
|
|
1582
1679
|
return ended;
|
|
1583
1680
|
});
|
|
@@ -1608,9 +1705,9 @@ function reduceTaskLog(view, event) {
|
|
|
1608
1705
|
case "turn_end":
|
|
1609
1706
|
return endTurn2(view, event);
|
|
1610
1707
|
case "text_delta":
|
|
1611
|
-
return agentTextDelta(view, event
|
|
1708
|
+
return agentTextDelta(view, event);
|
|
1612
1709
|
case "text":
|
|
1613
|
-
return agentText(view, event
|
|
1710
|
+
return agentText(view, event);
|
|
1614
1711
|
case "thinking_delta":
|
|
1615
1712
|
return thinkingDelta(view, event);
|
|
1616
1713
|
case "thinking":
|
|
@@ -1644,7 +1741,7 @@ function reduceTaskLog(view, event) {
|
|
|
1644
1741
|
case "approval_withdrawn":
|
|
1645
1742
|
return settleApproval2(view, event.approvalId, (block) => ({ ...block, status: "withdrawn" }));
|
|
1646
1743
|
case "runner_ended":
|
|
1647
|
-
return endOpenCalls(view);
|
|
1744
|
+
return closeOpenBlocks({ ...endOpenCalls(view), working: false, streams: {}, latestText: void 0 }, "stopped");
|
|
1648
1745
|
default:
|
|
1649
1746
|
return view;
|
|
1650
1747
|
}
|
|
@@ -1699,16 +1796,16 @@ function cutOff(gate, input) {
|
|
|
1699
1796
|
const turnId = "turnId" in input ? input.turnId : void 0;
|
|
1700
1797
|
return turnId === void 0 || turnId === gate.stopped;
|
|
1701
1798
|
}
|
|
1702
|
-
function withGate(
|
|
1703
|
-
return gate.open ===
|
|
1799
|
+
function withGate(live2, gate) {
|
|
1800
|
+
return gate.open === live2.gate.open && gate.stopped === live2.gate.stopped ? live2 : { ...live2, gate };
|
|
1704
1801
|
}
|
|
1705
1802
|
function followTurn(view, gate, input) {
|
|
1706
|
-
const
|
|
1803
|
+
const live2 = { view, gate };
|
|
1707
1804
|
if (input.type === "planner_turn_started") {
|
|
1708
1805
|
return withGate({ view: reduceConversation(view, input), gate }, { open: input.turnId, stopped: null });
|
|
1709
1806
|
}
|
|
1710
1807
|
if (cutOff(gate, input)) {
|
|
1711
|
-
return input.type === "planner_turn_ended" ? withGate(
|
|
1808
|
+
return input.type === "planner_turn_ended" ? withGate(live2, { ...gate, stopped: null }) : live2;
|
|
1712
1809
|
}
|
|
1713
1810
|
const next = { view: reduceConversation(view, input), gate };
|
|
1714
1811
|
return input.type === "planner_turn_ended" && input.turnId === gate.open ? withGate(next, { ...gate, open: null }) : next;
|
|
@@ -1761,6 +1858,60 @@ function markdownHtml(text2) {
|
|
|
1761
1858
|
return md.render(text2);
|
|
1762
1859
|
}
|
|
1763
1860
|
|
|
1861
|
+
// src/conversation/taskLogFollow.ts
|
|
1862
|
+
var EMPTY_TASK_LOG_FOLLOW = {
|
|
1863
|
+
view: EMPTY_TASK_LOG,
|
|
1864
|
+
attempts: [],
|
|
1865
|
+
attempt: 0,
|
|
1866
|
+
pending: [],
|
|
1867
|
+
loaded: false,
|
|
1868
|
+
followLatest: true
|
|
1869
|
+
};
|
|
1870
|
+
function covered(position, batch) {
|
|
1871
|
+
return !!position && !!batch.position && position.stream === batch.position.stream && batch.position.seq <= position.seq;
|
|
1872
|
+
}
|
|
1873
|
+
function live(state, batch) {
|
|
1874
|
+
if (batch.attempt <= 0 || batch.attempt < state.attempt) return state;
|
|
1875
|
+
const attempts = state.attempts.includes(batch.attempt) ? state.attempts : [...state.attempts, batch.attempt].sort((a, b) => a - b);
|
|
1876
|
+
if (batch.attempt > state.attempt) {
|
|
1877
|
+
if (!state.followLatest) return attempts === state.attempts ? state : { ...state, attempts };
|
|
1878
|
+
return { ...state, attempts, attempt: batch.attempt, position: void 0, view: batch.events.reduce(reduceTaskLog, EMPTY_TASK_LOG) };
|
|
1879
|
+
}
|
|
1880
|
+
if (covered(state.position, batch)) return state;
|
|
1881
|
+
return { ...state, attempts, view: batch.events.reduce(reduceTaskLog, state.view) };
|
|
1882
|
+
}
|
|
1883
|
+
function followTaskLog(state, input) {
|
|
1884
|
+
switch (input.type) {
|
|
1885
|
+
case "opened":
|
|
1886
|
+
return EMPTY_TASK_LOG_FOLLOW;
|
|
1887
|
+
case "picked":
|
|
1888
|
+
return { ...state, loaded: false, loadingAttempt: input.attempt, followLatest: input.attempt === state.attempts.at(-1) };
|
|
1889
|
+
case "live":
|
|
1890
|
+
return state.loaded ? live(state, input) : { ...state, pending: [...state.pending, input] };
|
|
1891
|
+
case "loaded": {
|
|
1892
|
+
if (state.loaded) return state;
|
|
1893
|
+
if (!input.abandoned && state.loadingAttempt !== void 0 && input.attempt !== state.loadingAttempt) return state;
|
|
1894
|
+
const attempts = [.../* @__PURE__ */ new Set([...input.attempts ?? state.attempts, ...state.pending.map((batch) => batch.attempt)])].filter((attempt) => attempt > 0).sort((a, b) => a - b);
|
|
1895
|
+
let next = {
|
|
1896
|
+
...state,
|
|
1897
|
+
attempts,
|
|
1898
|
+
loaded: true,
|
|
1899
|
+
pending: [],
|
|
1900
|
+
loadingAttempt: void 0,
|
|
1901
|
+
...input.abandoned ? {} : { attempt: input.attempt, view: replayTaskLog(input.events), position: input.position }
|
|
1902
|
+
};
|
|
1903
|
+
for (const batch of state.pending) {
|
|
1904
|
+
if (!input.abandoned && batch.attempt === input.attempt) {
|
|
1905
|
+
if (covered(input.position, batch)) continue;
|
|
1906
|
+
if (!input.position && !batch.position) continue;
|
|
1907
|
+
}
|
|
1908
|
+
next = live(next, batch);
|
|
1909
|
+
}
|
|
1910
|
+
return next;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1764
1915
|
// src/taskRow/actions.ts
|
|
1765
1916
|
var UNSTARTED_AI = (t) => t.type === "ai" && NOT_STARTED.has(t.status);
|
|
1766
1917
|
var QUEUED = (t) => t.status === "pending" || t.status === "approved";
|
|
@@ -1883,10 +2034,10 @@ function taskRowView(task, context = {}) {
|
|
|
1883
2034
|
function titledRefs(ids, tasks) {
|
|
1884
2035
|
return ids.map((id) => titledTaskRefOf(tasks, id) ?? id);
|
|
1885
2036
|
}
|
|
1886
|
-
function dependentsNotice(dependents) {
|
|
2037
|
+
function dependentsNotice(dependents, tasks = []) {
|
|
1887
2038
|
if (dependents.length === 0) return null;
|
|
1888
2039
|
const subject = dependents.length === 1 ? "1 task depends" : `${dependents.length} tasks depend`;
|
|
1889
|
-
return `${subject} on it and will lose that dependency: ${dependents.map((t) => titledTaskRef(t)).join(", ")}.`;
|
|
2040
|
+
return `${subject} on it and will lose that dependency: ${dependents.map((t) => (t.id ? titledTaskRefOf(tasks, t.id) : void 0) ?? titledTaskRef(t)).join(", ")}.`;
|
|
1890
2041
|
}
|
|
1891
2042
|
function pastGateConfirmation(unmerged, subject = "This task") {
|
|
1892
2043
|
return `${subject} waits for Merge all: the work of ${unmerged.join(", ")} is not merged into your branch yet, so it would act without it. Starting it now is kept on the task.`;
|
|
@@ -1907,6 +2058,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1907
2058
|
EMPTY_HOLD,
|
|
1908
2059
|
EMPTY_RUN,
|
|
1909
2060
|
EMPTY_TASK_LOG,
|
|
2061
|
+
EMPTY_TASK_LOG_FOLLOW,
|
|
1910
2062
|
NOT_STARTED,
|
|
1911
2063
|
NO_TURN,
|
|
1912
2064
|
SUPERVISOR_LEVEL_LABEL,
|
|
@@ -1927,6 +2079,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1927
2079
|
canSetDependencies,
|
|
1928
2080
|
canSplitTask,
|
|
1929
2081
|
capConflictFiles,
|
|
2082
|
+
clampThinkingEffort,
|
|
1930
2083
|
countedSessionCost,
|
|
1931
2084
|
dependencyCandidates,
|
|
1932
2085
|
dependentsNotice,
|
|
@@ -1936,6 +2089,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1936
2089
|
diffSummary,
|
|
1937
2090
|
drainNext,
|
|
1938
2091
|
endAttemptUsage,
|
|
2092
|
+
followTaskLog,
|
|
1939
2093
|
followTurn,
|
|
1940
2094
|
fromTranscript,
|
|
1941
2095
|
hasHiddenDetail,
|
|
@@ -1963,6 +2117,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1963
2117
|
reduceTaskLog,
|
|
1964
2118
|
replayTaskLog,
|
|
1965
2119
|
resolveTaskRef,
|
|
2120
|
+
resolveUserTaskRef,
|
|
1966
2121
|
resumeLabel,
|
|
1967
2122
|
resumeTime,
|
|
1968
2123
|
resumedSessionWindow,
|
|
@@ -1971,9 +2126,11 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1971
2126
|
skippedLabel,
|
|
1972
2127
|
startAttemptUsage,
|
|
1973
2128
|
stopTurn,
|
|
2129
|
+
subtreeIds,
|
|
1974
2130
|
summarizeToolCall,
|
|
1975
2131
|
takeAt,
|
|
1976
2132
|
taskOrderLabel,
|
|
2133
|
+
taskPlacement,
|
|
1977
2134
|
taskRef,
|
|
1978
2135
|
taskRefOf,
|
|
1979
2136
|
taskRowActions,
|
|
@@ -1988,6 +2145,7 @@ var EMPTY_RUN = { tasks: [], runMerge: null, handoff: null, mergeResult: null };
|
|
|
1988
2145
|
truncateCheckpointSummary,
|
|
1989
2146
|
unsendAll,
|
|
1990
2147
|
unsendLatest,
|
|
1991
|
-
usageLine
|
|
2148
|
+
usageLine,
|
|
2149
|
+
walkPlan
|
|
1992
2150
|
});
|
|
1993
2151
|
//# sourceMappingURL=plan-utils.js.map
|