@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
@@ -0,0 +1,117 @@
1
+ import * as React from "react";
2
+ //#region src/components/SessionCompaction.ts
3
+ /**
4
+ * Client-side session-compaction plumbing for Think conversations.
5
+ *
6
+ * The Agents Session broadcasts `cf_agent_session` status frames to every
7
+ * connected client: `phase` flips to `"compacting"` while a compaction runs
8
+ * and back to `"idle"` when it settles, with a `compacted` payload on the
9
+ * idle frame when an overlay was actually written. Think refreshes only its
10
+ * server-side message cache after a compaction (`_syncMessages()` does not
11
+ * push to clients), so a connected transcript keeps showing the uncompacted
12
+ * history until its next `getMessages()`. `useSessionCompaction` closes that
13
+ * gap: it tracks the live phase for a "Compacting context…" affordance and
14
+ * reloads the transcript once a compaction lands — deferring the reload to
15
+ * the end of the turn when one is streaming, so a mid-turn proactive
16
+ * compaction never clobbers streamed state.
17
+ *
18
+ * The composer half is AgentChat's built-in `/compact` entry: pass the
19
+ * app's compaction callable as its `onCompact` prop.
20
+ *
21
+ * This module is the "local adapter … documented runtime-only mirror" that
22
+ * docs/think-session-ui.md calls for: upstream exports no payload types or
23
+ * client hook for these frames. The doc records the complete frame shapes
24
+ * (including `tokenEstimate` and `tokenThreshold`); this adapter deliberately
25
+ * consumes only `phase`, the presence of `compacted`, and the error string of
26
+ * `cf_agent_session_error` so an upstream field change cannot break the UI.
27
+ * Per that doc,
28
+ * `tokenThreshold` is the auto-compaction threshold, not the model context
29
+ * window — never feed it to the `Context` ring.
30
+ *
31
+ * @see ../../docs/think-session-ui.md
32
+ * @see https://github.com/cloudflare/agents/blob/main/docs/agents/sessions.md#compaction
33
+ */
34
+ /**
35
+ * Parse a raw websocket payload as a `cf_agent_session` status frame.
36
+ * Returns null for every other frame on the connection.
37
+ */
38
+ function parseSessionStatusFrame(data) {
39
+ if (typeof data !== "string") return null;
40
+ let message;
41
+ try {
42
+ message = JSON.parse(data);
43
+ } catch {
44
+ return null;
45
+ }
46
+ if (typeof message !== "object" || message === null || !("type" in message) || message.type !== "cf_agent_session" || !("phase" in message) || message.phase !== "idle" && message.phase !== "compacting") return null;
47
+ return {
48
+ phase: message.phase,
49
+ compacted: "compacted" in message && message.compacted != null
50
+ };
51
+ }
52
+ /**
53
+ * Parse a raw websocket payload as a `cf_agent_session_error` frame,
54
+ * returning its error text. Null for every other frame on the connection.
55
+ */
56
+ function parseSessionErrorFrame(data) {
57
+ if (typeof data !== "string") return null;
58
+ let message;
59
+ try {
60
+ message = JSON.parse(data);
61
+ } catch {
62
+ return null;
63
+ }
64
+ if (typeof message !== "object" || message === null || !("type" in message) || message.type !== "cf_agent_session_error" || !("error" in message) || typeof message.error !== "string") return null;
65
+ return message.error;
66
+ }
67
+ function useSessionCompaction({ agent, chat, getMessages }) {
68
+ const [compacting, setCompacting] = React.useState(false);
69
+ const [refreshPending, setRefreshPending] = React.useState(false);
70
+ const [reloadError, setReloadError] = React.useState(null);
71
+ const [sessionError, setSessionError] = React.useState(null);
72
+ React.useEffect(() => {
73
+ setCompacting(false);
74
+ setSessionError(null);
75
+ const onMessage = (event) => {
76
+ const frame = parseSessionStatusFrame(event.data);
77
+ if (frame) {
78
+ setCompacting(frame.phase === "compacting");
79
+ if (frame.phase === "compacting") setSessionError(null);
80
+ if (frame.compacted) setRefreshPending(true);
81
+ return;
82
+ }
83
+ const error = parseSessionErrorFrame(event.data);
84
+ if (error !== null) {
85
+ setCompacting(false);
86
+ setSessionError(error);
87
+ }
88
+ };
89
+ agent.addEventListener("message", onMessage);
90
+ return () => agent.removeEventListener("message", onMessage);
91
+ }, [agent]);
92
+ const { status, setMessages } = chat;
93
+ React.useEffect(() => {
94
+ if (!refreshPending || status !== "ready") return;
95
+ let stale = false;
96
+ getMessages().then((messages) => {
97
+ if (stale) return;
98
+ setRefreshPending(false);
99
+ setReloadError(null);
100
+ setMessages(messages);
101
+ }, (error) => {
102
+ if (stale) return;
103
+ console.error("Transcript reload after compaction failed", error);
104
+ setReloadError(error);
105
+ });
106
+ return () => {
107
+ stale = true;
108
+ };
109
+ }, [refreshPending, status]);
110
+ return {
111
+ compacting,
112
+ reloadError,
113
+ sessionError
114
+ };
115
+ }
116
+ //#endregion
117
+ export { parseSessionErrorFrame, parseSessionStatusFrame, useSessionCompaction };
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Collapsible } from "./Collapsible.js";
3
- import { k as LinkIcon, m as ChevronRightIcon } from "../icons-ua6f_GH3.js";
3
+ import { k as LinkIcon, m as ChevronRightIcon } from "../icons-w5PpKGRz.js";
4
4
  import "react";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/Sources.tsx
