@workerdeck/ui 2.10.0 → 2.12.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/build/{SessionPanel-BVbau2eR.d.mts → SessionPanel-CJwp5B3q.d.mts} +8 -3
- package/build/index.d.mts +39 -20
- package/build/index.mjs +119 -52
- package/build/index.mjs.map +1 -1
- package/build/scoped.css +60 -11
- package/build/{use-path-links-CvcxdUXL.mjs → use-path-links-CepFsMdW.mjs} +541 -254
- package/build/use-path-links-CepFsMdW.mjs.map +1 -0
- package/build/workspace.d.mts +1 -1
- package/build/workspace.mjs +1 -1
- package/package.json +4 -4
- package/src/components/agent/Composer.tsx +28 -5
- package/src/components/agent/PromptTokenText.tsx +9 -1
- package/src/components/agent/SessionBrowser.tsx +17 -1
- package/src/components/agent/SessionItem.tsx +10 -26
- package/src/components/agent/SessionPanel.tsx +12 -0
- package/src/components/agent/SessionSteps.tsx +15 -55
- package/src/components/agent/SubagentToggle.tsx +69 -0
- package/src/components/agent/Transcript.tsx +91 -80
- package/src/components/agent/TranscriptItemView.tsx +2 -0
- package/src/components/agent/TranscriptRows.tsx +60 -56
- package/src/components/agent/UsageDialog.tsx +19 -6
- package/src/components/agent/composer-commands.ts +18 -0
- package/src/components/agent/pulse.tsx +53 -16
- package/src/components/agent/use-transcript-jumps.ts +25 -0
- package/src/components/terminal/TerminalTranscript.tsx +31 -27
- package/src/components/terminal/blocks.ts +15 -7
- package/src/components/terminal/height.ts +14 -5
- package/src/components/terminal/items.tsx +97 -11
- package/src/components/terminal/peer-names.tsx +16 -0
- package/src/components/terminal/row.tsx +1 -1
- package/src/components/terminal/tool-run.ts +68 -0
- package/src/index.ts +10 -2
- package/src/lib/session-cost.ts +12 -2
- package/src/lib/tool-icon.ts +5 -1
- package/src/styles/terminal.css +102 -1
- package/src/styles/theme.css +1 -1
- package/build/use-path-links-CvcxdUXL.mjs.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { C as rateLimitWindowSeconds, _ as formatDuration, a as meterTintClass, b as formatRelativeTime, f as compactionText, g as formatCountdown, h as formatCost, m as formatBytes, p as formatAgoPrecise, r as meterColorClass, w as toolInputPreview, x as formatTokens, y as formatRateLimitWindowLong } from "./status-kmsBhuFG.mjs";
|
|
2
|
-
import { Fragment, createContext, forwardRef, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { Fragment, createContext, forwardRef, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
4
|
import { clsx } from "clsx";
|
|
5
5
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Select } from "@base-ui/react/select";
|
|
8
|
-
import { ArrowDown, ArrowDownCircle, ArrowLeft, ArrowRight, ArrowUp, AtSign, Brain, ChartPie, Check, CheckSquare, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Circle, CircleAlert, ClipboardList, Clock, Code, Copy, Download, File, FileDiff, FileText, Folder, FolderSearch, FolderTree, Gauge, Globe, Hand, Image, Info, Link2, LoaderCircle, MessageCircleQuestion, MessageSquareText, MoreHorizontal, Paperclip, PencilLine, Plug, Power, PowerOff, Puzzle, RefreshCw, RotateCcw, RotateCw, Search, ShieldCheck, SlashSquare, SlidersHorizontal, Sparkles, Square, SquarePen, Terminal, TriangleAlert, UsersRound, WifiOff, Wrench, X, Zap } from "lucide-react";
|
|
8
|
+
import { ArrowDown, ArrowDownCircle, ArrowLeft, ArrowRight, ArrowUp, AtSign, Brain, ChartPie, Check, CheckSquare, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Circle, CircleAlert, ClipboardList, Clock, Code, Copy, Download, File, FileDiff, FileText, Folder, FolderSearch, FolderTree, Gauge, Globe, Hand, Image, Info, Link2, LoaderCircle, MessageCircleQuestion, MessageSquareText, MoreHorizontal, Paperclip, PencilLine, Plug, Power, PowerOff, Puzzle, RefreshCw, RotateCcw, RotateCw, Search, ShieldCheck, SlashSquare, SlidersHorizontal, Sparkles, Square, SquarePen, Terminal, TriangleAlert, Users, UsersRound, WifiOff, Wrench, X, Zap } from "lucide-react";
|
|
9
9
|
import { Menu } from "@base-ui/react/menu";
|
|
10
10
|
import { Dialog } from "@base-ui/react/dialog";
|
|
11
11
|
import { Tooltip } from "@base-ui/react/tooltip";
|
|
12
|
-
import { PRICING_NOTE, PROTOCOL_VERSION, UNPRICED_WARN_SHARE, canonicalModel, costOf, costOfByModel, mergeUsage, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, rateFor, sessionTasks, subagentLabel, taskCountLabel, taskSummary, toolTitle, totalTokens, usageInfos, usageIsStale, visibleTasks } from "@workerdeck/protocol";
|
|
13
|
-
import { recapLine, scanPromptTokens, summarizeSince, useAttachments, useClaudeSession, useDraft, useHostFileSearch, useProfileUsage, useToolCallHost } from "@workerdeck/react";
|
|
12
|
+
import { PRICING_NOTE, PROTOCOL_VERSION, UNPRICED_WARN_SHARE, canonicalModel, costOf, costOfByModel, isPeerSendTool, mergeUsage, orderUsageWindows, parseTodoWriteInput, parseUserQuestions, peerDeliveredTo, pricingAgeNote, rateFor, sessionTasks, subagentLabel, taskCountLabel, taskSummary, toolTitle, totalTokens, unknownBasisModels, usageInfos, usageIsStale, visibleTasks } from "@workerdeck/protocol";
|
|
13
|
+
import { recapLine, scanPromptTokens, summarizeSince, useAttachments, useClaudeSession, useDraft, useHostFileSearch, usePeerSessions, useProfileUsage, useToolCallHost } from "@workerdeck/react";
|
|
14
14
|
import { Streamdown } from "streamdown";
|
|
15
15
|
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
16
16
|
import { createPortal } from "react-dom";
|
|
@@ -4517,6 +4517,25 @@ function rankComposerRows(query, rows) {
|
|
|
4517
4517
|
scored.sort((a, b) => b.score - a.score || KIND_ORDER[a.row.kind] - KIND_ORDER[b.row.kind] || a.index - b.index);
|
|
4518
4518
|
return scored.map(({ row }) => row);
|
|
4519
4519
|
}
|
|
4520
|
+
function rankPeerSessions(query, peers) {
|
|
4521
|
+
const needle = query.trim();
|
|
4522
|
+
if (!needle) return [...peers];
|
|
4523
|
+
const scored = [];
|
|
4524
|
+
peers.forEach((peer, index) => {
|
|
4525
|
+
const score = matchScore(needle, [
|
|
4526
|
+
peer.slug,
|
|
4527
|
+
peer.label,
|
|
4528
|
+
...peer.slug.split("-")
|
|
4529
|
+
]);
|
|
4530
|
+
if (score > 0) scored.push({
|
|
4531
|
+
score,
|
|
4532
|
+
index,
|
|
4533
|
+
peer
|
|
4534
|
+
});
|
|
4535
|
+
});
|
|
4536
|
+
scored.sort((a, b) => b.score - a.score || a.index - b.index);
|
|
4537
|
+
return scored.map(({ peer }) => peer);
|
|
4538
|
+
}
|
|
4520
4539
|
function matchClientCommand(text, commands) {
|
|
4521
4540
|
const match = /^\/([\w:-]+)[ \t]*([\s\S]*)$/.exec(text.trim());
|
|
4522
4541
|
if (!match) return;
|
|
@@ -4606,7 +4625,11 @@ function toolIcon(toolName) {
|
|
|
4606
4625
|
case "WebSearch": return Globe;
|
|
4607
4626
|
case "Task":
|
|
4608
4627
|
case "Agent": return UsersRound;
|
|
4609
|
-
case "TodoWrite":
|
|
4628
|
+
case "TodoWrite":
|
|
4629
|
+
case "TaskCreate":
|
|
4630
|
+
case "TaskUpdate":
|
|
4631
|
+
case "TaskGet":
|
|
4632
|
+
case "TaskList": return CheckSquare;
|
|
4610
4633
|
case "Skill": return Sparkles;
|
|
4611
4634
|
case "AskUserQuestion": return MessageCircleQuestion;
|
|
4612
4635
|
case "CodexCommand": return Terminal;
|
|
@@ -4634,12 +4657,53 @@ function isMutatingTool(toolName) {
|
|
|
4634
4657
|
//#endregion
|
|
4635
4658
|
//#region src/components/agent/pulse.tsx
|
|
4636
4659
|
const PULSE_FRAMES = [
|
|
4637
|
-
"
|
|
4638
|
-
"
|
|
4639
|
-
"
|
|
4640
|
-
"
|
|
4660
|
+
"⠋",
|
|
4661
|
+
"⠙",
|
|
4662
|
+
"⠹",
|
|
4663
|
+
"⠸",
|
|
4664
|
+
"⠼",
|
|
4665
|
+
"⠴",
|
|
4666
|
+
"⠦",
|
|
4667
|
+
"⠧",
|
|
4668
|
+
"⠇",
|
|
4669
|
+
"⠏"
|
|
4641
4670
|
];
|
|
4642
|
-
const
|
|
4671
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4672
|
+
let ticker;
|
|
4673
|
+
let current = "⠿";
|
|
4674
|
+
function pulseFrameAt(now) {
|
|
4675
|
+
return PULSE_FRAMES[Math.floor(now / 90) % PULSE_FRAMES.length];
|
|
4676
|
+
}
|
|
4677
|
+
function tick() {
|
|
4678
|
+
const next = pulseFrameAt(Date.now());
|
|
4679
|
+
if (next === current) return;
|
|
4680
|
+
current = next;
|
|
4681
|
+
for (const listener of listeners) listener();
|
|
4682
|
+
}
|
|
4683
|
+
function subscribe(listener) {
|
|
4684
|
+
listeners.add(listener);
|
|
4685
|
+
if (ticker === void 0) {
|
|
4686
|
+
current = pulseFrameAt(Date.now());
|
|
4687
|
+
ticker = setInterval(tick, 90);
|
|
4688
|
+
}
|
|
4689
|
+
return () => {
|
|
4690
|
+
listeners.delete(listener);
|
|
4691
|
+
if (listeners.size === 0 && ticker !== void 0) {
|
|
4692
|
+
clearInterval(ticker);
|
|
4693
|
+
ticker = void 0;
|
|
4694
|
+
}
|
|
4695
|
+
};
|
|
4696
|
+
}
|
|
4697
|
+
function subscribeRest() {
|
|
4698
|
+
return unsubscribeRest;
|
|
4699
|
+
}
|
|
4700
|
+
function unsubscribeRest() {}
|
|
4701
|
+
function readFrame() {
|
|
4702
|
+
return current;
|
|
4703
|
+
}
|
|
4704
|
+
function readRest() {
|
|
4705
|
+
return "⠿";
|
|
4706
|
+
}
|
|
4643
4707
|
function usePrefersReducedMotion() {
|
|
4644
4708
|
const [reduced, setReduced] = useState(false);
|
|
4645
4709
|
useEffect(() => {
|
|
@@ -4655,27 +4719,31 @@ function usePrefersReducedMotion() {
|
|
|
4655
4719
|
function usePulse(animated) {
|
|
4656
4720
|
const reduced = usePrefersReducedMotion();
|
|
4657
4721
|
const running = animated && !reduced;
|
|
4658
|
-
|
|
4659
|
-
useEffect(() => {
|
|
4660
|
-
if (!running) return;
|
|
4661
|
-
const timer = setInterval(() => setFrame((f) => f + 1), 150);
|
|
4662
|
-
return () => clearInterval(timer);
|
|
4663
|
-
}, [running]);
|
|
4664
|
-
if (!running) return PULSE_REST;
|
|
4665
|
-
return PULSE_FRAMES[frame % PULSE_FRAMES.length];
|
|
4722
|
+
return useSyncExternalStore(running ? subscribe : subscribeRest, running ? readFrame : readRest, readRest);
|
|
4666
4723
|
}
|
|
4667
4724
|
//#endregion
|
|
4668
4725
|
//#region src/components/agent/PromptTokenText.tsx
|
|
4669
4726
|
const SkillNamesContext = createContext(void 0);
|
|
4727
|
+
const SessionNamesContext = createContext(void 0);
|
|
4670
4728
|
function SkillNamesProvider({ names, children }) {
|
|
4671
4729
|
return /* @__PURE__ */ jsx(SkillNamesContext.Provider, {
|
|
4672
4730
|
value: names,
|
|
4673
4731
|
children
|
|
4674
4732
|
});
|
|
4675
4733
|
}
|
|
4734
|
+
function SessionNamesProvider({ names, children }) {
|
|
4735
|
+
return /* @__PURE__ */ jsx(SessionNamesContext.Provider, {
|
|
4736
|
+
value: names,
|
|
4737
|
+
children
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4676
4740
|
function PromptTokenText({ text, className }) {
|
|
4677
4741
|
const skills = useContext(SkillNamesContext);
|
|
4678
|
-
const
|
|
4742
|
+
const sessions = useContext(SessionNamesContext);
|
|
4743
|
+
const tokens = scanPromptTokens(text, {
|
|
4744
|
+
skills,
|
|
4745
|
+
sessions
|
|
4746
|
+
});
|
|
4679
4747
|
if (tokens.length === 0) return /* @__PURE__ */ jsx("span", {
|
|
4680
4748
|
className,
|
|
4681
4749
|
children: text
|
|
@@ -5131,6 +5199,129 @@ const TerminalMarkdown = memo(function TerminalMarkdown({ children, streaming, c
|
|
|
5131
5199
|
});
|
|
5132
5200
|
}, (prev, next) => prev.children === next.children && prev.streaming === next.streaming && prev.className === next.className);
|
|
5133
5201
|
//#endregion
|
|
5202
|
+
//#region src/components/terminal/tool-run.ts
|
|
5203
|
+
function isPeerSend(item) {
|
|
5204
|
+
return item.kind === "tool_call" && isPeerSendTool(item.name);
|
|
5205
|
+
}
|
|
5206
|
+
function peerName(origin) {
|
|
5207
|
+
return origin.name ?? origin.sessionId.slice(0, 8);
|
|
5208
|
+
}
|
|
5209
|
+
function peerNamesOf(items) {
|
|
5210
|
+
const names = /* @__PURE__ */ new Map();
|
|
5211
|
+
for (const item of items) {
|
|
5212
|
+
if (item.kind === "user") {
|
|
5213
|
+
if (item.origin?.name) names.set(item.origin.sessionId, item.origin.name);
|
|
5214
|
+
continue;
|
|
5215
|
+
}
|
|
5216
|
+
if (item.kind === "tool_call" && isPeerSendTool(item.name) && item.result && !item.result.isError) {
|
|
5217
|
+
const delivered = peerDeliveredTo(item.result.text);
|
|
5218
|
+
if (delivered?.name) names.set(delivered.sessionId, delivered.name);
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
return names;
|
|
5222
|
+
}
|
|
5223
|
+
function peerSendTarget(item, names) {
|
|
5224
|
+
const delivered = item.result && !item.result.isError ? peerDeliveredTo(item.result.text) : void 0;
|
|
5225
|
+
const addressed = item.input?.sessionId;
|
|
5226
|
+
const sessionId = delivered?.sessionId ?? (typeof addressed === "string" ? addressed : void 0);
|
|
5227
|
+
if (sessionId === void 0) return "peer";
|
|
5228
|
+
return delivered?.name ?? names?.get(sessionId) ?? sessionId.slice(0, 8);
|
|
5229
|
+
}
|
|
5230
|
+
function peerSendText(item) {
|
|
5231
|
+
const text = item.input?.text;
|
|
5232
|
+
return typeof text === "string" ? text : "";
|
|
5233
|
+
}
|
|
5234
|
+
function peerOneLine(text) {
|
|
5235
|
+
return text.replace(/\s+/g, " ").trim();
|
|
5236
|
+
}
|
|
5237
|
+
function foldsTogether(a, b) {
|
|
5238
|
+
if (isPeerSend(a) || isPeerSend(b)) return false;
|
|
5239
|
+
return a.parentToolUseId === b.parentToolUseId;
|
|
5240
|
+
}
|
|
5241
|
+
function toolFamily(name) {
|
|
5242
|
+
if (isShellTool(name)) return "shell";
|
|
5243
|
+
const mcp = /^mcp__([^_]+(?:_[^_]+)*?)__/.exec(name);
|
|
5244
|
+
if (mcp?.[1]) return mcp[1].replace(/_/g, "-");
|
|
5245
|
+
return name.toLowerCase();
|
|
5246
|
+
}
|
|
5247
|
+
function planRun(items) {
|
|
5248
|
+
return items.length === 1 ? {
|
|
5249
|
+
kind: "call",
|
|
5250
|
+
item: items[0]
|
|
5251
|
+
} : {
|
|
5252
|
+
kind: "summary",
|
|
5253
|
+
items
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
function runSummary(items, busy) {
|
|
5257
|
+
const verb = busy ? "Running " : "Ran ";
|
|
5258
|
+
const tail = busy ? "…" : "";
|
|
5259
|
+
const n = items.length;
|
|
5260
|
+
const counts = /* @__PURE__ */ new Map();
|
|
5261
|
+
for (const item of items) {
|
|
5262
|
+
const family = toolFamily(item.name);
|
|
5263
|
+
counts.set(family, (counts.get(family) ?? 0) + 1);
|
|
5264
|
+
}
|
|
5265
|
+
if (counts.size === 1 && counts.has("shell")) return `${verb}${n} shell command${n === 1 ? "" : "s"}${tail}`;
|
|
5266
|
+
const breakdown = [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([family, count]) => `${count} ${family}`).join(", ");
|
|
5267
|
+
return `${verb}${n} tool${n === 1 ? "" : "s"} · ${breakdown}${tail}`;
|
|
5268
|
+
}
|
|
5269
|
+
function clip(text, max = 80) {
|
|
5270
|
+
return text.length > max ? text.slice(0, max - 1) + "…" : text;
|
|
5271
|
+
}
|
|
5272
|
+
function trimmed(value) {
|
|
5273
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
5274
|
+
}
|
|
5275
|
+
function taskLabel(task) {
|
|
5276
|
+
return `${task.name}(${taskIdentity(task)})`;
|
|
5277
|
+
}
|
|
5278
|
+
function taskIdentity(task) {
|
|
5279
|
+
const input = task.input;
|
|
5280
|
+
const description = trimmed(input?.description);
|
|
5281
|
+
const agent = trimmed(input?.subagent_type);
|
|
5282
|
+
return agent && description ? `${agent} · ${clip(description)}` : agent ?? (description ? clip(description) : toolInputPreview(task.input));
|
|
5283
|
+
}
|
|
5284
|
+
function taskBrief(task) {
|
|
5285
|
+
const input = task.input;
|
|
5286
|
+
return trimmed(input?.prompt);
|
|
5287
|
+
}
|
|
5288
|
+
function callBusy(call) {
|
|
5289
|
+
return call.status === "running" || call.status === "pending";
|
|
5290
|
+
}
|
|
5291
|
+
function callFailed(call) {
|
|
5292
|
+
return call.status === "failed" || call.result?.isError === true;
|
|
5293
|
+
}
|
|
5294
|
+
function runFailed(items) {
|
|
5295
|
+
const last = items[items.length - 1];
|
|
5296
|
+
return last !== void 0 && callFailed(last);
|
|
5297
|
+
}
|
|
5298
|
+
function taskBusy(task, children) {
|
|
5299
|
+
return callBusy(task) || children.some((child) => child.kind === "tool_call" && callBusy(child));
|
|
5300
|
+
}
|
|
5301
|
+
function taskFailed(task) {
|
|
5302
|
+
return callFailed(task);
|
|
5303
|
+
}
|
|
5304
|
+
function taskSummary$1(task, children) {
|
|
5305
|
+
const busy = taskBusy(task, children);
|
|
5306
|
+
const calls = children.reduce((n, child) => n + (child.kind === "tool_call" ? 1 : 0), 0);
|
|
5307
|
+
const label = taskLabel(task);
|
|
5308
|
+
if (calls === 0) return busy ? `${label} · working…` : `${label} · done`;
|
|
5309
|
+
return `${label} · ${calls} tool${calls === 1 ? "" : "s"}${busy ? "…" : ""}`;
|
|
5310
|
+
}
|
|
5311
|
+
//#endregion
|
|
5312
|
+
//#region src/components/terminal/peer-names.tsx
|
|
5313
|
+
const PeerNamesContext = createContext(/* @__PURE__ */ new Map());
|
|
5314
|
+
function PeerNamesProvider({ items, children }) {
|
|
5315
|
+
const names = useMemo(() => peerNamesOf(items), [items]);
|
|
5316
|
+
return /* @__PURE__ */ jsx(PeerNamesContext.Provider, {
|
|
5317
|
+
value: names,
|
|
5318
|
+
children
|
|
5319
|
+
});
|
|
5320
|
+
}
|
|
5321
|
+
function usePeerNames() {
|
|
5322
|
+
return useContext(PeerNamesContext);
|
|
5323
|
+
}
|
|
5324
|
+
//#endregion
|
|
5134
5325
|
//#region src/components/terminal/press.tsx
|
|
5135
5326
|
const DRAG_SLOP = 4;
|
|
5136
5327
|
function Pressable({ onPress, expanded, className, children }) {
|
|
@@ -5355,72 +5546,6 @@ function evict(cache, keep) {
|
|
|
5355
5546
|
}
|
|
5356
5547
|
}
|
|
5357
5548
|
//#endregion
|
|
5358
|
-
//#region src/components/terminal/tool-run.ts
|
|
5359
|
-
function foldsTogether(a, b) {
|
|
5360
|
-
return a.parentToolUseId === b.parentToolUseId;
|
|
5361
|
-
}
|
|
5362
|
-
function toolFamily(name) {
|
|
5363
|
-
if (isShellTool(name)) return "shell";
|
|
5364
|
-
const mcp = /^mcp__([^_]+(?:_[^_]+)*?)__/.exec(name);
|
|
5365
|
-
if (mcp?.[1]) return mcp[1].replace(/_/g, "-");
|
|
5366
|
-
return name.toLowerCase();
|
|
5367
|
-
}
|
|
5368
|
-
function runSummary(items, busy) {
|
|
5369
|
-
const verb = busy ? "Running " : "Ran ";
|
|
5370
|
-
const tail = busy ? "…" : "";
|
|
5371
|
-
const n = items.length;
|
|
5372
|
-
const counts = /* @__PURE__ */ new Map();
|
|
5373
|
-
for (const item of items) {
|
|
5374
|
-
const family = toolFamily(item.name);
|
|
5375
|
-
counts.set(family, (counts.get(family) ?? 0) + 1);
|
|
5376
|
-
}
|
|
5377
|
-
if (counts.size === 1 && counts.has("shell")) return `${verb}${n} shell command${n === 1 ? "" : "s"}${tail}`;
|
|
5378
|
-
const breakdown = [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([family, count]) => `${count} ${family}`).join(", ");
|
|
5379
|
-
return `${verb}${n} tool${n === 1 ? "" : "s"} · ${breakdown}${tail}`;
|
|
5380
|
-
}
|
|
5381
|
-
function clip(text, max = 80) {
|
|
5382
|
-
return text.length > max ? text.slice(0, max - 1) + "…" : text;
|
|
5383
|
-
}
|
|
5384
|
-
function trimmed(value) {
|
|
5385
|
-
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
5386
|
-
}
|
|
5387
|
-
function taskLabel(task) {
|
|
5388
|
-
return `${task.name}(${taskIdentity(task)})`;
|
|
5389
|
-
}
|
|
5390
|
-
function taskIdentity(task) {
|
|
5391
|
-
const input = task.input;
|
|
5392
|
-
const description = trimmed(input?.description);
|
|
5393
|
-
const agent = trimmed(input?.subagent_type);
|
|
5394
|
-
return agent && description ? `${agent} · ${clip(description)}` : agent ?? (description ? clip(description) : toolInputPreview(task.input));
|
|
5395
|
-
}
|
|
5396
|
-
function taskBrief(task) {
|
|
5397
|
-
const input = task.input;
|
|
5398
|
-
return trimmed(input?.prompt);
|
|
5399
|
-
}
|
|
5400
|
-
function callBusy(call) {
|
|
5401
|
-
return call.status === "running" || call.status === "pending";
|
|
5402
|
-
}
|
|
5403
|
-
function callFailed(call) {
|
|
5404
|
-
return call.status === "failed" || call.result?.isError === true;
|
|
5405
|
-
}
|
|
5406
|
-
function runFailed(items) {
|
|
5407
|
-
const last = items[items.length - 1];
|
|
5408
|
-
return last !== void 0 && callFailed(last);
|
|
5409
|
-
}
|
|
5410
|
-
function taskBusy(task, children) {
|
|
5411
|
-
return callBusy(task) || children.some((child) => child.kind === "tool_call" && callBusy(child));
|
|
5412
|
-
}
|
|
5413
|
-
function taskFailed(task) {
|
|
5414
|
-
return callFailed(task);
|
|
5415
|
-
}
|
|
5416
|
-
function taskSummary$1(task, children) {
|
|
5417
|
-
const busy = taskBusy(task, children);
|
|
5418
|
-
const calls = children.reduce((n, child) => n + (child.kind === "tool_call" ? 1 : 0), 0);
|
|
5419
|
-
const label = taskLabel(task);
|
|
5420
|
-
if (calls === 0) return busy ? `${label} · working…` : `${label} · done`;
|
|
5421
|
-
return `${label} · ${calls} tool${calls === 1 ? "" : "s"}${busy ? "…" : ""}`;
|
|
5422
|
-
}
|
|
5423
|
-
//#endregion
|
|
5424
5549
|
//#region src/components/terminal/todos.ts
|
|
5425
5550
|
const PREVIEW_TODOS = 8;
|
|
5426
5551
|
const GLYPH = {
|
|
@@ -5455,20 +5580,80 @@ function clipToChars(lines, maxChars) {
|
|
|
5455
5580
|
}
|
|
5456
5581
|
return out;
|
|
5457
5582
|
}
|
|
5583
|
+
function peerLabel(origin) {
|
|
5584
|
+
const who = origin.name ? `${origin.name} (${origin.sessionId.slice(0, 8)})` : origin.sessionId.slice(0, 8);
|
|
5585
|
+
return `message from ${origin.engine ? `${origin.engine} session ` : "session "}${who}`;
|
|
5586
|
+
}
|
|
5587
|
+
function PeerRow({ glyph, who, body, tone = "peer", clip }) {
|
|
5588
|
+
const line = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5589
|
+
/* @__PURE__ */ jsx(Ink, {
|
|
5590
|
+
tone,
|
|
5591
|
+
bold: true,
|
|
5592
|
+
children: who
|
|
5593
|
+
}),
|
|
5594
|
+
": ",
|
|
5595
|
+
body
|
|
5596
|
+
] });
|
|
5597
|
+
return /* @__PURE__ */ jsx(Row, {
|
|
5598
|
+
glyph,
|
|
5599
|
+
glyphTone: tone,
|
|
5600
|
+
tone,
|
|
5601
|
+
children: clip ? /* @__PURE__ */ jsx("span", {
|
|
5602
|
+
className: "term-clip-1",
|
|
5603
|
+
children: line
|
|
5604
|
+
}) : line
|
|
5605
|
+
});
|
|
5606
|
+
}
|
|
5607
|
+
function PeerSendRow({ item }) {
|
|
5608
|
+
const [open, setOpen] = useState(false);
|
|
5609
|
+
const names = usePeerNames();
|
|
5610
|
+
const reveal = useRevealOnOpen(open);
|
|
5611
|
+
const lines = peerSendText(item).split("\n");
|
|
5612
|
+
const tone = item.status === "failed" || item.result?.isError === true ? "red" : "peer";
|
|
5613
|
+
return /* @__PURE__ */ jsx(WithActions, {
|
|
5614
|
+
actions: /* @__PURE__ */ jsx(BookmarkAction, { id: item.id }),
|
|
5615
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
5616
|
+
ref: reveal,
|
|
5617
|
+
className: open ? "term-open" : void 0,
|
|
5618
|
+
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
5619
|
+
onPress: () => setOpen((v) => !v),
|
|
5620
|
+
expanded: open,
|
|
5621
|
+
children: /* @__PURE__ */ jsx(PeerRow, {
|
|
5622
|
+
glyph: "↤",
|
|
5623
|
+
who: peerSendTarget(item, names),
|
|
5624
|
+
tone,
|
|
5625
|
+
clip: !open,
|
|
5626
|
+
body: open ? lines[0] || "\xA0" : peerOneLine(lines.join(" "))
|
|
5627
|
+
})
|
|
5628
|
+
}), open ? /* @__PURE__ */ jsxs("div", { children: [lines.slice(1).map((line, index) => /* @__PURE__ */ jsx(Row, {
|
|
5629
|
+
tone,
|
|
5630
|
+
children: line || "\xA0"
|
|
5631
|
+
}, index)), item.result ? /* @__PURE__ */ jsx(Row, {
|
|
5632
|
+
tone: "faint",
|
|
5633
|
+
children: peerOneLine(item.result.text)
|
|
5634
|
+
}) : null] }) : null]
|
|
5635
|
+
})
|
|
5636
|
+
});
|
|
5637
|
+
}
|
|
5458
5638
|
function UserRow({ item }) {
|
|
5459
5639
|
return /* @__PURE__ */ jsx(WithActions, {
|
|
5460
5640
|
actions: /* @__PURE__ */ jsx(BookmarkAction, { id: item.id }),
|
|
5461
5641
|
children: /* @__PURE__ */ jsxs("div", {
|
|
5462
5642
|
className: "term-user",
|
|
5643
|
+
"data-peer": item.origin ? "" : void 0,
|
|
5463
5644
|
children: [item.attachments?.length ? /* @__PURE__ */ jsx(Row, {
|
|
5464
5645
|
glyph: "❯",
|
|
5465
5646
|
glyphTone: "dim",
|
|
5466
5647
|
tone: "dim",
|
|
5467
5648
|
children: item.attachments.map((attachment) => attachment.name).join(", ")
|
|
5468
|
-
}) : null, item.text ? item.text.split("\n").map((line, index) => /* @__PURE__ */ jsx(
|
|
5469
|
-
glyph:
|
|
5649
|
+
}) : null, item.text ? item.text.split("\n").map((line, index) => item.origin && index === 0 ? /* @__PURE__ */ jsx(PeerRow, {
|
|
5650
|
+
glyph: "↦",
|
|
5651
|
+
who: peerName(item.origin),
|
|
5652
|
+
body: line ? /* @__PURE__ */ jsx(PromptTokenText, { text: line }) : "\xA0"
|
|
5653
|
+
}, index) : /* @__PURE__ */ jsx(Row, {
|
|
5654
|
+
glyph: !item.origin && index === 0 ? "❯" : void 0,
|
|
5470
5655
|
glyphTone: "dim",
|
|
5471
|
-
tone: "fg",
|
|
5656
|
+
tone: item.origin ? "peer" : "fg",
|
|
5472
5657
|
children: line ? /* @__PURE__ */ jsx(PromptTokenText, { text: line }) : "\xA0"
|
|
5473
5658
|
}, index)) : null]
|
|
5474
5659
|
})
|
|
@@ -5553,6 +5738,7 @@ function ToolRow({ item }) {
|
|
|
5553
5738
|
/* @__PURE__ */ jsx(Ink, {
|
|
5554
5739
|
bold: true,
|
|
5555
5740
|
tone: "bright",
|
|
5741
|
+
className: busy ? "term-shimmer" : void 0,
|
|
5556
5742
|
children: title ?? item.name
|
|
5557
5743
|
}),
|
|
5558
5744
|
/* @__PURE__ */ jsxs(Ink, {
|
|
@@ -5688,11 +5874,19 @@ function ToolRunRow({ items }) {
|
|
|
5688
5874
|
glyph: busy ? pulse : void 0,
|
|
5689
5875
|
glyphTone: busy ? "mark" : void 0,
|
|
5690
5876
|
tone: failed ? "red" : "dim",
|
|
5691
|
-
children:
|
|
5877
|
+
children: busy ? /* @__PURE__ */ jsx("span", {
|
|
5878
|
+
className: "term-shimmer",
|
|
5879
|
+
children: runSummary(items, busy)
|
|
5880
|
+
}) : runSummary(items, busy)
|
|
5692
5881
|
})
|
|
5693
5882
|
}), open ? /* @__PURE__ */ jsx("div", { children: items.map((item) => /* @__PURE__ */ jsx(ToolRow, { item }, item.id)) }) : null]
|
|
5694
5883
|
});
|
|
5695
5884
|
}
|
|
5885
|
+
function RunRow({ items }) {
|
|
5886
|
+
const plan = planRun(items);
|
|
5887
|
+
if (plan.kind === "summary") return /* @__PURE__ */ jsx(ToolRunRow, { items: plan.items });
|
|
5888
|
+
return isPeerSend(plan.item) ? /* @__PURE__ */ jsx(PeerSendRow, { item: plan.item }) : /* @__PURE__ */ jsx(ToolRow, { item: plan.item });
|
|
5889
|
+
}
|
|
5696
5890
|
function TurnResultRow$1({ item }) {
|
|
5697
5891
|
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(Row, {
|
|
5698
5892
|
tone: item.isError ? "red" : "faint",
|
|
@@ -5770,7 +5964,10 @@ function WorkingRow({ label, startedAt, tokens }) {
|
|
|
5770
5964
|
glyph: pulse,
|
|
5771
5965
|
glyphTone: "mark",
|
|
5772
5966
|
tone: "mark",
|
|
5773
|
-
children: [
|
|
5967
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5968
|
+
className: "term-shimmer",
|
|
5969
|
+
children: label
|
|
5970
|
+
}), readings.length ? /* @__PURE__ */ jsxs(Ink, {
|
|
5774
5971
|
tone: "faint",
|
|
5775
5972
|
children: [
|
|
5776
5973
|
" (",
|
|
@@ -5805,7 +6002,7 @@ function TerminalSurface({ fontSize, lineHeight, bleed, affordances, className,
|
|
|
5805
6002
|
//#region src/components/agent/Composer.tsx
|
|
5806
6003
|
const SHELL_PLACEHOLDER = "Run a command on the host…";
|
|
5807
6004
|
const SHELL_HINT = "! shell mode · esc to exit";
|
|
5808
|
-
function Composer({ onSend, onInterrupt, busy, disabled, placeholder = "Message the agent…", commands, skills, clientCommands, onSearchFiles, onShellCommand, attachments, toolbar, layout = "stacked", fontSize, lineHeight, affordances, draft, className, ref }) {
|
|
6005
|
+
function Composer({ onSend, onInterrupt, busy, disabled, placeholder = "Message the agent…", commands, skills, clientCommands, onSearchFiles, peers, onShellCommand, attachments, toolbar, layout = "stacked", fontSize, lineHeight, affordances, draft, className, ref }) {
|
|
5809
6006
|
const inline = layout === "inline";
|
|
5810
6007
|
const terminal = useTranscriptVariant() === "terminal";
|
|
5811
6008
|
const [initialDraft] = useState(() => draft?.initialText ?? "");
|
|
@@ -5878,6 +6075,23 @@ function Composer({ onSend, onInterrupt, busy, disabled, placeholder = "Message
|
|
|
5878
6075
|
chipClassName: "font-mono",
|
|
5879
6076
|
emptyMessage: "No matching files"
|
|
5880
6077
|
}));
|
|
6078
|
+
if (peers?.length) configured.push(hashtagTrigger({
|
|
6079
|
+
accessibilityLabel: "session",
|
|
6080
|
+
onSearch: (query) => rankPeerSessions(query, peers).map((peer) => ({
|
|
6081
|
+
value: peer.slug,
|
|
6082
|
+
label: peer.label,
|
|
6083
|
+
description: [
|
|
6084
|
+
peer.engine,
|
|
6085
|
+
peer.project,
|
|
6086
|
+
peer.status
|
|
6087
|
+
].filter(Boolean).join(" · "),
|
|
6088
|
+
icon: /* @__PURE__ */ jsx(Users, { className: "size-3.5 text-fg-3" })
|
|
6089
|
+
})),
|
|
6090
|
+
onSelect: (suggestion) => suggestion.value,
|
|
6091
|
+
chipStyle: "inline",
|
|
6092
|
+
chipClassName: "font-mono",
|
|
6093
|
+
emptyMessage: "No matching sessions"
|
|
6094
|
+
}));
|
|
5881
6095
|
if (onShellCommand) configured.push(launchTrigger({
|
|
5882
6096
|
char: "!",
|
|
5883
6097
|
accessibilityLabel: "shell mode",
|
|
@@ -5889,6 +6103,7 @@ function Composer({ onSend, onInterrupt, busy, disabled, placeholder = "Message
|
|
|
5889
6103
|
skills,
|
|
5890
6104
|
clientCommands,
|
|
5891
6105
|
onSearchFiles,
|
|
6106
|
+
peers,
|
|
5892
6107
|
onShellCommand
|
|
5893
6108
|
]);
|
|
5894
6109
|
const saveDraft = draft?.save;
|
|
@@ -5928,6 +6143,10 @@ function Composer({ onSend, onInterrupt, busy, disabled, placeholder = "Message
|
|
|
5928
6143
|
key: "@",
|
|
5929
6144
|
what: "mention a file"
|
|
5930
6145
|
} : void 0,
|
|
6146
|
+
peers?.length ? {
|
|
6147
|
+
key: "#",
|
|
6148
|
+
what: "refer to another session"
|
|
6149
|
+
} : void 0,
|
|
5931
6150
|
onShellCommand ? {
|
|
5932
6151
|
key: "!",
|
|
5933
6152
|
what: "run a shell command"
|
|
@@ -7446,7 +7665,7 @@ function taskChildItems(block) {
|
|
|
7446
7665
|
}
|
|
7447
7666
|
function pushLeaf(out, item, index) {
|
|
7448
7667
|
const previous = out.at(-1);
|
|
7449
|
-
if (isRunCall(item)) {
|
|
7668
|
+
if (isRunCall(item) && !isPeerSend(item)) {
|
|
7450
7669
|
if (previous && "run" in previous && foldsTogether(previous.run[0], item)) {
|
|
7451
7670
|
previous.run.push(item);
|
|
7452
7671
|
previous.indices.push(index);
|
|
@@ -7512,12 +7731,15 @@ function terminalBlocks(items, offset = 0, fold = true) {
|
|
|
7512
7731
|
return out;
|
|
7513
7732
|
}
|
|
7514
7733
|
function needsBlank(previous, next) {
|
|
7515
|
-
if (previous
|
|
7516
|
-
return
|
|
7734
|
+
if (isPeerSend(previous) || isPeerSend(next)) return true;
|
|
7735
|
+
return !(previous.kind === "tool_call" && next.kind === "tool_call");
|
|
7736
|
+
}
|
|
7737
|
+
function blockKind(block) {
|
|
7738
|
+
if (!("item" in block)) return "tool_call";
|
|
7739
|
+
return isPeerSend(block.item) ? "peer_send" : block.item.kind;
|
|
7517
7740
|
}
|
|
7518
7741
|
function blockNeedsBlank(previous, next) {
|
|
7519
|
-
|
|
7520
|
-
return !(kind(previous) === "tool_call" && kind(next) === "tool_call");
|
|
7742
|
+
return !(blockKind(previous) === "tool_call" && blockKind(next) === "tool_call");
|
|
7521
7743
|
}
|
|
7522
7744
|
//#endregion
|
|
7523
7745
|
//#region src/components/agent/use-subagent-frame.ts
|
|
@@ -9272,12 +9494,20 @@ function itemHeight(item, m) {
|
|
|
9272
9494
|
exact: true
|
|
9273
9495
|
};
|
|
9274
9496
|
if (item.attachments?.length) acc = add(acc, rowH(item.attachments.map((a) => a.name).join(", "), m, { extraPx }));
|
|
9275
|
-
if (item.text)
|
|
9497
|
+
if (item.text) {
|
|
9498
|
+
const who = item.origin ? `${peerName(item.origin)}: ` : "";
|
|
9499
|
+
for (const [index, line] of item.text.split("\n").entries()) acc = add(acc, rowH((index === 0 ? who : "") + (line || " "), m, { extraPx }));
|
|
9500
|
+
}
|
|
9276
9501
|
return acc;
|
|
9277
9502
|
}
|
|
9278
9503
|
case "assistant_text": return markdownHeight(item.text, m, extraPx);
|
|
9279
9504
|
case "thinking": return rowH(item.text, m, { extraPx });
|
|
9280
|
-
case "tool_call":
|
|
9505
|
+
case "tool_call":
|
|
9506
|
+
if (isPeerSend(item)) return {
|
|
9507
|
+
px: m.line + extraPx,
|
|
9508
|
+
exact: true
|
|
9509
|
+
};
|
|
9510
|
+
return toolRowHeight(item, m, extraPx);
|
|
9281
9511
|
case "turn_result": {
|
|
9282
9512
|
let acc = rowH(`${item.isError ? item.subtype : "done"} · ${formatDuration(item.durationMs)} · ${formatCost(item.totalCostUsd)}`, m, { extraPx });
|
|
9283
9513
|
for (const message of item.errors ?? []) acc = add(acc, rowH(message, m, { extraPx }));
|
|
@@ -9295,8 +9525,10 @@ function itemHeight(item, m) {
|
|
|
9295
9525
|
function blockHeight(block, m) {
|
|
9296
9526
|
if ("task" in block) return rowH(taskSummary$1(block.task, taskChildItems(block)), m);
|
|
9297
9527
|
if ("run" in block) {
|
|
9298
|
-
const
|
|
9299
|
-
|
|
9528
|
+
const plan = planRun(block.run);
|
|
9529
|
+
if (plan.kind === "call") return itemHeight(plan.item, m);
|
|
9530
|
+
const busy = plan.items.some((item) => item.status === "running" || item.status === "pending");
|
|
9531
|
+
return rowH(runSummary(plan.items, busy), m);
|
|
9300
9532
|
}
|
|
9301
9533
|
return itemHeight(block.item, m);
|
|
9302
9534
|
}
|
|
@@ -10132,6 +10364,20 @@ function repinToBottom(stick) {
|
|
|
10132
10364
|
};
|
|
10133
10365
|
state.scrollTop = state.calculatedTargetScrollTop;
|
|
10134
10366
|
}
|
|
10367
|
+
function absorbScrollerResize(stick, difference) {
|
|
10368
|
+
const { state } = stick;
|
|
10369
|
+
state.resizeDifference = difference;
|
|
10370
|
+
requestAnimationFrame(() => {
|
|
10371
|
+
setTimeout(() => {
|
|
10372
|
+
if (state.resizeDifference === difference) state.resizeDifference = 0;
|
|
10373
|
+
}, 1);
|
|
10374
|
+
});
|
|
10375
|
+
if (state.animation?.ignoreEscapes) {
|
|
10376
|
+
state.scrollTop = state.calculatedTargetScrollTop;
|
|
10377
|
+
return;
|
|
10378
|
+
}
|
|
10379
|
+
stick.scrollToBottom("instant");
|
|
10380
|
+
}
|
|
10135
10381
|
function useTranscriptJumps(options) {
|
|
10136
10382
|
const { rows, terminal, stickyPrompt, epoch, promptRows, scrollElement, rowsRef, virtualizer, stick, jumpToRecapRef, repinRef } = options;
|
|
10137
10383
|
const aimTimer = useRef(void 0);
|
|
@@ -10209,7 +10455,7 @@ function TerminalItemView({ item, fileUrl }) {
|
|
|
10209
10455
|
case "user": return /* @__PURE__ */ jsx(UserRow, { item });
|
|
10210
10456
|
case "assistant_text": return /* @__PURE__ */ jsx(AssistantRow, { item });
|
|
10211
10457
|
case "thinking": return /* @__PURE__ */ jsx(ThinkingRow, { item });
|
|
10212
|
-
case "tool_call": return /* @__PURE__ */ jsx(ToolRow, { item });
|
|
10458
|
+
case "tool_call": return isPeerSend(item) ? /* @__PURE__ */ jsx(PeerSendRow, { item }) : /* @__PURE__ */ jsx(ToolRow, { item });
|
|
10213
10459
|
case "turn_result": return /* @__PURE__ */ jsx(TurnResultRow$1, { item });
|
|
10214
10460
|
case "notice": return /* @__PURE__ */ jsx(NoticeRow$1, { item });
|
|
10215
10461
|
case "compaction": return /* @__PURE__ */ jsx(CompactionRow$1, { item });
|
|
@@ -10263,14 +10509,17 @@ function TaskRow({ block, fileUrl, onOpenSubagent }) {
|
|
|
10263
10509
|
glyph: busy ? pulse : "●",
|
|
10264
10510
|
glyphTone: failed ? "red" : busy ? "mark" : "dim",
|
|
10265
10511
|
tone: failed ? "red" : "green",
|
|
10266
|
-
children:
|
|
10512
|
+
children: busy ? /* @__PURE__ */ jsx("span", {
|
|
10513
|
+
className: "term-shimmer",
|
|
10514
|
+
children: taskSummary$1(block.task, children)
|
|
10515
|
+
}) : taskSummary$1(block.task, children)
|
|
10267
10516
|
})
|
|
10268
10517
|
}), open ? /* @__PURE__ */ jsxs("div", {
|
|
10269
10518
|
className: "term-nested",
|
|
10270
10519
|
children: [brief ? /* @__PURE__ */ jsx(BriefRow, {
|
|
10271
10520
|
text: brief,
|
|
10272
10521
|
terminal: true
|
|
10273
|
-
}) : null, block.children.map((leaf, index) => /* @__PURE__ */ jsxs(Fragment, { children: [index > 0 && blockNeedsBlank(block.children[index - 1], leaf) ? /* @__PURE__ */ jsx(Blank, {}) : null, "run" in leaf ? /* @__PURE__ */ jsx(
|
|
10522
|
+
}) : null, block.children.map((leaf, index) => /* @__PURE__ */ jsxs(Fragment, { children: [index > 0 && blockNeedsBlank(block.children[index - 1], leaf) ? /* @__PURE__ */ jsx(Blank, {}) : null, "run" in leaf ? /* @__PURE__ */ jsx(RunRow, { items: leaf.run }) : /* @__PURE__ */ jsx(TerminalItemView, {
|
|
10274
10523
|
item: leaf.item,
|
|
10275
10524
|
fileUrl
|
|
10276
10525
|
})] }, leaf.key))]
|
|
@@ -10300,23 +10549,26 @@ function working(state) {
|
|
|
10300
10549
|
function TerminalTranscript({ state, fileUrl, fontSize, lineHeight, affordances, className }) {
|
|
10301
10550
|
const runStartedAt = useRunStart$1(state.status);
|
|
10302
10551
|
const blocks = useMemo(() => terminalBlocks(state.items), [state.items]);
|
|
10303
|
-
return /* @__PURE__ */
|
|
10552
|
+
return /* @__PURE__ */ jsx(TerminalSurface, {
|
|
10304
10553
|
fontSize,
|
|
10305
10554
|
lineHeight,
|
|
10306
10555
|
affordances,
|
|
10307
10556
|
bleed: "1ch",
|
|
10308
10557
|
className: cn("term-transcript", className),
|
|
10309
|
-
children:
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10558
|
+
children: /* @__PURE__ */ jsxs(PeerNamesProvider, {
|
|
10559
|
+
items: state.items,
|
|
10560
|
+
children: [blocks.map((block, index) => /* @__PURE__ */ jsxs(Fragment, { children: [index > 0 && blockNeedsBlank(blocks[index - 1], block) ? /* @__PURE__ */ jsx(Blank, {}) : null, "run" in block ? /* @__PURE__ */ jsx(RunRow, { items: block.run }) : "item" in block ? /* @__PURE__ */ jsx(TerminalItemView, {
|
|
10561
|
+
item: block.item,
|
|
10562
|
+
fileUrl
|
|
10563
|
+
}) : /* @__PURE__ */ jsx(TaskRow, {
|
|
10564
|
+
block,
|
|
10565
|
+
fileUrl
|
|
10566
|
+
})] }, block.key)), working(state) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [state.items.length > 0 ? /* @__PURE__ */ jsx(Blank, {}) : null, /* @__PURE__ */ jsx(WorkingRow, {
|
|
10567
|
+
label: state.status === "starting" ? "Starting…" : "Working…",
|
|
10568
|
+
startedAt: runStartedAt,
|
|
10569
|
+
tokens: state.contextUsage?.totalTokens
|
|
10570
|
+
})] }) : null]
|
|
10571
|
+
})
|
|
10320
10572
|
});
|
|
10321
10573
|
}
|
|
10322
10574
|
//#endregion
|
|
@@ -10702,10 +10954,17 @@ function TranscriptItemView({ item, fileUrl, attachmentUrl, hostImage, terminal
|
|
|
10702
10954
|
switch (item.kind) {
|
|
10703
10955
|
case "user": return /* @__PURE__ */ jsxs(Message, {
|
|
10704
10956
|
from: "user",
|
|
10705
|
-
children: [
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10957
|
+
children: [
|
|
10958
|
+
item.origin ? /* @__PURE__ */ jsx("div", {
|
|
10959
|
+
className: "wd-peer-origin text-xs text-muted-foreground",
|
|
10960
|
+
children: peerLabel(item.origin)
|
|
10961
|
+
}) : null,
|
|
10962
|
+
item.attachments?.length ? /* @__PURE__ */ jsx(SentAttachments, {
|
|
10963
|
+
attachments: item.attachments,
|
|
10964
|
+
attachmentUrl
|
|
10965
|
+
}) : null,
|
|
10966
|
+
item.text ? /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(PromptTokenText, { text: item.text }) }) : null
|
|
10967
|
+
]
|
|
10709
10968
|
});
|
|
10710
10969
|
case "assistant_text": return /* @__PURE__ */ jsx(Message, {
|
|
10711
10970
|
from: "assistant",
|
|
@@ -10880,8 +11139,9 @@ function TranscriptRows({ rows, boundary, since, terminal, replaying, stickyProm
|
|
|
10880
11139
|
const observer = new ResizeObserver(() => {
|
|
10881
11140
|
const height = scrollElement.clientHeight;
|
|
10882
11141
|
if (height === last) return;
|
|
11142
|
+
const difference = height - last;
|
|
10883
11143
|
last = height;
|
|
10884
|
-
if (stick.state.isAtBottom) stick
|
|
11144
|
+
if (stick.state.isAtBottom) absorbScrollerResize(stick, difference);
|
|
10885
11145
|
});
|
|
10886
11146
|
observer.observe(scrollElement);
|
|
10887
11147
|
return () => observer.disconnect();
|
|
@@ -11001,59 +11261,62 @@ function TranscriptRows({ rows, boundary, since, terminal, replaying, stickyProm
|
|
|
11001
11261
|
"data-slot": "transcript-rows",
|
|
11002
11262
|
className: "relative w-full",
|
|
11003
11263
|
style: { height: virtualizer.getTotalSize() },
|
|
11004
|
-
children: [
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11264
|
+
children: [/* @__PURE__ */ jsx(PeerNamesProvider, {
|
|
11265
|
+
items,
|
|
11266
|
+
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
11267
|
+
const row = rows[virtualRow.index];
|
|
11268
|
+
const gapClass = virtualRow.index > 0 && (!terminal || gapBefore(rows, virtualRow.index)) ? gap.className : void 0;
|
|
11269
|
+
const content = "run" in row ? /* @__PURE__ */ jsx("div", {
|
|
11270
|
+
className: cn(read(boundary, row.index) && "opacity-45"),
|
|
11271
|
+
children: /* @__PURE__ */ jsx(RunRow, { items: row.run })
|
|
11272
|
+
}) : "item" in row ? /* @__PURE__ */ jsx("div", {
|
|
11273
|
+
className: cn(read(boundary, row.index) && "opacity-45", nestedClass(row.item, frameParentId)),
|
|
11274
|
+
children: /* @__PURE__ */ jsx(TranscriptItemView, {
|
|
11275
|
+
item: row.item,
|
|
11276
|
+
fileUrl,
|
|
11277
|
+
attachmentUrl,
|
|
11278
|
+
hostImage,
|
|
11279
|
+
terminal
|
|
11280
|
+
})
|
|
11281
|
+
}) : "text" in row && row.key === "brief" ? /* @__PURE__ */ jsx(BriefRow, {
|
|
11282
|
+
text: row.text,
|
|
11017
11283
|
terminal
|
|
11018
|
-
})
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11284
|
+
}) : "line" in row ? /* @__PURE__ */ jsx(RecapRow, {
|
|
11285
|
+
line: row.line,
|
|
11286
|
+
since,
|
|
11287
|
+
terminal
|
|
11288
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
11289
|
+
className: cn(read(boundary, row.index) && "opacity-45"),
|
|
11290
|
+
children: /* @__PURE__ */ jsx(TaskRow, {
|
|
11291
|
+
block: row,
|
|
11292
|
+
fileUrl,
|
|
11293
|
+
onOpenSubagent
|
|
11294
|
+
})
|
|
11295
|
+
});
|
|
11296
|
+
if (stickyPrompt && "item" in row && row.item.kind === "user" && parentOf(row.item) === void 0) {
|
|
11297
|
+
const next = promptRows.find((index) => index > virtualRow.index);
|
|
11298
|
+
const laneEnd = next === void 0 ? virtualizer.getTotalSize() : measurements[next]?.start ?? virtualRow.start;
|
|
11299
|
+
return /* @__PURE__ */ jsx(StickyPromptLane, {
|
|
11300
|
+
top: virtualRow.start,
|
|
11301
|
+
height: Math.max(laneEnd - virtualRow.start, 0),
|
|
11302
|
+
gapClass,
|
|
11303
|
+
gapPx: gap.px,
|
|
11304
|
+
terminal,
|
|
11305
|
+
scrollRoot: scrollElement,
|
|
11306
|
+
index: virtualRow.index,
|
|
11307
|
+
measureRef: virtualizer.measureElement,
|
|
11308
|
+
head: terminal ? content : promptHeadText(row.item),
|
|
11309
|
+
content
|
|
11310
|
+
}, row.key);
|
|
11311
|
+
}
|
|
11312
|
+
return /* @__PURE__ */ jsx("div", {
|
|
11313
|
+
ref: virtualizer.measureElement,
|
|
11314
|
+
"data-index": virtualRow.index,
|
|
11315
|
+
className: cn("absolute inset-x-0 top-0", gapClass),
|
|
11316
|
+
style: { transform: `translateY(${virtualRow.start}px)` },
|
|
11317
|
+
children: content
|
|
11048
11318
|
}, row.key);
|
|
11049
|
-
}
|
|
11050
|
-
return /* @__PURE__ */ jsx("div", {
|
|
11051
|
-
ref: virtualizer.measureElement,
|
|
11052
|
-
"data-index": virtualRow.index,
|
|
11053
|
-
className: cn("absolute inset-x-0 top-0", gapClass),
|
|
11054
|
-
style: { transform: `translateY(${virtualRow.start}px)` },
|
|
11055
|
-
children: content
|
|
11056
|
-
}, row.key);
|
|
11319
|
+
})
|
|
11057
11320
|
}), scrubber && scrollElement?.parentElement ? createPortal(terminal ? /* @__PURE__ */ jsx(TerminalScrubber, {
|
|
11058
11321
|
items,
|
|
11059
11322
|
pendingApprovals,
|
|
@@ -11111,7 +11374,7 @@ function TerminalShell({ active, fontSize, lineHeight, affordances, children })
|
|
|
11111
11374
|
children
|
|
11112
11375
|
});
|
|
11113
11376
|
}
|
|
11114
|
-
function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage, variant = "cards", density = "comfortable", fontSize, lineHeight, affordances, stickyPrompt = false, scrubber, bookmarks, replaying = false, catchUp, jumpToRecapRef, repinRef, reveal, frame, onOpenSubagent, emptyState, className }) {
|
|
11377
|
+
function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage, variant = "cards", density = "comfortable", fontSize, lineHeight, affordances, stickyPrompt = false, scrubber, bookmarks, sessionNames, replaying = false, catchUp, jumpToRecapRef, repinRef, reveal, frame, onOpenSubagent, emptyState, className }) {
|
|
11115
11378
|
const terminal = variant === "terminal";
|
|
11116
11379
|
const items = useMemo(() => frame ? subagentItems(state.items, frame.parentToolUseId) : state.items, [state.items, frame]);
|
|
11117
11380
|
const frameTask = useMemo(() => frame ? state.items.find((item) => item.kind === "tool_call" && item.id === frame.parentToolUseId) : void 0, [state.items, frame]);
|
|
@@ -11151,79 +11414,82 @@ function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage,
|
|
|
11151
11414
|
value: variant,
|
|
11152
11415
|
children: /* @__PURE__ */ jsx(SkillNamesProvider, {
|
|
11153
11416
|
names: skillNames,
|
|
11154
|
-
children: /* @__PURE__ */
|
|
11155
|
-
|
|
11156
|
-
children:
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
affordances,
|
|
11164
|
-
children: [
|
|
11165
|
-
frame ? frameTask === void 0 && !replaying ? /* @__PURE__ */ jsx("div", {
|
|
11166
|
-
className: cn(terminal ? "term-row text-fg-4" : "p-4 text-body-sm text-fg-4"),
|
|
11167
|
-
children: "This sub-agent's work is not in this transcript."
|
|
11168
|
-
}) : null : items.length === 0 && state.status !== "starting" ? emptyState !== void 0 ? emptyState : /* @__PURE__ */ jsx(SessionEmptyState, {
|
|
11169
|
-
cwd: state.cwd,
|
|
11170
|
-
hasCommands: !!state.commands?.length,
|
|
11171
|
-
hasSkills: !!state.skills?.some((s) => s.enabled),
|
|
11172
|
-
canBrowseFiles
|
|
11173
|
-
}) : null,
|
|
11174
|
-
frame && frameTask === void 0 && !replaying ? null : /* @__PURE__ */ jsx(TranscriptRows, {
|
|
11175
|
-
rows,
|
|
11176
|
-
boundary,
|
|
11177
|
-
since: catchUp?.since,
|
|
11178
|
-
terminal,
|
|
11179
|
-
replaying,
|
|
11180
|
-
stickyPrompt: !frame && stickyPrompt,
|
|
11181
|
-
gap,
|
|
11182
|
-
fontSize,
|
|
11183
|
-
lineHeight,
|
|
11184
|
-
items,
|
|
11185
|
-
pendingApprovals: state.pendingApprovals,
|
|
11186
|
-
scrubber,
|
|
11187
|
-
bookmarks: frame ? void 0 : bookmarks,
|
|
11188
|
-
affordances,
|
|
11189
|
-
fileUrl,
|
|
11190
|
-
attachmentUrl,
|
|
11191
|
-
hostImage,
|
|
11192
|
-
jumpToRecapRef,
|
|
11193
|
-
repinRef,
|
|
11194
|
-
reveal: frame ? void 0 : reveal,
|
|
11195
|
-
frameParentId: frame?.parentToolUseId,
|
|
11196
|
-
onOpenSubagent: frame ? void 0 : onOpenSubagent
|
|
11197
|
-
}),
|
|
11198
|
-
(frame ? frameTask !== void 0 && taskBusy(frameTask, items) : showLoader(state)) ? terminal ? /* @__PURE__ */ jsxs(Fragment$1, { children: [state.items.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
11199
|
-
className: "term-blank",
|
|
11200
|
-
"aria-hidden": true
|
|
11201
|
-
}) : null, /* @__PURE__ */ jsx(WorkingRow, {
|
|
11202
|
-
label: state.status === "starting" ? "Starting…" : "Working…",
|
|
11203
|
-
startedAt: runStartedAt,
|
|
11204
|
-
tokens: state.contextUsage?.totalTokens
|
|
11205
|
-
})] }) : /* @__PURE__ */ jsx(Loader, { label: state.status === "starting" ? "Starting session…" : void 0 }) : null
|
|
11206
|
-
]
|
|
11207
|
-
})
|
|
11208
|
-
}),
|
|
11209
|
-
/* @__PURE__ */ jsx(ConversationScrollButton, {}),
|
|
11210
|
-
replaying ? /* @__PURE__ */ jsx("div", {
|
|
11211
|
-
"data-slot": "transcript-hold",
|
|
11212
|
-
"aria-hidden": true,
|
|
11213
|
-
className: "wd-hold-appear visible pointer-events-none absolute inset-0 overflow-hidden",
|
|
11214
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11215
|
-
className: cn("mx-auto w-full max-w-[var(--wd-transcript-max-width)]", !terminal && "px-4 py-4"),
|
|
11216
|
-
children: terminal ? /* @__PURE__ */ jsx(TerminalSurface, {
|
|
11417
|
+
children: /* @__PURE__ */ jsx(SessionNamesProvider, {
|
|
11418
|
+
names: sessionNames,
|
|
11419
|
+
children: /* @__PURE__ */ jsxs(Conversation, {
|
|
11420
|
+
className: cn(replaying && "invisible", className),
|
|
11421
|
+
children: [
|
|
11422
|
+
/* @__PURE__ */ jsx(ConversationContent, {
|
|
11423
|
+
className: cn(terminal && "gap-0 p-0"),
|
|
11424
|
+
children: /* @__PURE__ */ jsxs(TerminalShell, {
|
|
11425
|
+
active: terminal,
|
|
11217
11426
|
fontSize,
|
|
11218
11427
|
lineHeight,
|
|
11219
|
-
affordances
|
|
11220
|
-
|
|
11221
|
-
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
|
|
11428
|
+
affordances,
|
|
11429
|
+
children: [
|
|
11430
|
+
frame ? frameTask === void 0 && !replaying ? /* @__PURE__ */ jsx("div", {
|
|
11431
|
+
className: cn(terminal ? "term-row text-fg-4" : "p-4 text-body-sm text-fg-4"),
|
|
11432
|
+
children: "This sub-agent's work is not in this transcript."
|
|
11433
|
+
}) : null : items.length === 0 && state.status !== "starting" ? emptyState !== void 0 ? emptyState : /* @__PURE__ */ jsx(SessionEmptyState, {
|
|
11434
|
+
cwd: state.cwd,
|
|
11435
|
+
hasCommands: !!state.commands?.length,
|
|
11436
|
+
hasSkills: !!state.skills?.some((s) => s.enabled),
|
|
11437
|
+
canBrowseFiles
|
|
11438
|
+
}) : null,
|
|
11439
|
+
frame && frameTask === void 0 && !replaying ? null : /* @__PURE__ */ jsx(TranscriptRows, {
|
|
11440
|
+
rows,
|
|
11441
|
+
boundary,
|
|
11442
|
+
since: catchUp?.since,
|
|
11443
|
+
terminal,
|
|
11444
|
+
replaying,
|
|
11445
|
+
stickyPrompt: !frame && stickyPrompt,
|
|
11446
|
+
gap,
|
|
11447
|
+
fontSize,
|
|
11448
|
+
lineHeight,
|
|
11449
|
+
items,
|
|
11450
|
+
pendingApprovals: state.pendingApprovals,
|
|
11451
|
+
scrubber,
|
|
11452
|
+
bookmarks: frame ? void 0 : bookmarks,
|
|
11453
|
+
affordances,
|
|
11454
|
+
fileUrl,
|
|
11455
|
+
attachmentUrl,
|
|
11456
|
+
hostImage,
|
|
11457
|
+
jumpToRecapRef,
|
|
11458
|
+
repinRef,
|
|
11459
|
+
reveal: frame ? void 0 : reveal,
|
|
11460
|
+
frameParentId: frame?.parentToolUseId,
|
|
11461
|
+
onOpenSubagent: frame ? void 0 : onOpenSubagent
|
|
11462
|
+
}),
|
|
11463
|
+
(frame ? frameTask !== void 0 && taskBusy(frameTask, items) : showLoader(state)) ? terminal ? /* @__PURE__ */ jsxs(Fragment$1, { children: [state.items.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
11464
|
+
className: "term-blank",
|
|
11465
|
+
"aria-hidden": true
|
|
11466
|
+
}) : null, /* @__PURE__ */ jsx(WorkingRow, {
|
|
11467
|
+
label: state.status === "starting" ? "Starting…" : "Working…",
|
|
11468
|
+
startedAt: runStartedAt,
|
|
11469
|
+
tokens: state.contextUsage?.totalTokens
|
|
11470
|
+
})] }) : /* @__PURE__ */ jsx(Loader, { label: state.status === "starting" ? "Starting session…" : void 0 }) : null
|
|
11471
|
+
]
|
|
11472
|
+
})
|
|
11473
|
+
}),
|
|
11474
|
+
/* @__PURE__ */ jsx(ConversationScrollButton, {}),
|
|
11475
|
+
replaying ? /* @__PURE__ */ jsx("div", {
|
|
11476
|
+
"data-slot": "transcript-hold",
|
|
11477
|
+
"aria-hidden": true,
|
|
11478
|
+
className: "wd-hold-appear visible pointer-events-none absolute inset-0 overflow-hidden",
|
|
11479
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
11480
|
+
className: cn("mx-auto w-full max-w-[var(--wd-transcript-max-width)]", !terminal && "px-4 py-4"),
|
|
11481
|
+
children: terminal ? /* @__PURE__ */ jsx(TerminalSurface, {
|
|
11482
|
+
fontSize,
|
|
11483
|
+
lineHeight,
|
|
11484
|
+
affordances: false,
|
|
11485
|
+
bleed: "1ch",
|
|
11486
|
+
className: "term-transcript",
|
|
11487
|
+
children: /* @__PURE__ */ jsx(WorkingRow, { label: "Loading…" })
|
|
11488
|
+
}) : /* @__PURE__ */ jsx(Loader, { label: "Loading session…" })
|
|
11489
|
+
})
|
|
11490
|
+
}) : null
|
|
11491
|
+
]
|
|
11492
|
+
})
|
|
11227
11493
|
})
|
|
11228
11494
|
})
|
|
11229
11495
|
});
|
|
@@ -11233,14 +11499,16 @@ function Transcript({ state, fileUrl, attachmentUrl, canBrowseFiles, hostImage,
|
|
|
11233
11499
|
const GAP_SHARE = .02;
|
|
11234
11500
|
function sessionCost(input) {
|
|
11235
11501
|
const byModel = input.usageByModel ?? {};
|
|
11236
|
-
const
|
|
11502
|
+
const pricing = input.pricing;
|
|
11503
|
+
const breakdown = costOfByModel(byModel, pricing);
|
|
11237
11504
|
const computedUsd = input.costUsd ?? (breakdown.unpriced || Object.keys(byModel).length === 0 ? void 0 : breakdown.total);
|
|
11238
11505
|
const reportedUsd = input.totalCostUsd;
|
|
11239
11506
|
const rows = Object.entries(byModel).map(([model, usage]) => ({
|
|
11240
11507
|
model: canonicalModel(model),
|
|
11241
11508
|
usage,
|
|
11242
11509
|
tokens: totalTokens(usage),
|
|
11243
|
-
costUsd: rateFor(model) ? costOf(usage, model).total : void 0
|
|
11510
|
+
costUsd: rateFor(model, pricing) ? costOf(usage, model, pricing).total : void 0,
|
|
11511
|
+
costBasis: usage.costBasis
|
|
11244
11512
|
})).sort((a, b) => b.tokens - a.tokens);
|
|
11245
11513
|
const gap = computedUsd !== void 0 && reportedUsd !== void 0 ? reportedUsd - computedUsd : void 0;
|
|
11246
11514
|
const worthShowing = gap !== void 0 && Math.abs(gap) > Math.max(.01, GAP_SHARE * Math.max(computedUsd ?? 0, reportedUsd ?? 0));
|
|
@@ -11252,6 +11520,7 @@ function sessionCost(input) {
|
|
|
11252
11520
|
rows,
|
|
11253
11521
|
unpricedShare: breakdown.unpricedShare,
|
|
11254
11522
|
showUnpricedWarning: breakdown.unpricedShare > UNPRICED_WARN_SHARE,
|
|
11523
|
+
unknownBasisModels: unknownBasisModels(byModel),
|
|
11255
11524
|
gapUsd: worthShowing ? gap : void 0
|
|
11256
11525
|
};
|
|
11257
11526
|
}
|
|
@@ -11339,6 +11608,9 @@ function UsageMeter({ window, now }) {
|
|
|
11339
11608
|
}
|
|
11340
11609
|
//#endregion
|
|
11341
11610
|
//#region src/components/agent/UsageDialog.tsx
|
|
11611
|
+
function engineLabel(engine) {
|
|
11612
|
+
return engine === "claude" ? "Claude Code" : engine;
|
|
11613
|
+
}
|
|
11342
11614
|
function Line({ label, value, tone }) {
|
|
11343
11615
|
return /* @__PURE__ */ jsxs("div", {
|
|
11344
11616
|
className: "flex items-baseline justify-between gap-4",
|
|
@@ -11416,10 +11688,19 @@ function CostEvidence({ cost, engine }) {
|
|
|
11416
11688
|
className: "text-label text-warning",
|
|
11417
11689
|
children: [Math.round(cost.unpricedShare * 100), "% of these tokens ran on a model with no bundled rate, so the total is an understatement rather than an estimate."]
|
|
11418
11690
|
}) : null,
|
|
11691
|
+
cost.unknownBasisModels.length > 0 ? /* @__PURE__ */ jsxs("p", {
|
|
11692
|
+
className: "text-label text-warning",
|
|
11693
|
+
children: [
|
|
11694
|
+
engineLabel(engine),
|
|
11695
|
+
" matched no rate table of its own to ",
|
|
11696
|
+
cost.unknownBasisModels.join(", "),
|
|
11697
|
+
", so the figure it reports for those tokens is a guess rather than a rate."
|
|
11698
|
+
]
|
|
11699
|
+
}) : null,
|
|
11419
11700
|
cost.gapUsd !== void 0 ? /* @__PURE__ */ jsxs("p", {
|
|
11420
11701
|
className: "text-label text-fg-4",
|
|
11421
11702
|
children: [
|
|
11422
|
-
engine
|
|
11703
|
+
engineLabel(engine),
|
|
11423
11704
|
" reports ",
|
|
11424
11705
|
formatCost(cost.reportedUsd),
|
|
11425
11706
|
" for the same tokens."
|
|
@@ -11460,13 +11741,15 @@ function ProfileSpendSection({ spend }) {
|
|
|
11460
11741
|
function formatMultiple(ratio) {
|
|
11461
11742
|
return ratio >= 10 ? `${Math.round(ratio)}x` : `${ratio.toFixed(1)}x`;
|
|
11462
11743
|
}
|
|
11463
|
-
function UsageDialog({ rateLimits, subscriptionType, engine, totalCostUsd, costUsd, usageByModel, spend, updatedAt, open, onOpenChange, className }) {
|
|
11744
|
+
function UsageDialog({ rateLimits, subscriptionType, engine, totalCostUsd, costUsd, usageByModel, pricing, spend, updatedAt, open, onOpenChange, className }) {
|
|
11464
11745
|
const now = useMinuteClock(open);
|
|
11465
11746
|
const cost = sessionCost({
|
|
11466
11747
|
costUsd,
|
|
11467
11748
|
totalCostUsd,
|
|
11468
|
-
usageByModel
|
|
11749
|
+
usageByModel,
|
|
11750
|
+
pricing
|
|
11469
11751
|
});
|
|
11752
|
+
const ageNote = pricingAgeNote(now);
|
|
11470
11753
|
return /* @__PURE__ */ jsx(Dialog$1, {
|
|
11471
11754
|
open,
|
|
11472
11755
|
onOpenChange,
|
|
@@ -11474,7 +11757,7 @@ function UsageDialog({ rateLimits, subscriptionType, engine, totalCostUsd, costU
|
|
|
11474
11757
|
className,
|
|
11475
11758
|
children: [/* @__PURE__ */ jsx(DialogHeader, {
|
|
11476
11759
|
title: "Usage",
|
|
11477
|
-
description: engine
|
|
11760
|
+
description: engineLabel(engine),
|
|
11478
11761
|
actions: subscriptionType ? /* @__PURE__ */ jsx(Badge, {
|
|
11479
11762
|
variant: "accent",
|
|
11480
11763
|
className: "mt-0.5 shrink-0 capitalize",
|
|
@@ -11498,7 +11781,7 @@ function UsageDialog({ rateLimits, subscriptionType, engine, totalCostUsd, costU
|
|
|
11498
11781
|
spend ? /* @__PURE__ */ jsx(ProfileSpendSection, { spend }) : null,
|
|
11499
11782
|
/* @__PURE__ */ jsx("p", {
|
|
11500
11783
|
className: "mt-3 text-label text-fg-4",
|
|
11501
|
-
children: PRICING_NOTE
|
|
11784
|
+
children: ageNote ? `${PRICING_NOTE} ${ageNote}` : PRICING_NOTE
|
|
11502
11785
|
}),
|
|
11503
11786
|
updatedAt ? /* @__PURE__ */ jsxs("p", {
|
|
11504
11787
|
className: "mt-2 text-label text-fg-4",
|
|
@@ -11539,7 +11822,7 @@ const INTERACTIVE = [
|
|
|
11539
11822
|
"[role=\"radio\"]",
|
|
11540
11823
|
"[role=\"tab\"]"
|
|
11541
11824
|
].join(",");
|
|
11542
|
-
function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", statusPlacement = "top", onOpenPanel, onVitals, transcriptVariant = "cards", transcriptDensity = "comfortable", transcriptFont = "sans", affordances, terminalMetrics, scrubber = false, bookmarks, onToggleBookmark, reveal, subagents, openSubagent, onSubagentChange, stickyPrompt = false, controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, readOnly = false, approvalPrompts, toolHost, clientTools, cacheTranscript, emptyState, onLinkClick, onOpenFile, fontSize, className }) {
|
|
11825
|
+
function SessionPanel({ client, sessionId, header, panelSurface = "internal", statusSurface = "internal", statusPlacement = "top", onOpenPanel, onVitals, transcriptVariant = "cards", transcriptDensity = "comfortable", transcriptFont = "sans", affordances, terminalMetrics, scrubber = false, bookmarks, peerMentions = true, onToggleBookmark, reveal, subagents, openSubagent, onSubagentChange, stickyPrompt = false, controlsSurface = "internal", onControls, focusComposerOnClick = false, unseen, readOnly = false, approvalPrompts, toolHost, clientTools, cacheTranscript, emptyState, onLinkClick, onOpenFile, fontSize, className }) {
|
|
11543
11826
|
const effectiveTermFontSize = terminalMetrics?.fontSize ?? fontSize;
|
|
11544
11827
|
const effectiveTermLineHeight = terminalMetrics?.lineHeight ?? (fontSize !== void 0 ? Math.round(fontSize * (18 / 13)) : void 0);
|
|
11545
11828
|
const external = panelSurface === "external";
|
|
@@ -11550,7 +11833,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
11550
11833
|
const [panel, setPanel] = useState();
|
|
11551
11834
|
const [showCompletedTasks, setShowCompletedTasks] = useState(false);
|
|
11552
11835
|
const [taskReveal, setTaskReveal] = useState();
|
|
11553
|
-
const { state, connection, replaying, protocolMismatch, shell, models, effectiveModel, handle, send, runShell, approve, deny, interrupt, clearContext, setModel, setPermissionMode, reconnectNow, loadFullResult } = useClaudeSession(client, sessionId, {
|
|
11836
|
+
const { state, connection, replaying, protocolMismatch, shell, pricing, models, effectiveModel, handle, send, runShell, approve, deny, interrupt, clearContext, setModel, setPermissionMode, reconnectNow, loadFullResult } = useClaudeSession(client, sessionId, {
|
|
11554
11837
|
onProtocolError: setProtocolError,
|
|
11555
11838
|
cacheTranscript
|
|
11556
11839
|
});
|
|
@@ -11771,6 +12054,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
11771
12054
|
engine: state.engine
|
|
11772
12055
|
});
|
|
11773
12056
|
const hostFiles = useHostFileSearch(client, state.cwd);
|
|
12057
|
+
const peers = usePeerSessions(client, sessionId, peerMentions);
|
|
11774
12058
|
const draft = useDraft(client, sessionId);
|
|
11775
12059
|
const searchComposerFiles = useCallback((query, options) => hostFiles.search(query, {
|
|
11776
12060
|
...options,
|
|
@@ -11932,6 +12216,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
11932
12216
|
fileUrl: sessionId ? (path) => client.sessionFileUrl(sessionId, path) : void 0,
|
|
11933
12217
|
attachmentUrl: sessionId ? (id) => client.attachmentUrl(sessionId, id) : void 0,
|
|
11934
12218
|
canBrowseFiles: hostFiles.available,
|
|
12219
|
+
sessionNames: peers.names,
|
|
11935
12220
|
hostImage,
|
|
11936
12221
|
variant: transcriptVariant,
|
|
11937
12222
|
density: transcriptDensity,
|
|
@@ -12039,6 +12324,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
12039
12324
|
attachments,
|
|
12040
12325
|
draft,
|
|
12041
12326
|
onSearchFiles: hostFiles.available ? searchComposerFiles : void 0,
|
|
12327
|
+
peers: peers.peers,
|
|
12042
12328
|
onShellCommand: shell ? runShell : void 0,
|
|
12043
12329
|
layout: controlsExternal ? "inline" : "stacked",
|
|
12044
12330
|
toolbar: controlsExternal ? void 0 : sessionControls,
|
|
@@ -12068,6 +12354,7 @@ function SessionPanel({ client, sessionId, header, panelSurface = "internal", st
|
|
|
12068
12354
|
totalCostUsd: state.totalCostUsd,
|
|
12069
12355
|
costUsd: state.costUsd,
|
|
12070
12356
|
usageByModel: state.usageByModel,
|
|
12357
|
+
pricing,
|
|
12071
12358
|
spend: profileSpend,
|
|
12072
12359
|
updatedAt: usageUpdatedAt,
|
|
12073
12360
|
open: panel === "usage",
|
|
@@ -12279,6 +12566,6 @@ function resolveAgainstCwd(path, cwd) {
|
|
|
12279
12566
|
return parseFileLink(path, cwd)?.path ?? path;
|
|
12280
12567
|
}
|
|
12281
12568
|
//#endregion
|
|
12282
|
-
export { TerminalDiff as $,
|
|
12569
|
+
export { TerminalDiff as $, SelectItem as $t, PermissionPrompt as A, ProgressRing as At, EntryIcon as B, DialogBody as Bt, SessionInfoDialog as C, hashtagTrigger as Ct, QuestionPrompt as D, PromptArea as Dt, QUESTION_BEHAVIORS as E, usePromptAreaState as Et, permissionModeMeta as F, copyText as Ft, Composer as G, DialogTrigger as Gt, TaskList as H, DialogContent as Ht, ModelSelect as I, Tip as It, useToolTitle as J, MenuItem as Jt, TerminalSurface as K, Menu$1 as Kt, SkillsDialog as L, TooltipContent as Lt, PERMISSION_MODES as M, CodeBlock as Mt, PermissionModeSelect as N, Spinner as Nt, parseUserQuestions as O, plainTextToSegments as Ot, permissionModeChoices as P, CopyButton as Pt, parseFileLink as Q, SelectContent as Qt, McpDialog as R, TooltipProvider as Rt, STATUS_META as S, commandTrigger as St, TerminalPermissionPrompt as T, mentionTrigger as Tt, ContextDialog as U, DialogHeader as Ut, TasksDialog as V, DialogClose as Vt, contextNote as W, DialogRow as Wt, FileLinkProvider as X, MenuTrigger as Xt, TerminalMarkdown as Y, MenuSeparator as Yt, useFileLinks as Z, Select$1 as Zt, Loader as _, matchClientCommand as _t, UsageDialog as a, Input as an, CopyAction as at, ConversationScrollButton as b, rankPeerSessions as bt, Transcript as c, Button as cn, PromptTokenText as ct, Message as d, isMutatingTool as dt, SelectItemText as en, previewPatch as et, MessageContent as f, toolIcon as ft, SessionEmptyState as g, useTranscriptVariant as gt, TerminalTranscript as h, useTranscriptDensity as ht, SessionPanel as i, Textarea as in, Row as it, Response as j, Splitter as jt, SubagentStrip as k, segmentsToPlainText as kt, ToolCallCard as l, buttonVariants as ln, SessionNamesProvider as lt, TerminalItemView as m, TranscriptVariantProvider as mt, usePathLinks as n, SelectValue as nn, Blank as nt, UsageMeters as o, Badge as on, WithActions as ot, FileCard as p, TranscriptDensityProvider as pt, ToolTitleProvider as q, MenuContent as qt, matchPath as r, PortalScope as rn, Ink as rt, useMinuteClock as s, badgeVariants as sn, useAffordances as st, resolveAgainstCwd as t, SelectTrigger as tn, Band as tt, Reasoning as u, cn as un, SkillNamesProvider as ut, Conversation as v, mergeComposerRows as vt, TerminalQuestionPrompt as w, launchTrigger as wt, StatusBar as x, skillPrompt as xt, ConversationContent as y, rankComposerRows as yt, HostFilesDialog as z, Dialog$1 as zt };
|
|
12283
12570
|
|
|
12284
|
-
//# sourceMappingURL=use-path-links-
|
|
12571
|
+
//# sourceMappingURL=use-path-links-CepFsMdW.mjs.map
|