@mcp-b/react-components 0.41.0 → 0.42.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 (114) hide show
  1. package/dist/{ThinkChatActivity-DyGHj01E.d.ts → ThinkChatActivity-CsDql-ER.d.ts} +3 -0
  2. package/dist/{WorkspaceFileView-D0yFwoDr.js → WorkspaceFileView-DwdXiKku.js} +15 -20
  3. package/dist/components/agents-sdk/AgentActivity.js +3 -2
  4. package/dist/components/agents-sdk/AgentChat.js +1 -0
  5. package/dist/components/agents-sdk/BrowserRunPanel.js +2 -1
  6. package/dist/components/agents-sdk/ManagerOffice.d.ts +39 -27
  7. package/dist/components/agents-sdk/ManagerOffice.js +80 -44
  8. package/dist/components/agents-sdk/McpPluginCatalog.js +4 -2
  9. package/dist/components/agents-sdk/ModelSelector.js +1 -1
  10. package/dist/components/agents-sdk/SubagentRunSelector.js +1 -1
  11. package/dist/components/agents-sdk/ThinkChat.d.ts +1 -1
  12. package/dist/components/agents-sdk/ThinkChat.js +1 -1
  13. package/dist/components/agents-sdk/ThinkChatActivity.d.ts +1 -1
  14. package/dist/components/agents-sdk/ThinkChatActivity.js +19 -5
  15. package/dist/components/agents-sdk/ThinkChatToolPanels.js +6 -2
  16. package/dist/components/agents-sdk/ThinkExecutionDetail.js +3 -1
  17. package/dist/components/agents-sdk/ThinkExecutionWorkbench.js +1 -0
  18. package/dist/components/agents-sdk/ThinkFullApp.d.ts +40 -88
  19. package/dist/components/agents-sdk/ThinkFullApp.js +75 -124
  20. package/dist/components/agents-sdk/ThinkFullAppViewSwitch.d.ts +1 -1
  21. package/dist/components/agents-sdk/ThinkFullAppViewSwitch.js +1 -1
  22. package/dist/components/agents-sdk/ThinkRoutineDetail.js +1 -1
  23. package/dist/components/agents-sdk/ThinkRoutineLibrary.d.ts +7 -6
  24. package/dist/components/agents-sdk/ThinkRoutineLibrary.js +57 -65
  25. package/dist/components/agents-sdk/ThinkThreadPicker.js +2 -1
  26. package/dist/components/agents-sdk/WorkspaceExplorer.js +2 -1
  27. package/dist/components/agents-sdk/WorkspaceFileView.js +1 -1
  28. package/dist/components/ai-sdk/MessageScroller.js +2 -1
  29. package/dist/components/ai-sdk/MessageScrollerVirtual.js +1 -0
  30. package/dist/components/ai-sdk/PromptInput.js +20 -14
  31. package/dist/components/extension/ChatGptSignInScreen.js +1 -0
  32. package/dist/components/foundations/ToggleGroup.d.ts +79 -1
  33. package/dist/components/foundations/ToggleGroup.js +1 -1
  34. package/dist/components/foundations/Toolbar.d.ts +151 -1
  35. package/dist/components/general-purpose/AppFrame.js +1 -0
  36. package/dist/components/general-purpose/AppTopBar.d.ts +96 -1
  37. package/dist/components/general-purpose/PricingBillingToggle.js +1 -1
  38. package/dist/components/general-purpose/PricingUsageCalculator.js +1 -1
  39. package/dist/components/general-purpose/ResizableSidePanel.d.ts +8 -0
  40. package/dist/components/general-purpose/ResizableSidePanel.js +3 -2
  41. package/dist/components/general-purpose/ResponsiveSidebarShell.d.ts +59 -49
  42. package/dist/components/general-purpose/ResponsiveSidebarShell.js +74 -74
  43. package/dist/components/general-purpose/WebPreview.d.ts +3 -0
  44. package/dist/components/general-purpose/WebPreview.js +2 -2
  45. package/dist/components/nanites/AgentToolDetail.js +4 -3
  46. package/dist/styles/accordion.css +1 -0
  47. package/dist/styles/action-guide.css +8 -7
  48. package/dist/styles/activity-header.css +13 -39
  49. package/dist/styles/activity.css +40 -55
  50. package/dist/styles/agent-attention.css +14 -14
  51. package/dist/styles/agent-chat.css +62 -45
  52. package/dist/styles/agent-connection.css +10 -4
  53. package/dist/styles/agent-tool-detail.css +4 -4
  54. package/dist/styles/alert-dialog.css +4 -4
  55. package/dist/styles/app-frame.css +1 -3
  56. package/dist/styles/app-top-bar.css +5 -9
  57. package/dist/styles/approval.css +1 -0
  58. package/dist/styles/artifact.css +6 -6
  59. package/dist/styles/attachment-preview.css +5 -4
  60. package/dist/styles/browser-replay.css +6 -6
  61. package/dist/styles/browser-run-panel.css +1 -0
  62. package/dist/styles/button.css +15 -6
  63. package/dist/styles/card.css +5 -5
  64. package/dist/styles/chatgpt-sign-in-screen.css +1 -1
  65. package/dist/styles/code-block.css +14 -13
  66. package/dist/styles/codex-model-selector.css +2 -0
  67. package/dist/styles/collapsible.css +1 -0
  68. package/dist/styles/commit.css +6 -6
  69. package/dist/styles/context.css +9 -9
  70. package/dist/styles/conversation-tab-picker.css +1 -1
  71. package/dist/styles/conversation.css +6 -8
  72. package/dist/styles/dialog.css +4 -4
  73. package/dist/styles/empty-state.css +3 -3
  74. package/dist/styles/environment-variables.css +9 -9
  75. package/dist/styles/field.css +2 -1
  76. package/dist/styles/fieldset.css +2 -2
  77. package/dist/styles/index.css +3 -3
  78. package/dist/styles/manager-office.css +23 -29
  79. package/dist/styles/mcp-plugin-catalog.css +11 -10
  80. package/dist/styles/mcp-server-picker.css +3 -3
  81. package/dist/styles/message-scroller.css +9 -11
  82. package/dist/styles/message.css +43 -20
  83. package/dist/styles/navigation-menu.css +1 -0
  84. package/dist/styles/plan.css +13 -12
  85. package/dist/styles/pricing-page.css +26 -23
  86. package/dist/styles/prompt-input.css +18 -5
  87. package/dist/styles/queue.css +1 -0
  88. package/dist/styles/reasoning.css +1 -9
  89. package/dist/styles/recipes.css +28 -1
  90. package/dist/styles/responsive-sidebar-shell.css +44 -16
  91. package/dist/styles/separator.css +5 -5
  92. package/dist/styles/sources.css +4 -4
  93. package/dist/styles/stepper.css +1 -0
  94. package/dist/styles/streamdown.css +31 -21
  95. package/dist/styles/tabs.css +1 -0
  96. package/dist/styles/task.css +5 -17
  97. package/dist/styles/terminal.css +10 -10
  98. package/dist/styles/test-results.css +6 -6
  99. package/dist/styles/think-execution-status.css +2 -2
  100. package/dist/styles/think-execution-workbench.css +12 -15
  101. package/dist/styles/think-full-app.css +26 -64
  102. package/dist/styles/think-routine-library.css +26 -55
  103. package/dist/styles/think-thread-picker.css +9 -9
  104. package/dist/styles/utilities.css +33 -0
  105. package/dist/styles/web-preview.css +20 -19
  106. package/dist/styles/workspace-explorer.css +18 -21
  107. package/dist/styles/workspace-mount-manager.css +2 -2
  108. package/dist/utils/favicon.d.ts +6 -1
  109. package/dist/utils/favicon.js +18 -1
  110. package/package.json +2 -2
  111. package/dist/AppTopBar-ZdgmB_Lu.d.ts +0 -97
  112. package/dist/ToggleGroup-BrQZOQn_.d.ts +0 -80
  113. package/dist/Toolbar-CBOseBQr.d.ts +0 -152
  114. package/dist/{ThinkChat-BES_3Mb-.js → ThinkChat-DkA4Wr71.js} +1 -1
