@surf-kit/agent 0.1.1 → 0.2.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/README.md +19 -1
- package/dist/agent-BNSmiexZ.d.cts +44 -0
- package/dist/agent-BNSmiexZ.d.ts +44 -0
- package/dist/agent-identity/index.cjs +157 -0
- package/dist/agent-identity/index.cjs.map +1 -0
- package/dist/agent-identity/index.d.cts +35 -0
- package/dist/agent-identity/index.d.ts +35 -0
- package/dist/agent-identity/index.js +127 -0
- package/dist/agent-identity/index.js.map +1 -0
- package/dist/chat/index.cjs +1281 -0
- package/dist/chat/index.cjs.map +1 -0
- package/dist/chat/index.d.cts +72 -0
- package/dist/chat/index.d.ts +72 -0
- package/dist/chat/index.js +1239 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat--OifhIRe.d.ts +24 -0
- package/dist/chat-ChYl2XjV.d.cts +24 -0
- package/dist/confidence/index.cjs +253 -0
- package/dist/confidence/index.cjs.map +1 -0
- package/dist/confidence/index.d.cts +40 -0
- package/dist/confidence/index.d.ts +40 -0
- package/dist/confidence/index.js +222 -0
- package/dist/confidence/index.js.map +1 -0
- package/dist/feedback/index.cjs +186 -0
- package/dist/feedback/index.cjs.map +1 -0
- package/dist/feedback/index.d.cts +27 -0
- package/dist/feedback/index.d.ts +27 -0
- package/dist/feedback/index.js +157 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/{hooks-B8CSeOsn.d.cts → hooks-BGs8-4GK.d.ts} +4 -99
- package/dist/{hooks-B8CSeOsn.d.ts → hooks-DLfF18IU.d.cts} +4 -99
- package/dist/hooks.d.cts +4 -1
- package/dist/hooks.d.ts +4 -1
- package/dist/index-BazLnae1.d.cts +67 -0
- package/dist/index-BazLnae1.d.ts +67 -0
- package/dist/index.cjs +889 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -321
- package/dist/index.d.ts +15 -321
- package/dist/index.js +879 -142
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.cjs +1588 -0
- package/dist/layouts/index.cjs.map +1 -0
- package/dist/layouts/index.d.cts +46 -0
- package/dist/layouts/index.d.ts +46 -0
- package/dist/layouts/index.js +1548 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/mcp/index.cjs +522 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +2 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +492 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/response/index.cjs +519 -0
- package/dist/response/index.cjs.map +1 -0
- package/dist/response/index.d.cts +44 -0
- package/dist/response/index.d.ts +44 -0
- package/dist/response/index.js +478 -0
- package/dist/response/index.js.map +1 -0
- package/dist/sources/index.cjs +243 -0
- package/dist/sources/index.cjs.map +1 -0
- package/dist/sources/index.d.cts +44 -0
- package/dist/sources/index.d.ts +44 -0
- package/dist/sources/index.js +212 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/streaming/index.cjs +531 -0
- package/dist/streaming/index.cjs.map +1 -0
- package/dist/streaming/index.d.cts +81 -0
- package/dist/streaming/index.d.ts +81 -0
- package/dist/streaming/index.js +495 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming-DbQxScpi.d.ts +39 -0
- package/dist/streaming-DfT22A0z.d.cts +39 -0
- package/package.json +62 -17
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
// src/mcp/MCPToolCall/MCPToolCall.tsx
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
import { Badge, Spinner } from "@surf-kit/core";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
var statusBadgeIntent = {
|
|
7
|
+
pending: "default",
|
|
8
|
+
running: "info",
|
|
9
|
+
success: "success",
|
|
10
|
+
error: "error"
|
|
11
|
+
};
|
|
12
|
+
var statusLabel = {
|
|
13
|
+
pending: "Pending",
|
|
14
|
+
running: "Running",
|
|
15
|
+
success: "Success",
|
|
16
|
+
error: "Error"
|
|
17
|
+
};
|
|
18
|
+
var container = cva(
|
|
19
|
+
"rounded-lg border text-sm",
|
|
20
|
+
{
|
|
21
|
+
variants: {
|
|
22
|
+
status: {
|
|
23
|
+
pending: "border-neutral-200 bg-neutral-50",
|
|
24
|
+
running: "border-sky-200 bg-sky-50",
|
|
25
|
+
success: "border-status-success-subtle bg-status-success-subtle/30",
|
|
26
|
+
error: "border-status-error-subtle bg-status-error-subtle/30"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: { status: "pending" }
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
function formatDuration(start, end) {
|
|
33
|
+
if (!start || !end) return null;
|
|
34
|
+
const ms = end.getTime() - start.getTime();
|
|
35
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
36
|
+
return `${(ms / 1e3).toFixed(1)}s`;
|
|
37
|
+
}
|
|
38
|
+
function formatValue(value) {
|
|
39
|
+
if (typeof value === "string") return value;
|
|
40
|
+
return JSON.stringify(value, null, 2);
|
|
41
|
+
}
|
|
42
|
+
function MCPToolCall({ call, isExpanded = false, onToggleExpand, className }) {
|
|
43
|
+
const duration = formatDuration(call.startedAt, call.completedAt);
|
|
44
|
+
return /* @__PURE__ */ jsxs(
|
|
45
|
+
"div",
|
|
46
|
+
{
|
|
47
|
+
className: twMerge(container({ status: call.status }), className),
|
|
48
|
+
"data-testid": "mcp-tool-call",
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsxs(
|
|
51
|
+
"button",
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
className: "flex w-full items-center justify-between gap-2 px-3 py-2",
|
|
55
|
+
onClick: onToggleExpand,
|
|
56
|
+
"aria-expanded": isExpanded,
|
|
57
|
+
"data-testid": "mcp-tool-call-header",
|
|
58
|
+
children: [
|
|
59
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-text-primary truncate", "data-testid": "mcp-tool-name", children: call.name }),
|
|
61
|
+
call.serverName && /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary truncate", children: call.serverName })
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
64
|
+
call.status === "running" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Spinner, { size: "sm" }) }),
|
|
65
|
+
/* @__PURE__ */ jsx(
|
|
66
|
+
Badge,
|
|
67
|
+
{
|
|
68
|
+
intent: statusBadgeIntent[call.status],
|
|
69
|
+
size: "sm",
|
|
70
|
+
role: "status",
|
|
71
|
+
"aria-label": `Status: ${statusLabel[call.status]}`,
|
|
72
|
+
"data-testid": "mcp-tool-status",
|
|
73
|
+
children: statusLabel[call.status]
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
duration && /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", "data-testid": "mcp-tool-duration", children: duration }),
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
"svg",
|
|
79
|
+
{
|
|
80
|
+
className: `h-4 w-4 text-text-secondary transition-transform ${isExpanded ? "rotate-180" : ""}`,
|
|
81
|
+
viewBox: "0 0 20 20",
|
|
82
|
+
fill: "currentColor",
|
|
83
|
+
"aria-hidden": "true",
|
|
84
|
+
children: /* @__PURE__ */ jsx(
|
|
85
|
+
"path",
|
|
86
|
+
{
|
|
87
|
+
fillRule: "evenodd",
|
|
88
|
+
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
|
89
|
+
clipRule: "evenodd"
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
] })
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
isExpanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-inherit px-3 py-2 space-y-3", "data-testid": "mcp-tool-call-body", children: [
|
|
99
|
+
Object.keys(call.arguments).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
100
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xs font-medium text-text-secondary mb-1", children: "Arguments" }),
|
|
101
|
+
/* @__PURE__ */ jsx("dl", { className: "space-y-1", "data-testid": "mcp-tool-arguments", children: Object.entries(call.arguments).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
102
|
+
/* @__PURE__ */ jsxs("dt", { className: "text-xs font-mono text-text-secondary shrink-0", children: [
|
|
103
|
+
key,
|
|
104
|
+
":"
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsx("dd", { className: "text-xs font-mono text-text-primary break-all", children: formatValue(value) })
|
|
107
|
+
] }, key)) })
|
|
108
|
+
] }),
|
|
109
|
+
call.result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
110
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xs font-medium text-text-secondary mb-1", children: "Result" }),
|
|
111
|
+
/* @__PURE__ */ jsx(
|
|
112
|
+
"pre",
|
|
113
|
+
{
|
|
114
|
+
className: "text-xs font-mono text-text-primary bg-neutral-100 rounded p-2 overflow-x-auto whitespace-pre-wrap",
|
|
115
|
+
"data-testid": "mcp-tool-result",
|
|
116
|
+
children: typeof call.result === "string" ? call.result : JSON.stringify(call.result, null, 2)
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] }),
|
|
120
|
+
call.error && /* @__PURE__ */ jsxs("div", { children: [
|
|
121
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xs font-medium text-status-error mb-1", children: "Error" }),
|
|
122
|
+
/* @__PURE__ */ jsx(
|
|
123
|
+
"p",
|
|
124
|
+
{
|
|
125
|
+
className: "text-xs text-status-error bg-status-error-subtle/30 rounded p-2",
|
|
126
|
+
"data-testid": "mcp-tool-error",
|
|
127
|
+
children: call.error
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
] })
|
|
131
|
+
] })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/mcp/MCPResourceView/MCPResourceView.tsx
|
|
138
|
+
import { twMerge as twMerge2 } from "tailwind-merge";
|
|
139
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
140
|
+
function isImageMime(mime) {
|
|
141
|
+
return !!mime && mime.startsWith("image/");
|
|
142
|
+
}
|
|
143
|
+
function isTextMime(mime) {
|
|
144
|
+
if (!mime) return true;
|
|
145
|
+
return mime.startsWith("text/") || mime === "application/json" || mime === "application/xml" || mime === "application/javascript" || mime === "application/typescript";
|
|
146
|
+
}
|
|
147
|
+
function isUrlContent(content) {
|
|
148
|
+
if (typeof content !== "string") return false;
|
|
149
|
+
return /^https?:\/\//.test(content.trim());
|
|
150
|
+
}
|
|
151
|
+
function MCPResourceView({ resource, className }) {
|
|
152
|
+
const { uri, name, mimeType, description, content } = resource;
|
|
153
|
+
return /* @__PURE__ */ jsxs2(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: twMerge2("rounded-lg border border-border bg-surface p-3 text-sm", className),
|
|
157
|
+
"data-testid": "mcp-resource-view",
|
|
158
|
+
children: [
|
|
159
|
+
/* @__PURE__ */ jsxs2("div", { className: "mb-2", children: [
|
|
160
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium text-text-primary", "data-testid": "mcp-resource-name", children: name }),
|
|
161
|
+
/* @__PURE__ */ jsx2(
|
|
162
|
+
"span",
|
|
163
|
+
{
|
|
164
|
+
className: "ml-2 text-xs text-text-secondary font-mono truncate",
|
|
165
|
+
"data-testid": "mcp-resource-uri",
|
|
166
|
+
children: uri
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
] }),
|
|
170
|
+
description && /* @__PURE__ */ jsx2("p", { className: "text-xs text-text-secondary mb-2", "data-testid": "mcp-resource-description", children: description }),
|
|
171
|
+
content !== void 0 && /* @__PURE__ */ jsx2("div", { "data-testid": "mcp-resource-content", children: isImageMime(mimeType) && typeof content === "string" ? /* @__PURE__ */ jsx2(
|
|
172
|
+
"img",
|
|
173
|
+
{
|
|
174
|
+
src: content,
|
|
175
|
+
alt: name,
|
|
176
|
+
className: "max-w-full rounded",
|
|
177
|
+
"data-testid": "mcp-resource-image"
|
|
178
|
+
}
|
|
179
|
+
) : isUrlContent(content) ? /* @__PURE__ */ jsx2(
|
|
180
|
+
"a",
|
|
181
|
+
{
|
|
182
|
+
href: typeof content === "string" ? content.trim() : void 0,
|
|
183
|
+
target: "_blank",
|
|
184
|
+
rel: "noopener noreferrer",
|
|
185
|
+
className: "text-sm text-interactive-primary hover:underline break-all",
|
|
186
|
+
"data-testid": "mcp-resource-link",
|
|
187
|
+
children: typeof content === "string" ? content.trim() : ""
|
|
188
|
+
}
|
|
189
|
+
) : isTextMime(mimeType) ? /* @__PURE__ */ jsx2(
|
|
190
|
+
"pre",
|
|
191
|
+
{
|
|
192
|
+
className: "text-xs font-mono text-text-primary bg-neutral-100 rounded p-2 overflow-x-auto whitespace-pre-wrap",
|
|
193
|
+
"data-testid": "mcp-resource-code",
|
|
194
|
+
children: typeof content === "string" ? content : "[Binary data]"
|
|
195
|
+
}
|
|
196
|
+
) : /* @__PURE__ */ jsxs2("p", { className: "text-xs text-text-secondary italic", children: [
|
|
197
|
+
"Unsupported content type: ",
|
|
198
|
+
mimeType
|
|
199
|
+
] }) })
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/mcp/MCPServerStatus/MCPServerStatus.tsx
|
|
206
|
+
import { useState } from "react";
|
|
207
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
208
|
+
import { twMerge as twMerge3 } from "tailwind-merge";
|
|
209
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
210
|
+
var statusDot = cva2("inline-block h-2 w-2 rounded-full shrink-0", {
|
|
211
|
+
variants: {
|
|
212
|
+
status: {
|
|
213
|
+
connected: "bg-status-success",
|
|
214
|
+
disconnected: "bg-neutral-400",
|
|
215
|
+
error: "bg-status-error"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
defaultVariants: { status: "disconnected" }
|
|
219
|
+
});
|
|
220
|
+
var statusLabel2 = {
|
|
221
|
+
connected: "Connected",
|
|
222
|
+
disconnected: "Disconnected",
|
|
223
|
+
error: "Error"
|
|
224
|
+
};
|
|
225
|
+
function formatLastPing(date) {
|
|
226
|
+
if (!date) return null;
|
|
227
|
+
return date.toLocaleTimeString();
|
|
228
|
+
}
|
|
229
|
+
function MCPServerStatus({ server, className }) {
|
|
230
|
+
const [showTools, setShowTools] = useState(false);
|
|
231
|
+
const [showResources, setShowResources] = useState(false);
|
|
232
|
+
const lastPing = formatLastPing(server.lastPing);
|
|
233
|
+
return /* @__PURE__ */ jsxs3(
|
|
234
|
+
"div",
|
|
235
|
+
{
|
|
236
|
+
className: twMerge3("rounded-lg border border-border bg-surface p-3 text-sm", className),
|
|
237
|
+
"data-testid": "mcp-server-status",
|
|
238
|
+
children: [
|
|
239
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
240
|
+
/* @__PURE__ */ jsx3(
|
|
241
|
+
"span",
|
|
242
|
+
{
|
|
243
|
+
className: statusDot({ status: server.status }),
|
|
244
|
+
role: "status",
|
|
245
|
+
"aria-label": statusLabel2[server.status],
|
|
246
|
+
"data-testid": "mcp-server-status-dot"
|
|
247
|
+
}
|
|
248
|
+
),
|
|
249
|
+
/* @__PURE__ */ jsx3("span", { className: "font-medium text-text-primary", "data-testid": "mcp-server-name", children: server.name }),
|
|
250
|
+
server.version && /* @__PURE__ */ jsxs3("span", { className: "text-xs text-text-secondary", "data-testid": "mcp-server-version", children: [
|
|
251
|
+
"v",
|
|
252
|
+
server.version
|
|
253
|
+
] })
|
|
254
|
+
] }),
|
|
255
|
+
lastPing && /* @__PURE__ */ jsxs3("p", { className: "text-xs text-text-secondary ml-4 mb-2", "data-testid": "mcp-server-last-ping", children: [
|
|
256
|
+
"Last ping: ",
|
|
257
|
+
lastPing
|
|
258
|
+
] }),
|
|
259
|
+
server.tools.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "mt-2", children: [
|
|
260
|
+
/* @__PURE__ */ jsxs3(
|
|
261
|
+
"button",
|
|
262
|
+
{
|
|
263
|
+
type: "button",
|
|
264
|
+
className: "flex items-center gap-1 text-xs font-medium text-text-secondary hover:text-text-primary w-full",
|
|
265
|
+
onClick: () => setShowTools((prev) => !prev),
|
|
266
|
+
"aria-expanded": showTools,
|
|
267
|
+
"data-testid": "mcp-server-tools-toggle",
|
|
268
|
+
children: [
|
|
269
|
+
/* @__PURE__ */ jsx3(
|
|
270
|
+
"svg",
|
|
271
|
+
{
|
|
272
|
+
className: `h-3 w-3 transition-transform ${showTools ? "rotate-90" : ""}`,
|
|
273
|
+
viewBox: "0 0 20 20",
|
|
274
|
+
fill: "currentColor",
|
|
275
|
+
"aria-hidden": "true",
|
|
276
|
+
children: /* @__PURE__ */ jsx3(
|
|
277
|
+
"path",
|
|
278
|
+
{
|
|
279
|
+
fillRule: "evenodd",
|
|
280
|
+
d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z",
|
|
281
|
+
clipRule: "evenodd"
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
),
|
|
286
|
+
"Tools (",
|
|
287
|
+
server.tools.length,
|
|
288
|
+
")"
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
),
|
|
292
|
+
showTools && /* @__PURE__ */ jsx3("ul", { className: "mt-1 ml-4 space-y-1", "data-testid": "mcp-server-tools-list", children: server.tools.map((tool) => /* @__PURE__ */ jsxs3("li", { className: "text-xs text-text-primary", children: [
|
|
293
|
+
/* @__PURE__ */ jsx3("span", { className: "font-mono", children: tool.name }),
|
|
294
|
+
tool.description && /* @__PURE__ */ jsxs3("span", { className: "text-text-secondary ml-1", children: [
|
|
295
|
+
"\u2014 ",
|
|
296
|
+
tool.description
|
|
297
|
+
] })
|
|
298
|
+
] }, tool.name)) })
|
|
299
|
+
] }),
|
|
300
|
+
server.resources.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "mt-2", children: [
|
|
301
|
+
/* @__PURE__ */ jsxs3(
|
|
302
|
+
"button",
|
|
303
|
+
{
|
|
304
|
+
type: "button",
|
|
305
|
+
className: "flex items-center gap-1 text-xs font-medium text-text-secondary hover:text-text-primary w-full",
|
|
306
|
+
onClick: () => setShowResources((prev) => !prev),
|
|
307
|
+
"aria-expanded": showResources,
|
|
308
|
+
"data-testid": "mcp-server-resources-toggle",
|
|
309
|
+
children: [
|
|
310
|
+
/* @__PURE__ */ jsx3(
|
|
311
|
+
"svg",
|
|
312
|
+
{
|
|
313
|
+
className: `h-3 w-3 transition-transform ${showResources ? "rotate-90" : ""}`,
|
|
314
|
+
viewBox: "0 0 20 20",
|
|
315
|
+
fill: "currentColor",
|
|
316
|
+
"aria-hidden": "true",
|
|
317
|
+
children: /* @__PURE__ */ jsx3(
|
|
318
|
+
"path",
|
|
319
|
+
{
|
|
320
|
+
fillRule: "evenodd",
|
|
321
|
+
d: "M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z",
|
|
322
|
+
clipRule: "evenodd"
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
),
|
|
327
|
+
"Resources (",
|
|
328
|
+
server.resources.length,
|
|
329
|
+
")"
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
),
|
|
333
|
+
showResources && /* @__PURE__ */ jsx3("ul", { className: "mt-1 ml-4 space-y-1", "data-testid": "mcp-server-resources-list", children: server.resources.map((res) => /* @__PURE__ */ jsxs3("li", { className: "text-xs text-text-primary", children: [
|
|
334
|
+
/* @__PURE__ */ jsx3("span", { className: "font-mono", children: res.name }),
|
|
335
|
+
/* @__PURE__ */ jsxs3("span", { className: "text-text-secondary ml-1", children: [
|
|
336
|
+
"(",
|
|
337
|
+
res.uri,
|
|
338
|
+
")"
|
|
339
|
+
] })
|
|
340
|
+
] }, res.uri)) })
|
|
341
|
+
] })
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/mcp/MCPApprovalDialog/MCPApprovalDialog.tsx
|
|
348
|
+
import { useRef, useEffect } from "react";
|
|
349
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
350
|
+
import { twMerge as twMerge4 } from "tailwind-merge";
|
|
351
|
+
import { useDialog, FocusScope } from "react-aria";
|
|
352
|
+
import { Button, Badge as Badge2 } from "@surf-kit/core";
|
|
353
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
354
|
+
var riskBadgeIntent = {
|
|
355
|
+
low: "success",
|
|
356
|
+
medium: "warning",
|
|
357
|
+
high: "error"
|
|
358
|
+
};
|
|
359
|
+
var riskLabel = {
|
|
360
|
+
low: "Low Risk",
|
|
361
|
+
medium: "Medium Risk",
|
|
362
|
+
high: "High Risk"
|
|
363
|
+
};
|
|
364
|
+
var riskBorder = cva3("relative bg-surface rounded-xl shadow-xl border p-6 outline-none w-full max-w-lg", {
|
|
365
|
+
variants: {
|
|
366
|
+
risk: {
|
|
367
|
+
low: "border-status-success-subtle",
|
|
368
|
+
medium: "border-status-warning-subtle",
|
|
369
|
+
high: "border-status-error-subtle"
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
defaultVariants: { risk: "low" }
|
|
373
|
+
});
|
|
374
|
+
function formatValue2(value) {
|
|
375
|
+
if (typeof value === "string") return value;
|
|
376
|
+
return JSON.stringify(value, null, 2);
|
|
377
|
+
}
|
|
378
|
+
function MCPApprovalDialog({
|
|
379
|
+
call,
|
|
380
|
+
riskLevel = "low",
|
|
381
|
+
onApprove,
|
|
382
|
+
onDeny,
|
|
383
|
+
isOpen,
|
|
384
|
+
className
|
|
385
|
+
}) {
|
|
386
|
+
const ref = useRef(null);
|
|
387
|
+
const { dialogProps, titleProps } = useDialog({ role: "alertdialog" }, ref);
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (!isOpen) return;
|
|
390
|
+
const handleKeyDown = (e) => {
|
|
391
|
+
if (e.key === "Escape") {
|
|
392
|
+
e.preventDefault();
|
|
393
|
+
e.stopPropagation();
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
document.addEventListener("keydown", handleKeyDown, true);
|
|
397
|
+
return () => document.removeEventListener("keydown", handleKeyDown, true);
|
|
398
|
+
}, [isOpen]);
|
|
399
|
+
if (!isOpen) return null;
|
|
400
|
+
return /* @__PURE__ */ jsx4(
|
|
401
|
+
"div",
|
|
402
|
+
{
|
|
403
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50",
|
|
404
|
+
"data-testid": "mcp-approval-overlay",
|
|
405
|
+
children: /* @__PURE__ */ jsx4(FocusScope, { contain: true, restoreFocus: true, autoFocus: true, children: /* @__PURE__ */ jsxs4(
|
|
406
|
+
"div",
|
|
407
|
+
{
|
|
408
|
+
...dialogProps,
|
|
409
|
+
ref,
|
|
410
|
+
className: twMerge4(riskBorder({ risk: riskLevel }), className),
|
|
411
|
+
"data-testid": "mcp-approval-dialog",
|
|
412
|
+
children: [
|
|
413
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between mb-4", children: [
|
|
414
|
+
/* @__PURE__ */ jsx4(
|
|
415
|
+
"h2",
|
|
416
|
+
{
|
|
417
|
+
...titleProps,
|
|
418
|
+
className: "text-lg font-semibold text-text-primary",
|
|
419
|
+
"data-testid": "mcp-approval-title",
|
|
420
|
+
children: "Tool Approval Required"
|
|
421
|
+
}
|
|
422
|
+
),
|
|
423
|
+
/* @__PURE__ */ jsx4(
|
|
424
|
+
Badge2,
|
|
425
|
+
{
|
|
426
|
+
intent: riskBadgeIntent[riskLevel],
|
|
427
|
+
size: "sm",
|
|
428
|
+
"data-testid": "mcp-approval-risk-badge",
|
|
429
|
+
children: riskLabel[riskLevel]
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
] }),
|
|
433
|
+
/* @__PURE__ */ jsxs4("div", { className: "space-y-3 text-sm", children: [
|
|
434
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
435
|
+
/* @__PURE__ */ jsx4("h3", { className: "text-xs font-medium text-text-secondary mb-1", children: "Tool" }),
|
|
436
|
+
/* @__PURE__ */ jsx4("p", { className: "font-mono text-text-primary", "data-testid": "mcp-approval-tool-name", children: call.name }),
|
|
437
|
+
call.serverName && /* @__PURE__ */ jsxs4("p", { className: "text-xs text-text-secondary mt-0.5", "data-testid": "mcp-approval-server", children: [
|
|
438
|
+
"Server: ",
|
|
439
|
+
call.serverName
|
|
440
|
+
] })
|
|
441
|
+
] }),
|
|
442
|
+
Object.keys(call.arguments).length > 0 && /* @__PURE__ */ jsxs4("div", { children: [
|
|
443
|
+
/* @__PURE__ */ jsx4("h3", { className: "text-xs font-medium text-text-secondary mb-1", children: "Arguments" }),
|
|
444
|
+
/* @__PURE__ */ jsx4(
|
|
445
|
+
"dl",
|
|
446
|
+
{
|
|
447
|
+
className: "space-y-1 bg-neutral-100 rounded p-2",
|
|
448
|
+
"data-testid": "mcp-approval-arguments",
|
|
449
|
+
children: Object.entries(call.arguments).map(([key, value]) => /* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
|
|
450
|
+
/* @__PURE__ */ jsxs4("dt", { className: "text-xs font-mono text-text-secondary shrink-0", children: [
|
|
451
|
+
key,
|
|
452
|
+
":"
|
|
453
|
+
] }),
|
|
454
|
+
/* @__PURE__ */ jsx4("dd", { className: "text-xs font-mono text-text-primary break-all", children: formatValue2(value) })
|
|
455
|
+
] }, key))
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
] })
|
|
459
|
+
] }),
|
|
460
|
+
/* @__PURE__ */ jsxs4("div", { className: "mt-6 flex justify-end gap-3", children: [
|
|
461
|
+
/* @__PURE__ */ jsx4(
|
|
462
|
+
Button,
|
|
463
|
+
{
|
|
464
|
+
intent: "secondary",
|
|
465
|
+
onPress: onDeny,
|
|
466
|
+
"aria-label": "Deny tool execution",
|
|
467
|
+
children: "Deny"
|
|
468
|
+
}
|
|
469
|
+
),
|
|
470
|
+
/* @__PURE__ */ jsx4(
|
|
471
|
+
Button,
|
|
472
|
+
{
|
|
473
|
+
intent: "primary",
|
|
474
|
+
onPress: onApprove,
|
|
475
|
+
"aria-label": "Approve tool execution",
|
|
476
|
+
children: "Approve"
|
|
477
|
+
}
|
|
478
|
+
)
|
|
479
|
+
] })
|
|
480
|
+
]
|
|
481
|
+
}
|
|
482
|
+
) })
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
export {
|
|
487
|
+
MCPApprovalDialog,
|
|
488
|
+
MCPResourceView,
|
|
489
|
+
MCPServerStatus,
|
|
490
|
+
MCPToolCall
|
|
491
|
+
};
|
|
492
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/MCPToolCall/MCPToolCall.tsx","../../src/mcp/MCPResourceView/MCPResourceView.tsx","../../src/mcp/MCPServerStatus/MCPServerStatus.tsx","../../src/mcp/MCPApprovalDialog/MCPApprovalDialog.tsx"],"sourcesContent":["import React from 'react'\nimport { cva } from 'class-variance-authority'\nimport { twMerge } from 'tailwind-merge'\nimport { Badge, Spinner } from '@surf-kit/core'\nimport type { MCPToolCallData, MCPToolStatus } from '../../types/mcp'\n\nexport type MCPToolCallProps = {\n call: MCPToolCallData\n isExpanded?: boolean\n onToggleExpand?: () => void\n className?: string\n}\n\nconst statusBadgeIntent: Record<MCPToolStatus, 'default' | 'info' | 'success' | 'error'> = {\n pending: 'default',\n running: 'info',\n success: 'success',\n error: 'error',\n}\n\nconst statusLabel: Record<MCPToolStatus, string> = {\n pending: 'Pending',\n running: 'Running',\n success: 'Success',\n error: 'Error',\n}\n\nconst container = cva(\n 'rounded-lg border text-sm',\n {\n variants: {\n status: {\n pending: 'border-neutral-200 bg-neutral-50',\n running: 'border-sky-200 bg-sky-50',\n success: 'border-status-success-subtle bg-status-success-subtle/30',\n error: 'border-status-error-subtle bg-status-error-subtle/30',\n },\n },\n defaultVariants: { status: 'pending' },\n },\n)\n\nfunction formatDuration(start?: Date, end?: Date): string | null {\n if (!start || !end) return null\n const ms = end.getTime() - start.getTime()\n if (ms < 1000) return `${ms}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === 'string') return value\n return JSON.stringify(value, null, 2)\n}\n\nfunction MCPToolCall({ call, isExpanded = false, onToggleExpand, className }: MCPToolCallProps) {\n const duration = formatDuration(call.startedAt, call.completedAt)\n\n return (\n <div\n className={twMerge(container({ status: call.status }), className)}\n data-testid=\"mcp-tool-call\"\n >\n {/* Header */}\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-between gap-2 px-3 py-2\"\n onClick={onToggleExpand}\n aria-expanded={isExpanded}\n data-testid=\"mcp-tool-call-header\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className=\"font-medium text-text-primary truncate\" data-testid=\"mcp-tool-name\">\n {call.name}\n </span>\n {call.serverName && (\n <span className=\"text-xs text-text-secondary truncate\">\n {call.serverName}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {call.status === 'running' && (\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n )}\n <Badge\n intent={statusBadgeIntent[call.status]}\n size=\"sm\"\n role=\"status\"\n aria-label={`Status: ${statusLabel[call.status]}`}\n data-testid=\"mcp-tool-status\"\n >\n {statusLabel[call.status]}\n </Badge>\n {duration && (\n <span className=\"text-xs text-text-secondary\" data-testid=\"mcp-tool-duration\">\n {duration}\n </span>\n )}\n <svg\n className={`h-4 w-4 text-text-secondary transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n </button>\n\n {/* Expandable body */}\n {isExpanded && (\n <div className=\"border-t border-inherit px-3 py-2 space-y-3\" data-testid=\"mcp-tool-call-body\">\n {/* Arguments */}\n {Object.keys(call.arguments).length > 0 && (\n <div>\n <h4 className=\"text-xs font-medium text-text-secondary mb-1\">Arguments</h4>\n <dl className=\"space-y-1\" data-testid=\"mcp-tool-arguments\">\n {Object.entries(call.arguments).map(([key, value]) => (\n <div key={key} className=\"flex gap-2\">\n <dt className=\"text-xs font-mono text-text-secondary shrink-0\">{key}:</dt>\n <dd className=\"text-xs font-mono text-text-primary break-all\">\n {formatValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n )}\n\n {/* Result */}\n {call.result !== undefined && (\n <div>\n <h4 className=\"text-xs font-medium text-text-secondary mb-1\">Result</h4>\n <pre\n className=\"text-xs font-mono text-text-primary bg-neutral-100 rounded p-2 overflow-x-auto whitespace-pre-wrap\"\n data-testid=\"mcp-tool-result\"\n >\n {typeof call.result === 'string' ? call.result : JSON.stringify(call.result, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Error */}\n {call.error && (\n <div>\n <h4 className=\"text-xs font-medium text-status-error mb-1\">Error</h4>\n <p\n className=\"text-xs text-status-error bg-status-error-subtle/30 rounded p-2\"\n data-testid=\"mcp-tool-error\"\n >\n {call.error}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport { MCPToolCall }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport type { MCPResource } from '../../types/mcp'\n\nexport type MCPResourceViewProps = {\n resource: MCPResource\n className?: string\n}\n\nfunction isImageMime(mime?: string): boolean {\n return !!mime && mime.startsWith('image/')\n}\n\nfunction isTextMime(mime?: string): boolean {\n if (!mime) return true\n return (\n mime.startsWith('text/') ||\n mime === 'application/json' ||\n mime === 'application/xml' ||\n mime === 'application/javascript' ||\n mime === 'application/typescript'\n )\n}\n\nfunction isUrlContent(content?: string | Uint8Array): boolean {\n if (typeof content !== 'string') return false\n return /^https?:\\/\\//.test(content.trim())\n}\n\nfunction MCPResourceView({ resource, className }: MCPResourceViewProps) {\n const { uri, name, mimeType, description, content } = resource\n\n return (\n <div\n className={twMerge('rounded-lg border border-border bg-surface p-3 text-sm', className)}\n data-testid=\"mcp-resource-view\"\n >\n {/* Header */}\n <div className=\"mb-2\">\n <span className=\"font-medium text-text-primary\" data-testid=\"mcp-resource-name\">\n {name}\n </span>\n <span\n className=\"ml-2 text-xs text-text-secondary font-mono truncate\"\n data-testid=\"mcp-resource-uri\"\n >\n {uri}\n </span>\n </div>\n\n {description && (\n <p className=\"text-xs text-text-secondary mb-2\" data-testid=\"mcp-resource-description\">\n {description}\n </p>\n )}\n\n {/* Content rendering */}\n {content !== undefined && (\n <div data-testid=\"mcp-resource-content\">\n {isImageMime(mimeType) && typeof content === 'string' ? (\n <img\n src={content}\n alt={name}\n className=\"max-w-full rounded\"\n data-testid=\"mcp-resource-image\"\n />\n ) : isUrlContent(content) ? (\n <a\n href={typeof content === 'string' ? content.trim() : undefined}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-interactive-primary hover:underline break-all\"\n data-testid=\"mcp-resource-link\"\n >\n {typeof content === 'string' ? content.trim() : ''}\n </a>\n ) : isTextMime(mimeType) ? (\n <pre\n className=\"text-xs font-mono text-text-primary bg-neutral-100 rounded p-2 overflow-x-auto whitespace-pre-wrap\"\n data-testid=\"mcp-resource-code\"\n >\n {typeof content === 'string' ? content : '[Binary data]'}\n </pre>\n ) : (\n <p className=\"text-xs text-text-secondary italic\">\n Unsupported content type: {mimeType}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport { MCPResourceView }\n","import React, { useState } from 'react'\nimport { cva } from 'class-variance-authority'\nimport { twMerge } from 'tailwind-merge'\nimport type { MCPServerInfo } from '../../types/mcp'\n\nexport type MCPServerStatusProps = {\n server: MCPServerInfo\n className?: string\n}\n\nconst statusDot = cva('inline-block h-2 w-2 rounded-full shrink-0', {\n variants: {\n status: {\n connected: 'bg-status-success',\n disconnected: 'bg-neutral-400',\n error: 'bg-status-error',\n },\n },\n defaultVariants: { status: 'disconnected' },\n})\n\nconst statusLabel: Record<MCPServerInfo['status'], string> = {\n connected: 'Connected',\n disconnected: 'Disconnected',\n error: 'Error',\n}\n\nfunction formatLastPing(date?: Date): string | null {\n if (!date) return null\n return date.toLocaleTimeString()\n}\n\nfunction MCPServerStatus({ server, className }: MCPServerStatusProps) {\n const [showTools, setShowTools] = useState(false)\n const [showResources, setShowResources] = useState(false)\n const lastPing = formatLastPing(server.lastPing)\n\n return (\n <div\n className={twMerge('rounded-lg border border-border bg-surface p-3 text-sm', className)}\n data-testid=\"mcp-server-status\"\n >\n {/* Header */}\n <div className=\"flex items-center gap-2 mb-1\">\n <span\n className={statusDot({ status: server.status })}\n role=\"status\"\n aria-label={statusLabel[server.status]}\n data-testid=\"mcp-server-status-dot\"\n />\n <span className=\"font-medium text-text-primary\" data-testid=\"mcp-server-name\">\n {server.name}\n </span>\n {server.version && (\n <span className=\"text-xs text-text-secondary\" data-testid=\"mcp-server-version\">\n v{server.version}\n </span>\n )}\n </div>\n\n {lastPing && (\n <p className=\"text-xs text-text-secondary ml-4 mb-2\" data-testid=\"mcp-server-last-ping\">\n Last ping: {lastPing}\n </p>\n )}\n\n {/* Tools list */}\n {server.tools.length > 0 && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n className=\"flex items-center gap-1 text-xs font-medium text-text-secondary hover:text-text-primary w-full\"\n onClick={() => setShowTools((prev) => !prev)}\n aria-expanded={showTools}\n data-testid=\"mcp-server-tools-toggle\"\n >\n <svg\n className={`h-3 w-3 transition-transform ${showTools ? 'rotate-90' : ''}`}\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clipRule=\"evenodd\"\n />\n </svg>\n Tools ({server.tools.length})\n </button>\n {showTools && (\n <ul className=\"mt-1 ml-4 space-y-1\" data-testid=\"mcp-server-tools-list\">\n {server.tools.map((tool) => (\n <li key={tool.name} className=\"text-xs text-text-primary\">\n <span className=\"font-mono\">{tool.name}</span>\n {tool.description && (\n <span className=\"text-text-secondary ml-1\">— {tool.description}</span>\n )}\n </li>\n ))}\n </ul>\n )}\n </div>\n )}\n\n {/* Resources list */}\n {server.resources.length > 0 && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n className=\"flex items-center gap-1 text-xs font-medium text-text-secondary hover:text-text-primary w-full\"\n onClick={() => setShowResources((prev) => !prev)}\n aria-expanded={showResources}\n data-testid=\"mcp-server-resources-toggle\"\n >\n <svg\n className={`h-3 w-3 transition-transform ${showResources ? 'rotate-90' : ''}`}\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clipRule=\"evenodd\"\n />\n </svg>\n Resources ({server.resources.length})\n </button>\n {showResources && (\n <ul className=\"mt-1 ml-4 space-y-1\" data-testid=\"mcp-server-resources-list\">\n {server.resources.map((res) => (\n <li key={res.uri} className=\"text-xs text-text-primary\">\n <span className=\"font-mono\">{res.name}</span>\n <span className=\"text-text-secondary ml-1\">({res.uri})</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport { MCPServerStatus }\n","import React, { useRef, useEffect } from 'react'\nimport { cva } from 'class-variance-authority'\nimport { twMerge } from 'tailwind-merge'\nimport { useDialog, FocusScope } from 'react-aria'\nimport { Button, Badge } from '@surf-kit/core'\nimport type { MCPToolCallData } from '../../types/mcp'\n\nexport type MCPApprovalDialogProps = {\n call: MCPToolCallData\n riskLevel?: 'low' | 'medium' | 'high'\n onApprove: () => void\n onDeny: () => void\n isOpen: boolean\n className?: string\n}\n\nconst riskBadgeIntent: Record<string, 'success' | 'warning' | 'error'> = {\n low: 'success',\n medium: 'warning',\n high: 'error',\n}\n\nconst riskLabel: Record<string, string> = {\n low: 'Low Risk',\n medium: 'Medium Risk',\n high: 'High Risk',\n}\n\nconst riskBorder = cva('relative bg-surface rounded-xl shadow-xl border p-6 outline-none w-full max-w-lg', {\n variants: {\n risk: {\n low: 'border-status-success-subtle',\n medium: 'border-status-warning-subtle',\n high: 'border-status-error-subtle',\n },\n },\n defaultVariants: { risk: 'low' },\n})\n\nfunction formatValue(value: unknown): string {\n if (typeof value === 'string') return value\n return JSON.stringify(value, null, 2)\n}\n\nfunction MCPApprovalDialog({\n call,\n riskLevel = 'low',\n onApprove,\n onDeny,\n isOpen,\n className,\n}: MCPApprovalDialogProps) {\n const ref = useRef<HTMLDivElement>(null)\n const { dialogProps, titleProps } = useDialog({ role: 'alertdialog' }, ref)\n\n // Block Escape key — user must explicitly approve or deny\n useEffect(() => {\n if (!isOpen) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n }\n }\n document.addEventListener('keydown', handleKeyDown, true)\n return () => document.removeEventListener('keydown', handleKeyDown, true)\n }, [isOpen])\n\n if (!isOpen) return null\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n data-testid=\"mcp-approval-overlay\"\n >\n <FocusScope contain restoreFocus autoFocus>\n <div\n {...dialogProps}\n ref={ref}\n className={twMerge(riskBorder({ risk: riskLevel }), className)}\n data-testid=\"mcp-approval-dialog\"\n >\n {/* Title */}\n <div className=\"flex items-center justify-between mb-4\">\n <h2\n {...titleProps}\n className=\"text-lg font-semibold text-text-primary\"\n data-testid=\"mcp-approval-title\"\n >\n Tool Approval Required\n </h2>\n <Badge\n intent={riskBadgeIntent[riskLevel]}\n size=\"sm\"\n data-testid=\"mcp-approval-risk-badge\"\n >\n {riskLabel[riskLevel]}\n </Badge>\n </div>\n\n {/* Tool info */}\n <div className=\"space-y-3 text-sm\">\n <div>\n <h3 className=\"text-xs font-medium text-text-secondary mb-1\">Tool</h3>\n <p className=\"font-mono text-text-primary\" data-testid=\"mcp-approval-tool-name\">\n {call.name}\n </p>\n {call.serverName && (\n <p className=\"text-xs text-text-secondary mt-0.5\" data-testid=\"mcp-approval-server\">\n Server: {call.serverName}\n </p>\n )}\n </div>\n\n {/* Arguments */}\n {Object.keys(call.arguments).length > 0 && (\n <div>\n <h3 className=\"text-xs font-medium text-text-secondary mb-1\">Arguments</h3>\n <dl\n className=\"space-y-1 bg-neutral-100 rounded p-2\"\n data-testid=\"mcp-approval-arguments\"\n >\n {Object.entries(call.arguments).map(([key, value]) => (\n <div key={key} className=\"flex gap-2\">\n <dt className=\"text-xs font-mono text-text-secondary shrink-0\">{key}:</dt>\n <dd className=\"text-xs font-mono text-text-primary break-all\">\n {formatValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"mt-6 flex justify-end gap-3\">\n <Button\n intent=\"secondary\"\n onPress={onDeny}\n aria-label=\"Deny tool execution\"\n >\n Deny\n </Button>\n <Button\n intent=\"primary\"\n onPress={onApprove}\n aria-label=\"Approve tool execution\"\n >\n Approve\n </Button>\n </div>\n </div>\n </FocusScope>\n </div>\n )\n}\n\nexport { MCPApprovalDialog }\n"],"mappings":"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","names":["twMerge","jsx","jsxs","cva","twMerge","jsx","jsxs","statusLabel","cva","twMerge","Badge","jsx","jsxs","formatValue"]}
|