@mcp-b/react-components 0.33.0 → 0.34.1

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.
@@ -10,11 +10,21 @@ import { AgentToolRunState } from "agents/agent-tools";
10
10
  interface AgentToolDetailProps<State = unknown, MessageT extends UIMessage = UIMessage> extends React.HTMLAttributes<HTMLDivElement> {
11
11
  /** Whole retained run selected from the parent `useAgentToolEvents` result. */
12
12
  run: AgentToolRunState<MessageT["parts"][number]>;
13
- /** Whole child Think chat hook result; it owns the stored child transcript. */
14
- chat: ThinkChatValue<State, MessageT>;
13
+ /**
14
+ * Whole child Think chat hook result; it owns the stored child transcript.
15
+ * Optional because the run's chrome is parent-side data: while the child
16
+ * transcript is still loading, the detail renders without it and the chat
17
+ * region shows a loading status instead.
18
+ */
19
+ chat?: ThinkChatValue<State, MessageT>;
15
20
  messages?: ThinkChatMessagesProps<MessageT>;
16
21
  /** App-authored TanStack Router Link to the parent conversation. */
17
22
  backLink?: React.ReactElement;
23
+ /**
24
+ * Route-owned run controls (the app's cancel callable, for example),
25
+ * rendered in a `SubagentRunActions` bar pinned to the bottom edge.
26
+ */
27
+ actions?: React.ReactNode;
18
28
  }
19
29
  /**
20
30
  * Live retained-child detail composed from upstream connection and chat values.
@@ -22,6 +32,7 @@ interface AgentToolDetailProps<State = unknown, MessageT extends UIMessage = UIM
22
32
  * compact parent-side stream projection and is never promoted to fake history.
23
33
  */