@@ -1,5 +1,5 @@
1
1
  import { n as mergeBaseClassName, t as cx } from "../class-names-BiMDVpUo.js";
2
- import { d as CheckIcon, q as SpinnerIcon } from "../icons-ua6f_GH3.js";
2
+ import { d as CheckIcon, q as SpinnerIcon } from "../icons-w5PpKGRz.js";
3
3
  import { Tabs } from "./Tabs.js";
4
4
  import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { $ as WarningIcon, Y as StopIcon, d as CheckIcon, q as SpinnerIcon } from "../icons-ua6f_GH3.js";
2
+ import { Y as StopIcon, d as CheckIcon, et as WarningIcon, q as SpinnerIcon } from "../icons-w5PpKGRz.js";
3
3
  import "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/components/SubagentRunIndicator.tsx
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { Collapsible } from "./Collapsible.js";
3
- import { C as FileIcon, G as SearchIcon, m as ChevronRightIcon } from "../icons-ua6f_GH3.js";
3
+ import { C as FileIcon, G as SearchIcon, m as ChevronRightIcon } from "../icons-w5PpKGRz.js";
4
4
  import "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/Task.tsx
@@ -1,7 +1,7 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { Z as TerminalIcon, tt as XIcon } from "../icons-ua6f_GH3.js";
2
+ import { Q as TerminalIcon, nt as XIcon } from "../icons-w5PpKGRz.js";
3
3
  import { IconButton } from "./IconButton.js";
4
- import { t as CopyButton } from "../copy-button-TWq8nZhc.js";
4
+ import { t as CopyButton } from "../copy-button-Buxmtmp9.js";
5
5
  import { Badge } from "./Badge.js";
6
6
  import { ScrollArea } from "./ScrollArea.js";
7
7
  import * as React from "react";
@@ -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, tt as XIcon } from "../icons-ua6f_GH3.js";
3
+ import { d as CheckIcon, m as ChevronRightIcon, nt as XIcon, q as SpinnerIcon } from "../icons-w5PpKGRz.js";
4
4
  import { Progress } from "./Progress.js";
5
5
  import { Badge } from "./Badge.js";
6
6
  import * as React from "react";
@@ -1,4 +1,4 @@
1
- import { F as MonitorIcon, I as MoonIcon, X as SunIcon } from "../icons-ua6f_GH3.js";
1
+ import { F as MonitorIcon, I as MoonIcon, X as SunIcon } from "../icons-w5PpKGRz.js";
2
2
  import { Radio, RadioGroup } from "./RadioGroup.js";
3
3
  import { useTheme } from "./ThemeProvider.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,11 +1,11 @@
1
1
  import { i as AgentMessageRenderPartContext } from "../AgentMessageParts-CyD2UB3V.js";
2
- import { r as AgentChatProps } from "../AgentChat-Bm1qYbOo.js";
2
+ import { r as AgentChatProps } from "../AgentChat-DHxdTjwF.js";
3
3
  import { i as useOptionalAgentToolRuns, n as AgentToolRunsProvider, r as AgentToolRunsProviderProps, t as AgentToolEventsValue } from "../AgentToolRunsContext-BVe4stgw.js";
4
4
  import { S as isThinkChatActivityPart } from "../ThinkChatToolParts-CSzVwMXf.js";
