@mcp-b/react-components 0.7.0 → 0.8.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.
- package/dist/AgentChat-403mckDG.d.ts +101 -0
- package/dist/BrowserLiveView-ZktFZiMD.d.ts +47 -0
- package/dist/BrowserReplay-6G-mnwcn.d.ts +40 -0
- package/dist/{CodeBlock-BK0sOAbV.js → CodeBlock-XNQOupQ3.js} +1 -1
- package/dist/{FileTree-BWQZ0FSi.js → FileTree-wMyZhhHO.js} +1 -1
- package/dist/ModelSelector-9G_-GooI.js +306 -0
- package/dist/ThinkChatActivity-CeHzk6-K.d.ts +73 -0
- package/dist/ThinkChatContext-BLAAb8J5.d.ts +28 -0
- package/dist/components/Activity.js +1 -1
- package/dist/components/AgentChat.d.ts +1 -100
- package/dist/components/AgentChat.js +12 -7
- package/dist/components/AgentConnection.d.ts +43 -2
- package/dist/components/AgentConnection.js +154 -3
- package/dist/components/Artifact.js +1 -1
- package/dist/components/BrowserLiveView.d.ts +1 -46
- package/dist/components/BrowserLiveView.js +1 -1
- package/dist/components/BrowserReplay.d.ts +1 -39
- package/dist/components/BrowserReplay.js +1 -1
- package/dist/components/ChainOfThought.d.ts +1 -1
- package/dist/components/ChainOfThought.js +1 -1
- package/dist/components/ChatGptSignInScreen.d.ts +38 -0
- package/dist/components/ChatGptSignInScreen.js +201 -0
- package/dist/components/CodeBlock.js +1 -1
- package/dist/components/Commit.js +1 -1
- package/dist/components/ContextMenu.js +1 -1
- package/dist/components/Conversation.js +1 -1
- package/dist/components/Dialog.js +1 -1
- package/dist/components/EnvironmentVariables.js +1 -1
- package/dist/components/FileTree.js +1 -1
- package/dist/components/McpServerPicker.js +7 -5
- package/dist/components/Menubar.js +1 -1
- package/dist/components/Message.js +1 -1
- package/dist/components/MessageScroller.js +2 -2
- package/dist/components/ModelSelector.js +1 -305
- package/dist/components/NavigationMenu.js +1 -1
- package/dist/components/PromptInput.js +6 -5
- package/dist/components/Queue.js +1 -1
- package/dist/components/Reasoning.js +1 -1
- package/dist/components/Select.js +1 -1
- package/dist/components/Sources.js +1 -1
- package/dist/components/Stepper.js +1 -1
- package/dist/components/Task.js +1 -1
- package/dist/components/Terminal.js +4 -3
- package/dist/components/TestResults.js +1 -1
- package/dist/components/ThinkChat.d.ts +15 -7
- package/dist/components/ThinkChat.js +1 -1
- package/dist/components/ThinkChatActivity.d.ts +2 -72
- package/dist/components/ThinkChatActivity.js +4 -3
- package/dist/components/ThinkChatContext.d.ts +1 -27
- package/dist/components/ThinkChatToolPanels.js +1 -1
- package/dist/components/ThinkChatToolParts.js +4 -4
- package/dist/components/ThinkExecutionWorkbench.d.ts +27 -0
- package/dist/components/ThinkExecutionWorkbench.js +450 -0
- package/dist/components/ThinkFullApp.d.ts +61 -0
- package/dist/components/ThinkFullApp.js +258 -0
- package/dist/components/ThinkThreadPicker.d.ts +88 -0
- package/dist/components/ThinkThreadPicker.js +282 -0
- package/dist/components/WebPreview.js +1 -1
- package/dist/components/WorkspaceExplorer.js +5 -4
- package/dist/components/icons.d.ts +2 -2
- package/dist/components/icons.js +2 -2
- package/dist/{copy-button-CB2MWcau.js → copy-button-C6JSKtFE.js} +1 -1
- package/dist/{icons-BYpJY6L2.d.ts → icons-CbjtbIJK.d.ts} +3 -1
- package/dist/{icons-BCNawx-T.js → icons-D2Q5n5C1.js} +37 -1
- package/dist/styles/agent-connection.css +33 -5
- package/dist/styles/chatgpt-sign-in-screen.css +224 -0
- package/dist/styles/code-block.css +3 -1
- package/dist/styles/index.css +3 -0
- package/dist/styles/message-scroller.css +24 -1
- package/dist/styles/prompt-input.css +1 -0
- package/dist/styles/think-full-app.css +731 -0
- package/dist/styles/think-thread-picker.css +449 -0
- package/dist/utils/mcp-server-catalog.d.ts +28 -3
- package/dist/utils/mcp-server-catalog.js +27 -1
- package/package.json +7 -8
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { et as PromptInputMessage, n as ExecutionApprovals } from "./PromptInput-D6-G24p7.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ChatAddToolApproveResponseFunction, ChatStatus, UIMessage } from "ai";
|
|
4
|
+
import { PendingApproval } from "@cloudflare/think";
|
|
5
|
+
|
|
6
|
+
//#region src/components/AgentChat.d.ts
|
|
7
|
+
type AgentChatPart<MessageT extends UIMessage = UIMessage> = MessageT["parts"][number];
|
|
8
|
+
interface AgentChatRenderPartContext<MessageT extends UIMessage = UIMessage> {
|
|
9
|
+
message: MessageT;
|
|
10
|
+
part: AgentChatPart<MessageT>;
|
|
11
|
+
partIndex: number;
|
|
12
|
+
defaultRender: () => React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
interface AgentChatRenderMessageContext<MessageT extends UIMessage = UIMessage> {
|
|
15
|
+
message: MessageT;
|
|
16
|
+
messageIndex: number;
|
|
17
|
+
}
|
|
18
|
+
interface AgentChatProps<MessageT extends UIMessage = UIMessage> {
|
|
19
|
+
className?: string;
|
|
20
|
+
/** AI SDK `UIMessage`s to render, oldest first. */
|
|
21
|
+
messages: readonly MessageT[];
|
|
22
|
+
/** Drives the composer's send/stop affordance and streaming indicators. */
|
|
23
|
+
status?: ChatStatus;
|
|
24
|
+
/** Called with the composed message when the user submits. Omit for a read-only transcript. */
|
|
25
|
+
onSubmit?: (message: PromptInputMessage) => void | Promise<void>;
|
|
26
|
+
/** Called when the user hits stop while `status` is streaming/submitted. */
|
|
27
|
+
onStop?: () => void;
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
/** Rendered in place of the transcript while `messages` is empty. */
|
|
31
|
+
emptyState?: React.ReactNode;
|
|
32
|
+
/** Extra controls rendered in the composer toolbar. */
|
|
33
|
+
composerTools?: React.ReactNode;
|
|
34
|
+
/** Extra rows rendered in the built-in plus menu after files. */
|
|
35
|
+
composerAddMenuItems?: React.ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Transient status rendered between the transcript and the composer —
|
|
38
|
+
* e.g. a "Reconnecting…" pill. `ThinkChat.Messages` fills this from the
|
|
39
|
+
* hook's `isRecovering`/`connectionError` automatically.
|
|
40
|
+
*/
|
|
41
|
+
notice?: React.ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* When set, the last assistant message gets a Retry action that calls this
|
|
44
|
+
* with its message id — pass to the AI SDK's `regenerate({ messageId })`.
|
|
45
|
+
*/
|
|
46
|
+
onRegenerate?: (messageId: string) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Pass `addToolApprovalResponse` from `useAgentChat`/`useChat` directly.
|
|
49
|
+
* When set and a tool call awaits approval, the composer becomes the
|
|
50
|
+
* confirmation.
|
|
51
|
+
*/
|
|
52
|
+
onApprovalResponse?: ChatAddToolApproveResponseFunction;
|
|
53
|
+
/** Resolves Think execution approvals. See {@link ExecutionApprovals}. */
|
|
54
|
+
executionApprovals?: ExecutionApprovals;
|
|
55
|
+
/** Think durable-pause approvals from `pendingApprovals()`, rendered when `executionApprovals` is set. */
|
|
56
|
+
pendingApprovals?: readonly PendingApproval[];
|
|
57
|
+
/**
|
|
58
|
+
* When set, a Context ring in the composer footer shows how much of the
|
|
59
|
+
* model's window the conversation occupies. Used tokens come from the
|
|
60
|
+
* newest message carrying `metadata.usage` (the AI SDK `messageMetadata`
|
|
61
|
+
* convention; Think merges it into message metadata as turns finish).
|
|
62
|
+
*/
|
|
63
|
+
contextWindow?: {
|
|
64
|
+
maxTokens: number;
|
|
65
|
+
modelId?: string;
|
|
66
|
+
};
|
|
67
|
+
/** Override rendering per part; return `undefined` to fall back to the default part UI. */
|
|
68
|
+
renderPart?: (context: AgentChatRenderPartContext<MessageT>) => React.ReactNode | undefined;
|
|
69
|
+
/** Rendered after each message's parts — for actions, citations, and the like. */
|
|
70
|
+
renderMessageAfter?: (context: AgentChatRenderMessageContext<MessageT>) => React.ReactNode;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Low-level transcript/composer surface used by `ThinkChat`: props in, no
|
|
74
|
+
* transport. Product code that talks to a Cloudflare Think agent should render
|
|
75
|
+
* `ThinkChat`; use this directly only for plain AI SDK or read-only messages.
|
|
76
|
+
*/
|
|
77
|
+
declare function AgentChat<MessageT extends UIMessage = UIMessage>({
|
|
78
|
+
className,
|
|
79
|
+
messages,
|
|
80
|
+
status,
|
|
81
|
+
onSubmit,
|
|
82
|
+
onStop,
|
|
83
|
+
placeholder,
|
|
84
|
+
disabled,
|
|
85
|
+
emptyState,
|
|
86
|
+
composerTools,
|
|
87
|
+
composerAddMenuItems,
|
|
88
|
+
notice,
|
|
89
|
+
onRegenerate,
|
|
90
|
+
onApprovalResponse,
|
|
91
|
+
executionApprovals,
|
|
92
|
+
pendingApprovals: durableApprovals,
|
|
93
|
+
contextWindow,
|
|
94
|
+
renderPart,
|
|
95
|
+
renderMessageAfter,
|
|
96
|
+
ref
|
|
97
|
+
}: AgentChatProps<MessageT> & {
|
|
98
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
99
|
+
}): React.JSX.Element;
|
|
100
|
+
//#endregion
|
|
101
|
+
export { AgentChatRenderPartContext as a, AgentChatRenderMessageContext as i, AgentChatPart as n, AgentChatProps as r, AgentChat as t };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/BrowserLiveView.d.ts
|
|
4
|
+
interface BrowserLiveViewProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Live View URL (Browser Run `devtoolsFrontendUrl`, e.g. live.browser.run). */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Epoch ms after which the URL is dead (Browser Run mints ~5-minute links). */
|
|
8
|
+
expiresAt?: number;
|
|
9
|
+
/** The page the session was showing — used for the ended-state text. */
|
|
10
|
+
pageTitle?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Shown once the link expires — pass the last screenshot the agent took
|
|
13
|
+
* (`<img>`) to keep the final frame on screen. Defaults to a quiet
|
|
14
|
+
* "Live view ended" state.
|
|
15
|
+
*/
|
|
16
|
+
fallback?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Embeds a Browser Run Live View — a real-time, interactive view of the
|
|
20
|
+
* agent's browser session. Links expire (~5 minutes), so the iframe swaps to
|
|
21
|
+
* `fallback` (e.g. the last screenshot) once `expiresAt` passes. While the
|
|
22
|
+
* hosted viewer connects, a quiet loading overlay hides the frame; if it
|
|
23
|
+
* never loads, the view degrades to `fallback` or an unavailable state. An
|
|
24
|
+
* expand button opens the same view in a fullscreen dialog.
|
|
25
|
+
*
|
|
26
|
+
* Where URLs come from (upstream: `agents/browser` in
|
|
27
|
+
* github.com/cloudflare/agents — `BrowserLiveViewUrl`): the model calls
|
|
28
|
+
* `cdp.getLiveViewUrl()` inside a `browser_execute` tool run, or the host
|
|
29
|
+
* calls `connector.liveView()`/`sessionInfo()`. This package's chat rendering
|
|
30
|
+
* derives the component automatically from links found in tool results.
|
|
31
|
+
*
|
|
32
|
+
* Styling rides `@mcp-b/react-components/styles` (browser-live-view.css),
|
|
33
|
+
* which think-chat consumers load anyway.
|
|
34
|
+
*
|
|
35
|
+
* The iframe is unsandboxed by design: the hosted Live View UI needs scripts
|
|
36
|
+
* and its own origin to stream the session. Only pass trusted Live View URLs.
|
|
37
|
+
*/
|
|
38
|
+
declare function BrowserLiveView({
|
|
39
|
+
url,
|
|
40
|
+
expiresAt,
|
|
41
|
+
pageTitle,
|
|
42
|
+
fallback,
|
|
43
|
+
className,
|
|
44
|
+
...props
|
|
45
|
+
}: BrowserLiveViewProps): React.JSX.Element;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { BrowserLiveViewProps as n, BrowserLiveView as t };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/components/BrowserReplay.d.ts
|
|
4
|
+
interface BrowserReplayProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
5
|
+
/**
|
|
6
|
+
* rrweb events for one tab, e.g. one
|
|
7
|
+
* `BrowserRecording.events[targetId]` entry from Cloudflare Browser Run.
|
|
8
|
+
*/
|
|
9
|
+
events: unknown[];
|
|
10
|
+
/** Start playing on mount. */
|
|
11
|
+
autoPlay?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Replays a completed Cloudflare Browser Run recording locally with rrweb.
|
|
15
|
+
*
|
|
16
|
+
* This is intentionally not derived from Think chat message parts. Live view
|
|
17
|
+
* links and screenshots ride the `browser_execute` stream and belong to
|
|
18
|
+
* `BrowserLiveView`; replay events are fetched after a session closes with
|
|
19
|
+
* Browser Run's `getBrowserRecording()`. Upstream currently shapes those
|
|
20
|
+
* recordings as `Record<targetId, unknown[]>`, where each array is plain rrweb
|
|
21
|
+
* JSON for one tab. Playback happens in the viewer's browser through
|
|
22
|
+
* `@rrweb/replay`; no replay service is contacted at playback time.
|
|
23
|
+
*
|
|
24
|
+
* Styling rides `@mcp-b/react-components/styles` (browser-replay.css), which
|
|
25
|
+
* think-chat consumers load anyway.
|
|
26
|
+
*
|
|
27
|
+
* @see https://github.com/cloudflare/agents/tree/main/packages/agents/src/browser
|
|
28
|
+
* @see https://github.com/rrweb-io/rrweb/tree/main/packages/%40rrweb/replay
|
|
29
|
+
*/
|
|
30
|
+
declare function BrowserReplay({
|
|
31
|
+
className,
|
|
32
|
+
events,
|
|
33
|
+
autoPlay,
|
|
34
|
+
ref,
|
|
35
|
+
...props
|
|
36
|
+
}: BrowserReplayProps & {
|
|
37
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
38
|
+
}): React.JSX.Element;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { BrowserReplayProps as n, BrowserReplay as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as cx } from "./class-names-9UtZwb0J.js";
|
|
2
2
|
import { Select, SelectContent, SelectItem, SelectList, SelectTrigger, SelectValue } from "./components/Select.js";
|
|
3
|
-
import { t as CopyButton } from "./copy-button-
|
|
3
|
+
import { t as CopyButton } from "./copy-button-C6JSKtFE.js";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { createHighlighter } from "shiki";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cx } from "./class-names-9UtZwb0J.js";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as FolderOpenIcon, c as ChevronRightIcon, g as FolderIcon, h as FileIcon } from "./icons-D2Q5n5C1.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/_internal/use-file-tree-nav.ts
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { t as cx } from "./class-names-9UtZwb0J.js";
|
|
2
|
+
import { A as SearchIcon, o as ChevronDownIcon } from "./icons-D2Q5n5C1.js";
|
|
3
|
+
import { Button } from "./components/Button.js";
|
|
4
|
+
import { Dialog, DialogBackdrop, DialogPopup, DialogPortal, DialogTitle, DialogTrigger } from "./components/Dialog.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/_internal/provider-logos.tsx
|
|
8
|
+
function Svg({ children, size = 16, ...props }) {
|
|
9
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
10
|
+
width: size,
|
|
11
|
+
height: size,
|
|
12
|
+
viewBox: "0 0 24 24",
|
|
13
|
+
fill: "currentColor",
|
|
14
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
focusable: "false",
|
|
17
|
+
...props,
|
|
18
|
+
children
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const OpenAILogo = (props) => /* @__PURE__ */ jsx(Svg, {
|
|
22
|
+
...props,
|
|
23
|
+
children: /* @__PURE__ */ jsx("path", { d: "M22.28 9.81a5.99 5.99 0 0 0-.52-4.91 6.05 6.05 0 0 0-6.52-2.9A6.05 6.05 0 0 0 10.58 0a6.05 6.05 0 0 0-5.77 4.18 5.99 5.99 0 0 0-4 2.9 6.05 6.05 0 0 0 .74 7.09 5.99 5.99 0 0 0 .52 4.91 6.05 6.05 0 0 0 6.52 2.9A5.99 5.99 0 0 0 13.25 24a6.05 6.05 0 0 0 5.77-4.19 5.99 5.99 0 0 0 4-2.9 6.05 6.05 0 0 0-.74-7.1ZM13.25 22.44a4.48 4.48 0 0 1-2.88-1.04l.14-.08 4.79-2.76a.78.78 0 0 0 .39-.68v-6.75l2.02 1.17c.02 0 .04.03.04.05v5.58a4.5 4.5 0 0 1-4.5 4.5ZM3.57 18.3a4.5 4.5 0 0 1-.54-3.03l.14.09 4.79 2.76a.78.78 0 0 0 .78 0l5.85-3.37v2.33c0 .02 0 .04-.03.06L9.72 19.94a4.5 4.5 0 0 1-6.15-1.64ZM2.31 7.88a4.48 4.48 0 0 1 2.35-1.97v5.69a.78.78 0 0 0 .39.67l5.83 3.36-2.02 1.17a.07.07 0 0 1-.07 0l-4.83-2.8A4.5 4.5 0 0 1 2.3 7.9Zm16.64 3.87L13.1 8.37l2.02-1.17c.02 0 .05-.01.07 0l4.83 2.8a4.5 4.5 0 0 1-.67 8.11V12.4a.77.77 0 0 0-.4-.66Zm2-3.03-.14-.09-4.78-2.78a.78.78 0 0 0-.79 0L9.4 9.25V6.92c0-.02 0-.04.02-.05l4.83-2.79a4.5 4.5 0 0 1 6.68 4.66Zm-12.68 4.17-2.02-1.17a.07.07 0 0 1-.04-.06V6.1a4.5 4.5 0 0 1 7.38-3.45l-.14.08L8.66 5.5a.78.78 0 0 0-.4.68v6.74Zm1.1-2.36 2.6-1.5 2.61 1.5v3l-2.6 1.5-2.6-1.5Z" })
|
|
24
|
+
});
|
|
25
|
+
const AnthropicLogo = (props) => /* @__PURE__ */ jsxs(Svg, {
|
|
26
|
+
...props,
|
|
27
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M13.83 4H17.3L24 20h-3.47l-1.37-3.52h-7L10.82 20H7.36ZM13.25 13.58h4.8l-2.4-6.15Z" }), /* @__PURE__ */ jsx("path", { d: "M0 4h3.47l6.7 16H6.7Z" })]
|
|
28
|
+
});
|
|
29
|
+
const GoogleLogo = (props) => /* @__PURE__ */ jsx(Svg, {
|
|
30
|
+
...props,
|
|
31
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 2a8 8 0 0 1 5.34 2.05l-2.2 2.2A5 5 0 1 0 17 12.6h-5v-2.6h7.9A8 8 0 0 1 12 20 8 8 0 0 1 12 4Z" })
|
|
32
|
+
});
|
|
33
|
+
const MetaLogo = (props) => /* @__PURE__ */ jsx(Svg, {
|
|
34
|
+
...props,
|
|
35
|
+
children: /* @__PURE__ */ jsx("path", { d: "M2 12.5c0-3.5 1.8-6.5 4.4-6.5 1.8 0 3.2 1.3 4.9 3.8 2.2 3.2 3.3 5 4.6 5 1 0 1.5-.8 1.5-2.3 0-2.1-1-4.3-2.7-4.3-1 0-2 .6-3.2 2l-1.3-1.7C11.5 6.8 12.9 6 14.5 6c3 0 5.5 3.3 5.5 7 0 3.3-1.6 5-3.8 5-2.3 0-3.6-1.6-6-5.3C8.9 10.4 8 9.2 6.8 9.2 5.4 9.2 4.3 10.6 4.3 13c0 1.8.5 3 1.3 3 .6 0 1.1-.3 1.8-1.1l1.3 1.7C7.6 17.6 6.3 18 5.3 18 3.3 18 2 16 2 12.5Z" })
|
|
36
|
+
});
|
|
37
|
+
const KimiLogo = (props) => /* @__PURE__ */ jsxs(Svg, {
|
|
38
|
+
...props,
|
|
39
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
40
|
+
cx: "12",
|
|
41
|
+
cy: "12",
|
|
42
|
+
r: "9.5",
|
|
43
|
+
fill: "none",
|
|
44
|
+
stroke: "currentColor",
|
|
45
|
+
strokeWidth: "1.5"
|
|
46
|
+
}), /* @__PURE__ */ jsx("path", {
|
|
47
|
+
d: "M8 7.5v9M8 12l4.5-4.5M8 12l5 4.5M14 7.5h2.5v9H14z",
|
|
48
|
+
fill: "none",
|
|
49
|
+
stroke: "currentColor",
|
|
50
|
+
strokeWidth: "1.5",
|
|
51
|
+
strokeLinecap: "round",
|
|
52
|
+
strokeLinejoin: "round"
|
|
53
|
+
})]
|
|
54
|
+
});
|
|
55
|
+
const FallbackLogo = (props) => /* @__PURE__ */ jsx(Svg, {
|
|
56
|
+
...props,
|
|
57
|
+
children: /* @__PURE__ */ jsx("circle", {
|
|
58
|
+
cx: "12",
|
|
59
|
+
cy: "12",
|
|
60
|
+
r: "3"
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Resolves a provider string to its logo component.
|
|
65
|
+
* Unknown providers get a neutral dot fallback.
|
|
66
|
+
*/
|
|
67
|
+
function ProviderLogo({ provider, ...props }) {
|
|
68
|
+
switch (provider.toLowerCase()) {
|
|
69
|
+
case "openai": return /* @__PURE__ */ jsx(OpenAILogo, { ...props });
|
|
70
|
+
case "anthropic": return /* @__PURE__ */ jsx(AnthropicLogo, { ...props });
|
|
71
|
+
case "google": return /* @__PURE__ */ jsx(GoogleLogo, { ...props });
|
|
72
|
+
case "meta": return /* @__PURE__ */ jsx(MetaLogo, { ...props });
|
|
73
|
+
case "kimi": return /* @__PURE__ */ jsx(KimiLogo, { ...props });
|
|
74
|
+
default: return /* @__PURE__ */ jsx(FallbackLogo, { ...props });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/components/ModelSelector.tsx
|
|
79
|
+
const ModelSelectorContext = React.createContext(null);
|
|
80
|
+
function useModelSelectorContext() {
|
|
81
|
+
const ctx = React.useContext(ModelSelectorContext);
|
|
82
|
+
if (!ctx) throw new Error("ModelSelector subcomponents must be used inside <ModelSelector>.");
|
|
83
|
+
return ctx;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A searchable model picker. Click the trigger to open a dialog containing a
|
|
87
|
+
* search input and a grouped list of available models.
|
|
88
|
+
*
|
|
89
|
+
* Built internally for AI model selection. Use it when users choose one model
|
|
90
|
+
* from a grouped provider list. Do not use it as a general command palette or
|
|
91
|
+
* multiselect; use Combobox or a dedicated component for that.
|
|
92
|
+
*
|
|
93
|
+
* Sigvelo changes: composes the design-system Dialog and Button, filters item
|
|
94
|
+
* children locally, and maps provider logos plus listbox styling to Sigvelo
|
|
95
|
+
* CSS tokens.
|
|
96
|
+
*
|
|
97
|
+
* The dialog owns focus while open, the list uses `role="listbox"`, and items
|
|
98
|
+
* use `role="option"` with `aria-selected`. Styling consumes surface, border,
|
|
99
|
+
* spacing, radius, focus, and typography tokens. Add provider/item affordances
|
|
100
|
+
* here when they need to be shared.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* <ModelSelector>
|
|
105
|
+
* <ModelSelectorTrigger>
|
|
106
|
+
* <ModelSelectorLogo provider="anthropic" />
|
|
107
|
+
* <ModelSelectorName>Claude Opus 4.6</ModelSelectorName>
|
|
108
|
+
* </ModelSelectorTrigger>
|
|
109
|
+
* <ModelSelectorContent>
|
|
110
|
+
* <ModelSelectorDialog>
|
|
111
|
+
* <ModelSelectorInput placeholder="Search models…" />
|
|
112
|
+
* <ModelSelectorList>
|
|
113
|
+
* <ModelSelectorGroup label="Anthropic">
|
|
114
|
+
* <ModelSelectorItem value="claude-opus-4-6" onSelect={…}>
|
|
115
|
+
* <ModelSelectorLogo provider="anthropic" />
|
|
116
|
+
* <ModelSelectorName>Claude Opus 4.6</ModelSelectorName>
|
|
117
|
+
* </ModelSelectorItem>
|
|
118
|
+
* </ModelSelectorGroup>
|
|
119
|
+
* </ModelSelectorList>
|
|
120
|
+
* </ModelSelectorDialog>
|
|
121
|
+
* </ModelSelectorContent>
|
|
122
|
+
* </ModelSelector>
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
function ModelSelector({ open, defaultOpen = false, onOpenChange, children, className, ref, ...props }) {
|
|
126
|
+
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
127
|
+
const [query, setQuery] = React.useState("");
|
|
128
|
+
const isControlled = open !== void 0;
|
|
129
|
+
const currentOpen = isControlled ? open : internalOpen;
|
|
130
|
+
const handleOpenChange = React.useCallback((next) => {
|
|
131
|
+
if (!isControlled) setInternalOpen(next);
|
|
132
|
+
onOpenChange?.(next);
|
|
133
|
+
if (!next) setQuery("");
|
|
134
|
+
}, [isControlled, onOpenChange]);
|
|
135
|
+
const onSelectItem = React.useCallback(() => {
|
|
136
|
+
handleOpenChange(false);
|
|
137
|
+
}, [handleOpenChange]);
|
|
138
|
+
const ctxValue = React.useMemo(() => ({
|
|
139
|
+
query,
|
|
140
|
+
setQuery,
|
|
141
|
+
onSelectItem
|
|
142
|
+
}), [query, onSelectItem]);
|
|
143
|
+
return /* @__PURE__ */ jsx(ModelSelectorContext.Provider, {
|
|
144
|
+
value: ctxValue,
|
|
145
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
146
|
+
ref,
|
|
147
|
+
className: cx("model-selector", className),
|
|
148
|
+
...props,
|
|
149
|
+
children: /* @__PURE__ */ jsx(Dialog, {
|
|
150
|
+
open: currentOpen,
|
|
151
|
+
onOpenChange: handleOpenChange,
|
|
152
|
+
children
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function ModelSelectorTrigger({ className, children, ...props }) {
|
|
158
|
+
return /* @__PURE__ */ jsx(DialogTrigger, { render: /* @__PURE__ */ jsxs(Button, {
|
|
159
|
+
variant: "outline",
|
|
160
|
+
color: "neutral",
|
|
161
|
+
className: cx("model-selector__trigger", className),
|
|
162
|
+
...props,
|
|
163
|
+
children: [children, /* @__PURE__ */ jsx("span", {
|
|
164
|
+
className: "model-selector__trigger-chevron",
|
|
165
|
+
"aria-hidden": "true",
|
|
166
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
167
|
+
})]
|
|
168
|
+
}) });
|
|
169
|
+
}
|
|
170
|
+
function ModelSelectorContent({ children, title = "Model Selector", ...props }) {
|
|
171
|
+
return /* @__PURE__ */ jsxs(DialogPortal, { children: [/* @__PURE__ */ jsx(DialogBackdrop, {}), /* @__PURE__ */ jsxs(DialogPopup, {
|
|
172
|
+
...props,
|
|
173
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
174
|
+
className: "model-selector__title",
|
|
175
|
+
children: title
|
|
176
|
+
}), children]
|
|
177
|
+
})] });
|
|
178
|
+
}
|
|
179
|
+
function ModelSelectorDialog({ className, children, ref, ...props }) {
|
|
180
|
+
return /* @__PURE__ */ jsx("div", {
|
|
181
|
+
ref,
|
|
182
|
+
className: cx("model-selector__dialog", className),
|
|
183
|
+
...props,
|
|
184
|
+
children
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function ModelSelectorInput({ className, placeholder = "Search models…", ref, ...props }) {
|
|
188
|
+
const { query, setQuery } = useModelSelectorContext();
|
|
189
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
190
|
+
className: "model-selector__search",
|
|
191
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
192
|
+
className: "model-selector__search-icon",
|
|
193
|
+
"aria-hidden": "true",
|
|
194
|
+
children: /* @__PURE__ */ jsx(SearchIcon, {})
|
|
195
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
196
|
+
ref,
|
|
197
|
+
type: "search",
|
|
198
|
+
value: query,
|
|
199
|
+
onChange: (e) => setQuery(e.target.value),
|
|
200
|
+
placeholder,
|
|
201
|
+
className: cx("model-selector__input", className),
|
|
202
|
+
autoFocus: true,
|
|
203
|
+
...props
|
|
204
|
+
})]
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function ModelSelectorList({ className, children, ref, ...props }) {
|
|
208
|
+
return /* @__PURE__ */ jsx("div", {
|
|
209
|
+
ref,
|
|
210
|
+
role: "listbox",
|
|
211
|
+
className: cx("model-selector__list", className),
|
|
212
|
+
...props,
|
|
213
|
+
children
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function ModelSelectorGroup({ className, label, children, ref, ...props }) {
|
|
217
|
+
const { query } = useModelSelectorContext();
|
|
218
|
+
const childArray = React.Children.toArray(children).filter((child) => React.isValidElement(child));
|
|
219
|
+
const q = query.trim().toLowerCase();
|
|
220
|
+
const filtered = q ? childArray.filter((child) => {
|
|
221
|
+
const value = String(child.props.value ?? "").toLowerCase();
|
|
222
|
+
const keywords = String(child.props.keywords ?? "").toLowerCase();
|
|
223
|
+
return value.includes(q) || keywords.includes(q);
|
|
224
|
+
}) : childArray;
|
|
225
|
+
if (filtered.length === 0) return null;
|
|
226
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
227
|
+
ref,
|
|
228
|
+
role: "group",
|
|
229
|
+
"aria-label": label,
|
|
230
|
+
className: cx("model-selector__group", className),
|
|
231
|
+
...props,
|
|
232
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
233
|
+
className: "model-selector__group-label",
|
|
234
|
+
children: label
|
|
235
|
+
}), filtered]
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function ModelSelectorItem({ className, value, keywords, selected, onSelect, children, onClick, ref, ...props }) {
|
|
239
|
+
const { onSelectItem } = useModelSelectorContext();
|
|
240
|
+
const handleClick = (e) => {
|
|
241
|
+
onSelect?.(value);
|
|
242
|
+
onSelectItem();
|
|
243
|
+
onClick?.(e);
|
|
244
|
+
};
|
|
245
|
+
return /* @__PURE__ */ jsx("button", {
|
|
246
|
+
ref,
|
|
247
|
+
type: "button",
|
|
248
|
+
role: "option",
|
|
249
|
+
"aria-selected": selected,
|
|
250
|
+
"data-selected": selected ? "" : void 0,
|
|
251
|
+
className: cx("model-selector__item", className),
|
|
252
|
+
onClick: handleClick,
|
|
253
|
+
...props,
|
|
254
|
+
children
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function ModelSelectorEmpty({ className, children = "No models found", ref, ...props }) {
|
|
258
|
+
return /* @__PURE__ */ jsx("div", {
|
|
259
|
+
ref,
|
|
260
|
+
className: cx("model-selector__empty", className),
|
|
261
|
+
...props,
|
|
262
|
+
children
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function ModelSelectorSeparator({ className, ref, ...props }) {
|
|
266
|
+
return /* @__PURE__ */ jsx("hr", {
|
|
267
|
+
ref,
|
|
268
|
+
className: cx("model-selector__separator", className),
|
|
269
|
+
...props
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function ModelSelectorLogo({ className, provider, ...props }) {
|
|
273
|
+
return /* @__PURE__ */ jsx("span", {
|
|
274
|
+
className: cx("model-selector__logo", className),
|
|
275
|
+
children: /* @__PURE__ */ jsx(ProviderLogo, {
|
|
276
|
+
provider,
|
|
277
|
+
...props
|
|
278
|
+
})
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
function ModelSelectorLogoGroup({ className, children, ref, ...props }) {
|
|
282
|
+
return /* @__PURE__ */ jsx("div", {
|
|
283
|
+
ref,
|
|
284
|
+
className: cx("model-selector__logo-group", className),
|
|
285
|
+
...props,
|
|
286
|
+
children
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function ModelSelectorName({ className, children, ref, ...props }) {
|
|
290
|
+
return /* @__PURE__ */ jsx("span", {
|
|
291
|
+
ref,
|
|
292
|
+
className: cx("model-selector__name", className),
|
|
293
|
+
...props,
|
|
294
|
+
children
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function ModelSelectorShortcut({ className, children, ref, ...props }) {
|
|
298
|
+
return /* @__PURE__ */ jsx("kbd", {
|
|
299
|
+
ref,
|
|
300
|
+
className: cx("model-selector__shortcut", className),
|
|
301
|
+
...props,
|
|
302
|
+
children
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
//#endregion
|
|
306
|
+
export { ModelSelectorGroup as a, ModelSelectorList as c, ModelSelectorName as d, ModelSelectorSeparator as f, ModelSelectorEmpty as i, ModelSelectorLogo as l, ModelSelectorTrigger as m, ModelSelectorContent as n, ModelSelectorInput as o, ModelSelectorShortcut as p, ModelSelectorDialog as r, ModelSelectorItem as s, ModelSelector as t, ModelSelectorLogoGroup as u };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { a as AgentChatRenderPartContext, r as AgentChatProps } from "./AgentChat-403mckDG.js";
|
|
2
|
+
import { s as ThinkChatPart } from "./ThinkChatToolParts-DnUiZgCC.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { DynamicToolUIPart, ToolUIPart, UIMessage } from "ai";
|
|
5
|
+
|
|
6
|
+
//#region src/components/ThinkChatActivity.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Bespoke rendering for one tool inside the activity log. Both hooks fall
|
|
9
|
+
* through to the built-in families when they return `undefined`, so an
|
|
10
|
+
* override can adjust just the label or just the panel.
|
|
11
|
+
*/
|
|
12
|
+
interface ThinkChatToolRenderer {
|
|
13
|
+
/** One-line step label. `null` hides the step from the log. */
|
|
14
|
+
describe?: (part: ToolUIPart | DynamicToolUIPart) => string | null | undefined;
|
|
15
|
+
/** Expanded detail under the step. `null` keeps the step a plain row. */
|
|
16
|
+
panel?: (part: ToolUIPart | DynamicToolUIPart) => React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
type ThinkChatToolRenderers = Record<string, ThinkChatToolRenderer>;
|
|
19
|
+
interface ThinkChatActivityRendererOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Tool names to keep out of activity folding entirely — the run splits
|
|
22
|
+
* around them and they fall through to your own renderPart / AgentChat's
|
|
23
|
+
* generic standalone activity row. For tools that should stay in the log
|
|
24
|
+
* with custom UI, use `toolRenderers` instead.
|
|
25
|
+
*/
|
|
26
|
+
excludeTools?: readonly string[];
|
|
27
|
+
/** Per-tool label/panel overrides inside the activity log, keyed by tool name. */
|
|
28
|
+
toolRenderers?: ThinkChatToolRenderers;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One-line natural-language label for an activity part ("Ran vp test",
|
|
32
|
+
* "Fetched developers.cloudflare.com/agents/"); `null` for boundaries that
|
|
33
|
+
* aren't steps (step-start). Exported so a custom `renderPart` can reuse the
|
|
34
|
+
* built-in labels for tools it doesn't override.
|
|
35
|
+
*/
|
|
36
|
+
declare function describeThinkChatActivityPart(part: ThinkChatPart, toolRenderers?: ThinkChatToolRenderers): string | null;
|
|
37
|
+
interface ThinkChatActivityProps {
|
|
38
|
+
/** Render with the log expanded. */
|
|
39
|
+
defaultOpen?: boolean;
|
|
40
|
+
parts: readonly ThinkChatPart[];
|
|
41
|
+
/** Defaults to deriving from part states (reasoning streaming, tool awaiting output). */
|
|
42
|
+
isStreaming?: boolean;
|
|
43
|
+
/** Per-tool label/panel overrides, keyed by tool name. */
|
|
44
|
+
toolRenderers?: ThinkChatToolRenderers;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* One run of agent work as a collapsed Activity block: while streaming the
|
|
48
|
+
* label shimmers with the live step; settled, it becomes a short summary
|
|
49
|
+
* ("Thought, read 2 files and ran a command") over an expandable step log
|
|
50
|
+
* with per-tool panels. Normally reached through `ThinkChat.Messages`;
|
|
51
|
+
* exported for apps that lay out messages themselves.
|
|
52
|
+
*/
|
|
53
|
+
declare function ThinkChatActivity({
|
|
54
|
+
parts,
|
|
55
|
+
defaultOpen,
|
|
56
|
+
isStreaming,
|
|
57
|
+
toolRenderers
|
|
58
|
+
}: ThinkChatActivityProps): React.JSX.Element | null;
|
|
59
|
+
/**
|
|
60
|
+
* Builds a renderPart handler that folds every run of consecutive activity
|
|
61
|
+
* parts (reasoning + tool calls) into one collapsed Activity box. Everything
|
|
62
|
+
* is derived from the UIMessage stream: part order, tool states, reasoning
|
|
63
|
+
* state. Excluded tools split the run and return undefined so your own
|
|
64
|
+
* renderPart (or AgentChat's generic activity row) takes over for them.
|
|
65
|
+
*/
|
|
66
|
+
declare function createThinkChatActivityRenderer({
|
|
67
|
+
excludeTools,
|
|
68
|
+
toolRenderers
|
|
69
|
+
}?: ThinkChatActivityRendererOptions): NonNullable<AgentChatProps["renderPart"]>;
|
|
70
|
+
/** Default activity renderer — `createThinkChatActivityRenderer()` with no overrides. */
|
|
71
|
+
declare const renderThinkChatActivityPart: (context: AgentChatRenderPartContext<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>) => React.ReactNode | undefined;
|
|
72
|
+
//#endregion
|
|
73
|
+
export { ThinkChatToolRenderers as a, renderThinkChatActivityPart as c, ThinkChatToolRenderer as i, ThinkChatActivityProps as n, createThinkChatActivityRenderer as o, ThinkChatActivityRendererOptions as r, describeThinkChatActivityPart as s, ThinkChatActivity as t };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useAgentChat } from "@cloudflare/think/react";
|
|
3
|
+
import { UIMessage } from "ai";
|
|
4
|
+
|
|
5
|
+
//#region src/components/ThinkChatContext.d.ts
|
|
6
|
+
type ThinkChatValue = ReturnType<typeof useAgentChat<unknown, UIMessage>>;
|
|
7
|
+
declare const ThinkChatContext: React.Context<(Omit<import("@ai-sdk/react").UseChatHelpers<UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>, "addToolOutput"> & {
|
|
8
|
+
clearHistory: () => void;
|
|
9
|
+
addToolOutput: (opts: {
|
|
10
|
+
toolCallId: string;
|
|
11
|
+
toolName?: string;
|
|
12
|
+
output?: unknown;
|
|
13
|
+
state?: "output-available" | "output-error";
|
|
14
|
+
errorText?: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
isServerStreaming: boolean;
|
|
17
|
+
isStreaming: boolean;
|
|
18
|
+
isRecovering: boolean;
|
|
19
|
+
isToolContinuation: boolean;
|
|
20
|
+
connectionError: (Error & {
|
|
21
|
+
code: number;
|
|
22
|
+
reason: string;
|
|
23
|
+
wasClean: boolean;
|
|
24
|
+
}) | null;
|
|
25
|
+
}) | null>;
|
|
26
|
+
declare function useThinkChatContext(component: string): ThinkChatValue;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { ThinkChatValue as n, useThinkChatContext as r, ThinkChatContext as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CollapsiblePanel, CollapsibleRoot, CollapsibleTrigger } from "./Collapsible.js";
|
|
2
2
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
3
|
-
import { c as ChevronRightIcon } from "../icons-
|
|
3
|
+
import { c as ChevronRightIcon } from "../icons-D2Q5n5C1.js";
|
|
4
4
|
import "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/Activity.tsx
|