@mcp-b/react-components 0.24.0 → 0.25.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 (109) hide show
  1. package/dist/{AgentChat-Bm1qYbOo.d.ts → AgentChat-DHxdTjwF.d.ts} +34 -7
  2. package/dist/{CodeBlock-Cp67Njo3.js → CodeBlock-B3RLU3ez.js} +1 -1
  3. package/dist/{FileTree-DW60q1w7.js → FileTree-CYr5og0q.js} +1 -1
  4. package/dist/{Message-_-bEYLAO.js → Message-KlK8tlBZ.js} +1 -1
  5. package/dist/{ModelSelector-Brvj9Cab.js → ModelSelector-YTlqkIjs.js} +1 -1
  6. package/dist/{ThinkChat-E_HrfH76.js → ThinkChat-DVhCEjq-.js} +11 -2
  7. package/dist/{ThinkChatActivity-2BobmuvR.d.ts → ThinkChatActivity-DMTHKWrI.d.ts} +11 -9
  8. package/dist/{ThinkChatContext-DrsZqdaO.d.ts → ThinkChatContext-B-Nk84Wi.d.ts} +13 -1
  9. package/dist/{ThinkRecoveryNotice-DFIcG9UX.d.ts → ThinkRecoveryNotice-D6gYcBbr.d.ts} +1 -1
  10. package/dist/{WorkspaceFileView-rUEN2iox.js → WorkspaceFileView-CuMjXYQn.js} +3 -3
  11. package/dist/components/Activity.d.ts +11 -0
  12. package/dist/components/Activity.js +16 -4
  13. package/dist/components/AgentActivity.js +1 -1
  14. package/dist/components/AgentActivityPreview.js +1 -1
  15. package/dist/components/AgentChat.d.ts +1 -1
  16. package/dist/components/AgentChat.js +174 -94
  17. package/dist/components/AgentChatStartScreen.js +1 -1
  18. package/dist/components/AgentConnection.js +2 -2
  19. package/dist/components/AgentMessageParts.js +6 -2
  20. package/dist/components/AgentToolDetail.d.ts +1 -1
  21. package/dist/components/AgentToolDetail.js +2 -2
  22. package/dist/components/Approval.js +1 -1
  23. package/dist/components/Artifact.js +1 -1
  24. package/dist/components/BrowserLiveView.js +1 -1
  25. package/dist/components/BrowserReplay.js +1 -1
  26. package/dist/components/BrowserRunPanel.js +1 -1
  27. package/dist/components/ChainOfThought.d.ts +1 -1
  28. package/dist/components/ChainOfThought.js +1 -1
  29. package/dist/components/ChatGptSignInScreen.js +2 -2
  30. package/dist/components/Checkbox.js +1 -1
  31. package/dist/components/Checkpoint.js +1 -1
  32. package/dist/components/CodeBlock.js +1 -1
  33. package/dist/components/CodexModelSelector.js +1 -1
  34. package/dist/components/Commit.js +2 -2
  35. package/dist/components/ContextMenu.js +1 -1
  36. package/dist/components/Conversation.js +1 -1
  37. package/dist/components/EnvironmentVariables.js +2 -2
  38. package/dist/components/ExpansionState.d.ts +51 -0
  39. package/dist/components/ExpansionState.js +46 -0
  40. package/dist/components/FileTree.js +1 -1
  41. package/dist/components/Goal.d.ts +87 -0
  42. package/dist/components/Goal.js +92 -0
  43. package/dist/components/McpConnectionRequest.js +1 -1
  44. package/dist/components/McpPluginCatalog.js +1 -1
  45. package/dist/components/McpServerPicker.js +1 -1
  46. package/dist/components/MediaPreviewCard.js +13 -2
  47. package/dist/components/Menubar.js +1 -1
  48. package/dist/components/Message.js +1 -1
  49. package/dist/components/MessageScroller.js +1 -1
  50. package/dist/components/MessageScrollerVirtual.d.ts +72 -0
  51. package/dist/components/MessageScrollerVirtual.js +110 -0
  52. package/dist/components/ModelSelector.js +1 -1
  53. package/dist/components/Plan.js +1 -1
  54. package/dist/components/PricingPlanCard.js +1 -1
  55. package/dist/components/PromptInput.js +1 -1
  56. package/dist/components/Queue.js +1 -1
  57. package/dist/components/Reasoning.js +2 -2
  58. package/dist/components/ResponsiveSidebarShell.js +1 -1
  59. package/dist/components/SearchField.js +1 -1
  60. package/dist/components/Select.js +1 -1
  61. package/dist/components/SessionCompaction.d.ts +58 -0
  62. package/dist/components/SessionCompaction.js +117 -0
  63. package/dist/components/Sources.js +1 -1
  64. package/dist/components/Stepper.js +1 -1
  65. package/dist/components/SubagentRunIndicator.js +1 -1
  66. package/dist/components/Task.js +1 -1
  67. package/dist/components/Terminal.js +2 -2
  68. package/dist/components/TestResults.js +1 -1
  69. package/dist/components/ThemeModeControl.js +1 -1
  70. package/dist/components/ThinkChat.d.ts +6 -6
  71. package/dist/components/ThinkChat.js +1 -1
  72. package/dist/components/ThinkChatActivity.d.ts +1 -1
  73. package/dist/components/ThinkChatActivity.js +68 -14
  74. package/dist/components/ThinkChatContext.d.ts +2 -2
  75. package/dist/components/ThinkChatContext.js +5 -1
  76. package/dist/components/ThinkChatToolPanels.js +1 -1
  77. package/dist/components/ThinkExecutionDetail.js +1 -1
  78. package/dist/components/ThinkExecutionStatus.js +1 -1
  79. package/dist/components/ThinkExecutionWorkbench.d.ts +4 -3
  80. package/dist/components/ThinkExecutionWorkbench.js +7 -10
  81. package/dist/components/ThinkFullApp.js +65 -54
  82. package/dist/components/ThinkRecoveryNotice.d.ts +1 -1
  83. package/dist/components/ThinkRoutineBrowser.js +1 -1
  84. package/dist/components/ThinkRoutineForm.js +1 -1
  85. package/dist/components/ThinkRoutineLibrary.js +1 -1
  86. package/dist/components/ThinkThreadPicker.js +1 -1
  87. package/dist/components/Toast.js +1 -1
  88. package/dist/components/ToolInvocation.d.ts +8 -1
  89. package/dist/components/ToolInvocation.js +3 -2
  90. package/dist/components/WebPreview.js +1 -1
  91. package/dist/components/WorkspaceBrowser.js +1 -1
  92. package/dist/components/WorkspaceExplorer.js +1 -1
  93. package/dist/components/WorkspaceFileView.js +1 -1
  94. package/dist/components/WorkspaceHeader.js +1 -1
  95. package/dist/components/icons.d.ts +2 -2
  96. package/dist/components/icons.js +2 -2
  97. package/dist/{copy-button-TWq8nZhc.js → copy-button-Buxmtmp9.js} +1 -1
  98. package/dist/{icons-wP1yFUXF.d.ts → icons-Cih3W-zM.d.ts} +6 -1
  99. package/dist/{icons-ua6f_GH3.js → icons-w5PpKGRz.js} +3 -2
  100. package/dist/styles/activity.css +6 -0
  101. package/dist/styles/agent-chat.css +20 -4
  102. package/dist/styles/composition-motion.css +13 -23
  103. package/dist/styles/goal.css +57 -0
  104. package/dist/styles/index.css +1 -0
  105. package/dist/styles/message-scroller.css +25 -0
  106. package/dist/styles/responsive-sidebar-shell.css +12 -0
  107. package/dist/styles/think-full-app.css +22 -14
  108. package/package.json +7 -6
  109. package/dist/view-transitions-DyUP0lSg.js +0 -77