5
5
  import { u as describeThinkChatActivityPart } from "../ThinkChatActivitySummary-kr5fE0wg.js";
6
- import { a as ThinkChatToolRenderers, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as renderThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-2BobmuvR.js";
7
- import { n as ThinkChatValue } from "../ThinkChatContext-DrsZqdaO.js";
8
- import { n as ThinkRecoveryNoticeProps, t as ThinkRecoveryNotice } from "../ThinkRecoveryNotice-DFIcG9UX.js";
6
+ import { a as ThinkChatToolRenderers, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as renderThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-DMTHKWrI.js";
7
+ import { i as ThinkChatValue } from "../ThinkChatContext-B-Nk84Wi.js";
8
+ import { n as ThinkRecoveryNoticeProps, t as ThinkRecoveryNotice } from "../ThinkRecoveryNotice-D6gYcBbr.js";
9
9
  import { n as BrowserLiveViewProps, t as BrowserLiveView } from "../BrowserLiveView-BV5qgFgI.js";
10
10
  import { n as BrowserReplayProps, t as BrowserReplay } from "../BrowserReplay-xWvRjRAC.js";
11
11
  import { d as inferWorkspaceLanguage, i as WorkspaceFileState } from "../WorkspaceFile-DMtRMwVv.js";
@@ -59,6 +59,8 @@ interface ThinkChatMessagesProps<MessageT extends UIMessage = UIMessage> extends
59
59
  composerTools?: React.ReactNode;
60
60
  /** Host-owned slash-command catalog and selection policy. */
61
61
  slashCommands?: AgentChatProps<MessageT>["slashCommands"];
62
+ /** App compaction callable behind the built-in `/compact` slash entry. */
63
+ onCompact?: AgentChatProps<MessageT>["onCompact"];
62
64
  /** Controlled MCP catalog revealed by `@`; selections become composer references. */
63
65
  mentionCommands?: AgentChatProps<MessageT>["mentionCommands"];
64
66
  /** Controlled folder or working-context picker in the composer footer. */
@@ -79,8 +81,6 @@ interface ThinkChatMessagesProps<MessageT extends UIMessage = UIMessage> extends
79
81
  renderMessageAfter?: AgentChatProps<MessageT>["renderMessageAfter"];
80
82
  /** Per-message policy for AgentChat's built-in assistant copy/retry toolbar. */
81
83
  showAssistantActions?: AgentChatProps<MessageT>["showAssistantActions"];
82
- /** Overrides which rows anchor at the top when added; user messages are the default. */
83
- isMessageScrollAnchor?: AgentChatProps<MessageT>["isMessageScrollAnchor"];
84
84
  /**
85
85
  * Durable backend edit/resend operation. Think does not synchronize
86
86
  * `setMessages`, so wire this to an agent callable that creates the branch.
@@ -5,7 +5,7 @@ import { inferWorkspaceLanguage } from "./WorkspaceFile.js";
5
5
  import { describeThinkChatActivityPart } from "./ThinkChatActivitySummary.js";
6
6
  import { ThinkChatActivity, createThinkChatActivityRenderer, renderThinkChatActivityPart } from "./ThinkChatActivity.js";
7
7
  import { ThinkRecoveryNotice } from "./ThinkRecoveryNotice.js";
8
- import { a as thinkPendingExecutionApprovalsQueryOptions, i as ThinkChatRoot, n as ThinkChatMessages, o as useThinkChat, r as ThinkChatProvider, s as useThinkPendingExecutionApprovals, t as ThinkChat } from "../ThinkChat-E_HrfH76.js";
8
+ import { a as thinkPendingExecutionApprovalsQueryOptions, i as ThinkChatRoot, n as ThinkChatMessages, o as useThinkChat, r as ThinkChatProvider, s as useThinkPendingExecutionApprovals, t as ThinkChat } from "../ThinkChat-DVhCEjq-.js";
9
9
  import { BrowserReplay } from "./BrowserReplay.js";
10
10
  import { useWorkspace, workspaceBinaryFileQueryOptions, workspaceDirectoryQueryOptions, workspaceFileAssetQueryOptions, workspaceFileStatQueryOptions, workspaceInfoQueryOptions, workspaceQueryKey, workspaceTextFileQueryOptions } from "./Workspace.js";
11
11
  import { WorkspaceExplorer } from "./WorkspaceExplorer.js";
@@ -1,4 +1,4 @@
1
1
  import { S as isThinkChatActivityPart } from "../ThinkChatToolParts-CSzVwMXf.js";
2
2
  import { u as describeThinkChatActivityPart } from "../ThinkChatActivitySummary-kr5fE0wg.js";
3
- import { a as ThinkChatToolRenderers, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as renderThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-2BobmuvR.js";
3
+ import { a as ThinkChatToolRenderers, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as renderThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-DMTHKWrI.js";
4
4
  export { ThinkChatActivity, ThinkChatActivityProps, ThinkChatActivityRendererOptions, ThinkChatToolRenderer, ThinkChatToolRenderers, createThinkChatActivityRenderer, describeThinkChatActivityPart, isThinkChatActivityPart, renderThinkChatActivityPart };
@@ -1,10 +1,12 @@
1
+ import { Button } from "./Button.js";
2
+ import { useExpansionState } from "./ExpansionState.js";
1
3
  import { Activity, ActivityContent, ActivityItem, ActivityItemGroup, ActivityText, ActivityTrigger } from "./Activity.js";
2
4
  import { AgentActivityFavicon, AgentActivityIcon } from "./AgentActivity.js";
3
- import { f as MessageResponse } from "../Message-_-bEYLAO.js";
5
+ import { f as MessageResponse } from "../Message-KlK8tlBZ.js";
4
6
  import { isBrowserToolPart, isExecuteToolPart, isFetchToolPart, isPartWorking, isSessionContextToolPart, isSkillToolPart, isThinkChatActivityPart, isWorkspaceToolPart } from "./ThinkChatToolParts.js";
5
7
  import { useOptionalAgentToolRuns } from "./AgentToolRunsContext.js";
6
8
  import { SubagentRunList } from "./SubagentRunList.js";
7
- import { useOptionalThinkChatContext } from "./ThinkChatContext.js";
9
+ import { useOptionalThinkChatLive } from "./ThinkChatContext.js";
8
10
  import { ThinkChatBrowserPanel, ThinkChatExecutePanel, ThinkChatFetchPanel, ThinkChatSessionContextPanel, ThinkChatSkillPanel, ThinkChatWorkspacePanel } from "./ThinkChatToolPanels.js";
9
11
  import { activityPartIconKind, activityPartUrl, deriveThinkChatActivityHeader, describeThinkChatActivityPart } from "./ThinkChatActivitySummary.js";
10
12
  import * as React from "react";
@@ -22,7 +24,15 @@ function activityPartIcon(part) {
22
24
  * with per-tool panels. Normally reached through `ThinkChat.Messages`;
23
25
  * exported for apps that lay out messages themselves.
24
26
  */
25
- function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers }) {
27
+ /**
28
+ * An expanded run shows at most this many trailing steps before a "show
29
+ * earlier" reveal. Steps inside the live message get new identities on every
30
+ * streamed delta (the AI SDK clones the streaming message), so memoization
31
+ * can't bound an open log — capping the mounted rows is what keeps a
32
+ * thousands-of-tools run expandable.
33
+ */
34
+ const VISIBLE_STEP_LIMIT = 100;
35
+ function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers, stateKey }) {
26
36
  const steps = parts.flatMap((part, index) => {
27
37
  const description = describeThinkChatActivityPart(part, toolRenderers);
28
38
  if (!description) return [];
@@ -32,7 +42,11 @@ function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers }) {
32
42
  part
33
43
  }];