@@ -2,10 +2,7 @@ import { l as WorkspaceNavigationAdapter } from "../../WorkspaceLink-Bh9-Jo1r.js
2
2
  import { n as AgentToolEventsValue } from "../../AgentToolRunsContext-daY67hFM.js";
3
3
  import { McpPluginCatalogProps } from "./McpPluginCatalog.js";
4
4
  import { ThinkChatMessagesProps } from "./ThinkChat.js";
5
- import { t as ThinkExecutionRun } from "../../ThinkExecutionRun-k8bpyXqt.js";
6
- import { ThinkExecutionWorkbenchProps } from "./ThinkExecutionWorkbench.js";
7
- import { ResponsiveSidebarShell } from "../general-purpose/ResponsiveSidebarShell.js";
8
- import { ThinkFullAppView } from "./ThinkFullAppViewSwitch.js";
5
+ import { AppBarSlots, ResponsiveSidebarShell } from "../general-purpose/ResponsiveSidebarShell.js";
9
6
  import { ThinkThreadStatusSummary } from "./ThinkThreadPicker.js";
10
7
  import { r as WorkspaceFileAssetResolver } from "../../WorkspaceFile-BLaFmMrt.js";
11
8
  import { WorkspaceSource } from "./Workspace.js";
@@ -16,9 +13,15 @@ import { useAgentChat } from "@cloudflare/think/react";
16
13
  import { useAgent } from "agents/react";
17
14
 
18
15
  //#region src/components/agents-sdk/ThinkFullApp.d.ts
19
- type ThinkFullAppMobileView = "chat" | "workbench";
20
16
  type ThinkFullAppAgent<State = unknown> = ThinkAgent<State>;