@@ -1,23 +1,24 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { B as PencilIcon, H as PlusIcon, L as MoveToFrontIcon, Q as TrashIcon, U as QueueIcon, W as RefreshIcon } from "../icons-ua6f_GH3.js";
3
+ import { ExpansionStateProvider } from "./ExpansionState.js";
4
+ import { $ as TrashIcon, B as PencilIcon, H as PlusIcon, L as MoveToFrontIcon, U as QueueIcon, W as RefreshIcon, t as ArchiveIcon } from "../icons-w5PpKGRz.js";
4
5
  import { IconButton } from "./IconButton.js";
5
- import { n as MessageAction, r as MessageActions, t as Message } from "../Message-_-bEYLAO.js";
6
+ import { n as MessageAction, r as MessageActions, t as Message } from "../Message-KlK8tlBZ.js";
6
7
  import { AgentMessageParts } from "./AgentMessageParts.js";
7
8
  import { Context, ContextContent, ContextContentBody, ContextContentHeader, ContextTrigger, getContextUsage, getContextUsedTokens } from "./Context.js";
8
9
  import { EmptyState } from "./EmptyState.js";
9
- import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport } from "./MessageScroller.js";
10
+ import { VirtualMessageScroller } from "./MessageScrollerVirtual.js";
10
11
  import { Menu } from "./Menu.js";
11
12
  import { PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuTrigger, PromptInputApproval, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputCommandComposer, PromptInputContextSelector, PromptInputDictation, PromptInputFooter, PromptInputHeader, PromptInputPermissionSelector, PromptInputReferences, PromptInputSubmit, PromptInputTextarea, PromptInputTools, PromptInputTray, getApprovalRequestId, getApprovalStateKey, getPendingToolApprovals, usePromptInputAttachments } from "./PromptInput.js";
12
13
  import { AgentChatStartScreen } from "./AgentChatStartScreen.js";
13
14
  import { AgentChatMessageEditor } from "./AgentChatMessageEditor.js";
14
15
  import { Marker, MarkerContent } from "./Marker.js";
15
16
  import { TransitionSurface } from "./TransitionSurface.js";
16
- import { t as CopyButton } from "../copy-button-TWq8nZhc.js";
17
+ import { t as CopyButton } from "../copy-button-Buxmtmp9.js";
17
18
  import * as React from "react";
18
19
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
19
20
  import { isCompactionMessage } from "agents/experimental/memory/utils";
20
- import { isReasoningUIPart, isTextUIPart } from "ai";
21
+ import { isTextUIPart } from "ai";
21
22
  //#region src/components/AgentChat.tsx
22
23
  /**
23
24
  * Agents exports this helper from `agents/sessions` after cloudflare/agents#1896;
@@ -27,6 +28,20 @@ import { isReasoningUIPart, isTextUIPart } from "ai";
27
28
  * the `SessionMessage` fields it reads, so use the upstream helper directly
28
29
  * instead of duplicating the prefix contract locally.
29
30
  */