34
44
  });
45
+ const scope = `run:${stateKey ?? steps[0]?.key}`;
46
+ const [showAllSteps, setShowAllSteps] = useExpansionState(steps.length ? `${scope}:all-steps` : void 0, false);
35
47
  if (steps.length === 0) return null;
48
+ const hiddenStepCount = showAllSteps ? 0 : Math.max(0, steps.length - VISIBLE_STEP_LIMIT);
49
+ const visibleSteps = hiddenStepCount ? steps.slice(hiddenStepCount) : steps;
36
50
  const streaming = isStreaming ?? parts.some(isPartWorking);
37
51
  const header = deriveThinkChatActivityHeader(parts, {
38
52
  isStreaming: streaming,
@@ -42,18 +56,31 @@ function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers }) {
42
56
  return /* @__PURE__ */ jsxs(Activity, {
43
57
  isStreaming: streaming,
44
58
  defaultOpen,
59
+ stateKey: scope,
45
60
  children: [/* @__PURE__ */ jsx(ActivityTrigger, {
46
61
  icon: header.url ? /* @__PURE__ */ jsx(AgentActivityFavicon, { url: header.url }) : /* @__PURE__ */ jsx(AgentActivityIcon, { kind: header.iconKind }),
47
62
  action: header.action,
48
63
  detail: header.detail
49
- }), /* @__PURE__ */ jsx(ActivityContent, { children: steps.map((step) => /* @__PURE__ */ jsx(ThinkChatActivityStep, {
64
+ }), /* @__PURE__ */ jsxs(ActivityContent, { children: [hiddenStepCount > 0 ? /* @__PURE__ */ jsxs(Button, {
65
+ size: "sm",
66
+ variant: "ghost",
67
+ className: "activity__show-earlier",
68
+ onClick: () => setShowAllSteps(true),
69
+ children: [
70
+ "Show ",
71
+ hiddenStepCount,
72
+ " earlier ",
73
+ hiddenStepCount === 1 ? "step" : "steps"
74
+ ]
75
+ }) : null, visibleSteps.map((step) => /* @__PURE__ */ jsx(ThinkChatActivityStep, {
76
+ stateKey: `${scope}:${step.key}`,
50
77
  description: step.description,
51
78
  part: step.part,
52
79
  toolRenderers
53
- }, step.key)) })]
80
+ }, step.key))] })]
54
81
  });
