@mcp-b/react-components 0.5.6 → 0.6.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/components/Activity.d.ts +3 -0
- package/dist/components/Activity.js +17 -9
- package/dist/components/AgentConnection.d.ts +5 -0
- package/dist/components/AgentConnection.js +79 -2
- package/dist/components/McpServerPicker.d.ts +2 -15
- package/dist/components/ThinkChat.js +169 -12
- package/dist/styles/activity.css +9 -0
- package/dist/styles/agent-connection.css +144 -0
- package/dist/utils/mcp-server-catalog.d.ts +520 -0
- package/dist/utils/mcp-server-catalog.js +592 -0
- package/package.json +2 -2
|
@@ -40,6 +40,8 @@ interface ActivityTriggerProps extends Omit<CollapsibleTriggerProps, "className"
|
|
|
40
40
|
className?: string;
|
|
41
41
|
/** Header text. Defaults to "Working…". */
|
|
42
42
|
label?: React.ReactNode;
|
|
43
|
+
/** Optional leading icon for the header. */
|
|
44
|
+
icon?: React.ReactNode;
|
|
43
45
|
}
|
|
44
46
|
/**
|
|
45
47
|
* Clickable header line that toggles the activity log. The label shimmers
|
|
@@ -48,6 +50,7 @@ interface ActivityTriggerProps extends Omit<CollapsibleTriggerProps, "className"
|
|
|
48
50
|
declare function ActivityTrigger({
|
|
49
51
|
className,
|
|
50
52
|
label,
|
|
53
|
+
icon,
|
|
51
54
|
children,
|
|
52
55
|
ref,
|
|
53
56
|
...props
|
|
@@ -38,7 +38,7 @@ function Activity({ className, isStreaming = false, defaultOpen = false, ref, ..
|
|
|
38
38
|
* Clickable header line that toggles the activity log. The label shimmers
|
|
39
39
|
* while the parent Activity is streaming.
|
|
40
40
|
*/
|
|
41
|
-
function ActivityTrigger({ className, label = "Working…", children, ref, ...props }) {
|
|
41
|
+
function ActivityTrigger({ className, label = "Working…", icon, children, ref, ...props }) {
|
|
42
42
|
if (children !== void 0 && children !== null) return /* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
43
43
|
ref,
|
|
44
44
|
className: cx("activity__trigger", className),
|
|
@@ -51,14 +51,22 @@ function ActivityTrigger({ className, label = "Working…", children, ref, ...pr
|
|
|
51
51
|
className: cx("activity__trigger", className),
|
|
52
52
|
...props,
|
|
53
53
|
unstyled: true,
|
|
54
|
-
children: [
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
children: [
|
|
55
|
+
icon ? /* @__PURE__ */ jsx("span", {
|
|
56
|
+
className: "activity__item-icon",
|
|
57
|
+
"aria-hidden": "true",
|
|
58
|
+
children: icon
|
|
59
|
+
}) : null,
|
|
60
|
+
/* @__PURE__ */ jsx("span", {
|
|
61
|
+
className: "activity__trigger-label",
|
|
62
|
+
children: label
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ jsx("span", {
|
|
65
|
+
className: "activity__trigger-icon",
|
|
66
|
+
"aria-hidden": "true",
|
|
67
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
68
|
+
})
|
|
69
|
+
]
|
|
62
70
|
});
|
|
63
71
|
}
|
|
64
72
|
/** The collapsible log of ActivityItem children. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { McpServerCard } from "../utils/mcp-server-catalog.js";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
|
|
3
4
|
//#region src/components/AgentConnection.d.ts
|
|
@@ -24,8 +25,10 @@ type NanitesAgentConnectionOptions = {
|
|
|
24
25
|
type AgentConnectionPanelProps = {
|
|
25
26
|
readonly className?: string;
|
|
26
27
|
readonly commands?: readonly AgentConnectionCommand[];
|
|
28
|
+
readonly dcrMcpServers?: readonly McpServerCard[];
|
|
27
29
|
readonly defaultTarget?: AgentConnectionTarget;
|
|
28
30
|
readonly headingLevel?: 2 | 3;
|
|
31
|
+
readonly manualMcpServers?: readonly McpServerCard[];
|
|
29
32
|
readonly origin?: string;
|
|
30
33
|
readonly section?: boolean;
|
|
31
34
|
};
|
|
@@ -53,8 +56,10 @@ declare function buildNanitesAgentConnectionCommands(origin: string, {
|
|
|
53
56
|
declare function AgentConnectionPanel({
|
|
54
57
|
className,
|
|
55
58
|
commands: commandsProp,
|
|
59
|
+
dcrMcpServers,
|
|
56
60
|
defaultTarget,
|
|
57
61
|
headingLevel,
|
|
62
|
+
manualMcpServers,
|
|
58
63
|
origin,
|
|
59
64
|
section
|
|
60
65
|
}: AgentConnectionPanelProps): React.JSX.Element | null;
|
|
@@ -3,6 +3,7 @@ import { y as LinkIcon } from "../icons-BCNawx-T.js";
|
|
|
3
3
|
import { Popover } from "./Popover.js";
|
|
4
4
|
import { Button } from "./Button.js";
|
|
5
5
|
import { a as CodeBlockCopyButton, i as CodeBlockContent, n as CodeBlockActions, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock } from "../CodeBlock-BK0sOAbV.js";
|
|
6
|
+
import { DCR_MCP_SERVER_CARDS, MANUAL_MCP_SERVER_CARDS } from "../utils/mcp-server-catalog.js";
|
|
6
7
|
import * as React from "react";
|
|
7
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
9
|
//#region src/components/AgentConnection.tsx
|
|
@@ -95,7 +96,7 @@ function buildNanitesAgentConnectionCommands(origin, { mcpName = "nanites", plug
|
|
|
95
96
|
* Use inside setup screens where users need Codex, Claude Code, skill-only,
|
|
96
97
|
* or raw MCP JSON connection instructions.
|
|
97
98
|
*/
|
|
98
|
-
function AgentConnectionPanel({ className, commands: commandsProp, defaultTarget = "codex", headingLevel = 2, origin, section = true }) {
|
|
99
|
+
function AgentConnectionPanel({ className, commands: commandsProp, dcrMcpServers = DCR_MCP_SERVER_CARDS, defaultTarget = "codex", headingLevel = 2, manualMcpServers = MANUAL_MCP_SERVER_CARDS, origin, section = true }) {
|
|
99
100
|
const commands = React.useMemo(() => commandsProp ?? buildNanitesAgentConnectionCommands(origin ?? getBrowserOrigin()), [commandsProp, origin]);
|
|
100
101
|
const [target, setTarget] = React.useState(defaultTarget);
|
|
101
102
|
const selected = commands.find((command) => command.target === target) ?? commands[0];
|
|
@@ -141,10 +142,86 @@ function AgentConnectionPanel({ className, commands: commandsProp, defaultTarget
|
|
|
141
142
|
code: selected.code,
|
|
142
143
|
language: selected.language,
|
|
143
144
|
children: [/* @__PURE__ */ jsxs(CodeBlockHeader, { children: [/* @__PURE__ */ jsx(CodeBlockTitle, { children: selected.label }), /* @__PURE__ */ jsx(CodeBlockActions, { children: /* @__PURE__ */ jsx(CodeBlockCopyButton, {}) })] }), /* @__PURE__ */ jsx(CodeBlockContainer, { children: /* @__PURE__ */ jsx(CodeBlockContent, {}) })]
|
|
144
|
-
})
|
|
145
|
+
}),
|
|
146
|
+
dcrMcpServers.length > 0 ? /* @__PURE__ */ jsx(McpServerList, {
|
|
147
|
+
heading: "DCR-ready MCP servers",
|
|
148
|
+
servers: dcrMcpServers
|
|
149
|
+
}) : null,
|
|
150
|
+
manualMcpServers.length > 0 ? /* @__PURE__ */ jsx(McpServerList, {
|
|
151
|
+
heading: "Manual setup MCP servers",
|
|
152
|
+
servers: manualMcpServers
|
|
153
|
+
}) : null
|
|
145
154
|
]
|
|
146
155
|
});
|
|
147
156
|
}
|
|
157
|
+
function McpServerList({ heading, servers }) {
|
|
158
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
159
|
+
className: "agent-connect__mcp",
|
|
160
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
161
|
+
className: "agent-connect__mcp-heading",
|
|
162
|
+
children: heading
|
|
163
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
164
|
+
className: "agent-connect__mcp-list",
|
|
165
|
+
role: "list",
|
|
166
|
+
children: servers.map((server) => /* @__PURE__ */ jsxs("li", {
|
|
167
|
+
className: "agent-connect__mcp-item",
|
|
168
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
169
|
+
className: "agent-connect__mcp-icon",
|
|
170
|
+
children: renderMcpServerIcon(server)
|
|
171
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
172
|
+
className: "agent-connect__mcp-copy",
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx("a", {
|
|
175
|
+
className: "agent-connect__mcp-name",
|
|
176
|
+
href: server.url,
|
|
177
|
+
target: "_blank",
|
|
178
|
+
rel: "noreferrer",
|
|
179
|
+
children: server.name
|
|
180
|
+
}),
|
|
181
|
+
server.description ? /* @__PURE__ */ jsx("span", {
|
|
182
|
+
className: "agent-connect__mcp-description",
|
|
183
|
+
children: server.description
|
|
184
|
+
}) : null,
|
|
185
|
+
server.manualSetup ? /* @__PURE__ */ jsx(McpServerSetup, { setup: server.manualSetup }) : null
|
|
186
|
+
]
|
|
187
|
+
})]
|
|
188
|
+
}, server.id))
|
|
189
|
+
})]
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function McpServerSetup({ setup }) {
|
|
193
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
194
|
+
className: "agent-connect__mcp-setup",
|
|
195
|
+
children: [/* @__PURE__ */ jsx("p", { children: setup.description }), setup.links.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
196
|
+
className: "agent-connect__mcp-setup-links",
|
|
197
|
+
role: "list",
|
|
198
|
+
children: setup.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
|
|
199
|
+
href: link.url,
|
|
200
|
+
target: "_blank",
|
|
201
|
+
rel: "noreferrer",
|
|
202
|
+
children: link.label
|
|
203
|
+
}) }, `${link.label}:${link.url}`))
|
|
204
|
+
}) : null]
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function renderMcpServerIcon(server) {
|
|
208
|
+
const icon = server.icon;
|
|
209
|
+
if (typeof icon === "string") return /* @__PURE__ */ jsx("img", {
|
|
210
|
+
src: icon,
|
|
211
|
+
alt: "",
|
|
212
|
+
loading: "lazy",
|
|
213
|
+
decoding: "async",
|
|
214
|
+
referrerPolicy: "no-referrer"
|
|
215
|
+
});
|
|
216
|
+
if (icon) return /* @__PURE__ */ jsx("img", {
|
|
217
|
+
src: icon.src,
|
|
218
|
+
alt: "",
|
|
219
|
+
loading: "lazy",
|
|
220
|
+
decoding: "async",
|
|
221
|
+
referrerPolicy: "no-referrer"
|
|
222
|
+
});
|
|
223
|
+
return server.name.slice(0, 1);
|
|
224
|
+
}
|
|
148
225
|
/**
|
|
149
226
|
* Compact popover trigger for showing AgentConnectionPanel inline.
|
|
150
227
|
*/
|
|
@@ -1,20 +1,7 @@
|
|
|
1
|
+
import { McpServerCard } from "../utils/mcp-server-catalog.js";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
|
|
3
4
|
//#region src/components/McpServerPicker.d.ts
|
|
4
|
-
type McpServerPickerStatus = "connecting" | "needs-auth" | "authenticating" | "ready" | "failed";
|
|
5
|
-
interface McpServerCardIcon {
|
|
6
|
-
src: string;
|
|
7
|
-
}
|
|
8
|
-
interface McpServerCard {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
url: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
category?: string;
|
|
14
|
-
icon?: string | McpServerCardIcon;
|
|
15
|
-
status?: McpServerPickerStatus;
|
|
16
|
-
statusLabel?: string;
|
|
17
|
-
}
|
|
18
5
|
interface McpServerPickerProps {
|
|
19
6
|
/** MCP servers to show in the plus-menu picker. */
|
|
20
7
|
servers: readonly McpServerCard[];
|
|
@@ -38,4 +25,4 @@ declare function McpServerPickerItems({
|
|
|
38
25
|
onConnect
|
|
39
26
|
}: McpServerPickerItemsProps): React.JSX.Element | React.JSX.Element[];
|
|
40
27
|
//#endregion
|
|
41
|
-
export {
|
|
28
|
+
export { McpServerPicker, McpServerPickerItems, McpServerPickerItemsProps, McpServerPickerProps };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { M as TerminalIcon, N as WarningIcon, P as WrenchIcon, S as MonitorIcon, T as PencilIcon, k as SearchIcon, m as FileIcon, v as InfoIcon, y as LinkIcon } from "../icons-BCNawx-T.js";
|
|
1
2
|
import { Activity, ActivityContent, ActivityItem, ActivityItemGroup, ActivityOutput, ActivityPanel, ActivityText, ActivityTrigger } from "./Activity.js";
|
|
2
3
|
import { Tab, TabPanel, Tabs, TabsList } from "./Tabs.js";
|
|
3
4
|
import { AgentChat } from "./AgentChat.js";
|
|
@@ -171,6 +172,142 @@ function summarizeToolInput(input) {
|
|
|
171
172
|
}
|
|
172
173
|
return null;
|
|
173
174
|
}
|
|
175
|
+
const HTTP_URL_PATTERN = /https?:\/\/[^\s"'<>)}\]]+/i;
|
|
176
|
+
function firstHttpUrl(value) {
|
|
177
|
+
const text = typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
178
|
+
const raw = HTTP_URL_PATTERN.exec(text)?.[0]?.replace(/[.,;:!?]+$/, "");
|
|
179
|
+
if (!raw) return null;
|
|
180
|
+
try {
|
|
181
|
+
return new URL(raw).href;
|
|
182
|
+
} catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function ActivityFavicon({ url }) {
|
|
187
|
+
const src = faviconHref(url);
|
|
188
|
+
const [failed, setFailed] = React.useState(false);
|
|
189
|
+
React.useEffect(() => setFailed(false), [src]);
|
|
190
|
+
if (!src || failed) return /* @__PURE__ */ jsx(LinkIcon, {});
|
|
191
|
+
return /* @__PURE__ */ jsx("img", {
|
|
192
|
+
className: "activity__favicon",
|
|
193
|
+
src,
|
|
194
|
+
alt: "",
|
|
195
|
+
loading: "lazy",
|
|
196
|
+
decoding: "async",
|
|
197
|
+
onError: () => setFailed(true)
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function faviconHref(url) {
|
|
201
|
+
try {
|
|
202
|
+
return new URL("/favicon.ico", url).href;
|
|
203
|
+
} catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function ActivityKindIcon({ kind }) {
|
|
208
|
+
switch (kind) {
|
|
209
|
+
case "thought": return /* @__PURE__ */ jsx(InfoIcon, {});
|
|
210
|
+
case "read": return /* @__PURE__ */ jsx(FileIcon, {});
|
|
211
|
+
case "edit": return /* @__PURE__ */ jsx(PencilIcon, {});
|
|
212
|
+
case "search": return /* @__PURE__ */ jsx(SearchIcon, {});
|
|
213
|
+
case "web": return /* @__PURE__ */ jsx(LinkIcon, {});
|
|
214
|
+
case "command": return /* @__PURE__ */ jsx(TerminalIcon, {});
|
|
215
|
+
case "browser": return /* @__PURE__ */ jsx(MonitorIcon, {});
|
|
216
|
+
case "tool": return /* @__PURE__ */ jsx(WrenchIcon, {});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function genericToolLabels(name, hasUrl) {
|
|
220
|
+
const normalized = name.toLowerCase();
|
|
221
|
+
if (normalized.includes("grep") || normalized.includes("find") || normalized.includes("code")) return {
|
|
222
|
+
working: "Searching code",
|
|
223
|
+
done: "Searched code",
|
|
224
|
+
failed: "Code search failed",
|
|
225
|
+
summary: "searched code",
|
|
226
|
+
icon: "search"
|
|
227
|
+
};
|
|
228
|
+
if (normalized.includes("search") || normalized.includes("web") || normalized.includes("browser") || normalized.includes("google")) return {
|
|
229
|
+
working: "Searching the web",
|
|
230
|
+
done: "Searched the web",
|
|
231
|
+
failed: "Web search failed",
|
|
232
|
+
summary: "searched the web",
|
|
233
|
+
icon: "web"
|
|
234
|
+
};
|
|
235
|
+
if (hasUrl || normalized.includes("fetch") || normalized.includes("http") || normalized.includes("url")) return {
|
|
236
|
+
working: "Reading a URL",
|
|
237
|
+
done: "Read a URL",
|
|
238
|
+
failed: "URL read failed",
|
|
239
|
+
summary: "read a URL",
|
|
240
|
+
icon: "web"
|
|
241
|
+
};
|
|
242
|
+
if (normalized.includes("edit") || normalized.includes("write") || normalized.includes("delete") || normalized.includes("patch") || normalized.includes("apply") || normalized.includes("create") || normalized.includes("update")) return {
|
|
243
|
+
working: "Editing files",
|
|
244
|
+
done: "Edited files",
|
|
245
|
+
failed: "Edit failed",
|
|
246
|
+
summary: "edited files",
|
|
247
|
+
icon: "edit"
|
|
248
|
+
};
|
|
249
|
+
if (normalized.includes("exec") || normalized.includes("bash") || normalized.includes("shell") || normalized.includes("terminal") || normalized.includes("command")) return {
|
|
250
|
+
working: "Running a command",
|
|
251
|
+
done: "Ran a command",
|
|
252
|
+
failed: "Command failed",
|
|
253
|
+
summary: "ran a command",
|
|
254
|
+
icon: "command"
|
|
255
|
+
};
|
|
256
|
+
if (normalized.includes("read") || normalized.includes("open") || normalized.includes("list") || normalized.includes("file")) return {
|
|
257
|
+
working: "Reading files",
|
|
258
|
+
done: "Read files",
|
|
259
|
+
failed: "Read failed",
|
|
260
|
+
summary: "read files",
|
|
261
|
+
icon: "read"
|
|
262
|
+
};
|
|
263
|
+
return {
|
|
264
|
+
working: "Using a tool",
|
|
265
|
+
done: "Used a tool",
|
|
266
|
+
failed: "Tool failed",
|
|
267
|
+
summary: "used a tool",
|
|
268
|
+
icon: "tool"
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function describeGenericToolPart(part) {
|
|
272
|
+
const labels = genericToolLabels(getToolName(part), activityPartUrl(part) !== null);
|
|
273
|
+
const label = isPartFailed(part) ? labels.failed : isPartWorking(part) ? labels.working : labels.done;
|
|
274
|
+
const detail = summarizeToolInput(part.input);
|
|
275
|
+
return detail ? `${label} · ${detail}` : label;
|
|
276
|
+
}
|
|
277
|
+
function activityPartUrl(part) {
|
|
278
|
+
if (isFetchToolPart(part)) return firstHttpUrl(part.input?.url ?? part.input?.path);
|
|
279
|
+
if (isBrowserToolPart(part) && part.type !== "tool-browser_execute") return firstHttpUrl(part.input?.url);
|
|
280
|
+
if (isToolUIPart(part) && !isExecuteToolPart(part)) return firstHttpUrl(part.input) ?? (part.state === "output-available" ? firstHttpUrl(part.output) : null);
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
function activityPartIconKind(part) {
|
|
284
|
+
if (isReasoningUIPart(part)) return "thought";
|
|
285
|
+
if (isWorkspaceToolPart(part)) switch (part.type) {
|
|
286
|
+
case "tool-read":
|
|
287
|
+
case "tool-list": return "read";
|
|
288
|
+
case "tool-write":
|
|
289
|
+
case "tool-edit":
|
|
290
|
+
case "tool-delete": return "edit";
|
|
291
|
+
case "tool-find":
|
|
292
|
+
case "tool-grep": return "search";
|
|
293
|
+
case "tool-bash": return "command";
|
|
294
|
+
}
|
|
295
|
+
if (isSkillToolPart(part)) return "tool";
|
|
296
|
+
if (isFetchToolPart(part)) return "web";
|
|
297
|
+
if (isBrowserToolPart(part)) return part.type === "tool-browser_execute" ? "browser" : "web";
|
|
298
|
+
if (isExecuteToolPart(part)) return "command";
|
|
299
|
+
if (isToolUIPart(part)) return genericToolLabels(getToolName(part), activityPartUrl(part) !== null).icon;
|
|
300
|
+
return "tool";
|
|
301
|
+
}
|
|
302
|
+
function activityPartIcon(part) {
|
|
303
|
+
const url = activityPartUrl(part);
|
|
304
|
+
return url ? /* @__PURE__ */ jsx(ActivityFavicon, { url }) : /* @__PURE__ */ jsx(ActivityKindIcon, { kind: activityPartIconKind(part) });
|
|
305
|
+
}
|
|
306
|
+
function activitySummaryIcon(parts) {
|
|
307
|
+
if (parts.find((part) => isToolUIPart(part) && isPartFailed(part))) return /* @__PURE__ */ jsx(WarningIcon, {});
|
|
308
|
+
const representative = parts.find((part) => activityPartIconKind(part) === "edit") ?? parts.find((part) => activityPartUrl(part)) ?? parts.find((part) => describeThinkChatActivityPart(part));
|
|
309
|
+
return representative ? activityPartIcon(representative) : /* @__PURE__ */ jsx(ActivityKindIcon, { kind: "tool" });
|
|
310
|
+
}
|
|
174
311
|
/**
|
|
175
312
|
* One-line natural-language label for an activity part ("Ran vp test",
|
|
176
313
|
* "Fetched developers.cloudflare.com/agents/"); `null` for boundaries that
|
|
@@ -192,12 +329,7 @@ function describeThinkChatActivityPart(part, toolRenderers) {
|
|
|
192
329
|
if (isFetchToolPart(part)) return describeFetchToolPart(part);
|
|
193
330
|
if (isBrowserToolPart(part)) return describeBrowserToolPart(part);
|
|
194
331
|
if (isExecuteToolPart(part)) return describeExecuteToolPart(part);
|
|
195
|
-
if (isToolUIPart(part))
|
|
196
|
-
const name = getToolName(part);
|
|
197
|
-
const verb = isPartFailed(part) ? `${name} failed` : isPartWorking(part) ? `Running ${name}` : `Ran ${name}`;
|
|
198
|
-
const detail = summarizeToolInput(part.input);
|
|
199
|
-
return detail ? `${verb} · ${detail}` : verb;
|
|
200
|
-
}
|
|
332
|
+
if (isToolUIPart(part)) return describeGenericToolPart(part);
|
|
201
333
|
return null;
|
|
202
334
|
}
|
|
203
335
|
function basename(path) {
|
|
@@ -283,7 +415,7 @@ function describeFetchToolPart(part) {
|
|
|
283
415
|
}
|
|
284
416
|
function summarizeActivitySteps(parts) {
|
|
285
417
|
const byTool = /* @__PURE__ */ new Map();
|
|
286
|
-
const
|
|
418
|
+
const genericSegments = /* @__PURE__ */ new Set();
|
|
287
419
|
const skillNames = /* @__PURE__ */ new Set();
|
|
288
420
|
let thoughts = 0;
|
|
289
421
|
let skillParts = 0;
|
|
@@ -300,7 +432,7 @@ function summarizeActivitySteps(parts) {
|
|
|
300
432
|
} else if (isFetchToolPart(part)) fetches++;
|
|
301
433
|
else if (isBrowserToolPart(part)) browses++;
|
|
302
434
|
else if (isExecuteToolPart(part)) codeRuns++;
|
|
303
|
-
else if (isToolUIPart(part))
|
|
435
|
+
else if (isToolUIPart(part)) genericSegments.add(genericToolLabels(getToolName(part), activityPartUrl(part) !== null).summary);
|
|
304
436
|
const count = (name) => byTool.get(name) ?? 0;
|
|
305
437
|
const files = (n) => n === 1 ? "a file" : `${n} files`;
|
|
306
438
|
const reads = count("read");
|
|
@@ -319,7 +451,15 @@ function summarizeActivitySteps(parts) {
|
|
|
319
451
|
if (browses > 0) segments.push("used the browser");
|
|
320
452
|
if (codeRuns > 0) segments.push("ran code");
|
|
321
453
|
if (commands > 0) segments.push(commands === 1 ? "ran a command" : `ran ${commands} commands`);
|
|
322
|
-
for (const
|
|
454
|
+
for (const segment of [
|
|
455
|
+
"edited files",
|
|
456
|
+
"searched code",
|
|
457
|
+
"searched the web",
|
|
458
|
+
"read a URL",
|
|
459
|
+
"ran a command",
|
|
460
|
+
"read files",
|
|
461
|
+
"used a tool"
|
|
462
|
+
]) if (genericSegments.has(segment)) segments.push(segment);
|
|
323
463
|
if (segments.length === 0) return "Worked";
|
|
324
464
|
const top = segments.slice(0, 3);
|
|
325
465
|
const joined = top.length === 1 ? top[0] : `${top.slice(0, -1).join(", ")} and ${top.at(-1)}`;
|
|
@@ -349,7 +489,10 @@ function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers }) {
|
|
|
349
489
|
return /* @__PURE__ */ jsxs(Activity, {
|
|
350
490
|
isStreaming: streaming,
|
|
351
491
|
defaultOpen,
|
|
352
|
-
children: [/* @__PURE__ */ jsx(ActivityTrigger, {
|
|
492
|
+
children: [/* @__PURE__ */ jsx(ActivityTrigger, {
|
|
493
|
+
icon: streaming && latest ? activityPartIcon(latest.part) : activitySummaryIcon(parts),
|
|
494
|
+
label: streaming && latest ? latest.text : settledLabel
|
|
495
|
+
}), /* @__PURE__ */ jsx(ActivityContent, { children: steps.map((step) => /* @__PURE__ */ jsx(ThinkChatActivityStep, {
|
|
353
496
|
text: step.text,
|
|
354
497
|
part: step.part,
|
|
355
498
|
toolRenderers
|
|
@@ -357,39 +500,53 @@ function ThinkChatActivity({ parts, defaultOpen, isStreaming, toolRenderers }) {
|
|
|
357
500
|
});
|
|
358
501
|
}
|
|
359
502
|
function ThinkChatActivityStep({ text, part, toolRenderers }) {
|
|
503
|
+
const icon = activityPartIcon(part);
|
|
360
504
|
if (isToolUIPart(part)) {
|
|
361
505
|
const customPanel = toolRenderers?.[getToolName(part)]?.panel?.(part);
|
|
362
|
-
if (customPanel === null) return /* @__PURE__ */ jsx(ActivityItem, {
|
|
506
|
+
if (customPanel === null) return /* @__PURE__ */ jsx(ActivityItem, {
|
|
507
|
+
icon,
|
|
508
|
+
children: text
|
|
509
|
+
});
|
|
363
510
|
if (customPanel !== void 0) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
364
511
|
label: text,
|
|
512
|
+
icon,
|
|
365
513
|
children: customPanel
|
|
366
514
|
});
|
|
367
515
|
}
|
|
368
516
|
if (isReasoningUIPart(part) && part.text.trim()) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
369
517
|
label: text,
|
|
518
|
+
icon,
|
|
370
519
|
children: /* @__PURE__ */ jsx(ActivityText, { children: part.text })
|
|
371
520
|
});
|
|
372
521
|
if (isWorkspaceToolPart(part) && part.type !== "tool-delete") return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
373
522
|
label: text,
|
|
523
|
+
icon,
|
|
374
524
|
children: /* @__PURE__ */ jsx(ThinkChatWorkspacePanel, { part })
|
|
375
525
|
});
|
|
376
526
|
if (isSkillToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
377
527
|
label: text,
|
|
528
|
+
icon,
|
|
378
529
|
children: /* @__PURE__ */ jsx(ThinkChatSkillPanel, { part })
|
|
379
530
|
});
|
|
380
531
|
if (isFetchToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
381
532
|
label: text,
|
|
533
|
+
icon,
|
|
382
534
|
children: /* @__PURE__ */ jsx(ThinkChatFetchPanel, { part })
|
|
383
535
|
});
|
|
384
536
|
if (isBrowserToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
385
537
|
label: text,
|
|
538
|
+
icon,
|
|
386
539
|
children: /* @__PURE__ */ jsx(ThinkChatBrowserPanel, { part })
|
|
387
540
|
});
|
|
388
541
|
if (isExecuteToolPart(part)) return /* @__PURE__ */ jsx(ActivityItemGroup, {
|
|
389
542
|
label: text,
|
|
543
|
+
icon,
|
|
390
544
|
children: /* @__PURE__ */ jsx(ThinkChatExecutePanel, { part })
|
|
391
545
|
});
|
|
392
|
-
return /* @__PURE__ */ jsx(ActivityItem, {
|
|
546
|
+
return /* @__PURE__ */ jsx(ActivityItem, {
|
|
547
|
+
icon,
|
|
548
|
+
children: text
|
|
549
|
+
});
|
|
393
550
|
}
|
|
394
551
|
function renderDeniedPanel(label, reason) {
|
|
395
552
|
return /* @__PURE__ */ jsx(ActivityPanel, {
|
package/dist/styles/activity.css
CHANGED
|
@@ -342,6 +342,15 @@
|
|
|
342
342
|
color: var(--sigvelo-color-text-muted);
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
.activity__favicon {
|
|
346
|
+
display: block;
|
|
347
|
+
width: 1rem;
|
|
348
|
+
height: 1rem;
|
|
349
|
+
border-radius: var(--sigvelo-radius-xs);
|
|
350
|
+
background-color: var(--sigvelo-color-surface);
|
|
351
|
+
object-fit: contain;
|
|
352
|
+
}
|
|
353
|
+
|
|
345
354
|
.activity__item-text {
|
|
346
355
|
min-width: 0;
|
|
347
356
|
overflow-wrap: anywhere;
|
|
@@ -145,6 +145,146 @@
|
|
|
145
145
|
line-height: 1.5;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
.agent-connect__mcp {
|
|
149
|
+
display: grid;
|
|
150
|
+
gap: 0.5rem;
|
|
151
|
+
min-inline-size: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.agent-connect__mcp-heading {
|
|
155
|
+
margin: 0;
|
|
156
|
+
color: var(--sigvelo-color-text-muted);
|
|
157
|
+
font-size: 0.74rem;
|
|
158
|
+
font-weight: var(--sigvelo-font-weight-semibold);
|
|
159
|
+
line-height: 1.25;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.agent-connect__mcp-list {
|
|
163
|
+
display: grid;
|
|
164
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
165
|
+
gap: 0.35rem;
|
|
166
|
+
max-block-size: 24rem;
|
|
167
|
+
margin: 0;
|
|
168
|
+
padding: 0;
|
|
169
|
+
overflow-y: auto;
|
|
170
|
+
overscroll-behavior: contain;
|
|
171
|
+
list-style: none;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.agent-connect__mcp-item {
|
|
175
|
+
display: grid;
|
|
176
|
+
grid-template-columns: 1.625rem minmax(0, 1fr);
|
|
177
|
+
gap: 0.5rem;
|
|
178
|
+
align-items: start;
|
|
179
|
+
min-inline-size: 0;
|
|
180
|
+
padding: 0.5rem;
|
|
181
|
+
border: var(--sigvelo-border-style) var(--sigvelo-border-width)
|
|
182
|
+
var(--sigvelo-color-neutral-border-subtle);
|
|
183
|
+
border-radius: var(--sigvelo-radius-md);
|
|
184
|
+
background: var(--sigvelo-color-surface);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.agent-connect__mcp-icon {
|
|
188
|
+
display: grid;
|
|
189
|
+
place-items: center;
|
|
190
|
+
inline-size: 1.625rem;
|
|
191
|
+
block-size: 1.625rem;
|
|
192
|
+
border-radius: var(--sigvelo-radius-sm);
|
|
193
|
+
background: var(--sigvelo-color-neutral-bg-subtle);
|
|
194
|
+
color: var(--sigvelo-color-text-muted);
|
|
195
|
+
font-size: 0.72rem;
|
|
196
|
+
font-weight: var(--sigvelo-font-weight-bold);
|
|
197
|
+
line-height: 1;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.agent-connect__mcp-icon img {
|
|
201
|
+
display: block;
|
|
202
|
+
max-inline-size: 1rem;
|
|
203
|
+
max-block-size: 1rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.agent-connect__mcp-copy {
|
|
207
|
+
display: grid;
|
|
208
|
+
gap: 0.08rem;
|
|
209
|
+
min-inline-size: 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.agent-connect__mcp-name {
|
|
213
|
+
color: var(--sigvelo-color-text);
|
|
214
|
+
font-size: 0.78rem;
|
|
215
|
+
font-weight: var(--sigvelo-font-weight-semibold);
|
|
216
|
+
line-height: 1.2;
|
|
217
|
+
overflow-wrap: anywhere;
|
|
218
|
+
text-decoration: none;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.agent-connect__mcp-name:hover {
|
|
222
|
+
color: var(--sigvelo-color-primary-text);
|
|
223
|
+
text-decoration: underline;
|
|
224
|
+
text-underline-offset: 0.16em;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.agent-connect__mcp-name:focus-visible {
|
|
228
|
+
outline: 2px solid var(--sigvelo-color-focus);
|
|
229
|
+
outline-offset: 2px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.agent-connect__mcp-description {
|
|
233
|
+
color: var(--sigvelo-color-text-muted);
|
|
234
|
+
font-size: 0.7rem;
|
|
235
|
+
line-height: 1.25;
|
|
236
|
+
overflow-wrap: anywhere;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.agent-connect__mcp-setup {
|
|
240
|
+
display: grid;
|
|
241
|
+
gap: 0.3rem;
|
|
242
|
+
margin-block-start: 0.2rem;
|
|
243
|
+
min-inline-size: 0;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.agent-connect__mcp-setup p {
|
|
247
|
+
margin: 0;
|
|
248
|
+
color: var(--sigvelo-color-text-muted);
|
|
249
|
+
font-size: 0.68rem;
|
|
250
|
+
line-height: 1.3;
|
|
251
|
+
overflow-wrap: anywhere;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.agent-connect__mcp-setup-links {
|
|
255
|
+
display: flex;
|
|
256
|
+
flex-wrap: wrap;
|
|
257
|
+
gap: 0.25rem;
|
|
258
|
+
margin: 0;
|
|
259
|
+
padding: 0;
|
|
260
|
+
list-style: none;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.agent-connect__mcp-setup-links a {
|
|
264
|
+
display: inline-flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
min-block-size: 1.35rem;
|
|
267
|
+
padding: 0 0.35rem;
|
|
268
|
+
border: var(--sigvelo-border-style) var(--sigvelo-border-width)
|
|
269
|
+
var(--sigvelo-color-neutral-border-subtle);
|
|
270
|
+
border-radius: var(--sigvelo-radius-sm);
|
|
271
|
+
color: var(--sigvelo-color-text-muted);
|
|
272
|
+
font-size: 0.65rem;
|
|
273
|
+
font-weight: var(--sigvelo-font-weight-semibold);
|
|
274
|
+
line-height: 1.1;
|
|
275
|
+
text-decoration: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.agent-connect__mcp-setup-links a:hover {
|
|
279
|
+
border-color: var(--sigvelo-color-primary-border-muted);
|
|
280
|
+
color: var(--sigvelo-color-primary-text);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.agent-connect__mcp-setup-links a:focus-visible {
|
|
284
|
+
outline: 2px solid var(--sigvelo-color-focus);
|
|
285
|
+
outline-offset: 2px;
|
|
286
|
+
}
|
|
287
|
+
|
|
148
288
|
.agent-connect-trigger {
|
|
149
289
|
inline-size: 100%;
|
|
150
290
|
}
|
|
@@ -160,6 +300,10 @@
|
|
|
160
300
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
161
301
|
}
|
|
162
302
|
|
|
303
|
+
.agent-connect__mcp-list {
|
|
304
|
+
grid-template-columns: 1fr;
|
|
305
|
+
}
|
|
306
|
+
|
|
163
307
|
.agent-connect-popover {
|
|
164
308
|
inline-size: min(24rem, calc(100dvi - 1.5rem));
|
|
165
309
|
}
|