@ordewell/core 0.5.5 → 0.6.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/dist/IFileSystem-CFYf4yR2.d.mts +76 -0
- package/dist/IFileSystem-D4dAl2r8.d.ts +76 -0
- package/dist/{ModeResolver-D-SUFRNF.d.mts → ModeResolver-DVYVRbJp.d.ts} +6 -2
- package/dist/{ModeResolver-D3XO0fT9.d.ts → ModeResolver-a4xJFlEp.d.mts} +6 -2
- package/dist/Task-CZJr6rmz.d.mts +2121 -0
- package/dist/Task-CZJr6rmz.d.ts +2121 -0
- package/dist/{chunk-KLN7ELXO.mjs → chunk-2SOVKO7P.mjs} +1561 -1269
- package/dist/chunk-2SOVKO7P.mjs.map +1 -0
- package/dist/{chunk-T2S5O36I.mjs → chunk-C44UWIAD.mjs} +6 -6
- package/dist/chunk-C44UWIAD.mjs.map +1 -0
- package/dist/{chunk-HD2FWPRV.mjs → chunk-EDGUFCIR.mjs} +6 -1
- package/dist/chunk-EDGUFCIR.mjs.map +1 -0
- package/dist/{chunk-UUBGVCGJ.mjs → chunk-OM4D274O.mjs} +20 -2
- package/dist/chunk-OM4D274O.mjs.map +1 -0
- package/dist/index.d.mts +1594 -803
- package/dist/index.d.ts +1594 -803
- package/dist/index.js +9540 -6040
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8167 -4996
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +3 -1
- package/dist/order-labels.d.ts +3 -1
- package/dist/{parsing-BTP4bwkk.d.ts → parsing-Bd6-b644.d.ts} +2 -2
- package/dist/{parsing-CDtRSxBY.d.mts → parsing-DIaGZmiQ.d.mts} +2 -2
- package/dist/parsing.d.mts +5 -3
- package/dist/parsing.d.ts +5 -3
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +2 -2
- package/dist/{plan-utils-pE4TBwxl.d.mts → plan-utils-Ba-l8EZS.d.mts} +212 -43
- package/dist/{plan-utils-BFaPo-IT.d.ts → plan-utils-_T5S7Mnk.d.ts} +212 -43
- package/dist/plan-utils.d.mts +5 -4
- package/dist/plan-utils.d.ts +5 -4
- package/dist/plan-utils.js +352 -64
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +11 -5
- package/dist/testing.d.mts +54 -4
- package/dist/testing.d.ts +54 -4
- package/dist/testing.js +93 -2
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +91 -2
- package/dist/testing.mjs.map +1 -1
- package/package.json +2 -1
- package/skills/grilling/SKILL.md +6 -16
- package/skills/improve-codebase-architecture/SKILL.md +1 -1
- package/dist/ApprovalPolicy-BVhGdECT.d.mts +0 -79
- package/dist/ApprovalPolicy-BVhGdECT.d.ts +0 -79
- package/dist/ITerminalRunner-BV9Rd2o9.d.ts +0 -563
- package/dist/ITerminalRunner-C77ZNZS9.d.mts +0 -563
- package/dist/Task-Vl5Zq_D-.d.mts +0 -825
- package/dist/Task-Vl5Zq_D-.d.ts +0 -825
- package/dist/chunk-HD2FWPRV.mjs.map +0 -1
- package/dist/chunk-KLN7ELXO.mjs.map +0 -1
- package/dist/chunk-T2S5O36I.mjs.map +0 -1
- package/dist/chunk-UUBGVCGJ.mjs.map +0 -1
package/dist/plan-utils.js
CHANGED
|
@@ -23,6 +23,7 @@ __export(plan_utils_exports, {
|
|
|
23
23
|
CHECKPOINT_TRUNCATE_LENGTH: () => CHECKPOINT_TRUNCATE_LENGTH,
|
|
24
24
|
EMPTY_CONVERSATION: () => EMPTY_CONVERSATION,
|
|
25
25
|
EMPTY_HOLD: () => EMPTY_HOLD,
|
|
26
|
+
EMPTY_TASK_LOG: () => EMPTY_TASK_LOG,
|
|
26
27
|
NO_TURN: () => NO_TURN,
|
|
27
28
|
aheadOfDraft: () => aheadOfDraft,
|
|
28
29
|
canMergeTasks: () => canMergeTasks,
|
|
@@ -39,6 +40,9 @@ __export(plan_utils_exports, {
|
|
|
39
40
|
outputLines: () => outputLines,
|
|
40
41
|
outputPreview: () => outputPreview,
|
|
41
42
|
reduceConversation: () => reduceConversation,
|
|
43
|
+
reduceTaskLog: () => reduceTaskLog,
|
|
44
|
+
replayTaskLog: () => replayTaskLog,
|
|
45
|
+
runnerToolSubject: () => runnerToolSubject,
|
|
42
46
|
stopTurn: () => stopTurn,
|
|
43
47
|
summarizeToolCall: () => summarizeToolCall,
|
|
44
48
|
taskStartedNotice: () => taskStartedNotice,
|
|
@@ -190,12 +194,35 @@ function truncateCheckpointSummary(summary) {
|
|
|
190
194
|
return firstLine.slice(0, CHECKPOINT_TRUNCATE_LENGTH - 1) + "\u2026";
|
|
191
195
|
}
|
|
192
196
|
|
|
193
|
-
// src/services/
|
|
197
|
+
// src/services/conflictFiles.ts
|
|
194
198
|
function capConflictFiles(files, max = 5) {
|
|
195
199
|
return files.length <= max ? files.join(", ") : `${files.slice(0, max).join(", ")}, +${files.length - max} more`;
|
|
196
200
|
}
|
|
197
201
|
|
|
198
202
|
// src/models/Usage.ts
|
|
203
|
+
var TOKEN_FIELDS = ["inputTokens", "outputTokens", "cachedInputTokens"];
|
|
204
|
+
function addUsage(totals, record) {
|
|
205
|
+
const next = { ...totals };
|
|
206
|
+
for (const field of TOKEN_FIELDS) {
|
|
207
|
+
const reported = record[field];
|
|
208
|
+
if (reported !== void 0) next[field] = (totals[field] ?? 0) + reported;
|
|
209
|
+
}
|
|
210
|
+
if (record.reportedCost) {
|
|
211
|
+
const { amount, currency } = record.reportedCost;
|
|
212
|
+
next.reportedCost = { ...totals.reportedCost, [currency]: (totals.reportedCost?.[currency] ?? 0) + amount };
|
|
213
|
+
}
|
|
214
|
+
return next;
|
|
215
|
+
}
|
|
216
|
+
function addPlannerUsage(usage, record) {
|
|
217
|
+
const next = { ...usage, totals: addUsage(usage.totals, record) };
|
|
218
|
+
if (record.subagentId) {
|
|
219
|
+
next.bySubagent = { ...usage.bySubagent, [record.subagentId]: addUsage(usage.bySubagent?.[record.subagentId] ?? {}, record) };
|
|
220
|
+
return next;
|
|
221
|
+
}
|
|
222
|
+
if (record.inputTokens !== void 0) next.lastPromptTokens = record.inputTokens;
|
|
223
|
+
if (record.contextWindow !== void 0 && record.contextWindow > 0) next.contextWindow = record.contextWindow;
|
|
224
|
+
return next;
|
|
225
|
+
}
|
|
199
226
|
function isMeasured(totals) {
|
|
200
227
|
return totals.inputTokens !== void 0 || totals.outputTokens !== void 0 || totals.cachedInputTokens !== void 0 || Object.keys(totals.reportedCost ?? {}).length > 0;
|
|
201
228
|
}
|
|
@@ -325,8 +352,11 @@ var STATUS_OF_OUTCOME = {
|
|
|
325
352
|
denied: "denied",
|
|
326
353
|
not_executed: "interrupted"
|
|
327
354
|
};
|
|
355
|
+
function finishedTool(call, output, outcome) {
|
|
356
|
+
return { ...call, status: STATUS_OF_OUTCOME[outcome], outcome, output, outputLineCount: outputLines(output).length };
|
|
357
|
+
}
|
|
328
358
|
function settledTool(call, step) {
|
|
329
|
-
return
|
|
359
|
+
return finishedTool(call, step.result, step.outcome);
|
|
330
360
|
}
|
|
331
361
|
function pendingTool(id, { tool, toolLabel, args, toolCallId, turnId }) {
|
|
332
362
|
return {
|
|
@@ -351,8 +381,7 @@ function planMarker(content) {
|
|
|
351
381
|
return { status: content.startsWith("Plan updated") ? "updated" : "generated", ...count ? { taskCount: Number(count[1]) } : {} };
|
|
352
382
|
}
|
|
353
383
|
|
|
354
|
-
// src/conversation/
|
|
355
|
-
var EMPTY_CONVERSATION = { blocks: [], nextId: 1 };
|
|
384
|
+
// src/conversation/lanes.ts
|
|
356
385
|
function findLastIndex(items, match) {
|
|
357
386
|
for (let i = items.length - 1; i >= 0; i--) if (match(items[i])) return i;
|
|
358
387
|
return -1;
|
|
@@ -405,6 +434,72 @@ function appendOutput(view, lane, make) {
|
|
|
405
434
|
const next = laneAppend(view, lane, make);
|
|
406
435
|
return sealLane(next, lane, findLastIndex(laneBlocks(next, lane), (b) => b.type !== "usage"));
|
|
407
436
|
}
|
|
437
|
+
function subagentLane(view, subagentId, turnId) {
|
|
438
|
+
const existing = findLastIndex(view.blocks, (b) => b.type === "subagent" && b.subagentId === subagentId);
|
|
439
|
+
if (existing >= 0) return [view, existing];
|
|
440
|
+
const spawn = findLastIndex(view.blocks, (b) => b.type === "tool" && (b.spawns === subagentId || b.toolCallId === subagentId));
|
|
441
|
+
const call = view.blocks[spawn];
|
|
442
|
+
if (call?.type === "tool") {
|
|
443
|
+
const block = subagentBlock(call.id, {
|
|
444
|
+
subagentId,
|
|
445
|
+
brief: call.headline.keyArg,
|
|
446
|
+
status: "running",
|
|
447
|
+
children: [],
|
|
448
|
+
digest: "",
|
|
449
|
+
toolCallId: call.toolCallId,
|
|
450
|
+
turnId: call.turnId
|
|
451
|
+
});
|
|
452
|
+
return [{ ...view, blocks: replaceAt(view.blocks, spawn, block) }, spawn];
|
|
453
|
+
}
|
|
454
|
+
const next = append(view, (id) => subagentBlock(id, { subagentId, brief: "", status: "running", children: [], digest: "", turnId }));
|
|
455
|
+
return [next, findLastIndex(next.blocks, (b) => b.type === "subagent" && b.subagentId === subagentId)];
|
|
456
|
+
}
|
|
457
|
+
function updateSubagent(view, subagentId, turnId, update) {
|
|
458
|
+
const [next, lane] = subagentLane(view, subagentId, turnId);
|
|
459
|
+
return { ...next, blocks: replaceAt(next.blocks, lane, update(subagentAt(next, lane))) };
|
|
460
|
+
}
|
|
461
|
+
function laneOf(view, subagentId, turnId) {
|
|
462
|
+
return subagentId ? subagentLane(view, subagentId, turnId) : [view, null];
|
|
463
|
+
}
|
|
464
|
+
function think(view, text2, turnId, segmentId, subagentId) {
|
|
465
|
+
const [placed, lane] = laneOf(view, subagentId, turnId);
|
|
466
|
+
const blocks = laneBlocks(placed, lane);
|
|
467
|
+
const lastIndex = findLastIndex(blocks, (b) => b.type !== "usage");
|
|
468
|
+
const last = blocks[lastIndex];
|
|
469
|
+
if (last?.type === "thinking" && last.streaming && last.segmentId === segmentId) {
|
|
470
|
+
return laneReplace(placed, lane, lastIndex, { ...last, text: last.text + text2 });
|
|
471
|
+
}
|
|
472
|
+
return appendOutput(placed, lane, (id) => ({
|
|
473
|
+
type: "thinking",
|
|
474
|
+
id,
|
|
475
|
+
text: text2,
|
|
476
|
+
streaming: true,
|
|
477
|
+
...turnId ? { turnId } : {},
|
|
478
|
+
...segmentId ? { segmentId } : {},
|
|
479
|
+
...subagentId ? { subagentId } : {}
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
482
|
+
function setUsageLine(view, line) {
|
|
483
|
+
const last = view.blocks[view.blocks.length - 1];
|
|
484
|
+
const block = usageBlock(last?.type === "usage" ? last.id : `b${view.nextId}`, line);
|
|
485
|
+
if (last?.type === "usage") return { ...view, blocks: replaceAt(view.blocks, view.blocks.length - 1, block) };
|
|
486
|
+
return { ...view, blocks: [...view.blocks, block], nextId: view.nextId + 1 };
|
|
487
|
+
}
|
|
488
|
+
function closeBlock(block, interrupted) {
|
|
489
|
+
return interrupted && block.type === "tool" && block.status === "pending" ? { ...block, status: "interrupted" } : sealed(block);
|
|
490
|
+
}
|
|
491
|
+
function closeSubagent(block, cut) {
|
|
492
|
+
const children = block.children.map((c) => closeBlock(c, cut !== null));
|
|
493
|
+
const status = cut && block.status === "running" ? cut : block.status;
|
|
494
|
+
return status === block.status && children.every((c, i) => c === block.children[i]) ? block : { ...block, status, children };
|
|
495
|
+
}
|
|
496
|
+
function closeOpenBlocks(view, cut) {
|
|
497
|
+
const blocks = view.blocks.map((b) => b.type === "subagent" ? closeSubagent(b, cut) : closeBlock(b, cut !== null));
|
|
498
|
+
return blocks.every((b, i) => b === view.blocks[i]) ? view : { ...view, blocks };
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/conversation/reduce.ts
|
|
502
|
+
var EMPTY_CONVERSATION = { blocks: [], nextId: 1 };
|
|
408
503
|
function isUnsettledSegment(block, turnId) {
|
|
409
504
|
return block.type === "message" && block.turnId === turnId && block.segmentId !== void 0;
|
|
410
505
|
}
|
|
@@ -453,30 +548,6 @@ function retractText(view, { turnId, segmentId }) {
|
|
|
453
548
|
const blocks = view.blocks.filter((b) => !(isUnsettledSegment(b, turnId) && (segmentId === void 0 || b.segmentId === segmentId)));
|
|
454
549
|
return dropBuildingPlan(blocks.length === view.blocks.length ? view : { ...view, blocks }, turnId, segmentId);
|
|
455
550
|
}
|
|
456
|
-
function subagentLane(view, subagentId, turnId) {
|
|
457
|
-
const existing = findLastIndex(view.blocks, (b) => b.type === "subagent" && b.subagentId === subagentId);
|
|
458
|
-
if (existing >= 0) return [view, existing];
|
|
459
|
-
const spawn = findLastIndex(view.blocks, (b) => b.type === "tool" && (b.spawns === subagentId || b.toolCallId === subagentId));
|
|
460
|
-
const call = view.blocks[spawn];
|
|
461
|
-
if (call?.type === "tool") {
|
|
462
|
-
const block = subagentBlock(call.id, {
|
|
463
|
-
subagentId,
|
|
464
|
-
brief: call.headline.keyArg,
|
|
465
|
-
status: "running",
|
|
466
|
-
children: [],
|
|
467
|
-
digest: "",
|
|
468
|
-
toolCallId: call.toolCallId,
|
|
469
|
-
turnId: call.turnId
|
|
470
|
-
});
|
|
471
|
-
return [{ ...view, blocks: replaceAt(view.blocks, spawn, block) }, spawn];
|
|
472
|
-
}
|
|
473
|
-
const next = append(view, (id) => subagentBlock(id, { subagentId, brief: "", status: "running", children: [], digest: "", turnId }));
|
|
474
|
-
return [next, findLastIndex(next.blocks, (b) => b.type === "subagent" && b.subagentId === subagentId)];
|
|
475
|
-
}
|
|
476
|
-
function updateSubagent(view, subagentId, turnId, update) {
|
|
477
|
-
const [next, lane] = subagentLane(view, subagentId, turnId);
|
|
478
|
-
return { ...next, blocks: replaceAt(next.blocks, lane, update(subagentAt(next, lane))) };
|
|
479
|
-
}
|
|
480
551
|
function startSubagent(view, { subagentId, brief, model, turnId }) {
|
|
481
552
|
return updateSubagent(view, subagentId, turnId, (block) => ({ ...block, ...brief ? { brief } : {}, ...model ? { model } : {} }));
|
|
482
553
|
}
|
|
@@ -489,27 +560,9 @@ function finishSubagent(view, { subagentId, outcome, digest, usage, turnId }) {
|
|
|
489
560
|
...usage ? { usage } : {}
|
|
490
561
|
}));
|
|
491
562
|
}
|
|
492
|
-
function think(view, text2, turnId, segmentId, subagentId) {
|
|
493
|
-
const [placed, lane] = subagentId ? subagentLane(view, subagentId, turnId) : [view, null];
|
|
494
|
-
const blocks = laneBlocks(placed, lane);
|
|
495
|
-
const lastIndex = findLastIndex(blocks, (b) => b.type !== "usage");
|
|
496
|
-
const last = blocks[lastIndex];
|
|
497
|
-
if (last?.type === "thinking" && last.streaming && last.segmentId === segmentId) {
|
|
498
|
-
return laneReplace(placed, lane, lastIndex, { ...last, text: last.text + text2 });
|
|
499
|
-
}
|
|
500
|
-
return appendOutput(placed, lane, (id) => ({
|
|
501
|
-
type: "thinking",
|
|
502
|
-
id,
|
|
503
|
-
text: text2,
|
|
504
|
-
streaming: true,
|
|
505
|
-
...turnId ? { turnId } : {},
|
|
506
|
-
...segmentId ? { segmentId } : {},
|
|
507
|
-
...subagentId ? { subagentId } : {}
|
|
508
|
-
}));
|
|
509
|
-
}
|
|
510
563
|
function announceTool(view, call) {
|
|
511
564
|
const spawns = call.tool === "spawn_research_agent" ? call.subagentId : void 0;
|
|
512
|
-
const [placed, lane] =
|
|
565
|
+
const [placed, lane] = laneOf(view, spawns ? void 0 : call.subagentId, call.turnId);
|
|
513
566
|
return appendOutput(placed, lane, (id) => ({ ...pendingTool(id, call), ...spawns ? { spawns } : {} }));
|
|
514
567
|
}
|
|
515
568
|
function isPendingCallOf(block, step) {
|
|
@@ -517,7 +570,7 @@ function isPendingCallOf(block, step) {
|
|
|
517
570
|
return step.toolCallId ? block.toolCallId === step.toolCallId : block.toolCallId === void 0 && block.tool === step.tool;
|
|
518
571
|
}
|
|
519
572
|
function settleTool(view, { step, turnId }) {
|
|
520
|
-
const [placed, lane] =
|
|
573
|
+
const [placed, lane] = laneOf(view, step.subagentId, turnId);
|
|
521
574
|
const blocks = laneBlocks(placed, lane);
|
|
522
575
|
const i = findLastIndex(blocks, (b) => isPendingCallOf(b, step));
|
|
523
576
|
const pending = blocks[i];
|
|
@@ -582,27 +635,13 @@ function decideApproval(view, { kind, subject, scope, detail, granted, source })
|
|
|
582
635
|
}));
|
|
583
636
|
}
|
|
584
637
|
function reportUsage(view, message) {
|
|
585
|
-
|
|
586
|
-
const last = view.blocks[view.blocks.length - 1];
|
|
587
|
-
const line = usageBlock(last?.type === "usage" ? last.id : `b${view.nextId}`, message);
|
|
588
|
-
if (last?.type === "usage") return { ...view, blocks: replaceAt(view.blocks, view.blocks.length - 1, line) };
|
|
589
|
-
return { ...view, blocks: [...view.blocks, line], nextId: view.nextId + 1 };
|
|
590
|
-
}
|
|
591
|
-
function closeBlock(block, interrupted) {
|
|
592
|
-
return interrupted && block.type === "tool" && block.status === "pending" ? { ...block, status: "interrupted" } : sealed(block);
|
|
593
|
-
}
|
|
594
|
-
function closeSubagent(block, cut) {
|
|
595
|
-
const children = block.children.map((c) => closeBlock(c, cut !== null));
|
|
596
|
-
const status = cut && block.status === "running" ? cut : block.status;
|
|
597
|
-
return status === block.status && children.every((c, i) => c === block.children[i]) ? block : { ...block, status, children };
|
|
638
|
+
return isMeasured(message.totals) ? setUsageLine(view, message) : view;
|
|
598
639
|
}
|
|
599
640
|
function endTurn(view, { turnId, outcome }) {
|
|
600
641
|
let next = dropBuildingPlan(view, turnId);
|
|
601
642
|
const planText = outcome === "plan" ? finalSegmentIndex(next.blocks, turnId, true) : -1;
|
|
602
643
|
if (planText >= 0) next = { ...next, blocks: next.blocks.filter((_, i) => i !== planText) };
|
|
603
|
-
|
|
604
|
-
const blocks = next.blocks.map((b) => b.type === "subagent" ? closeSubagent(b, cut) : closeBlock(b, cut !== null));
|
|
605
|
-
return blocks.every((b, i) => b === next.blocks[i]) ? next : { ...next, blocks };
|
|
644
|
+
return closeOpenBlocks(next, outcome === "stopped" ? "stopped" : outcome === "error" ? "failed" : null);
|
|
606
645
|
}
|
|
607
646
|
function markCompaction(view, summary) {
|
|
608
647
|
const i = findLastIndex(view.blocks, (b) => b.type === "message" && b.role === "planner" && b.turnId === void 0 && b.text === summary);
|
|
@@ -749,6 +788,251 @@ function fromTranscript(conversationHistory, researchLog, plannerUsage) {
|
|
|
749
788
|
return { blocks, nextId, ...transcriptAt ? { transcriptAt } : {} };
|
|
750
789
|
}
|
|
751
790
|
|
|
791
|
+
// src/services/harness/agentTools.ts
|
|
792
|
+
var KNOWN_TOOLS = {
|
|
793
|
+
// Claude Code
|
|
794
|
+
read: "read_file",
|
|
795
|
+
grep: "grep",
|
|
796
|
+
glob: "glob",
|
|
797
|
+
bash: "bash",
|
|
798
|
+
ls: "list_dir",
|
|
799
|
+
webfetch: "fetch",
|
|
800
|
+
websearch: "web_search",
|
|
801
|
+
// Codex — its sandboxed command tool is a shell by another name
|
|
802
|
+
shell: "bash",
|
|
803
|
+
exec_command: "bash",
|
|
804
|
+
local_shell: "bash",
|
|
805
|
+
// OpenCode
|
|
806
|
+
list: "list_dir",
|
|
807
|
+
fetch: "fetch"
|
|
808
|
+
};
|
|
809
|
+
function mapAgentTool(name) {
|
|
810
|
+
const normalized = name.trim().toLowerCase().replace(/[_-]/g, "");
|
|
811
|
+
const direct = KNOWN_TOOLS[normalized] ?? KNOWN_TOOLS[name.trim().toLowerCase()];
|
|
812
|
+
if (direct) {
|
|
813
|
+
return { tool: direct, toolLabel: name };
|
|
814
|
+
}
|
|
815
|
+
return { tool: "agent_tool", toolLabel: name };
|
|
816
|
+
}
|
|
817
|
+
function normalizeAgentArgs(tool, args) {
|
|
818
|
+
const out = { ...args };
|
|
819
|
+
const alias = (from, to) => {
|
|
820
|
+
if (out[to] === void 0 && out[from] !== void 0) out[to] = out[from];
|
|
821
|
+
};
|
|
822
|
+
if (tool === "read_file" || tool === "list_dir") {
|
|
823
|
+
alias("filePath", "path");
|
|
824
|
+
alias("file_path", "path");
|
|
825
|
+
alias("target", "path");
|
|
826
|
+
}
|
|
827
|
+
if (tool === "bash") {
|
|
828
|
+
alias("cmd", "command");
|
|
829
|
+
alias("script", "command");
|
|
830
|
+
if (typeof out.command !== "string" && Array.isArray(out.command)) {
|
|
831
|
+
out.command = out.command.join(" ");
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (tool === "fetch") alias("uri", "url");
|
|
835
|
+
if (tool === "web_search") alias("q", "query");
|
|
836
|
+
return out;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/conversation/taskLog.ts
|
|
840
|
+
var EMPTY_TASK_LOG = { blocks: [], nextId: 1, queued: [], working: false, streams: {} };
|
|
841
|
+
var TEXT_STREAM = "text";
|
|
842
|
+
var thinkingStream = (subagentId) => `thinking:${subagentId ?? ""}`;
|
|
843
|
+
function withoutStream(view, key) {
|
|
844
|
+
if (!(key in view.streams)) return view;
|
|
845
|
+
return { ...view, streams: Object.fromEntries(Object.entries(view.streams).filter(([k]) => k !== key)) };
|
|
846
|
+
}
|
|
847
|
+
function blockText(text2) {
|
|
848
|
+
return text2.replace(/^\n+/, "");
|
|
849
|
+
}
|
|
850
|
+
function openStream(view, lane, key) {
|
|
851
|
+
const id = view.streams[key];
|
|
852
|
+
if (id === void 0) return -1;
|
|
853
|
+
const blocks = laneBlocks(view, lane);
|
|
854
|
+
const i = findLastIndex(blocks, (b) => b.type !== "usage");
|
|
855
|
+
const block = blocks[i];
|
|
856
|
+
return block?.id === id && (block.type === "message" || block.type === "thinking") && block.streaming ? i : -1;
|
|
857
|
+
}
|
|
858
|
+
function streamDelta(view, lane, key, text2, make) {
|
|
859
|
+
const i = openStream(view, lane, key);
|
|
860
|
+
const open = laneBlocks(view, lane)[i];
|
|
861
|
+
if (open?.type === "message" || open?.type === "thinking") return laneReplace(view, lane, i, { ...open, text: open.text + text2 });
|
|
862
|
+
const next = appendOutput(view, lane, (id) => make(id, blockText(text2)));
|
|
863
|
+
return { ...next, streams: { ...next.streams, [key]: `b${view.nextId}` } };
|
|
864
|
+
}
|
|
865
|
+
function streamWhole(view, lane, key, text2, make) {
|
|
866
|
+
const id = view.streams[key];
|
|
867
|
+
const blocks = laneBlocks(view, lane);
|
|
868
|
+
const i = id === void 0 ? -1 : findLastIndex(blocks, (b) => b.id === id);
|
|
869
|
+
const streamed = blocks[i];
|
|
870
|
+
const next = withoutStream(view, key);
|
|
871
|
+
if (streamed?.type === "message" || streamed?.type === "thinking") {
|
|
872
|
+
return laneReplace(next, lane, i, { ...streamed, text: blockText(text2), streaming: false });
|
|
873
|
+
}
|
|
874
|
+
return appendOutput(next, lane, make);
|
|
875
|
+
}
|
|
876
|
+
function agentText(view, text2) {
|
|
877
|
+
return streamWhole(view, null, TEXT_STREAM, text2, (id) => settledMessage(id, "agent", blockText(text2)));
|
|
878
|
+
}
|
|
879
|
+
function agentTextDelta(view, text2) {
|
|
880
|
+
return streamDelta(view, null, TEXT_STREAM, text2, (id, t) => ({ type: "message", id, role: "agent", text: t, streaming: true }));
|
|
881
|
+
}
|
|
882
|
+
function thinkingBlock(id, text2, streaming, subagentId) {
|
|
883
|
+
return { type: "thinking", id, text: text2, streaming, ...subagentId ? { subagentId } : {} };
|
|
884
|
+
}
|
|
885
|
+
function thinkingDelta(view, { text: text2, subagentId }) {
|
|
886
|
+
const [placed, lane] = laneOf(view, subagentId);
|
|
887
|
+
return streamDelta(placed, lane, thinkingStream(subagentId), text2, (id, t) => thinkingBlock(id, t, true, subagentId));
|
|
888
|
+
}
|
|
889
|
+
function thinkingWhole(view, { text: text2, subagentId }) {
|
|
890
|
+
const [placed, lane] = laneOf(view, subagentId);
|
|
891
|
+
return streamWhole(placed, lane, thinkingStream(subagentId), text2, (id) => thinkingBlock(id, blockText(text2), false, subagentId));
|
|
892
|
+
}
|
|
893
|
+
function announceTool2(view, { id: toolCallId, name, args, subagentId }) {
|
|
894
|
+
const { tool, toolLabel } = mapAgentTool(name);
|
|
895
|
+
const [placed, lane] = laneOf(view, subagentId);
|
|
896
|
+
return appendOutput(placed, lane, (id) => {
|
|
897
|
+
const call = pendingTool(id, { tool, toolLabel, args, toolCallId });
|
|
898
|
+
const parsed = parseArgs2(args);
|
|
899
|
+
return parsed ? { ...call, headline: toolHeadline(tool, JSON.stringify(normalizeAgentArgs(tool, parsed)), toolLabel) } : call;
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
function parseArgs2(args) {
|
|
903
|
+
try {
|
|
904
|
+
const parsed = JSON.parse(args);
|
|
905
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
906
|
+
} catch {
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function settleTool2(view, { id: toolCallId, output, success, subagentId }) {
|
|
911
|
+
const [placed, lane] = laneOf(view, subagentId);
|
|
912
|
+
const blocks = laneBlocks(placed, lane);
|
|
913
|
+
const i = findLastIndex(blocks, (b) => b.type === "tool" && b.status === "pending" && b.toolCallId === toolCallId);
|
|
914
|
+
const pending = blocks[i];
|
|
915
|
+
const outcome = success ? "success" : "failure";
|
|
916
|
+
if (pending?.type === "tool") return laneReplace(placed, lane, i, finishedTool(pending, output, outcome));
|
|
917
|
+
if (lane === null && blocks.some((b) => b.type === "subagent" && b.toolCallId === toolCallId)) return view;
|
|
918
|
+
return laneAppend(placed, lane, (id) => finishedTool(pendingTool(id, { tool: "agent_tool", toolLabel: "Tool", args: "", toolCallId }), output, outcome));
|
|
919
|
+
}
|
|
920
|
+
function startSubagent2(view, { subagentId, brief, model }) {
|
|
921
|
+
return updateSubagent(view, subagentId, void 0, (block) => ({ ...block, ...brief ? { brief } : {}, ...model ? { model } : {} }));
|
|
922
|
+
}
|
|
923
|
+
function finishSubagent2(view, { subagentId, outcome, digest }) {
|
|
924
|
+
const usage = view.usage?.bySubagent?.[subagentId];
|
|
925
|
+
const next = updateSubagent(view, subagentId, void 0, (block) => ({
|
|
926
|
+
...block,
|
|
927
|
+
status: outcome,
|
|
928
|
+
digest,
|
|
929
|
+
children: block.children.map(sealed),
|
|
930
|
+
...usage ? { usage } : {}
|
|
931
|
+
}));
|
|
932
|
+
return withoutStream(next, thinkingStream(subagentId));
|
|
933
|
+
}
|
|
934
|
+
function reportUsage2(view, { record }) {
|
|
935
|
+
const usage = addPlannerUsage(view.usage ?? { totals: {} }, record);
|
|
936
|
+
const next = { ...view, usage };
|
|
937
|
+
return isMeasured(usage.totals) ? setUsageLine(next, usageLine(usage)) : next;
|
|
938
|
+
}
|
|
939
|
+
function runnerToolSubject(tool, args) {
|
|
940
|
+
const { tool: mapped, toolLabel } = mapAgentTool(tool);
|
|
941
|
+
const parsed = parseArgs2(args);
|
|
942
|
+
const headline = toolHeadline(mapped, parsed ? JSON.stringify(normalizeAgentArgs(mapped, parsed)) : args, toolLabel);
|
|
943
|
+
return headline.keyArg ? `${headline.name}(${headline.keyArg})` : headline.name;
|
|
944
|
+
}
|
|
945
|
+
function requestApproval2(view, { approvalId, tool, args, allowForTask, toolCallId }) {
|
|
946
|
+
if (view.blocks.some((b) => b.type === "approval" && b.approvalId === approvalId)) return view;
|
|
947
|
+
return append(view, (id) => ({
|
|
948
|
+
type: "approval",
|
|
949
|
+
id,
|
|
950
|
+
approvalId,
|
|
951
|
+
kind: "runner_tool",
|
|
952
|
+
subject: runnerToolSubject(tool, args),
|
|
953
|
+
scope: tool,
|
|
954
|
+
status: "pending",
|
|
955
|
+
...allowForTask ? { allowForTask } : {},
|
|
956
|
+
...toolCallId ? { toolCallId } : {}
|
|
957
|
+
}));
|
|
958
|
+
}
|
|
959
|
+
function settleApproval2(view, approvalId, settle) {
|
|
960
|
+
const i = findLastIndex(view.blocks, (b) => b.type === "approval" && b.approvalId === approvalId);
|
|
961
|
+
const block = view.blocks[i];
|
|
962
|
+
if (block?.type !== "approval" || block.status !== "pending") return view;
|
|
963
|
+
return { ...view, blocks: replaceAt(view.blocks, i, settle(block)) };
|
|
964
|
+
}
|
|
965
|
+
function decideApproval2(view, { approvalId, decision, note }) {
|
|
966
|
+
return settleApproval2(view, approvalId, (block) => ({
|
|
967
|
+
...block,
|
|
968
|
+
status: decision === "deny" ? "denied" : "granted",
|
|
969
|
+
decidedBy: "asked",
|
|
970
|
+
...decision === "allowForTask" ? { forTask: true } : {},
|
|
971
|
+
...note ? { note } : {}
|
|
972
|
+
}));
|
|
973
|
+
}
|
|
974
|
+
function startTurn(view, { message, messageId }) {
|
|
975
|
+
const queued = messageId ? view.queued.filter((m) => m.id !== messageId) : view.queued;
|
|
976
|
+
const working = { ...view, queued, working: true };
|
|
977
|
+
return message ? append(working, (id) => settledMessage(id, "user", message)) : working;
|
|
978
|
+
}
|
|
979
|
+
var CUT = { completed: null, interrupted: "stopped", failed: "failed" };
|
|
980
|
+
function endTurn2(view, { reason }) {
|
|
981
|
+
const closed = closeOpenBlocks({ ...view, working: false, lastTurnEnd: reason, streams: {} }, CUT[reason]);
|
|
982
|
+
return reason === "interrupted" ? append(closed, (id) => settledMessage(id, "system", "Interrupted.")) : closed;
|
|
983
|
+
}
|
|
984
|
+
function queueMessage(view, { messageId, text: text2 }) {
|
|
985
|
+
if (view.queued.some((m) => m.id === messageId)) return view;
|
|
986
|
+
return { ...view, queued: [...view.queued, { id: messageId, text: text2 }] };
|
|
987
|
+
}
|
|
988
|
+
function unqueueMessage(view, { messageId }) {
|
|
989
|
+
const queued = view.queued.filter((m) => m.id !== messageId);
|
|
990
|
+
return queued.length === view.queued.length ? view : { ...view, queued };
|
|
991
|
+
}
|
|
992
|
+
function reduceTaskLog(view, event) {
|
|
993
|
+
switch (event.type) {
|
|
994
|
+
case "turn_start":
|
|
995
|
+
return startTurn(view, event);
|
|
996
|
+
case "turn_end":
|
|
997
|
+
return endTurn2(view, event);
|
|
998
|
+
case "text_delta":
|
|
999
|
+
return agentTextDelta(view, event.text);
|
|
1000
|
+
case "text":
|
|
1001
|
+
return agentText(view, event.text);
|
|
1002
|
+
case "thinking_delta":
|
|
1003
|
+
return thinkingDelta(view, event);
|
|
1004
|
+
case "thinking":
|
|
1005
|
+
return thinkingWhole(view, event);
|
|
1006
|
+
case "tool_call":
|
|
1007
|
+
return announceTool2(view, event);
|
|
1008
|
+
case "tool_result":
|
|
1009
|
+
return settleTool2(view, event);
|
|
1010
|
+
case "subagent_started":
|
|
1011
|
+
return startSubagent2(view, event);
|
|
1012
|
+
case "subagent_finished":
|
|
1013
|
+
return finishSubagent2(view, event);
|
|
1014
|
+
case "usage":
|
|
1015
|
+
return reportUsage2(view, event);
|
|
1016
|
+
case "message_queued":
|
|
1017
|
+
return queueMessage(view, event);
|
|
1018
|
+
case "message_removed":
|
|
1019
|
+
return unqueueMessage(view, event);
|
|
1020
|
+
case "error":
|
|
1021
|
+
return appendOutput(view, null, (id) => settledMessage(id, "error", event.message));
|
|
1022
|
+
case "approval_requested":
|
|
1023
|
+
return requestApproval2(view, event);
|
|
1024
|
+
case "approval_decided":
|
|
1025
|
+
return decideApproval2(view, event);
|
|
1026
|
+
case "approval_withdrawn":
|
|
1027
|
+
return settleApproval2(view, event.approvalId, (block) => ({ ...block, status: "withdrawn" }));
|
|
1028
|
+
default:
|
|
1029
|
+
return view;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
function replayTaskLog(events, from = EMPTY_TASK_LOG) {
|
|
1033
|
+
return events.reduce(reduceTaskLog, from);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
752
1036
|
// src/conversation/promptHold.ts
|
|
753
1037
|
var EMPTY_HOLD = [];
|
|
754
1038
|
function holdPrompt(hold, text2) {
|
|
@@ -826,6 +1110,7 @@ function taskStartedNotice(title, runner) {
|
|
|
826
1110
|
CHECKPOINT_TRUNCATE_LENGTH,
|
|
827
1111
|
EMPTY_CONVERSATION,
|
|
828
1112
|
EMPTY_HOLD,
|
|
1113
|
+
EMPTY_TASK_LOG,
|
|
829
1114
|
NO_TURN,
|
|
830
1115
|
aheadOfDraft,
|
|
831
1116
|
canMergeTasks,
|
|
@@ -842,6 +1127,9 @@ function taskStartedNotice(title, runner) {
|
|
|
842
1127
|
outputLines,
|
|
843
1128
|
outputPreview,
|
|
844
1129
|
reduceConversation,
|
|
1130
|
+
reduceTaskLog,
|
|
1131
|
+
replayTaskLog,
|
|
1132
|
+
runnerToolSubject,
|
|
845
1133
|
stopTurn,
|
|
846
1134
|
summarizeToolCall,
|
|
847
1135
|
taskStartedNotice,
|