55
82
  }
56
- function ThinkChatActivityStep({ description, part, toolRenderers }) {
83
+ function ThinkChatActivityStep({ description, part, stateKey, toolRenderers }) {
57
84
  const icon = activityPartIcon(part);
58
85
  const { action: text, detail } = description;
59
86
  if (isToolUIPart(part)) {
@@ -67,6 +94,7 @@ function ThinkChatActivityStep({ description, part, toolRenderers }) {
67
94
  action: text,
68
95
  detail,
69
96
  icon,
97
+ stateKey,
70
98
  children: customPanel
71
99
  });
72
100
  }
@@ -74,42 +102,49 @@ function ThinkChatActivityStep({ description, part, toolRenderers }) {
74
102
  action: text,
75
103
  detail,
76
104
  icon,
105
+ stateKey,
77
106
  children: /* @__PURE__ */ jsx(ActivityText, { children: /* @__PURE__ */ jsx(MessageResponse, { children: part.text }) })
78
107
  });
79
108
  if (isWorkspaceToolPart(part) && part.type !== "tool-delete") return /* @__PURE__ */ jsx(ActivityItemGroup, {
80
109
  action: text,
81
110
  detail,
82
111
  icon,
112
+ stateKey,
83
113
  children: /* @__PURE__ */ jsx(ThinkChatWorkspacePanel, { part })
84
114
  });
85
115
  if (isSkillToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
86
116
  action: text,
87
117
  detail,
88
118
  icon,
119
+ stateKey,
89
120
  children: /* @__PURE__ */ jsx(ThinkChatSkillPanel, { part })
90
121
  });
91
122
  if (isSessionContextToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
92
123
  action: text,
93
124
  detail,
94
125
  icon,
126
+ stateKey,
95
127
  children: /* @__PURE__ */ jsx(ThinkChatSessionContextPanel, { part })
96
128
  });
97
129
  if (isFetchToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
98
130
  action: text,
99
131
  detail,
100
132
  icon,
133
+ stateKey,
101
134
  children: /* @__PURE__ */ jsx(ThinkChatFetchPanel, { part })
102
135
  });
103
136
  if (isBrowserToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
104
137
  action: text,
105
138
  detail,
106
139
  icon,
140
+ stateKey,
107
141
  children: /* @__PURE__ */ jsx(ThinkChatBrowserPanel, { part })
108
142
  });
109
143
  if (isExecuteToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
110
144
  action: text,
111
145
  detail,
112
146
  icon,
147
+ stateKey,
113
148
  children: /* @__PURE__ */ jsx(ThinkChatExecutePanel, { part })
114
149
  });
115
150
  return /* @__PURE__ */ jsx(ActivityItem, {
@@ -118,9 +153,9 @@ function ThinkChatActivityStep({ description, part, toolRenderers }) {
118
153
  children: text
119
154
  });
120
155
  }
