@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.
Files changed (37) hide show
  1. package/build/{SessionPanel-BVbau2eR.d.mts → SessionPanel-CJwp5B3q.d.mts} +8 -3
  2. package/build/index.d.mts +39 -20
  3. package/build/index.mjs +119 -52
  4. package/build/index.mjs.map +1 -1
  5. package/build/scoped.css +60 -11
  6. package/build/{use-path-links-CvcxdUXL.mjs → use-path-links-CepFsMdW.mjs} +541 -254
  7. package/build/use-path-links-CepFsMdW.mjs.map +1 -0
  8. package/build/workspace.d.mts +1 -1
  9. package/build/workspace.mjs +1 -1
  10. package/package.json +4 -4
  11. package/src/components/agent/Composer.tsx +28 -5
  12. package/src/components/agent/PromptTokenText.tsx +9 -1
  13. package/src/components/agent/SessionBrowser.tsx +17 -1
  14. package/src/components/agent/SessionItem.tsx +10 -26
  15. package/src/components/agent/SessionPanel.tsx +12 -0
  16. package/src/components/agent/SessionSteps.tsx +15 -55
  17. package/src/components/agent/SubagentToggle.tsx +69 -0
  18. package/src/components/agent/Transcript.tsx +91 -80
  19. package/src/components/agent/TranscriptItemView.tsx +2 -0
  20. package/src/components/agent/TranscriptRows.tsx +60 -56
  21. package/src/components/agent/UsageDialog.tsx +19 -6
  22. package/src/components/agent/composer-commands.ts +18 -0
  23. package/src/components/agent/pulse.tsx +53 -16
  24. package/src/components/agent/use-transcript-jumps.ts +25 -0
  25. package/src/components/terminal/TerminalTranscript.tsx +31 -27
  26. package/src/components/terminal/blocks.ts +15 -7
  27. package/src/components/terminal/height.ts +14 -5
  28. package/src/components/terminal/items.tsx +97 -11
  29. package/src/components/terminal/peer-names.tsx +16 -0
  30. package/src/components/terminal/row.tsx +1 -1
  31. package/src/components/terminal/tool-run.ts +68 -0
  32. package/src/index.ts +10 -2
  33. package/src/lib/session-cost.ts +12 -2
  34. package/src/lib/tool-icon.ts +5 -1
  35. package/src/styles/terminal.css +102 -1
  36. package/src/styles/theme.css +1 -1
  37. 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": return CheckSquare;
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 PULSE_REST = PULSE_FRAMES[PULSE_FRAMES.length - 1];
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
- const [frame, setFrame] = useState(0);
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 tokens = scanPromptTokens(text, { skills });
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(Row, {
5469
- glyph: index === 0 ? "❯" : void 0,
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: runSummary(items, busy)
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: [label, readings.length ? /* @__PURE__ */ jsxs(Ink, {
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.kind === "tool_call" && next.kind === "tool_call") return false;
7516
- return true;
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
- const kind = (block) => "item" in block ? block.item.kind : "tool_call";
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) for (const line of item.text.split("\n")) acc = add(acc, rowH(line || " ", m, { extraPx }));
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": return toolRowHeight(item, m, extraPx);
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 busy = block.run.some((item) => item.status === "running" || item.status === "pending");
9299
- return rowH(runSummary(block.run, busy), m);
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: taskSummary$1(block.task, 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(ToolRunRow, { items: leaf.run }) : /* @__PURE__ */ jsx(TerminalItemView, {
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__ */ jsxs(TerminalSurface, {
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: [blocks.map((block, index) => /* @__PURE__ */ jsxs(Fragment, { children: [index > 0 && blockNeedsBlank(blocks[index - 1], block) ? /* @__PURE__ */ jsx(Blank, {}) : null, "run" in block ? /* @__PURE__ */ jsx(ToolRunRow, { items: block.run }) : "item" in block ? /* @__PURE__ */ jsx(TerminalItemView, {
10310
- item: block.item,
10311
- fileUrl
10312
- }) : /* @__PURE__ */ jsx(TaskRow, {
10313
- block,
10314
- fileUrl
10315
- })] }, block.key)), working(state) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [state.items.length > 0 ? /* @__PURE__ */ jsx(Blank, {}) : null, /* @__PURE__ */ jsx(WorkingRow, {
10316
- label: state.status === "starting" ? "Starting…" : "Working…",
10317
- startedAt: runStartedAt,
10318
- tokens: state.contextUsage?.totalTokens
10319
- })] }) : null]
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: [item.attachments?.length ? /* @__PURE__ */ jsx(SentAttachments, {
10706
- attachments: item.attachments,
10707
- attachmentUrl
10708
- }) : null, item.text ? /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(PromptTokenText, { text: item.text }) }) : null]
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.scrollToBottom("instant");
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: [virtualizer.getVirtualItems().map((virtualRow) => {
11005
- const row = rows[virtualRow.index];
11006
- const gapClass = virtualRow.index > 0 && (!terminal || gapBefore(rows, virtualRow.index)) ? gap.className : void 0;
11007
- const content = "run" in row ? /* @__PURE__ */ jsx("div", {
11008
- className: cn(read(boundary, row.index) && "opacity-45"),
11009
- children: /* @__PURE__ */ jsx(ToolRunRow, { items: row.run })
11010
- }) : "item" in row ? /* @__PURE__ */ jsx("div", {
11011
- className: cn(read(boundary, row.index) && "opacity-45", nestedClass(row.item, frameParentId)),
11012
- children: /* @__PURE__ */ jsx(TranscriptItemView, {
11013
- item: row.item,
11014
- fileUrl,
11015
- attachmentUrl,
11016
- hostImage,
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
- }) : "text" in row && row.key === "brief" ? /* @__PURE__ */ jsx(BriefRow, {
11020
- text: row.text,
11021
- terminal
11022
- }) : "line" in row ? /* @__PURE__ */ jsx(RecapRow, {
11023
- line: row.line,
11024
- since,
11025
- terminal
11026
- }) : /* @__PURE__ */ jsx("div", {
11027
- className: cn(read(boundary, row.index) && "opacity-45"),
11028
- children: /* @__PURE__ */ jsx(TaskRow, {
11029
- block: row,
11030
- fileUrl,
11031
- onOpenSubagent
11032
- })
11033
- });
11034
- if (stickyPrompt && "item" in row && row.item.kind === "user" && parentOf(row.item) === void 0) {
11035
- const next = promptRows.find((index) => index > virtualRow.index);
11036
- const laneEnd = next === void 0 ? virtualizer.getTotalSize() : measurements[next]?.start ?? virtualRow.start;
11037
- return /* @__PURE__ */ jsx(StickyPromptLane, {
11038
- top: virtualRow.start,
11039
- height: Math.max(laneEnd - virtualRow.start, 0),
11040
- gapClass,
11041
- gapPx: gap.px,
11042
- terminal,
11043
- scrollRoot: scrollElement,
11044
- index: virtualRow.index,
11045
- measureRef: virtualizer.measureElement,
11046
- head: terminal ? content : promptHeadText(row.item),
11047
- content
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__ */ jsxs(Conversation, {
11155
- className: cn(replaying && "invisible", className),
11156
- children: [
11157
- /* @__PURE__ */ jsx(ConversationContent, {
11158
- className: cn(terminal && "gap-0 p-0"),
11159
- children: /* @__PURE__ */ jsxs(TerminalShell, {
11160
- active: terminal,
11161
- fontSize,
11162
- lineHeight,
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: false,
11220
- bleed: "1ch",
11221
- className: "term-transcript",
11222
- children: /* @__PURE__ */ jsx(WorkingRow, { label: "Loading…" })
11223
- }) : /* @__PURE__ */ jsx(Loader, { label: "Loading session…" })
11224
- })
11225
- }) : null
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 breakdown = costOfByModel(byModel);
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 === "claude" ? "Claude Code" : 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 === "claude" ? "Claude Code" : 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 $, SelectValue as $t, PermissionPrompt as A, Spinner as At, EntryIcon as B, DialogHeader as Bt, SessionInfoDialog as C, usePromptAreaState as Ct, QuestionPrompt as D, ProgressRing as Dt, QUESTION_BEHAVIORS as E, segmentsToPlainText as Et, permissionModeMeta as F, TooltipProvider as Ft, Composer as G, MenuItem as Gt, TaskList as H, DialogTrigger as Ht, ModelSelect as I, Dialog$1 as It, useToolTitle as J, Select$1 as Jt, TerminalSurface as K, MenuSeparator as Kt, SkillsDialog as L, DialogBody as Lt, PERMISSION_MODES as M, copyText as Mt, PermissionModeSelect as N, Tip as Nt, parseUserQuestions as O, Splitter as Ot, permissionModeChoices as P, TooltipContent as Pt, parseFileLink as Q, SelectTrigger as Qt, McpDialog as R, DialogClose as Rt, STATUS_META as S, mentionTrigger as St, TerminalPermissionPrompt as T, plainTextToSegments as Tt, ContextDialog as U, Menu$1 as Ut, TasksDialog as V, DialogRow as Vt, contextNote as W, MenuContent as Wt, FileLinkProvider as X, SelectItem as Xt, TerminalMarkdown as Y, SelectContent as Yt, useFileLinks as Z, SelectItemText as Zt, Loader as _, rankComposerRows as _t, UsageDialog as a, Button as an, CopyAction as at, ConversationScrollButton as b, hashtagTrigger as bt, Transcript as c, PromptTokenText as ct, Message as d, TranscriptDensityProvider as dt, PortalScope as en, previewPatch as et, MessageContent as f, TranscriptVariantProvider as ft, SessionEmptyState as g, mergeComposerRows as gt, TerminalTranscript as h, matchClientCommand as ht, SessionPanel as i, badgeVariants as in, Row as it, Response as j, CopyButton as jt, SubagentStrip as k, CodeBlock as kt, ToolCallCard as l, isMutatingTool as lt, TerminalItemView as m, useTranscriptVariant as mt, usePathLinks as n, Input as nn, Blank as nt, UsageMeters as o, buttonVariants as on, WithActions as ot, FileCard as p, useTranscriptDensity as pt, ToolTitleProvider as q, MenuTrigger as qt, matchPath as r, Badge as rn, Ink as rt, useMinuteClock as s, cn as sn, useAffordances as st, resolveAgainstCwd as t, Textarea as tn, Band as tt, Reasoning as u, toolIcon as ut, Conversation as v, skillPrompt as vt, TerminalQuestionPrompt as w, PromptArea as wt, StatusBar as x, launchTrigger as xt, ConversationContent as y, commandTrigger as yt, HostFilesDialog as z, DialogContent as zt };
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-CvcxdUXL.mjs.map
12571
+ //# sourceMappingURL=use-path-links-CepFsMdW.mjs.map