21
- type ThinkFullAppWorkbenchView = "files" | "execution" | "plugins" | (string & {});
17
+ type ThinkFullAppWorkbenchView = "files" | "plugins" | (string & {});
18
+ /**
19
+ * The one view axis: the conversation alone, or the conversation with a named
20
+ * workbench panel raised beside it (leading at narrow widths). Apps that make
21
+ * views durable derive this from validated route search state and pass
22
+ * `onViewChange` back into their router.
23
+ */
24
+ type ThinkFullAppView = "chat" | ThinkFullAppWorkbenchView;
22
25
  interface ThinkFullAppWorkspaceConfig {
23
26
  source: WorkspaceSource;
24
27
  /**
@@ -34,13 +37,15 @@ interface ThinkFullAppWorkspaceConfig {
34
37
  leading?: React.ReactNode;
35
38
  actions?: React.ReactNode;
36
39
  }
37
- interface ThinkFullAppPanel extends ThinkFullAppView {
38
- /** Unique panel id used by `workbenchView`; custom panels should not reuse built-in ids. */
40
+ interface ThinkFullAppPanel {
41
+ /** Unique panel id used by `view`; custom panels should not reuse built-in ids. */
39
42
  id: ThinkFullAppWorkbenchView;
43
+ label: string;
44
+ icon: React.ReactNode;
40
45
  /** Panels are app-authored, so anything one needs is already in its scope. */
41
46
  render: () => React.ReactNode;
42
47
  }
43
- /** The live conversation the chat lane, approvals, and executions belong to. */
48
+ /** The live conversation the chat lane and approvals belong to. */
44
49
  interface ThinkFullAppConversation<AgentT extends ThinkFullAppAgent<State>, State = unknown, MessageT extends UIMessage = UIMessage> {
45
50
  /** The `useAgent` value from `agents/react`; its stub drives approvals and execution records. */
46
51
  agent: ReturnType<typeof useAgent<AgentT, State>>;
@@ -57,49 +62,25 @@ interface ThinkFullAppConversation<AgentT extends ThinkFullAppAgent<State>, Stat
57
62
  interface ThinkFullAppProps<AgentT extends ThinkFullAppAgent<State>, State = unknown, MessageT extends UIMessage = UIMessage> extends React.HTMLAttributes<HTMLDivElement> {
58
63
  /**
59
64
  * Omit it and supply `messages.draft` for the first turn of a conversation
60
- * that does not exist yet. The approvals, execution, and background-agent
61
- * surfaces wait for a conversation to belong to; everything else is unchanged.
65
+ * that does not exist yet. The approvals and background-agent surfaces wait
66
+ * for a conversation to belong to; everything else is unchanged.
62
67
  */
63
68
  conversation?: ThinkFullAppConversation<AgentT, State, MessageT>;
64
69
  /** Atomic workspace source, navigation, media, and header configuration. */
65
70
  workspace?: ThinkFullAppWorkspaceConfig;
66
71
  /** Plugin directory backed by the host's live Agents MCP state and connection callbacks. */
67
72
  plugins?: McpPluginCatalogProps;
68
- /** Product-specific actions rendered in the application top bar. */
69
- appBarActions?: React.ReactNode;
70
- /** Product-specific navigation that owns the leading slot at every width. */
71
- appBarLeading?: React.ReactNode;
72
- /** Product-specific compact navigation; the wide layout keeps its sidebar toggle. */
73
- compactAppBarLeading?: React.ReactNode;
74
- /** Active conversation or page title rendered in the application top bar. */
75
- appBarTitle?: React.ReactNode;
73
+ /** Application bar slots: back control, leading navigation, title, actions. */
74
+ bar?: AppBarSlots;
76
75
  /** Aggregate thread activity rendered beside the compact thread-title disclosure. */
77
76
  threadStatusSummary?: ThinkThreadStatusSummary;
78
- /** Whether narrow layouts render the built-in chat/workbench switch. Defaults to true. */
79
- showMobileViewSwitch?: boolean;
80
- /** Whether desktop layouts render the built-in workbench switch. Defaults to true. */
81
- showWorkbenchViewSwitch?: boolean;
82
- /** Hide the thread app bar when a narrow workbench supplies its own navigation. */
83
- hideAppBarInWorkbench?: boolean;
84
- /** Whole native execution selected by the application route. */
85
- selectedExecutionRun?: ThinkExecutionRun | null;
86
77
  /**
87
- * Stable, non-secret identity for the remote Think agent used by approvals
88
- * and execution queries. Include endpoint, account or tenant scope, and
78
+ * Stable, non-secret identity for the remote Think agent used by approvals.
79
+ * Include endpoint, account or tenant scope, and
89
80
  * agent path so two sources cannot share cached data. The optional workspace
90
81
  * has its own source identity.
91
82
  */
92
83
  sourceKey: string;
93
- /**
94
- * Returns an application-authored TanStack Router Link for a run. Together
95
- * with `renderExecutionRunsLink` this enables the Execution workbench.
96
- */
97
- renderExecutionRunLink?: ThinkExecutionWorkbenchProps["renderRunLink"];
98
- /**
99
- * Returns an application-authored TanStack Router Link back to the run
100
- * list — the way out of a selected run, which replaces the list in place.
101
- */
102
- renderExecutionRunsLink?: ThinkExecutionWorkbenchProps["renderRunsLink"];
103
84
  /** Message rendering labels and approval overrides for ThinkChat. */
104
85
  messages?: ThinkChatMessagesProps<MessageT>;
105
86
  /** Extra workbench panels appended after the enabled built-in panels. */
@@ -111,73 +92,44 @@ interface ThinkFullAppProps<AgentT extends ThinkFullAppAgent<State>, State = unk
111
92
  * Use the render form to close the compact drawer after selecting a thread.
112
93
  */
113
94
  threadSidebar?: React.ComponentProps<typeof ResponsiveSidebarShell>["sidebar"];
114
- /** Whether the thread sidebar is open. Omit for internal state. */
115
- threadSidebarOpen?: boolean;
116
- /** Initial thread sidebar state when `threadSidebarOpen` is uncontrolled. */
117
- defaultThreadSidebarOpen?: boolean;
118
- /** Called when the thread sidebar is opened or closed. */
119
- onThreadSidebarOpenChange?: (open: boolean) => void;
120
- /** Visible surface at narrow widths. Omit for internal state. */
121
- mobileView?: ThinkFullAppMobileView;
122
- /** Initial narrow-width surface when `mobileView` is uncontrolled. */
123
- defaultMobileView?: ThinkFullAppMobileView;
124
- /** Called when narrow layouts switch between chat and the workbench. */
125
- onMobileViewChange?: (view: ThinkFullAppMobileView) => void;
126
95
  /**
127
- * Selected workbench lane for controlled, ephemeral panel UI.
128
- * Apps that make lanes durable should derive this value from validated route search state.
96
+ * Visible surface. Omit for internal state. A controlled `view` naming a
97
+ * panel that does not exist renders the conversation alone it is never
98
+ * silently substituted with another panel.
99
+ */
100
+ view?: ThinkFullAppView;
101
+ /**
102
+ * Uncontrolled starting view. Ignored when `view` is set. Omit it to open
103
+ * Files beside the conversation on a wide app when a workspace exists, and
104
+ * to stay on chat at compact (extension) widths.
129
105
  */
130
- workbenchView?: ThinkFullAppWorkbenchView;
131
- /** Initial workbench lane when `workbenchView` is uncontrolled. */
132
- defaultWorkbenchView?: ThinkFullAppWorkbenchView;
133
- /** Called when the shell toolbar asks to switch workbench lanes. */
134
- onWorkbenchViewChange?: (view: ThinkFullAppWorkbenchView) => void;
135
- /** Whether the desktop workbench panel is open. Omit for internal state. */
136
- workbenchOpen?: boolean;
137
- /** Initial desktop workbench state when `workbenchOpen` is uncontrolled. */
138
- defaultWorkbenchOpen?: boolean;
139
- /** Called when toolbar or resize input opens or closes the workbench. */
140
- onWorkbenchOpenChange?: (open: boolean) => void;
106
+ defaultView?: ThinkFullAppView;
107
+ /** Called when the built-in switch (or a collapse) asks for another view. */
108
+ onViewChange?: (view: ThinkFullAppView) => void;
141
109
  }
142
- /** Combines ThinkChat with an optional resizable workbench shell. */
110
+ /** Combines ThinkChat with a resizable workbench. Wide apps with a workspace
111
+ * open Files beside the conversation; compact (extension) widths stay on chat
112
+ * until a view is selected. */
143
113
  declare function ThinkFullApp<AgentT extends ThinkFullAppAgent<State>, State = unknown, MessageT extends UIMessage = UIMessage>({
144
- appBarActions,
145
- appBarLeading,
146
- appBarTitle,
147
- compactAppBarLeading,
114
+ bar,
148
115
  className,
149
116
  conversation,
150
- defaultMobileView,
151
- defaultWorkbenchOpen,
152
- defaultWorkbenchView,
153
- defaultThreadSidebarOpen,
154
- hideAppBarInWorkbench,
117
+ defaultView: defaultViewProp,
155
118
  messages,
156
- mobileView,
157
- onMobileViewChange,
158
- onThreadSidebarOpenChange,
159
- onWorkbenchOpenChange,
160
- onWorkbenchViewChange,
119
+ onViewChange,
161
120
  plugins,
162
121
  ref,
163
122
  renderAgentToolRunLink,
164
- renderExecutionRunLink,
165
- renderExecutionRunsLink,
166
- selectedExecutionRun,
167
- showMobileViewSwitch,
168
- showWorkbenchViewSwitch,
169
123
  sourceKey,
170
124
  style,
171
125
  threadSidebar,
172
- threadSidebarOpen,
173
126
  threadStatusSummary,
174
- workbenchOpen,
127
+ view,
175
128
  workbenchPanels,
176
- workbenchView,
177
129
  workspace,
178
130
  ...props
179
131
  }: ThinkFullAppProps<AgentT, State, MessageT> & {
180
132
  ref?: React.Ref<HTMLDivElement>;
181
133
  }): React.JSX.Element;
182
134
  //#endregion
183
- export { ThinkFullApp, ThinkFullAppAgent, ThinkFullAppConversation, ThinkFullAppMobileView, ThinkFullAppPanel, ThinkFullAppProps, ThinkFullAppWorkbenchView, ThinkFullAppWorkspaceConfig };
135
+ export { ThinkFullApp, ThinkFullAppAgent, ThinkFullAppConversation, ThinkFullAppPanel, ThinkFullAppProps, ThinkFullAppView, ThinkFullAppWorkbenchView, ThinkFullAppWorkspaceConfig };
@@ -1,13 +1,11 @@
1
1
  import { t as cx } from "../../class-names-BiMDVpUo.js";
2
- import { K as SpinnerIcon, S as FileIcon, Z as TerminalIcon, c as BoxIcon } from "../../icons-CVFSeTJn.js";
2
+ import { S as FileIcon, c as BoxIcon } from "../../icons-CVFSeTJn.js";
3
3
  import { n as mergeRefs } from "../../merge-refs-DF_7w2x_.js";
4
- import { EmptyState } from "../foundations/EmptyState.js";
5
4
  import { ResizableSidePanel } from "../general-purpose/ResizableSidePanel.js";
6
5
  import { ResponsiveSidebarShell } from "../general-purpose/ResponsiveSidebarShell.js";
7
- import { McpPluginCatalog } from "./McpPluginCatalog.js";
8
6
  import { a as WorkspaceNavigationRestorationBoundary, i as WorkspaceNavigationFocusRestorer, n as WorkspaceNavigationProvider } from "../../WorkspaceLink-DtH66bAY.js";
9
- import { c as resolveThinkApprovalProps, s as useThinkPendingExecutionApprovals, t as ThinkChat } from "../../ThinkChat-BES_3Mb-.js";
10
- import { ThinkExecutionWorkbench } from "./ThinkExecutionWorkbench.js";
7
+ import { c as resolveThinkApprovalProps, s as useThinkPendingExecutionApprovals, t as ThinkChat } from "../../ThinkChat-DkA4Wr71.js";
8
+ import { McpPluginCatalog } from "./McpPluginCatalog.js";
11
9
  import { ThinkFullAppViewSwitch } from "./ThinkFullAppViewSwitch.js";
12
10
  import { ThinkThreadStatusIndicators } from "./ThinkThreadPicker.js";
13
11
  import { useWorkspace } from "./Workspace.js";
@@ -15,10 +13,21 @@ import { WorkspaceExplorer } from "./WorkspaceExplorer.js";
15
13
  import * as React from "react";
16
14
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
15
  //#region src/components/agents-sdk/ThinkFullApp.tsx
18
- const conversationDefaultWidth = 393;
16
+ /** Matches --sigvelo-layout-conversation (24.5rem). */
17
+ const conversationDefaultWidth = 392;
19
18
  const conversationMinWidth = 320;
20
19
  const conversationMaxWidth = 640;
21
20
  const conversationKeyboardStep = 24;
21
+ /** Keep in lockstep with --sigvelo-layout-break-compact / the 56rem @container. */
22
+ function compactBreakPx(el) {
23
+ const raw = getComputedStyle(el).getPropertyValue("--sigvelo-layout-break-compact").trim();
24
+ if (raw.endsWith("rem")) return Number.parseFloat(raw) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize);
25
+ const px = Number.parseFloat(raw);
26
+ return Number.isFinite(px) ? px : 896;
27
+ }
28
+ function isCompactApp(el) {
29
+ return el.getBoundingClientRect().width <= compactBreakPx(el);
30
+ }
22
31
  function WorkspacePanel({ config }) {
23
32
  const selectedPath = config.navigation.current.destination.kind === "file" ? config.navigation.current.destination.path : null;
24
33
  return /* @__PURE__ */ jsx(WorkspaceExplorer, {
@@ -71,33 +80,40 @@ function ThinkFullAppThreadChat({ agent, agentTools, chat, messages, renderAgent
71
80
  })
72
81
  });
73
82
  }
74
- /** Combines ThinkChat with an optional resizable workbench shell. */
75
- function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBarLeading, className, conversation, defaultMobileView, defaultWorkbenchOpen, defaultWorkbenchView, defaultThreadSidebarOpen, hideAppBarInWorkbench = false, messages, mobileView, onMobileViewChange, onThreadSidebarOpenChange, onWorkbenchOpenChange, onWorkbenchViewChange, plugins, ref, renderAgentToolRunLink, renderExecutionRunLink, renderExecutionRunsLink, selectedExecutionRun = null, showMobileViewSwitch = true, showWorkbenchViewSwitch = true, sourceKey, style, threadSidebar, threadSidebarOpen, threadStatusSummary, workbenchOpen, workbenchPanels, workbenchView, workspace, ...props }) {
76
- const agent = conversation?.agent;
83
+ /** Combines ThinkChat with a resizable workbench. Wide apps with a workspace
84
+ * open Files beside the conversation; compact (extension) widths stay on chat
85
+ * until a view is selected. */
86
+ function ThinkFullApp({ bar, className, conversation, defaultView: defaultViewProp, messages, onViewChange, plugins, ref, renderAgentToolRunLink, sourceKey, style, threadSidebar, threadStatusSummary, view, workbenchPanels, workspace, ...props }) {
77
87
  const appRef = React.useRef(null);
78
88
  const workbenchPanelRef = React.useRef(null);
79
89
  const pendingPanelFocusRef = React.useRef(null);
80
- const [innerMobileView, setInnerMobileView] = React.useState(defaultMobileView ?? "chat");
81
- const [innerWorkbenchView, setInnerWorkbenchView] = React.useState(defaultWorkbenchView ?? "files");
82
- const [innerWorkbenchOpen, setInnerWorkbenchOpen] = React.useState(defaultWorkbenchOpen ?? true);
83
- const requestedMobileView = mobileView ?? innerMobileView;
84
- const requestedWorkbenchView = workbenchView ?? innerWorkbenchView;
85
- const requestedWorkbenchOpen = workbenchOpen ?? innerWorkbenchOpen;
86
- const setWorkbenchView = React.useCallback((next) => {
87
- if (workbenchView === void 0) setInnerWorkbenchView(next);
88
- onWorkbenchViewChange?.(next);
89
- }, [onWorkbenchViewChange, workbenchView]);
90
- const setMobileView = React.useCallback((next) => {
91
- if (mobileView === void 0) setInnerMobileView(next);
92
- onMobileViewChange?.(next);
93
- }, [mobileView, onMobileViewChange]);
94
- const setWorkbenchOpen = React.useCallback((next) => {
95
- if (workbenchOpen === void 0) setInnerWorkbenchOpen(next);
96
- onWorkbenchOpenChange?.(next);
97
- }, [onWorkbenchOpenChange, workbenchOpen]);
98
- const updateAppView = React.useCallback((update) => {
99
- React.startTransition(update);
100
- }, []);
90
+ const [innerView, setInnerView] = React.useState(defaultViewProp ?? "chat");
91
+ const userChoseView = React.useRef(defaultViewProp !== void 0 || view !== void 0);
92
+ const requestedView = view ?? innerView;
93
+ const setView = React.useCallback((next) => {
94
+ userChoseView.current = true;
95
+ if (view === void 0) setInnerView(next);
96
+ onViewChange?.(next);
97
+ }, [onViewChange, view]);
98
+ React.useLayoutEffect(() => {
99
+ if (view !== void 0 || defaultViewProp !== void 0 || userChoseView.current) return;
100
+ if (workspace === void 0) return;
101
+ const el = appRef.current;
102
+ if (!el) return;
103
+ const syncViewToWidth = () => {
104
+ if (userChoseView.current) return;
105
+ const next = isCompactApp(el) ? "chat" : "files";
106
+ setInnerView((current) => current === next ? current : next);
107
+ };
108
+ syncViewToWidth();
109
+ const observer = new ResizeObserver(syncViewToWidth);
110
+ observer.observe(el);
111
+ return () => observer.disconnect();
112
+ }, [
113
+ defaultViewProp,
114
+ view,
115
+ workspace
116
+ ]);
101
117
  const availableWorkbenchPanels = [];
102
118
  if (workspace !== void 0) availableWorkbenchPanels.push({
103
119
  id: "files",
@@ -105,29 +121,6 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
105
121
  icon: /* @__PURE__ */ jsx(FileIcon, {}),
106
122
  render: () => /* @__PURE__ */ jsx(WorkspacePanel, { config: workspace })
107
123
  });
108
- if (renderExecutionRunLink && renderExecutionRunsLink && agent) availableWorkbenchPanels.push({
109
- id: "execution",
110
- label: "Execution",
111
- icon: /* @__PURE__ */ jsx(TerminalIcon, {}),
112
- render: () => /* @__PURE__ */ jsx(React.Suspense, {
113
- fallback: /* @__PURE__ */ jsx("div", {
114
- className: "think-full-app__workbench think-full-app__workbench--loading",
115
- role: "status",
116
- children: /* @__PURE__ */ jsx(EmptyState, {
117
- icon: /* @__PURE__ */ jsx(SpinnerIcon, {}),
118
- description: "Loading execution"
119
- })
120
- }),
121
- children: /* @__PURE__ */ jsx(ThinkExecutionWorkbench, {
122
- source: agent.stub,
123
- sourceKey,
124
- title: "Execution",
125
- selectedRun: selectedExecutionRun,
126
- renderRunLink: renderExecutionRunLink,
127
- renderRunsLink: renderExecutionRunsLink
128
- })
129
- })
130
- });
131
124
  if (plugins) availableWorkbenchPanels.push({
132
125
  id: "plugins",
133
126
  label: "Plugins",
@@ -135,24 +128,17 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
135
128
  render: () => /* @__PURE__ */ jsx(McpPluginCatalog, { ...plugins })
136
129
  });
137
130
  if (workbenchPanels) availableWorkbenchPanels.push(...workbenchPanels);
138
- const selectedPanel = availableWorkbenchPanels.find((panel) => panel.id === requestedWorkbenchView) ?? availableWorkbenchPanels[0];
139
- const activePanel = requestedWorkbenchOpen ? selectedPanel : void 0;
140
- const activeWorkbenchView = activePanel?.id;
131
+ const activePanel = requestedView === "chat" ? void 0 : availableWorkbenchPanels.find((panel) => panel.id === requestedView);
141
132
  const hasWorkbench = activePanel !== void 0;
142
- const hasAvailableWorkbench = selectedPanel !== void 0;
143
- const activeMobileView = hasWorkbench ? requestedMobileView : "chat";
144
- const shouldShowWorkbenchViewSwitch = showWorkbenchViewSwitch && availableWorkbenchPanels.length > 0;
145
- const workbenchViews = availableWorkbenchPanels;
146
- const hasApplicationChrome = Boolean(appBarActions || appBarLeading || compactAppBarLeading || appBarTitle || threadSidebar);
147
- const shouldShowMobileViewSwitch = Boolean(selectedPanel) && showMobileViewSwitch;
148
- const hasAppBarRow = hasApplicationChrome || shouldShowWorkbenchViewSwitch || shouldShowMobileViewSwitch;
133
+ const activeMobileView = hasWorkbench ? "workbench" : "chat";
134
+ const hasAppBarRow = Boolean(bar?.back || bar?.leading || bar?.compactLeading || bar?.title || bar?.actions || threadSidebar) || availableWorkbenchPanels.length > 0;
149
135
  React.useLayoutEffect(() => {
150
136
  const pendingFocus = pendingPanelFocusRef.current;
151
- if (!pendingFocus || pendingFocus.id !== activeWorkbenchView) return;
137
+ if (!pendingFocus || pendingFocus.id !== activePanel?.id) return;
152
138
  pendingPanelFocusRef.current = null;
153
139
  Array.from(workbenchPanelRef.current?.querySelectorAll("button") ?? []).find((button) => button.getAttribute("aria-label") === pendingFocus.label)?.focus({ preventScroll: true });
154
- }, [activeWorkbenchView]);
155
- const updateWorkbenchPanel = (next) => {
140
+ }, [activePanel?.id]);
141
+ const updateView = (next) => {
156
142
  const activeElement = document.activeElement;
157
143
  const restorePanelSwitchFocus = activeElement instanceof HTMLElement && workbenchPanelRef.current?.contains(activeElement);
158
144
  const nextLabel = availableWorkbenchPanels.find((panel) => panel.id === next)?.label;
@@ -160,50 +146,22 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
160
146
  id: next,
161
147
  label: nextLabel
162
148
  } : null;
163
- React.startTransition(() => setWorkbenchView(next));
149
+ React.startTransition(() => setView(next));
164
150
  };