24
34
  declare function AgentToolDetail<State = unknown, MessageT extends UIMessage = UIMessage>({
35
+ actions,
25
36
  backLink,
26
37
  chat,
27
38
  className,
@@ -41,9 +52,25 @@ interface SelectedAgentToolChildProps<ParentAgentT extends ThinkAgent<ParentStat
41
52
  * configuration as the parent; the selected `run.subAgent` is appended.
42
53
  */
43
54
  connectionOptions?: UseAgentOptions<ChildState>;
55
+ /**
56
+ * Initial child-transcript loader for hosts that do not serve the agent HTTP
57
+ * routes (upstream's default fetches `/get-messages` over HTTP). Receives the
58
+ * connected child agent so socket-only hosts can read through its stub;
59
+ * wired into `useAgentChat({ getInitialMessages })`.
60
+ */
61
+ getInitialMessages?: (childAgent: ReturnType<typeof useAgent<ThinkAgent<ChildState>, ChildState>>) => Promise<MessageT[]>;
44
62
  messages?: ThinkChatMessagesProps<MessageT>;
45
63
  /** App-authored TanStack Router Link to the parent conversation. */
46
64
  backLink?: React.ReactElement;
65
+ /**
66
+ * Replaces the whole detail while the child transcript loads. Defaults to
67
+ * the detail surface itself with a loading chat region, so the run's chrome
68
+ * — back link, run state, and pinned actions such as cancel — is available
69
+ * the moment the route opens.
70
+ */
71
+ fallback?: React.ReactNode;
72
+ /** Route-owned run controls, forwarded to `AgentToolDetail`'s pinned actions bar. */
73
+ actions?: React.ReactNode;
47
74
  }
48
75
  /**
49
76
  * Child connection options for a selected retained run: the parent's
@@ -58,10 +85,22 @@ declare function selectedAgentToolChildOptions<ChildState = unknown>(parentAgent
58
85
  name: string;
59
86
  }>;
60
87
  }, run: Pick<AgentToolRunState, "subAgent">, connectionOptions?: UseAgentOptions<ChildState>): UseAgentOptions<ChildState>;
61
- /** Lazily connects one selected retained child and renders its real Think chat. */
88
+ /**
89
+ * Lazily connects one selected retained child and renders its real Think chat.
90
+ *
91
+ * The Suspense boundary between the connection and the chat is load-bearing:
92
+ * the child socket opens in an effect, and `useAgentChat` suspends while the
93
+ * initial transcript loads. Under one suspension the render never commits, the
94
+ * effect never runs, and the socket the load is waiting on never dials — so
95
+ * this component holds the connection and always commits, while the chat
96
+ * suspends behind the internal boundary.
97
+ */
62
98
  declare function SelectedAgentToolChild<ParentAgentT extends ThinkAgent<ParentState>, ParentState = unknown, ChildState = unknown, MessageT extends UIMessage = UIMessage>({
99
+ actions,
63
100
  backLink,
64
101
  connectionOptions,
102
+ fallback,
103
+ getInitialMessages,
65
104
  messages,
66
105
  parentAgent,
67
106
  run
@@ -1,7 +1,7 @@
1
1
  import { t as cx } from "../../class-names-BiMDVpUo.js";
2
- import { r as ArrowLeftIcon } from "../../icons-B1Qw05te.js";
2
+ import { J as SpinnerIcon, r as ArrowLeftIcon } from "../../icons-B1Qw05te.js";
3
3
  import { TransitionSurface } from "../foundations/TransitionSurface.js";
4
- import { SubagentRunMilestone, SubagentRunMilestones, SubagentRunProgress } from "../agents-sdk/SubagentRunDetails.js";
4
+ import { SubagentRunActions, SubagentRunMilestone, SubagentRunMilestones, SubagentRunProgress } from "../agents-sdk/SubagentRunDetails.js";
5
5
  import { SubagentRunIndicator, getSubagentRunName } from "../agents-sdk/SubagentRunIndicator.js";
6
6
  import { t as ThinkChat } from "../../ThinkChat-en0UbkVv.js";
7
7
  import { AppTopBar } from "../general-purpose/AppTopBar.js";
@@ -16,7 +16,7 @@ import { useAgent } from "agents/react";
16
16
  * The full child transcript comes from `chat.messages`; `run.parts` remains a
17
17
  * compact parent-side stream projection and is never promoted to fake history.
18
18
  */
19
- function AgentToolDetail({ backLink, chat, className, messages, ref, run, ...props }) {
19
+ function AgentToolDetail({ actions, backLink, chat, className, messages, ref, run, ...props }) {
20
20
  const backRef = React.useRef(null);
21
21
  const name = getSubagentRunName(run);
22
22
  const progressLabel = run.progress?.message ?? run.progress?.phase;
@@ -69,14 +69,20 @@ function AgentToolDetail({ backLink, chat, className, messages, ref, run, ...pro
69
69
  }) : null,
70
70
  /* @__PURE__ */ jsx("div", {
71
71
  className: "agent-tool-detail__chat",
72
- children: /* @__PURE__ */ jsx(ThinkChat.Provider, {
72
+ children: chat ? /* @__PURE__ */ jsx(ThinkChat.Provider, {
73
73
  chat,
74
74
  children: /* @__PURE__ */ jsx(ThinkChat.Messages, {
75
75
  ...messages,
76
76
  showComposer: false
77
77
  })
78
+ }) : /* @__PURE__ */ jsx("div", {
79
+ className: "agent-tool-detail__chat-loading",
80
+ role: "status",
81
+ "aria-label": `${name} transcript loading`,
82
+ children: /* @__PURE__ */ jsx(SpinnerIcon, {})
78
83
  })
79
- })
84
+ }),
85
+ actions ? /* @__PURE__ */ jsx(SubagentRunActions, { children: actions }) : null
80
86
  ]
81
87
  });
82
88
  }
@@ -95,14 +101,46 @@ function selectedAgentToolChildOptions(parentAgent, run, connectionOptions) {
95
101
  sub: [...connectionOptions?.sub ?? parentSubPath, run.subAgent]
96
102
  };
97
103
  }