31
+ /**
32
+ * Built-in `/compact` entry, present whenever `onCompact` is provided.
33
+ * Selection is intercepted in `selectComposerCommand` before any reference
34
+ * chip or host `onSelect` runs.
35
+ */
36
+ const COMPACT_SLASH_COMMAND = {
37
+ id: "agent-chat:compact",
38
+ value: "compact",
39
+ label: "compact",
40
+ description: "Summarize earlier messages to free up context",
41
+ icon: /* @__PURE__ */ jsx(ArchiveIcon, {}),
42
+ group: "Conversation",
43
+ meta: "Built in"
44
+ };
30
45
  function observeAgentChatComposer(element) {
31
46
  if (!element || typeof ResizeObserver === "undefined") return;
32
47
  const root = element.parentElement;
@@ -86,9 +101,6 @@ function AgentChatSubmitAction({ status, onStop, disabled, hasDraft }) {
86
101
  disabled
87
102
  });
88
103
  }
89
- function getMessageText(message) {
90
- return message.parts.filter((part) => isTextUIPart(part) || isReasoningUIPart(part)).map((part) => part.text).join("");
91
- }
92
104
  function getCopyableResponseText(message) {
93
105
  return message.parts.filter(isTextUIPart).map((part) => part.text).join("\n\n").trim() || void 0;
94
106
  }
@@ -119,11 +131,86 @@ function getEditableUserText(message) {
119
131
  return isTextUIPart(part) && part.text.trim() ? part.text : void 0;
120
132
  }
121
133
  /**
134
+ * One transcript row's content, memoized so a streaming delta re-renders only
135
+ * the rows whose props changed — in practice the live message. This only
136
+ * holds up if the host keeps unchanged message objects and render callbacks
137
+ * referentially stable across updates (AI SDK chat state does); see
138
+ * "Transcript rendering performance" in docs/think-chat.md.
139
+ */
140
+ function AgentChatTranscriptRowBodyImpl({ message, messageIndex, status, renderPart, renderMessageAfter, editing, canEdit, onEditAndResend, onStartEdit, onCancelEdit, onFinishEdit, editButtonRef, responseNumber, showAssistantActions, showCopy, showRetry, onRegenerate, onCopyStatus }) {
141
+ return /* @__PURE__ */ jsx(Fragment, { children: isCompactionMessage(message) ? /* @__PURE__ */ jsx(Marker, {
142
+ variant: "separator",
143
+ children: /* @__PURE__ */ jsx(MarkerContent, { children: "Context compacted" })
144
+ }) : /* @__PURE__ */ jsx(Message, {
145
+ from: message.role,
146
+ children: editing && onEditAndResend ? /* @__PURE__ */ jsx(AgentChatMessageEditor, {
147
+ message,
148
+ originalText: getEditableUserText(message) ?? "",
149
+ onSubmit: onEditAndResend,
150
+ onCancel: onCancelEdit,
151
+ onSuccess: onFinishEdit
152
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [
153
+ /* @__PURE__ */ jsx(AgentMessageParts, {
154
+ message,
155
+ status,
156
+ renderPart
157
+ }),
158
+ renderMessageAfter?.({
159
+ message,
160
+ messageIndex
161
+ }),
162
+ canEdit && getEditableUserText(message) !== void 0 ? /* @__PURE__ */ jsx(MessageActions, {
163
+ "aria-label": "Message actions",
164
+ children: /* @__PURE__ */ jsx(MessageAction, {
165
+ ref: editButtonRef,
166
+ label: "Edit message",
167
+ tooltip: "Edit and resend",
168
+ onClick: () => onStartEdit(message.id),
169
+ children: /* @__PURE__ */ jsx(PencilIcon, {})
170
+ })
171
+ }) : null,
172
+ showAssistantActions ? /* @__PURE__ */ jsx(AgentChatAssistantActions, {
173
+ message,
174
+ responseNumber,
175
+ showCopy,
176
+ showRetry,
177
+ onRegenerate,
178
+ onCopyStatus
179
+ }) : null
180
+ ] })
181
+ }) });
182
+ }
183
+ const AgentChatTranscriptRowBody = React.memo(AgentChatTranscriptRowBodyImpl);
184
+ /**
122
185
  * Low-level transcript/composer surface used by `ThinkChat`: props in, no
123
186
  * transport. Product code that talks to a Cloudflare Think agent should render
124
187
  * `ThinkChat`; use this directly only for plain AI SDK or read-only messages.
188
+ *
189
+ * The transcript is always windowed with TanStack Virtual (end-anchored,
190
+ * follow-on-append): only the visible rows exist in the DOM, so hours-long
191
+ * runs stay cheap. Consequences and the host-side contract:
192
+ * - Every message needs a stable `id`; keys must survive prepends and stream
193
+ * growth.
194
+ * - Keep unchanged message objects referentially stable across updates.
195
+ * Structured-cloning the array per delta over a worker/extension boundary
196
+ * rebuilds every identity and defeats row memoization — clone once per
197
+ * throttled batch instead.
198
+ * - Throttle stream deltas before React state (AI SDK
199
+ * `experimental_throttle: 50` or equivalent).
200
+ * - Bound the data itself: windowing caps DOM size, not JS memory. Truncate
201
+ * stored tool output at the buffer (~20k chars) and keep history
202
+ * compaction on.
203
+ * - Unmount the transcript to hide it; don't `display: none` it — hidden
204
+ * rows measure 0 and corrupt the virtualizer's cached heights.
205
+ * - Rows unmount off-screen: find-in-page only searches the window;
206
+ * disclosure state persists via the built-in `ExpansionStateProvider`
207
+ * (pass your own store via a wrapper to survive route remounts), but the
208
+ * default `Reasoning` disclosure resets.
209
+ * - The transcript is not a screen-reader live region (windowing would
210
+ * announce re-inserted old rows as new); announce new messages from a
211
+ * host-owned live region if that matters.
125
212
  */