165
- const appBarTrailing = appBarActions || shouldShowWorkbenchViewSwitch || shouldShowMobileViewSwitch ? /* @__PURE__ */ jsxs(Fragment, { children: [
166
- appBarActions,
167
- shouldShowWorkbenchViewSwitch ? /* @__PURE__ */ jsx(ThinkFullAppViewSwitch, {
168
- className: "think-full-app__workbench-view-switch",
169
- views: workbenchViews,
170
- value: activeWorkbenchView,
171
- allowEmpty: true,
172
- onValueChange: (next) => {
173
- updateAppView(() => {
174
- if (!next) {
175
- setWorkbenchOpen(false);
176
- return;
177
- }
178
- updateWorkbenchPanel(next);
179
- setWorkbenchOpen(true);
180
- });
181
- },
182
- "aria-label": "Workbench views"
183
- }) : null,
184
- shouldShowMobileViewSwitch ? /* @__PURE__ */ jsx(ThinkFullAppViewSwitch, {
185
- className: "think-full-app__mobile-view-switch",
186
- views: workbenchViews,
187
- value: activeMobileView === "workbench" ? activeWorkbenchView : void 0,
188
- allowEmpty: true,
189
- onValueChange: (next) => {
190
- updateAppView(() => {
191
- if (!next) {
192
- setMobileView("chat");
193
- return;
194
- }
195
- setWorkbenchView(next);
196
- setMobileView("workbench");
197
- });
198
- },
199
- "aria-label": "App views"
200
- }) : null
201
- ] }) : void 0;
151
+ const viewSwitch = availableWorkbenchPanels.length ? /* @__PURE__ */ jsx(ThinkFullAppViewSwitch, {
152
+ views: availableWorkbenchPanels,
153
+ value: activePanel?.id,
154
+ allowEmpty: true,
155
+ "aria-label": "App views",
156
+ onValueChange: (next) => updateView(next ?? "chat")
157
+ }) : null;
158
+ const appBarActions = bar?.actions || viewSwitch ? /* @__PURE__ */ jsxs(Fragment, { children: [bar?.actions, viewSwitch] }) : void 0;
202
159
  const appContent = /* @__PURE__ */ jsxs(ResizableSidePanel.Root, {
203
160
  ref: mergeRefs(appRef, ref),
204
161
  className: cx("think-full-app", className),
205
162
  label: "workbench",
206
163
  side: "start",
164
+ sizeVariable: "--think-full-app-conversation-size",
207
165
  defaultSize: conversationDefaultWidth,
208
166
  minSize: conversationMinWidth,
209
167
  maxSize: conversationMaxWidth,
@@ -212,6 +170,7 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
212
170
  "data-mobile-view": activeMobileView,
213
171
  style,
214
172
  ...props,
173
+ "data-recipe": "fill-host",
215
174
  children: [/* @__PURE__ */ jsxs("div", {
216
175
  className: "think-full-app__view-scope",
217
176
  "data-mobile-view": activeMobileView,
@@ -234,10 +193,10 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
234
193
  })
235
194
  })
236
195
  })