121
- function ThinkChatActivityGroup({ message, parts, renderAgentToolRunLink, isTrailing, toolRenderers }) {
122
- const chat = useOptionalThinkChatContext();
123
- const chatStillWorking = isTrailing && Boolean(chat?.isStreaming) && chat?.messages.at(-1)?.id === message.id;
156
+ function ThinkChatActivityGroup({ message, parts, renderAgentToolRunLink, isTrailing, toolRenderers, stateKey }) {
157
+ const live = useOptionalThinkChatLive();
158
+ const streaming = isTrailing && (live ? live.isStreaming && live.lastMessageId === message.id : parts.some(isPartWorking));
124
159
  const agentTools = useOptionalAgentToolRuns();
125
160
  const runs = React.useMemo(() => {
126
161
  if (!agentTools || !renderAgentToolRunLink) return [];
@@ -132,8 +167,9 @@ function ThinkChatActivityGroup({ message, parts, renderAgentToolRunLink, isTrai
132
167
  ]);
133
168
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ThinkChatActivity, {
134
169
  parts,
135
- isStreaming: parts.some(isPartWorking) || chatStillWorking,
136
- toolRenderers
170
+ isStreaming: streaming,
171
+ toolRenderers,
172
+ stateKey
137
173
  }), runs.length && renderAgentToolRunLink ? /* @__PURE__ */ jsx(SubagentRunList, {
138
174
  className: "subagent-run__list--adjacent",
139
175
  "aria-label": "Delegated agent runs",
@@ -151,17 +187,35 @@ function ThinkChatActivityGroup({ message, parts, renderAgentToolRunLink, isTrai
151
187
  function createThinkChatActivityRenderer({ excludeTools, renderAgentToolRunLink, toolRenderers } = {}) {
152
188
  const excluded = excludeTools?.length ? new Set(excludeTools) : void 0;
153
189
  const isActivity = (part) => isThinkChatActivityPart(part, excluded);
190
+ const runStartsCache = /* @__PURE__ */ new WeakMap();
191
+ const runStartsFor = (parts) => {
192
+ let starts = runStartsCache.get(parts);
193
+ if (!starts) {
194
+ starts = Array.from({ length: parts.length }, () => -1);
195
+ let runStart = -1;
196
+ for (let index = 0; index < parts.length; index++) if (isActivity(parts[index])) {
197
+ if (runStart === -1) runStart = index;
198
+ starts[index] = runStart;
199
+ } else {
200
+ starts[index] = -1;
201
+ runStart = -1;
202
+ }
203
+ runStartsCache.set(parts, starts);
204
+ }
205
+ return starts;
206
+ };
154
207
  return (context) => {
155
208
  const { message, part, partIndex } = context;
156
209
  if (!isActivity(part)) return void 0;
157
- let start = partIndex;
158
- while (start > 0 && isActivity(message.parts[start - 1])) start--;
210
+ const runStarts = runStartsFor(message.parts);
211
+ const start = runStarts[partIndex] ?? partIndex;
159
212
  if (partIndex !== start) return null;
160
213
  let end = partIndex;
161
- while (end + 1 < message.parts.length && isActivity(message.parts[end + 1])) end++;
214
+ while (end + 1 < message.parts.length && runStarts[end + 1] === start) end++;
162
215
  return /* @__PURE__ */ jsx(ThinkChatActivityGroup, {
163
216
  message,
164
217
  parts: message.parts.slice(start, end + 1),
218
+ stateKey: `${message.id}:${start}`,
165
219
  isTrailing: end === message.parts.length - 1,
166
220
  toolRenderers,
167
221
  renderAgentToolRunLink
@@ -1,2 +1,2 @@
1
- import { i as useThinkChatContext, n as ThinkChatValue, r as useOptionalThinkChatContext, t as ThinkChatContext } from "../ThinkChatContext-DrsZqdaO.js";
2
- export { ThinkChatContext, ThinkChatValue, useOptionalThinkChatContext, useThinkChatContext };
1
+ import { a as useOptionalThinkChatContext, i as ThinkChatValue, n as ThinkChatLiveContext, o as useOptionalThinkChatLive, r as ThinkChatLiveValue, s as useThinkChatContext, t as ThinkChatContext } from "../ThinkChatContext-B-Nk84Wi.js";
2
+ export { ThinkChatContext, ThinkChatLiveContext, ThinkChatLiveValue, ThinkChatValue, useOptionalThinkChatContext, useOptionalThinkChatLive, useThinkChatContext };
@@ -13,5 +13,9 @@ function useThinkChatContext(component) {
13
13
  if (!context) throw new Error(`${component} must be used inside <ThinkChat.Provider> or <ThinkChat.Root>.`);
14
14
  return context;
15
15
  }
16
+ const ThinkChatLiveContext = React.createContext(null);
17
+ function useOptionalThinkChatLive() {
18
+ return React.useContext(ThinkChatLiveContext);
19
+ }
16
20
  //#endregion
17
- export { ThinkChatContext, useOptionalThinkChatContext, useThinkChatContext };
21
+ export { ThinkChatContext, ThinkChatLiveContext, useOptionalThinkChatContext, useOptionalThinkChatLive, useThinkChatContext };
@@ -1,7 +1,7 @@
1
1
  import { ActivityOutput, ActivityPanel } from "./Activity.js";
2
2
  import { displayUrl, isSessionContextToolFailure } from "./ThinkChatToolParts.js";
3
3
  import { Tabs } from "./Tabs.js";
4
- import { t as CodeBlock } from "../CodeBlock-Cp67Njo3.js";
4
+ import { t as CodeBlock } from "../CodeBlock-B3RLU3ez.js";
5
5
  import { BrowserLiveView } from "./BrowserLiveView.js";
6
6
  import { inferWorkspaceLanguage } from "./WorkspaceFile.js";
7
7
  import * as React from "react";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { C as FileIcon, O as InfoIcon, W as RefreshIcon, Z as TerminalIcon, d as CheckIcon, n as ArrowDownIcon, tt as XIcon } from "../icons-ua6f_GH3.js";
2
+ import { C as FileIcon, O as InfoIcon, Q as TerminalIcon, W as RefreshIcon, d as CheckIcon, n as ArrowDownIcon, nt as XIcon } from "../icons-w5PpKGRz.js";
3
3
  import { Activity, ActivityContent, ActivityItem, ActivityItemGroup, ActivityOutput, ActivityPanel, ActivityTrigger } from "./Activity.js";
4
4
  import { formatThinkExecutionRunProgress, formatThinkExecutionStatus, formatThinkExecutionTimestamp, getThinkExecutionRunError, getThinkExecutionRunId, getThinkExecutionRunProgressedAt, getThinkExecutionRunProgressedLabel, getThinkExecutionRunStatus, getThinkExecutionRunTitle, isThinkSubmissionRun } from "./ThinkExecutionRun.js";
5
5
  import { ThinkExecutionStatus } from "./ThinkExecutionStatus.js";
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
- import { O as InfoIcon, d as CheckIcon, q as SpinnerIcon, tt as XIcon, z as PauseIcon } from "../icons-ua6f_GH3.js";
2
+ import { O as InfoIcon, d as CheckIcon, nt as XIcon, q as SpinnerIcon, z as PauseIcon } from "../icons-w5PpKGRz.js";
3
3
  import { Tooltip } from "./Tooltip.js";
4
4
  import { formatThinkExecutionStatus, getThinkExecutionRunStatus, getThinkExecutionRunStatusTone } from "./ThinkExecutionRun.js";
5
5
  import "react";
@@ -1,6 +1,6 @@
1
1
  import { t as ThinkExecutionRun } from "../ThinkExecutionRun-ChhWhOoU.js";
2
2
  import * as React from "react";
3
- import { DataTag, UndefinedInitialDataOptions } from "@tanstack/react-query";
3
+ import { DataTag, UnusedSkipTokenOptions } from "@tanstack/react-query";
4
4
  import { Think, ThinkSubmissionInspection } from "@cloudflare/think";
5
5
  import { AgentStub } from "agents/client";
6
6
  import { WorkflowPage } from "agents/workflows";
@@ -29,7 +29,7 @@ interface ThinkExecutionRunsData {
29
29
  type ThinkExecutionRunsQueryKey = readonly ["think", sourceKey: string, "execution-runs", {
30
30
  readonly limit: number;
31
31
  }];
32
- type ThinkExecutionRunsQueryOptions = UndefinedInitialDataOptions<ThinkExecutionRunsData, Error, ThinkExecutionRunsData, ThinkExecutionRunsQueryKey> & {
32
+ type ThinkExecutionRunsQueryOptions = UnusedSkipTokenOptions<ThinkExecutionRunsData, Error, ThinkExecutionRunsData, ThinkExecutionRunsQueryKey> & {
33
33
  queryKey: DataTag<ThinkExecutionRunsQueryKey, ThinkExecutionRunsData, Error>;
34
34
  };
35
35
  /**
@@ -39,7 +39,8 @@ declare function thinkExecutionRunsQueryOptions(source: AgentStub<Think>, source
39
39
  /**
40
40
  * Unified execution history for native Think submissions and Agents workflows.
41
41
  * The workbench reads and acts through the whole upstream agent stub; it does
42
- * not normalize execution records or own workflow authoring.
42
+ * not normalize execution records or own workflow authoring. Its first
43
+ * uncached list read suspends to the consuming route's Suspense boundary.
43
44
  */
44
45
  declare function ThinkExecutionWorkbench({
45
46
  backButton,
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../class-names-BiMDVpUo.js";
2
2
  import { buttonVariants } from "./Button.js";
3
- import { W as RefreshIcon, b as EllipsisIcon } from "../icons-ua6f_GH3.js";
3
+ import { W as RefreshIcon, b as EllipsisIcon } from "../icons-w5PpKGRz.js";
4
4
  import { t as NavigationLink } from "../navigation-link-Cob7KBlM.js";
5
5
  import { IconButton } from "./IconButton.js";
6
6
  import { EmptyState } from "./EmptyState.js";
@@ -11,7 +11,7 @@ import { ThinkExecutionStatus } from "./ThinkExecutionStatus.js";
11
11
  import { ThinkExecutionDetail } from "./ThinkExecutionDetail.js";
12
12
  import * as React from "react";
13
13
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
- import { queryOptions, useMutation, useQuery } from "@tanstack/react-query";
14
+ import { queryOptions, useMutation, useSuspenseQuery } from "@tanstack/react-query";
15
15
  //#region src/components/ThinkExecutionWorkbench.tsx
16
16
  const executionPanelPageSize = 20;
17
17
  function getErrorMessage(error) {
@@ -116,13 +116,14 @@ function thinkExecutionRunsQueryOptions(source, sourceKey, pageSize = executionP
116
116
  /**
117
117
  * Unified execution history for native Think submissions and Agents workflows.
118
118
  * The workbench reads and acts through the whole upstream agent stub; it does
119
- * not normalize execution records or own workflow authoring.
119
+ * not normalize execution records or own workflow authoring. Its first
120
+ * uncached list read suspends to the consuming route's Suspense boundary.
120
121
  */
121
122
  function ThinkExecutionWorkbench({ backButton, className, pageSize = executionPanelPageSize, ref, renderRunLink, selectedRun, source, sourceKey, title = "Execution", ...props }) {
122
123
  const runsId = React.useId();
123
124
  const runsOptions = thinkExecutionRunsQueryOptions(source, sourceKey, pageSize);
124
125
  const runsQueryKey = thinkExecutionRunsScopeQueryKey(sourceKey);
125
- const runsQuery = useQuery(runsOptions);
126
+ const runsQuery = useSuspenseQuery(runsOptions);
126
127
  const actionMutation = useMutation({
127
128
  mutationFn: ({ action }) => action(),
128
129
  onSuccess: (_result, action, _onMutateResult, context) => context.client.invalidateQueries({ queryKey: action.runsQueryKey })
@@ -131,7 +132,7 @@ function ThinkExecutionWorkbench({ backButton, className, pageSize = executionPa
131
132
  const actionIsPending = currentAction !== null && actionMutation.isPending;
132
133
  const busyAction = actionIsPending ? currentAction.key : runsQuery.isFetching ? "refresh" : null;
133
134
  const error = currentAction && actionMutation.isError ? actionMutation.error : runsQuery.error;
134
- const runs = React.useMemo(() => [...runsQuery.data?.submissions ?? [], ...runsQuery.data?.workflows.workflows ?? []].sort((first, second) => Number(second.createdAt) - Number(first.createdAt)), [runsQuery.data]);
135
+ const runs = React.useMemo(() => [...runsQuery.data.submissions, ...runsQuery.data.workflows.workflows].sort((first, second) => Number(second.createdAt) - Number(first.createdAt)), [runsQuery.data]);
135
136
  const runAction = (key, action) => {
136
137
  actionMutation.mutate({
137
138
  action,
@@ -182,11 +183,7 @@ function ThinkExecutionWorkbench({ backButton, className, pageSize = executionPa
182
183
  id: runsId,
183
184
  children: "Runs"
184
185
  })
185
- }), runsQuery.isPending && runs.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
186
- className: "think-execution-workbench__empty",
187
- role: "status",
188
- description: "Loading runs..."
189
- }) : runs.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
186
+ }), runs.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
190
187
  className: "think-execution-workbench__empty",
191
188
  description: "No runs yet."
192
189
  }) : /* @__PURE__ */ jsx("ul", {