126
- function AgentChat({ className, messages, status = "ready", onSubmit, showComposer = onSubmit !== void 0, onStop, placeholder = "Ask anything...", disabled, emptyState, startScreen, composerHeader, composerTools, slashCommands, mentionCommands, contextSelector, composerEndTools, voiceInput, beforeVoiceStart, composerAddMenuItems, notice, onRegenerate, onEditAndResend, onApprovalResponse, thinkStub, approvalsEnabled = true, permissionModeControl, onExecutionSettled, pendingApprovals: durableApprovals = EMPTY_PENDING_APPROVALS, contextWindow, renderPart, renderMessageAfter, showAssistantActions, isMessageScrollAnchor, ref }) {
213
+ function AgentChat({ className, messages, status = "ready", onSubmit, showComposer = onSubmit !== void 0, onStop, placeholder = "Ask anything...", disabled, emptyState, startScreen, composerHeader, composerTools, slashCommands, onCompact, mentionCommands, contextSelector, composerEndTools, voiceInput, beforeVoiceStart, composerAddMenuItems, notice, onRegenerate, onEditAndResend, onApprovalResponse, thinkStub, approvalsEnabled = true, permissionModeControl, onExecutionSettled, pendingApprovals: durableApprovals = EMPTY_PENDING_APPROVALS, contextWindow, renderPart, renderMessageAfter, showAssistantActions, ref }) {
127
214
  const [copyAnnouncement, setCopyAnnouncement] = React.useState("");
128
215
  const [composerDraft, setComposerDraft] = React.useState("");
129
216
  const [composerReferences, setComposerReferences] = React.useState([]);
@@ -178,7 +265,23 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
178
265
  onSubmit,
179
266
  pendingPrompts
180
267
  ]);