237
- }), hasAvailableWorkbench ? /* @__PURE__ */ jsx("aside", {
196
+ }), activePanel ? /* @__PURE__ */ jsx("aside", {
238
197
  className: "think-full-app__aside",
239
198
  "aria-label": "Workbench",
240
- children: activePanel ? /* @__PURE__ */ jsx("div", {
199
+ children: /* @__PURE__ */ jsx("div", {
241
200
  className: "think-full-app__workbench-slot",
242
201
  children: /* @__PURE__ */ jsx(React.ViewTransition, {
243
202
  default: "sigvelo-layout-transition",
@@ -248,7 +207,7 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
248
207
  children: activePanel.render()
249
208
  })
250
209
  })
251
- }) : null
210
+ })
252
211
  }) : null]
253
212
  }), activePanel ? /* @__PURE__ */ jsx(ResizableSidePanel.Handle, { className: "think-full-app__resizer" }) : null]
254
213
  });
@@ -269,26 +228,18 @@ function ThinkFullApp({ appBarActions, appBarLeading, appBarTitle, compactAppBar
269
228
  className: "think-full-app-shell",
270
229
  sidebar: threadSidebar,
271
230
  sidebarLabel: "threads",
272
- sidebarOpen: threadSidebarOpen,
273
- defaultSidebarOpen: defaultThreadSidebarOpen,
274
- onSidebarOpenChange: onThreadSidebarOpenChange,
275
231
  showMainLabel: "Show selected thread",
276
- topBarHidden: !hasAppBarRow,
277
- topBarProps: {
232
+ bar: {
233
+ ...bar,
234
+ actions: appBarActions,
278
235
  className: "think-full-app__app-bar",
279
- "aria-label": "Workbench controls",
280
- "data-app-chrome": hasApplicationChrome || shouldShowWorkbenchViewSwitch ? "true" : "false",
281
- "data-mobile-view": activeMobileView,
282
- "data-hide-in-workbench": hideAppBarInWorkbench ? "" : void 0
236
+ label: "Workbench controls",
237
+ hidden: !hasAppBarRow,
238
+ compactTitleTrigger: threadSidebar ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
239
+ className: "sigvelo-truncate",
240
+ children: bar?.title ?? "Threads"
241
+ }), threadStatusSummary ? /* @__PURE__ */ jsx(ThinkThreadStatusIndicators, { summary: threadStatusSummary }) : null] }) : void 0
283
242
  },