98
- /** Lazily connects one selected retained child and renders its real Think chat. */
99
- function SelectedAgentToolChild({ backLink, connectionOptions, messages, parentAgent, run }) {
104
+ /**
105
+ * Lazily connects one selected retained child and renders its real Think chat.
106
+ *
107
+ * The Suspense boundary between the connection and the chat is load-bearing:
108
+ * the child socket opens in an effect, and `useAgentChat` suspends while the
109
+ * initial transcript loads. Under one suspension the render never commits, the
110
+ * effect never runs, and the socket the load is waiting on never dials — so
111
+ * this component holds the connection and always commits, while the chat
112
+ * suspends behind the internal boundary.
113
+ */
114
+ function SelectedAgentToolChild({ actions, backLink, connectionOptions, fallback, getInitialMessages, messages, parentAgent, run }) {
115
+ const childAgent = useAgent(selectedAgentToolChildOptions(parentAgent, run, connectionOptions));
116
+ return /* @__PURE__ */ jsx(React.Suspense, {
117
+ fallback: fallback ?? /* @__PURE__ */ jsx(AgentToolDetail, {
118
+ run,
119
+ messages,
120
+ backLink,
121
+ actions
122
+ }),
123
+ children: /* @__PURE__ */ jsx(SelectedAgentToolChildChat, {
124
+ actions,
125
+ backLink,
126
+ childAgent,
127
+ getInitialMessages,
128
+ messages,
129
+ run
130
+ }, run.runId)
131
+ });
132
+ }
133
+ function SelectedAgentToolChildChat({ actions, backLink, childAgent, getInitialMessages, messages, run }) {
100
134
  return /* @__PURE__ */ jsx(AgentToolDetail, {
101
135
  run,
102
- chat: useAgentChat({ agent: useAgent(selectedAgentToolChildOptions(parentAgent, run, connectionOptions)) }),
136
+ chat: useAgentChat({
137
+ agent: childAgent,
138
+ ...getInitialMessages ? { getInitialMessages: () => getInitialMessages(childAgent) } : {}
139
+ }),
103
140
  messages,
104
- backLink
105
- }, run.runId);
141
+ backLink,
142
+ actions
143
+ });
106
144
  }
107
145
  //#endregion
108
146
  export { AgentToolDetail, SelectedAgentToolChild, selectedAgentToolChildOptions };
@@ -1,6 +1,6 @@
1
1
  .agent-tool-detail {
2
2
  display: grid;
3
- grid-template-rows: auto auto minmax(0, 1fr);
3
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
4
4
  min-inline-size: 0;
5
5
  block-size: 100%;
6
6
  background-color: var(--sigvelo-color-surface);
@@ -47,8 +47,25 @@
47
47
  block-size: 100%;
48
48
  }
49
49
 
50
+ .agent-tool-detail__chat-loading {
51
+ display: grid;
52
+ place-items: center;
53
+ block-size: 100%;
54
+ color: var(--sigvelo-color-text-muted);
55
+ }
56
+
57
+ .agent-tool-detail > .subagent-run__actions {
58
+ grid-row: 4;
59
+ display: flex;
60
+ justify-content: center;
61
+ padding: var(--sigvelo-spacing-2) var(--sigvelo-spacing-3);
62
+ border-block-start: var(--sigvelo-border-width) var(--sigvelo-border-style)
63
+ var(--sigvelo-color-neutral-border-subtle);
64
+ }
65
+
50
66
  @media (forced-colors: active) {
51
- .agent-tool-detail__run-state {
67
+ .agent-tool-detail__run-state,
68
+ .agent-tool-detail > .subagent-run__actions {
52
69
  border-color: CanvasText;
53
70
  }
54
71
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/react-components",
3
- "version": "0.33.0",
3
+ "version": "0.34.1",
4
4
  "description": "MCP-B React components built on Base UI and shared design tokens, including Cloudflare Think chat primitives.",
5
5
  "homepage": "https://design-system.sigvelo.com",
6
6
  "bugs": {
@@ -58,7 +58,7 @@
58
58
  "streamdown": "^2.5.0",
59
59
  "unist-util-visit": "^5.1.0",
60
60
  "yet-another-react-lightbox": "^3.32.1",
61
- "@mcp-b/design-tokens": "0.33.0"
61
+ "@mcp-b/design-tokens": "0.34.1"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@ai-sdk/react": "^3.0.230",