268
+ const [compactionNotice, setCompactionNotice] = React.useState(null);
269
+ const compactionInFlight = React.useRef(false);
181
270
  const selectComposerCommand = React.useCallback((command, trigger) => {
271
+ if (trigger === "/" && onCompact && command.id === COMPACT_SLASH_COMMAND.id) {
272
+ if (compactionInFlight.current) return;
273
+ compactionInFlight.current = true;
274
+ setCompactionNotice(null);
275
+ setComposerDraft("");
276
+ onCompact().then(() => {
277
+ compactionInFlight.current = false;
278
+ }, (error) => {
279
+ compactionInFlight.current = false;
280
+ console.warn("Manual compaction failed", error);
281
+ setCompactionNotice("Compaction failed — run /compact to try again.");
282
+ });
283
+ return;
284
+ }
182
285
  const reference = {
183
286
  id: command.id,
184
287
  value: command.value,
@@ -203,6 +306,7 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
203
306
  composerDraft,
204
307
  composerReferences,
205
308
  mentionCommands,
309
+ onCompact,
206
310
  removeComposerReference,
207
311
  slashCommands
208
312
  ]);
@@ -290,6 +394,18 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
290
394
  const [editingMessageId, setEditingMessageId] = React.useState();
291
395
  const restoreEditFocus = React.useRef(false);
292
396
  const editButtonRef = React.useRef(null);
397
+ const handleStartEdit = React.useCallback((messageId) => {
398
+ restoreEditFocus.current = false;
399
+ setEditingMessageId(messageId);
400
+ }, []);
401
+ const handleCancelEdit = React.useCallback(() => {
402
+ restoreEditFocus.current = true;
403
+ setEditingMessageId(void 0);
404
+ }, []);
405
+ const handleFinishEdit = React.useCallback(() => {
406
+ restoreEditFocus.current = false;
407
+ setEditingMessageId(void 0);
408
+ }, []);
293
409
  let assistantResponseCount = 0;
294
410
  const assistantResponseNumbers = messages.map((message) => {
295
411
  if (message.role !== "assistant" || isCompactionMessage(message)) return 0;
@@ -301,15 +417,38 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
301
417
  editButtonRef.current?.focus();
302
418
  restoreEditFocus.current = false;
303
419
  }, [editingMessageId]);
420
+ const transcriptRowProps = (message, messageIndex) => ({
421
+ message,
422
+ messageIndex,
423
+ status: messageIndex === messages.length - 1 ? status : "ready",
424
+ renderPart,
425
+ renderMessageAfter,
426
+ editing: editingMessageId === message.id,
427
+ canEdit: messageIndex === lastUserIndex,
428
+ onEditAndResend,
429
+ onStartEdit: handleStartEdit,
430
+ onCancelEdit: handleCancelEdit,
431
+ onFinishEdit: handleFinishEdit,
432
+ editButtonRef,
433
+ responseNumber: assistantResponseNumbers[messageIndex] ?? 0,
434
+ showAssistantActions: message.role === "assistant" && (showAssistantActions?.({
435
+ message,
436
+ messageIndex
437
+ }) ?? true),
438
+ showCopy: messageIndex !== newestAssistantIndex || status !== "streaming" && status !== "submitted",
439
+ showRetry: messageIndex === lastAssistantIndex,
440
+ onRegenerate,
441
+ onCopyStatus: announceCopyStatus
442
+ });
304
443
  const composer = showComposer ? /* @__PURE__ */ jsxs("div", {
305
444
  ref: observeAgentChatComposer,
306
445
  className: "agent-chat__composer",
307
446
  children: [
308
- /* @__PURE__ */ jsx("div", {
447
+ /* @__PURE__ */ jsxs("div", {
309
448
  className: "agent-chat__notice",
310
449
  role: "status",
311
450
  "aria-atomic": "true",
312
- children: notice
451
+ children: [notice, compactionNotice]
313
452
  }),
314
453
  pendingPrompts.length ? /* @__PURE__ */ jsx(PromptInputTray, {
315
454
  side: "top",
@@ -378,11 +517,11 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
378
517
  /* @__PURE__ */ jsxs(PromptInputBody, { children: [/* @__PURE__ */ jsx(PromptInputReferences, {
379
518
  references: composerReferences,
380
519
  onRemove: removeComposerReference
381
- }), slashCommands || mentionCommands ? /* @__PURE__ */ jsx(PromptInputCommandComposer, {
520
+ }), slashCommands || mentionCommands || onCompact ? /* @__PURE__ */ jsx(PromptInputCommandComposer, {
382
521
  "aria-label": "Message",
383
522
  placeholder: composerReferences.length ? "" : placeholder,
384
523
  disabled,
385
- commands: slashCommands?.items ?? [],
524
+ commands: onCompact ? [COMPACT_SLASH_COMMAND, ...slashCommands?.items ?? []] : slashCommands?.items ?? [],
386
525
  mentionCommands: mentionCommands?.items,
387
526
  value: composerDraft,
388
527
  onValueChange: setComposerDraft,
@@ -430,6 +569,10 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
430
569
  })
431
570
  ]
432
571
  }) : null;
572
+ const emptyRow = emptyState ?? /* @__PURE__ */ jsx(EmptyState, {
573
+ title: "Start a conversation",
574
+ description: "Ask the agent to inspect, plan, or build."
575
+ });
433
576
  const showsStartScreen = messages.length === 0 && showComposer && startScreen !== false && (startScreen !== void 0 || emptyState === void 0);
434
577
  const startScreenProps = startScreen && typeof startScreen === "object" ? startScreen : void 0;
435
578
  return /* @__PURE__ */ jsxs(TransitionSurface, {
@@ -447,87 +590,24 @@ function AgentChat({ className, messages, status = "ready", onSubmit, showCompos
447
590
  showsStartScreen ? /* @__PURE__ */ jsx(AgentChatStartScreen, {
448
591
  ...startScreenProps,
449
592
  composer
450
- }) : /* @__PURE__ */ jsx(MessageScrollerProvider, {
451
- autoScroll: true,
452
- defaultScrollPosition: "last-anchor",
453
- children: /* @__PURE__ */ jsxs(MessageScroller, {
454
- className: "agent-chat__conversation",
455
- children: [/* @__PURE__ */ jsx(MessageScrollerViewport, { children: /* @__PURE__ */ jsxs(MessageScrollerContent, {
456
- "aria-busy": status === "streaming" || status === "submitted",
457
- className: "agent-chat__transcript-content",
458
- children: [messages.length === 0 ? /* @__PURE__ */ jsx(MessageScrollerItem, {
459
- className: "conversation__empty-row",
460
- children: emptyState ?? /* @__PURE__ */ jsx(EmptyState, {
461
- title: "Start a conversation",
462
- description: "Ask the agent to inspect, plan, or build."
463
- })
464
- }) : null, messages.map((message, messageIndex) => /* @__PURE__ */ jsx(MessageScrollerItem, {
465
- messageId: message.id,
466
- scrollAnchor: isMessageScrollAnchor?.({
467
- message,
468
- messageIndex
469
- }) ?? message.role === "user",
470
- children: isCompactionMessage(message) ? /* @__PURE__ */ jsx(Marker, {
471
- variant: "separator",
472
- children: /* @__PURE__ */ jsx(MarkerContent, { children: getMessageText(message) || "Conversation compacted" })
473
- }) : /* @__PURE__ */ jsx(Message, {
474
- from: message.role,
475
- children: editingMessageId === message.id && onEditAndResend ? /* @__PURE__ */ jsx(AgentChatMessageEditor, {
476
- message,
477
- originalText: getEditableUserText(message) ?? "",
478
- onSubmit: onEditAndResend,
479
- onCancel: () => {
480
- restoreEditFocus.current = true;
481
- setEditingMessageId(void 0);
482
- },
483
- onSuccess: () => {
484
- restoreEditFocus.current = false;
485
- setEditingMessageId(void 0);
486
- }
487
- }, message.id) : /* @__PURE__ */ jsxs(Fragment, { children: [
488
- /* @__PURE__ */ jsx(AgentMessageParts, {
489
- message,
490
- status: messageIndex === messages.length - 1 ? status : "ready",
491
- renderPart
492
- }),
493
- renderMessageAfter?.({
494
- message,
495
- messageIndex
496
- }),
497
- onEditAndResend && messageIndex === lastUserIndex && getEditableUserText(message) !== void 0 ? /* @__PURE__ */ jsx(MessageActions, {
498
- "aria-label": "Message actions",
499
- children: /* @__PURE__ */ jsx(MessageAction, {
500
- ref: editButtonRef,
501
- label: "Edit message",
502
- tooltip: "Edit and resend",
503
- onClick: () => {
504
- restoreEditFocus.current = false;
505
- setEditingMessageId(message.id);
506
- },
507
- children: /* @__PURE__ */ jsx(PencilIcon, {})
508
- })
509
- }) : null,
510
- message.role === "assistant" && (showAssistantActions?.({
511
- message,
512
- messageIndex
513
- }) ?? true) ? /* @__PURE__ */ jsx(AgentChatAssistantActions, {
514
- message,
515
- responseNumber: assistantResponseNumbers[messageIndex],
516
- showCopy: messageIndex !== newestAssistantIndex || status !== "streaming" && status !== "submitted",
517
- showRetry: messageIndex === lastAssistantIndex,
518
- onRegenerate,
519
- onCopyStatus: announceCopyStatus
520
- }) : null
521
- ] })
522
- })
523
- }, message.id ?? messageIndex))]
524
- }) }), /* @__PURE__ */ jsx(MessageScrollerButton, {
525
- "aria-label": "Scroll to latest",
526
- className: "agent-chat__scroll-button",
527
- size: "sm"
528
- })]
529
- })
530
- }),
593
+ }) : /* @__PURE__ */ jsx(ExpansionStateProvider, { children: /* @__PURE__ */ jsx(VirtualMessageScroller, {
594
+ className: "agent-chat__conversation",
595
+ items: messages,
596
+ getItemKey: (message) => message.id,
597
+ emptyState: /* @__PURE__ */ jsx("div", {
598
+ className: "conversation__empty-row",
599
+ children: emptyRow
600
+ }),
601
+ contentProps: {
602
+ role: "log",
603
+ "aria-live": "off",
604
+ "aria-busy": status === "streaming" || status === "submitted",
605
+ className: "agent-chat__transcript-content"
606
+ },
607
+ scrollButtonLabel: "Scroll to latest",
608
+ scrollButtonProps: { className: "agent-chat__scroll-button" },
609
+ renderItem: (message, messageIndex) => /* @__PURE__ */ jsx(AgentChatTranscriptRowBody, { ...transcriptRowProps(message, messageIndex) })
610
+ }) }),
531
611
  showsStartScreen ? null : composer
532
612
  ]
533
613
  });
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { tt as XIcon } from "../icons-ua6f_GH3.js";
3
+ import { nt as XIcon } from "../icons-w5PpKGRz.js";
4
4
  import { IconButton } from "./IconButton.js";
5
5
  import { PromptInputTray } from "./PromptInput.js";
6
6
  import * as React from "react";
@@ -1,10 +1,10 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { k as LinkIcon } from "../icons-ua6f_GH3.js";
3
+ import { k as LinkIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Popover } from "./Popover.js";
5
5
  import { Field } from "./Field.js";
6
6
  import { Form } from "./Form.js";
7
- import { a as CodeBlockCopyButton, i as CodeBlockContent, n as CodeBlockActions, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock } from "../CodeBlock-Cp67Njo3.js";
7
+ import { a as CodeBlockCopyButton, i as CodeBlockContent, n as CodeBlockActions, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock } from "../CodeBlock-B3RLU3ez.js";
8
8
  import { CUSTOM_MCP_SERVER_CARD } from "../utils/mcp-server-catalog.js";
9
9
  import * as React from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,6 +1,7 @@
1
- import { d as MessageContent, f as MessageResponse, i as MessageAttachment } from "../Message-_-bEYLAO.js";
1
+ import { d as MessageContent, f as MessageResponse, i as MessageAttachment } from "../Message-KlK8tlBZ.js";
2
2
  import { Reasoning, ReasoningContent, ReasoningTrigger } from "./Reasoning.js";
3
3
  import { Source, Sources, SourcesContent, SourcesTrigger } from "./Sources.js";
4
+ import { isToolPartWorking } from "./ThinkChatToolParts.js";
4
5
  import { ToolInvocation } from "./ToolInvocation.js";
5
6
  import "react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -85,7 +86,10 @@ function renderDefaultPart(message, part, partIndex, status) {
85
86
  children: [/* @__PURE__ */ jsx(ReasoningTrigger, {}), /* @__PURE__ */ jsx(ReasoningContent, { children: reasoningText })]
86
87
  });
87
88
  }
88
- if (isToolUIPart(part)) return /* @__PURE__ */ jsx(ToolInvocation, { part });
89
+ if (isToolUIPart(part)) return /* @__PURE__ */ jsx(ToolInvocation, {
90
+ part,
91
+ isStreaming: (status === "streaming" || status === "submitted") && isToolPartWorking(part)
92
+ });
89
93
  return null;
90
94
  }
91
95
  /**
@@ -1,4 +1,4 @@
1
- import { n as ThinkChatValue } from "../ThinkChatContext-DrsZqdaO.js";
1
+ import { i as ThinkChatValue } from "../ThinkChatContext-B-Nk84Wi.js";
2
2
  import { ThinkChatMessagesProps } from "./ThinkChat.js";
3
3
  import { t as ThinkAgent } from "../think-agent-Cip5KAPj.js";
4
4
  import * as React from "react";
@@ -1,11 +1,11 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { r as ArrowLeftIcon } from "../icons-ua6f_GH3.js";
2
+ import { r as ArrowLeftIcon } from "../icons-w5PpKGRz.js";
3
3
  import { TransitionSurface } from "./TransitionSurface.js";
4
4
  import { AppTopBar } from "./AppTopBar.js";
5
5
  import { NaniteMark } from "./NaniteScene.js";
6
6
  import { SubagentRunIndicator, getSubagentRunName } from "./SubagentRunIndicator.js";
7
7
  import { SubagentRunMilestone, SubagentRunMilestones, SubagentRunProgress } from "./SubagentRunDetails.js";
8
- import { t as ThinkChat } from "../ThinkChat-E_HrfH76.js";
8
+ import { t as ThinkChat } from "../ThinkChat-DVhCEjq-.js";
9
9
  import * as React from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  import { useAgentChat } from "@cloudflare/think/react";
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { B as PencilIcon } from "../icons-ua6f_GH3.js";
3
+ import { B as PencilIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Kbd } from "./Kbd.js";
5
5
  import * as React from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { tt as XIcon } from "../icons-ua6f_GH3.js";
2
+ import { nt as XIcon } from "../icons-w5PpKGRz.js";
3
3
  import { IconButton } from "./IconButton.js";
4
4
  import "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { A as MaximizeIcon, q as SpinnerIcon } from "../icons-ua6f_GH3.js";
3
+ import { A as MaximizeIcon, q as SpinnerIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Dialog } from "./Dialog.js";
5
5
  import { TransitionSurface } from "./TransitionSurface.js";
6
6
  import { StatusPill } from "./StatusPill.js";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { V as PlayIcon, z as PauseIcon } from "../icons-ua6f_GH3.js";
2
+ import { V as PlayIcon, z as PauseIcon } from "../icons-w5PpKGRz.js";
3
3
  import { IconButton } from "./IconButton.js";
4
4
  import { r as formatClock } from "../format-S6uWyoSb.js";
5
5
  import { EmptyState } from "./EmptyState.js";
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { q as SpinnerIcon, tt as XIcon } from "../icons-ua6f_GH3.js";
3
+ import { nt as XIcon, q as SpinnerIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Tabs } from "./Tabs.js";
5
5
  import { BrowserLiveView } from "./BrowserLiveView.js";
6
6
  import { WebPreview, WebPreviewNavigation, WebPreviewNavigationButton, WebPreviewUrl } from "./WebPreview.js";
@@ -1,5 +1,5 @@
1
1
  import { t as Collapsible } from "../Collapsible-N64ASIQr.js";
2
- import { O as IconProps } from "../icons-wP1yFUXF.js";
2
+ import { O as IconProps } from "../icons-Cih3W-zM.js";
3
3
  import * as React from "react";
4
4
 
5
5
  //#region src/components/ChainOfThought.d.ts
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Collapsible } from "./Collapsible.js";
3
- import { d as CheckIcon, m as ChevronRightIcon, q as SpinnerIcon, v as DotIcon } from "../icons-ua6f_GH3.js";
3
+ import { d as CheckIcon, m as ChevronRightIcon, q as SpinnerIcon, v as DotIcon } from "../icons-w5PpKGRz.js";
4
4
  import "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/ChainOfThought.tsx
@@ -1,7 +1,7 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Button } from "./Button.js";
3
- import { q as SpinnerIcon } from "../icons-ua6f_GH3.js";
4
- import { u as ModelSelectorLogo } from "../ModelSelector-Brvj9Cab.js";
3
+ import { q as SpinnerIcon } from "../icons-w5PpKGRz.js";
4
+ import { u as ModelSelectorLogo } from "../ModelSelector-YTlqkIjs.js";
5
5
  import "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/components/ChatGptSignInScreen.tsx
@@ -1,5 +1,5 @@
1
1
  import { n as mergeBaseClassName } from "../class-names-BiMDVpUo.js";
2
- import { d as CheckIcon } from "../icons-ua6f_GH3.js";
2
+ import { d as CheckIcon } from "../icons-w5PpKGRz.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox";
5
5
  //#region src/components/Checkbox.tsx
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { s as BookmarkIcon } from "../icons-ua6f_GH3.js";
2
+ import { s as BookmarkIcon } from "../icons-w5PpKGRz.js";
3
3
  import { Marker, MarkerIcon } from "./Marker.js";
4
4
  import "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -1,2 +1,2 @@
1
- import { a as CodeBlockCopyButton, c as CodeBlockLanguageSelector, d as CodeBlockLanguageSelectorTrigger, f as CodeBlockLanguageSelectorValue, h as CODE_BLOCK_LANGUAGES, i as CodeBlockContent, l as CodeBlockLanguageSelectorContent, m as highlightCode, n as CodeBlockActions, o as CodeBlockFilename, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock, u as CodeBlockLanguageSelectorItem } from "../CodeBlock-Cp67Njo3.js";
1
+ import { a as CodeBlockCopyButton, c as CodeBlockLanguageSelector, d as CodeBlockLanguageSelectorTrigger, f as CodeBlockLanguageSelectorValue, h as CODE_BLOCK_LANGUAGES, i as CodeBlockContent, l as CodeBlockLanguageSelectorContent, m as highlightCode, n as CodeBlockActions, o as CodeBlockFilename, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock, u as CodeBlockLanguageSelectorItem } from "../CodeBlock-B3RLU3ez.js";
2
2
  export { CODE_BLOCK_LANGUAGES, CodeBlock, CodeBlockActions, CodeBlockContainer, CodeBlockContent, CodeBlockCopyButton, CodeBlockFilename, CodeBlockHeader, CodeBlockLanguageSelector, CodeBlockLanguageSelectorContent, CodeBlockLanguageSelectorItem, CodeBlockLanguageSelectorTrigger, CodeBlockLanguageSelectorValue, CodeBlockTitle, highlightCode };
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { W as RefreshIcon, d as CheckIcon, f as ChevronDownIcon, l as BrainIcon, m as ChevronRightIcon } from "../icons-ua6f_GH3.js";
2
+ import { W as RefreshIcon, d as CheckIcon, f as ChevronDownIcon, l as BrainIcon, m as ChevronRightIcon } from "../icons-w5PpKGRz.js";
3
3
  import { Tooltip } from "./Tooltip.js";
4
4
  import { i as titleCase } from "../format-S6uWyoSb.js";
5
5
  import { Menu } from "./Menu.js";
@@ -1,8 +1,8 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Collapsible } from "./Collapsible.js";
3
- import { C as FileIcon, m as ChevronRightIcon } from "../icons-ua6f_GH3.js";
3
+ import { C as FileIcon, m as ChevronRightIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Avatar } from "./Avatar.js";
5
- import { t as CopyButton } from "../copy-button-TWq8nZhc.js";
5
+ import { t as CopyButton } from "../copy-button-Buxmtmp9.js";
6
6
  import { Badge } from "./Badge.js";
7
7
  import "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  import { n as mergeBaseClassName, t as cx } from "../class-names-BiMDVpUo.js";
2
- import { d as CheckIcon, v as DotIcon } from "../icons-ua6f_GH3.js";
2
+ import { d as CheckIcon, v as DotIcon } from "../icons-w5PpKGRz.js";
3
3
  import "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { n as ArrowDownIcon, y as DownloadIcon } from "../icons-ua6f_GH3.js";
2
+ import { n as ArrowDownIcon, y as DownloadIcon } from "../icons-w5PpKGRz.js";
3
3
  import { IconButton } from "./IconButton.js";
4
4
  import { t as assignRef } from "../merge-refs-DF_7w2x_.js";
5
5
  import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport } from "./MessageScroller.js";
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { S as EyeOffIcon, x as EyeIcon } from "../icons-ua6f_GH3.js";
3
- import { t as CopyButton } from "../copy-button-TWq8nZhc.js";
2
+ import { S as EyeOffIcon, x as EyeIcon } from "../icons-w5PpKGRz.js";
3
+ import { t as CopyButton } from "../copy-button-Buxmtmp9.js";
4
4
  import { Badge } from "./Badge.js";
5
5
  import { Switch } from "./Switch.js";
6
6
  import * as React from "react";
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/components/ExpansionState.d.ts
4
+ /**
5
+ * Disclosure open states keyed by stable transcript ids, held outside the
6
+ * rows so a virtualized transcript can unmount a row and restore its
7
+ * disclosures when it scrolls back into view.
8
+ */
9
+ interface ExpansionStore {
10
+ get(key: string): boolean | undefined;
11
+ set(key: string, open: boolean): void;
12
+ }
13
+ /** Plain Map-backed store. Create one per conversation/thread. */
14
+ declare function createExpansionStore(): ExpansionStore;
15
+ interface ExpansionStateProviderProps {
16
+ /**
17
+ * Store to record disclosure state in. Omit to scope persistence to this
18
+ * provider's lifetime — enough for scrolling within a mounted transcript.
19
+ *
20
+ * Host-side note: pass your own `createExpansionStore()` instance held
21
+ * above the route (module scope, a ref in a layout component, or keyed by
22
+ * conversation id) when transcripts should keep their expanded disclosures
23
+ * across route navigation or panel remounts. The store is a plain Map —
24
+ * drop it when the conversation is discarded so it doesn't accumulate keys
25
+ * for messages that no longer exist.
26
+ */
27
+ store?: ExpansionStore;
28
+ children: React.ReactNode;
29
+ }
30
+ /**
31
+ * Provides the expansion store that `Activity`, `ActivityItemGroup`, and
32
+ * `ToolInvocation` write through when given a `stateKey`. (`Reasoning` is the
33
+ * deliberate exception — it keeps its own auto-open/auto-close streaming
34
+ * state and resets on remount.) `AgentChat` renders one around its transcript
35
+ * automatically; wrap it yourself (with an app-held `store`) to persist
36
+ * across remounts. A provider without an explicit `store` defers to an
37
+ * enclosing one, so AgentChat's built-in provider never shadows a host's.
38
+ */
39
+ declare function ExpansionStateProvider({
40
+ store,
41
+ children
42
+ }: ExpansionStateProviderProps): React.JSX.Element;
43
+ /**
44
+ * Open state initialized from the surrounding store (falling back to
45
+ * `defaultOpen`) and written through on every change. Only the mounted row
46
+ * reads a given key, so there is no subscription — remounting re-reads the
47
+ * store. Without a provider or a `stateKey` this is plain local state.
48
+ */
49
+ declare function useExpansionState(stateKey: string | undefined, defaultOpen: boolean): [boolean, (open: boolean) => void];
50
+ //#endregion
51
+ export { ExpansionStateProvider, ExpansionStateProviderProps, ExpansionStore, createExpansionStore, useExpansionState };