284
- topBarLeading: appBarLeading,
285
- compactTopBarLeading: compactAppBarLeading,
286
- topBarTitle: appBarTitle,
287
- compactTitleTrigger: threadSidebar ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
288
- className: "sigvelo-truncate",
289
- children: appBarTitle ?? "Threads"
290
- }), threadStatusSummary ? /* @__PURE__ */ jsx(ThinkThreadStatusIndicators, { summary: threadStatusSummary }) : null] }) : void 0,
291
- topBarTrailing: appBarTrailing,
292
243
  children: app
293
244
  });
294
245
  }
@@ -1,4 +1,4 @@
1
- import { r as ToggleGroupProps } from "../../ToggleGroup-BrQZOQn_.js";
1
+ import { ToggleGroupProps } from "../foundations/ToggleGroup.js";
2
2
  import * as React from "react";
3
3
 
4
4
  //#region src/components/agents-sdk/ThinkFullAppViewSwitch.d.ts
@@ -1,6 +1,6 @@
1
1
  import { n as mergeBaseClassName } from "../../class-names-BiMDVpUo.js";
2
- import { AppTopBar } from "../general-purpose/AppTopBar.js";
3
2
  import { ToggleGroup } from "../foundations/ToggleGroup.js";
3
+ import { AppTopBar } from "../general-purpose/AppTopBar.js";
4
4
  import "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/agents-sdk/ThinkFullAppViewSwitch.tsx
@@ -1,6 +1,6 @@
1
1
  import { t as cx } from "../../class-names-BiMDVpUo.js";
2
- import { getThinkRoutineNextRun } from "./ThinkRoutine.js";
3
2
  import { Switch } from "../foundations/Switch.js";
3
+ import { getThinkRoutineNextRun } from "./ThinkRoutine.js";
4
4
  import { ThinkRoutineRuns } from "./ThinkRoutineRuns.js";
5
5
  import * as React from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,3 +1,4 @@
1
+ import { AppBarSlots } from "../general-purpose/ResponsiveSidebarShell.js";
1
2
  import { ThinkRoutine, ThinkRoutineRunOf } from "./ThinkRoutine.js";
2
3
  import * as React from "react";
3
4
 
@@ -29,10 +30,11 @@ interface ThinkRoutineLibraryProps<TRoutine extends ThinkRoutine = ThinkRoutine>
29
30
  showOwner?: boolean;
30
31
  /** Host-owned catalog error shown above the library without replacing loaded routines. */
31
32
  error?: React.ReactNode;
32
- /** Product navigation rendered after the built-in schedule navigation control. */
33
- appBarLeading?: React.ReactNode;
34
- /** Product navigation rendered before the selected schedule actions. */
35
- appBarActions?: React.ReactNode;
33
+ /**
34
+ * Application bar slots. `title` defaults to the selected schedule's name;
35
+ * `actions` render before the built-in schedule actions.
36
+ */
37
+ bar?: AppBarSlots;
36
38
  /** Starts the selected routine immediately. */
37
39
  onRunRoutine?: (routine: TRoutine) => void | Promise<void>;
38
40
  /** Activates or pauses the selected app-owned routine. */
@@ -54,8 +56,7 @@ interface ThinkRoutineLibraryProps<TRoutine extends ThinkRoutine = ThinkRoutine>
54
56
  * route and may also use these surfaces independently.
55
57
  */
56
58
  declare function ThinkRoutineLibrary<TRoutine extends ThinkRoutine = ThinkRoutine>({
57
- appBarActions,
58
- appBarLeading,
59
+ bar,
59
60
  className,
60
61
  createRoutineLink,
61
62
  error: catalogError,