mcp-use 1.3.3-canary.2 → 1.3.3-canary.4
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/.tsbuildinfo +1 -1
- package/dist/chunk-QKPVHYJU.js +2027 -0
- package/dist/index.cjs +1248 -5
- package/dist/index.js +5 -1
- package/dist/src/react/WidgetDebugger.d.ts +31 -0
- package/dist/src/react/WidgetDebugger.d.ts.map +1 -0
- package/dist/src/react/WidgetFullscreenWrapper.d.ts +32 -0
- package/dist/src/react/WidgetFullscreenWrapper.d.ts.map +1 -0
- package/dist/src/react/index.cjs +1248 -5
- package/dist/src/react/index.d.ts +2 -0
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/react/index.js +5 -1
- package/dist/src/react/useWidget.d.ts.map +1 -1
- package/dist/src/server/index.cjs +31 -14
- package/dist/src/server/index.js +31 -14
- package/dist/src/server/mcp-server.d.ts +10 -0
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-VNEGDXZO.js +0 -784
|
@@ -0,0 +1,2027 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrowserMCPClient,
|
|
3
|
+
BrowserOAuthClientProvider
|
|
4
|
+
} from "./chunk-TIUSJAAE.js";
|
|
5
|
+
import {
|
|
6
|
+
__name
|
|
7
|
+
} from "./chunk-3GQAWCBQ.js";
|
|
8
|
+
|
|
9
|
+
// src/react/useMcp.ts
|
|
10
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
|
+
import { sanitizeUrl } from "strict-url-sanitise";
|
|
12
|
+
|
|
13
|
+
// src/utils/assert.ts
|
|
14
|
+
function assert(condition, message) {
|
|
15
|
+
if (!condition) {
|
|
16
|
+
throw new Error(message);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
__name(assert, "assert");
|
|
20
|
+
|
|
21
|
+
// src/react/useMcp.ts
|
|
22
|
+
var DEFAULT_RECONNECT_DELAY = 3e3;
|
|
23
|
+
var DEFAULT_RETRY_DELAY = 5e3;
|
|
24
|
+
var AUTH_TIMEOUT = 5 * 60 * 1e3;
|
|
25
|
+
function useMcp(options) {
|
|
26
|
+
const {
|
|
27
|
+
url,
|
|
28
|
+
enabled = true,
|
|
29
|
+
clientName,
|
|
30
|
+
clientUri,
|
|
31
|
+
callbackUrl = typeof window !== "undefined" ? sanitizeUrl(
|
|
32
|
+
new URL("/oauth/callback", window.location.origin).toString()
|
|
33
|
+
) : "/oauth/callback",
|
|
34
|
+
storageKeyPrefix = "mcp:auth",
|
|
35
|
+
clientConfig = {},
|
|
36
|
+
customHeaders = {},
|
|
37
|
+
debug: _debug = false,
|
|
38
|
+
autoRetry = false,
|
|
39
|
+
autoReconnect = DEFAULT_RECONNECT_DELAY,
|
|
40
|
+
transportType = "auto",
|
|
41
|
+
preventAutoAuth = false,
|
|
42
|
+
onPopupWindow,
|
|
43
|
+
timeout = 3e4,
|
|
44
|
+
// 30 seconds default for connection timeout
|
|
45
|
+
sseReadTimeout = 3e5
|
|
46
|
+
// 5 minutes default for SSE read timeout
|
|
47
|
+
} = options;
|
|
48
|
+
const [state, setState] = useState("discovering");
|
|
49
|
+
const [tools, setTools] = useState([]);
|
|
50
|
+
const [resources, setResources] = useState([]);
|
|
51
|
+
const [resourceTemplates, setResourceTemplates] = useState([]);
|
|
52
|
+
const [prompts, setPrompts] = useState([]);
|
|
53
|
+
const [serverInfo, setServerInfo] = useState();
|
|
54
|
+
const [capabilities, setCapabilities] = useState();
|
|
55
|
+
const [error, setError] = useState(void 0);
|
|
56
|
+
const [log, setLog] = useState([]);
|
|
57
|
+
const [authUrl, setAuthUrl] = useState(void 0);
|
|
58
|
+
const clientRef = useRef(null);
|
|
59
|
+
const authProviderRef = useRef(null);
|
|
60
|
+
const connectingRef = useRef(false);
|
|
61
|
+
const isMountedRef = useRef(true);
|
|
62
|
+
const connectAttemptRef = useRef(0);
|
|
63
|
+
const authTimeoutRef = useRef(null);
|
|
64
|
+
const stateRef = useRef(state);
|
|
65
|
+
const autoReconnectRef = useRef(autoReconnect);
|
|
66
|
+
const successfulTransportRef = useRef(null);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
stateRef.current = state;
|
|
69
|
+
autoReconnectRef.current = autoReconnect;
|
|
70
|
+
}, [state, autoReconnect]);
|
|
71
|
+
const addLog = useCallback(
|
|
72
|
+
(level, message, ...args) => {
|
|
73
|
+
const fullMessage = args.length > 0 ? `${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}` : message;
|
|
74
|
+
console[level](`[useMcp] ${fullMessage}`);
|
|
75
|
+
if (isMountedRef.current) {
|
|
76
|
+
setLog((prevLog) => [
|
|
77
|
+
...prevLog.slice(-100),
|
|
78
|
+
{ level, message: fullMessage, timestamp: Date.now() }
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
[]
|
|
83
|
+
);
|
|
84
|
+
const disconnect = useCallback(
|
|
85
|
+
async (quiet = false) => {
|
|
86
|
+
if (!quiet) addLog("info", "Disconnecting...");
|
|
87
|
+
connectingRef.current = false;
|
|
88
|
+
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
89
|
+
authTimeoutRef.current = null;
|
|
90
|
+
if (clientRef.current) {
|
|
91
|
+
try {
|
|
92
|
+
const serverName = "inspector-server";
|
|
93
|
+
await clientRef.current.closeSession(serverName);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
if (!quiet) addLog("warn", "Error closing session:", err);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
clientRef.current = null;
|
|
99
|
+
if (isMountedRef.current && !quiet) {
|
|
100
|
+
setState("discovering");
|
|
101
|
+
setTools([]);
|
|
102
|
+
setResources([]);
|
|
103
|
+
setResourceTemplates([]);
|
|
104
|
+
setPrompts([]);
|
|
105
|
+
setError(void 0);
|
|
106
|
+
setAuthUrl(void 0);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
[addLog]
|
|
110
|
+
);
|
|
111
|
+
const failConnection = useCallback(
|
|
112
|
+
(errorMessage, connectionError) => {
|
|
113
|
+
addLog("error", errorMessage, connectionError ?? "");
|
|
114
|
+
if (isMountedRef.current) {
|
|
115
|
+
setState("failed");
|
|
116
|
+
setError(errorMessage);
|
|
117
|
+
const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
|
|
118
|
+
if (manualUrl) {
|
|
119
|
+
setAuthUrl(manualUrl);
|
|
120
|
+
addLog(
|
|
121
|
+
"info",
|
|
122
|
+
"Manual authentication URL may be available.",
|
|
123
|
+
manualUrl
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
connectingRef.current = false;
|
|
128
|
+
},
|
|
129
|
+
[addLog]
|
|
130
|
+
);
|
|
131
|
+
const connect = useCallback(async () => {
|
|
132
|
+
if (!enabled || !url) {
|
|
133
|
+
addLog(
|
|
134
|
+
"debug",
|
|
135
|
+
enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
|
|
136
|
+
);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (connectingRef.current) {
|
|
140
|
+
addLog("debug", "Connection attempt already in progress.");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (!isMountedRef.current) {
|
|
144
|
+
addLog("debug", "Connect called after unmount, aborting.");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
connectingRef.current = true;
|
|
148
|
+
connectAttemptRef.current += 1;
|
|
149
|
+
setError(void 0);
|
|
150
|
+
setAuthUrl(void 0);
|
|
151
|
+
successfulTransportRef.current = null;
|
|
152
|
+
setState("discovering");
|
|
153
|
+
addLog(
|
|
154
|
+
"info",
|
|
155
|
+
`Connecting attempt #${connectAttemptRef.current} to ${url}...`
|
|
156
|
+
);
|
|
157
|
+
if (!authProviderRef.current) {
|
|
158
|
+
authProviderRef.current = new BrowserOAuthClientProvider(url, {
|
|
159
|
+
storageKeyPrefix,
|
|
160
|
+
clientName,
|
|
161
|
+
clientUri,
|
|
162
|
+
callbackUrl,
|
|
163
|
+
preventAutoAuth,
|
|
164
|
+
onPopupWindow
|
|
165
|
+
});
|
|
166
|
+
addLog("debug", "BrowserOAuthClientProvider initialized in connect.");
|
|
167
|
+
}
|
|
168
|
+
if (!clientRef.current) {
|
|
169
|
+
clientRef.current = new BrowserMCPClient();
|
|
170
|
+
addLog("debug", "BrowserMCPClient initialized in connect.");
|
|
171
|
+
}
|
|
172
|
+
const tryConnectWithTransport = /* @__PURE__ */ __name(async (transportTypeParam, isAuthRetry = false) => {
|
|
173
|
+
addLog(
|
|
174
|
+
"info",
|
|
175
|
+
`Attempting connection with transport: ${transportTypeParam}`
|
|
176
|
+
);
|
|
177
|
+
try {
|
|
178
|
+
const serverName = "inspector-server";
|
|
179
|
+
const serverConfig = {
|
|
180
|
+
url,
|
|
181
|
+
transport: transportTypeParam === "sse" ? "http" : transportTypeParam
|
|
182
|
+
};
|
|
183
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
184
|
+
serverConfig.headers = customHeaders;
|
|
185
|
+
}
|
|
186
|
+
if (authProviderRef.current) {
|
|
187
|
+
const tokens = await authProviderRef.current.tokens();
|
|
188
|
+
if (tokens?.access_token) {
|
|
189
|
+
serverConfig.headers = {
|
|
190
|
+
...serverConfig.headers,
|
|
191
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
clientRef.current.addServer(serverName, {
|
|
196
|
+
...serverConfig,
|
|
197
|
+
authProvider: authProviderRef.current
|
|
198
|
+
// ← SDK handles OAuth automatically!
|
|
199
|
+
});
|
|
200
|
+
const session = await clientRef.current.createSession(serverName);
|
|
201
|
+
await session.initialize();
|
|
202
|
+
addLog("info", "\u2705 Successfully connected to MCP server");
|
|
203
|
+
addLog("info", "Server info:", session.connector.serverInfo);
|
|
204
|
+
addLog(
|
|
205
|
+
"info",
|
|
206
|
+
"Server capabilities:",
|
|
207
|
+
session.connector.serverCapabilities
|
|
208
|
+
);
|
|
209
|
+
console.log("[useMcp] Server info:", session.connector.serverInfo);
|
|
210
|
+
console.log(
|
|
211
|
+
"[useMcp] Server capabilities:",
|
|
212
|
+
session.connector.serverCapabilities
|
|
213
|
+
);
|
|
214
|
+
setState("ready");
|
|
215
|
+
successfulTransportRef.current = transportTypeParam;
|
|
216
|
+
setTools(session.connector.tools || []);
|
|
217
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
218
|
+
setResources(resourcesResult.resources || []);
|
|
219
|
+
const promptsResult = await session.connector.listPrompts();
|
|
220
|
+
setPrompts(promptsResult.prompts || []);
|
|
221
|
+
const serverInfo2 = session.connector.serverInfo;
|
|
222
|
+
const capabilities2 = session.connector.serverCapabilities;
|
|
223
|
+
if (serverInfo2) {
|
|
224
|
+
console.log("[useMcp] Server info:", serverInfo2);
|
|
225
|
+
setServerInfo(serverInfo2);
|
|
226
|
+
}
|
|
227
|
+
if (capabilities2) {
|
|
228
|
+
console.log("[useMcp] Server capabilities:", capabilities2);
|
|
229
|
+
setCapabilities(capabilities2);
|
|
230
|
+
}
|
|
231
|
+
return "success";
|
|
232
|
+
} catch (err) {
|
|
233
|
+
const errorMessage = err?.message || String(err);
|
|
234
|
+
if (err.code === 401 || errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
235
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
236
|
+
failConnection(
|
|
237
|
+
"Authentication failed: Server returned 401 Unauthorized. Check your Authorization header value is correct."
|
|
238
|
+
);
|
|
239
|
+
return "failed";
|
|
240
|
+
}
|
|
241
|
+
failConnection(
|
|
242
|
+
"Authentication required: Server returned 401 Unauthorized. Add an Authorization header in the Custom Headers section (e.g., Authorization: Bearer YOUR_API_KEY)."
|
|
243
|
+
);
|
|
244
|
+
return "failed";
|
|
245
|
+
}
|
|
246
|
+
failConnection(errorMessage, err);
|
|
247
|
+
return "failed";
|
|
248
|
+
}
|
|
249
|
+
}, "tryConnectWithTransport");
|
|
250
|
+
let finalStatus = "failed";
|
|
251
|
+
if (transportType === "sse") {
|
|
252
|
+
addLog("debug", "Using SSE-only transport mode");
|
|
253
|
+
finalStatus = await tryConnectWithTransport("sse");
|
|
254
|
+
} else if (transportType === "http") {
|
|
255
|
+
addLog("debug", "Using HTTP-only transport mode");
|
|
256
|
+
finalStatus = await tryConnectWithTransport("http");
|
|
257
|
+
} else {
|
|
258
|
+
addLog("debug", "Using auto transport mode (HTTP with SSE fallback)");
|
|
259
|
+
const httpResult = await tryConnectWithTransport("http");
|
|
260
|
+
if (httpResult === "fallback" && isMountedRef.current && stateRef.current !== "authenticating") {
|
|
261
|
+
addLog("info", "HTTP failed, attempting SSE fallback...");
|
|
262
|
+
const sseResult = await tryConnectWithTransport("sse");
|
|
263
|
+
finalStatus = sseResult;
|
|
264
|
+
} else {
|
|
265
|
+
finalStatus = httpResult;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (finalStatus === "success" || finalStatus === "failed" || finalStatus === "auth_redirect") {
|
|
269
|
+
connectingRef.current = false;
|
|
270
|
+
}
|
|
271
|
+
addLog("debug", `Connection sequence finished with status: ${finalStatus}`);
|
|
272
|
+
}, [
|
|
273
|
+
addLog,
|
|
274
|
+
failConnection,
|
|
275
|
+
disconnect,
|
|
276
|
+
url,
|
|
277
|
+
storageKeyPrefix,
|
|
278
|
+
clientName,
|
|
279
|
+
clientUri,
|
|
280
|
+
callbackUrl,
|
|
281
|
+
clientConfig.name,
|
|
282
|
+
clientConfig.version,
|
|
283
|
+
customHeaders,
|
|
284
|
+
transportType,
|
|
285
|
+
preventAutoAuth,
|
|
286
|
+
onPopupWindow,
|
|
287
|
+
enabled,
|
|
288
|
+
timeout,
|
|
289
|
+
sseReadTimeout
|
|
290
|
+
]);
|
|
291
|
+
const callTool = useCallback(
|
|
292
|
+
async (name, args) => {
|
|
293
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
`MCP client is not ready (current state: ${state}). Cannot call tool "${name}".`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
addLog("info", `Calling tool: ${name}`, args);
|
|
299
|
+
try {
|
|
300
|
+
const serverName = "inspector-server";
|
|
301
|
+
const session = clientRef.current.getSession(serverName);
|
|
302
|
+
if (!session) {
|
|
303
|
+
throw new Error("No active session found");
|
|
304
|
+
}
|
|
305
|
+
const result = await session.connector.callTool(name, args || {});
|
|
306
|
+
addLog("info", `Tool "${name}" call successful:`, result);
|
|
307
|
+
return result;
|
|
308
|
+
} catch (err) {
|
|
309
|
+
addLog("error", `Tool "${name}" call failed:`, err);
|
|
310
|
+
throw err;
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
[state]
|
|
314
|
+
);
|
|
315
|
+
const retry = useCallback(() => {
|
|
316
|
+
if (stateRef.current === "failed") {
|
|
317
|
+
addLog("info", "Retry requested...");
|
|
318
|
+
connect();
|
|
319
|
+
} else {
|
|
320
|
+
addLog(
|
|
321
|
+
"warn",
|
|
322
|
+
`Retry called but state is not 'failed' (state: ${stateRef.current}). Ignoring.`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}, [addLog, connect]);
|
|
326
|
+
const authenticate = useCallback(async () => {
|
|
327
|
+
addLog("info", "Manual authentication requested...");
|
|
328
|
+
const currentState = stateRef.current;
|
|
329
|
+
if (currentState === "failed") {
|
|
330
|
+
addLog("info", "Attempting to reconnect and authenticate via retry...");
|
|
331
|
+
retry();
|
|
332
|
+
} else if (currentState === "pending_auth") {
|
|
333
|
+
addLog("info", "Proceeding with authentication from pending state...");
|
|
334
|
+
setState("authenticating");
|
|
335
|
+
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
336
|
+
authTimeoutRef.current = setTimeout(() => {
|
|
337
|
+
if (isMountedRef.current) {
|
|
338
|
+
const currentStateValue = stateRef.current;
|
|
339
|
+
if (currentStateValue === "authenticating") {
|
|
340
|
+
failConnection("Authentication timed out. Please try again.");
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}, AUTH_TIMEOUT);
|
|
344
|
+
try {
|
|
345
|
+
assert(
|
|
346
|
+
authProviderRef.current,
|
|
347
|
+
"Auth Provider not available for manual auth"
|
|
348
|
+
);
|
|
349
|
+
assert(url, "Server URL is required for authentication");
|
|
350
|
+
addLog(
|
|
351
|
+
"info",
|
|
352
|
+
"Redirecting for manual authentication. Waiting for callback..."
|
|
353
|
+
);
|
|
354
|
+
} catch (authError) {
|
|
355
|
+
if (!isMountedRef.current) return;
|
|
356
|
+
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
357
|
+
failConnection(
|
|
358
|
+
`Manual authentication failed: ${authError instanceof Error ? authError.message : String(authError)}`,
|
|
359
|
+
authError instanceof Error ? authError : void 0
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
} else if (currentState === "authenticating") {
|
|
363
|
+
addLog(
|
|
364
|
+
"warn",
|
|
365
|
+
"Already attempting authentication. Check for blocked popups or wait for timeout."
|
|
366
|
+
);
|
|
367
|
+
const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
|
|
368
|
+
if (manualUrl && !authUrl) {
|
|
369
|
+
setAuthUrl(manualUrl);
|
|
370
|
+
addLog("info", "Manual authentication URL retrieved:", manualUrl);
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
addLog(
|
|
374
|
+
"info",
|
|
375
|
+
`Client not in a state requiring manual authentication trigger (state: ${currentState}). If needed, try disconnecting and reconnecting.`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
}, [addLog, retry, authUrl, url, failConnection, connect]);
|
|
379
|
+
const clearStorage = useCallback(() => {
|
|
380
|
+
if (authProviderRef.current) {
|
|
381
|
+
const count = authProviderRef.current.clearStorage();
|
|
382
|
+
addLog("info", `Cleared ${count} item(s) from localStorage for ${url}.`);
|
|
383
|
+
setAuthUrl(void 0);
|
|
384
|
+
disconnect();
|
|
385
|
+
} else {
|
|
386
|
+
addLog("warn", "Auth provider not initialized, cannot clear storage.");
|
|
387
|
+
}
|
|
388
|
+
}, [url, addLog, disconnect]);
|
|
389
|
+
const listResources = useCallback(async () => {
|
|
390
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
391
|
+
throw new Error(
|
|
392
|
+
`MCP client is not ready (current state: ${state}). Cannot list resources.`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
addLog("info", "Listing resources");
|
|
396
|
+
try {
|
|
397
|
+
const serverName = "inspector-server";
|
|
398
|
+
const session = clientRef.current.getSession(serverName);
|
|
399
|
+
if (!session) {
|
|
400
|
+
throw new Error("No active session found");
|
|
401
|
+
}
|
|
402
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
403
|
+
setResources(resourcesResult.resources || []);
|
|
404
|
+
addLog("info", "Resources listed successfully");
|
|
405
|
+
} catch (err) {
|
|
406
|
+
addLog("error", "List resources failed:", err);
|
|
407
|
+
throw err;
|
|
408
|
+
}
|
|
409
|
+
}, [state]);
|
|
410
|
+
const readResource = useCallback(
|
|
411
|
+
async (uri) => {
|
|
412
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`MCP client is not ready (current state: ${state}). Cannot read resource.`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
addLog("info", `Reading resource: ${uri}`);
|
|
418
|
+
try {
|
|
419
|
+
const serverName = "inspector-server";
|
|
420
|
+
const session = clientRef.current.getSession(serverName);
|
|
421
|
+
if (!session) {
|
|
422
|
+
throw new Error("No active session found");
|
|
423
|
+
}
|
|
424
|
+
const result = await session.connector.readResource(uri);
|
|
425
|
+
addLog("info", "Resource read successful:", result);
|
|
426
|
+
return result;
|
|
427
|
+
} catch (err) {
|
|
428
|
+
addLog("error", "Resource read failed:", err);
|
|
429
|
+
throw err;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
[state]
|
|
433
|
+
);
|
|
434
|
+
const listPrompts = useCallback(async () => {
|
|
435
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
436
|
+
throw new Error(
|
|
437
|
+
`MCP client is not ready (current state: ${state}). Cannot list prompts.`
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
addLog("info", "Listing prompts");
|
|
441
|
+
try {
|
|
442
|
+
const serverName = "inspector-server";
|
|
443
|
+
const session = clientRef.current.getSession(serverName);
|
|
444
|
+
if (!session) {
|
|
445
|
+
throw new Error("No active session found");
|
|
446
|
+
}
|
|
447
|
+
const promptsResult = await session.connector.listPrompts();
|
|
448
|
+
setPrompts(promptsResult.prompts || []);
|
|
449
|
+
addLog("info", "Prompts listed successfully");
|
|
450
|
+
} catch (err) {
|
|
451
|
+
addLog("error", "List prompts failed:", err);
|
|
452
|
+
throw err;
|
|
453
|
+
}
|
|
454
|
+
}, [state]);
|
|
455
|
+
const getPrompt = useCallback(
|
|
456
|
+
async (name, args) => {
|
|
457
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
458
|
+
throw new Error(
|
|
459
|
+
`MCP client is not ready (current state: ${state}). Cannot get prompt.`
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
addLog("info", `Getting prompt: ${name}`, args);
|
|
463
|
+
try {
|
|
464
|
+
const serverName = "inspector-server";
|
|
465
|
+
const session = clientRef.current.getSession(serverName);
|
|
466
|
+
if (!session) {
|
|
467
|
+
throw new Error("No active session found");
|
|
468
|
+
}
|
|
469
|
+
const result = await session.connector.getPrompt(name, args || {});
|
|
470
|
+
addLog("info", `Prompt "${name}" retrieved successfully:`, result);
|
|
471
|
+
return result;
|
|
472
|
+
} catch (err) {
|
|
473
|
+
addLog("error", `Prompt "${name}" retrieval failed:`, err);
|
|
474
|
+
throw err;
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
[state]
|
|
478
|
+
);
|
|
479
|
+
const connectRef = useRef(connect);
|
|
480
|
+
const failConnectionRef = useRef(failConnection);
|
|
481
|
+
useEffect(() => {
|
|
482
|
+
connectRef.current = connect;
|
|
483
|
+
failConnectionRef.current = failConnection;
|
|
484
|
+
});
|
|
485
|
+
useEffect(() => {
|
|
486
|
+
const messageHandler = /* @__PURE__ */ __name((event) => {
|
|
487
|
+
if (event.origin !== window.location.origin) return;
|
|
488
|
+
if (event.data?.type === "mcp_auth_callback") {
|
|
489
|
+
addLog("info", "Received auth callback message.", event.data);
|
|
490
|
+
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
491
|
+
authTimeoutRef.current = null;
|
|
492
|
+
if (event.data.success) {
|
|
493
|
+
addLog(
|
|
494
|
+
"info",
|
|
495
|
+
"Authentication successful via popup. Reconnecting client..."
|
|
496
|
+
);
|
|
497
|
+
if (connectingRef.current) {
|
|
498
|
+
addLog(
|
|
499
|
+
"debug",
|
|
500
|
+
"Connection attempt already in progress, resetting flag to allow reconnection."
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
connectingRef.current = false;
|
|
504
|
+
setTimeout(() => {
|
|
505
|
+
if (isMountedRef.current) {
|
|
506
|
+
addLog(
|
|
507
|
+
"debug",
|
|
508
|
+
"Initiating reconnection after successful auth callback."
|
|
509
|
+
);
|
|
510
|
+
connectRef.current();
|
|
511
|
+
}
|
|
512
|
+
}, 100);
|
|
513
|
+
} else {
|
|
514
|
+
failConnectionRef.current(
|
|
515
|
+
`Authentication failed in callback: ${event.data.error || "Unknown reason."}`
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}, "messageHandler");
|
|
520
|
+
window.addEventListener("message", messageHandler);
|
|
521
|
+
addLog("debug", "Auth callback message listener added.");
|
|
522
|
+
return () => {
|
|
523
|
+
window.removeEventListener("message", messageHandler);
|
|
524
|
+
addLog("debug", "Auth callback message listener removed.");
|
|
525
|
+
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
526
|
+
};
|
|
527
|
+
}, [addLog]);
|
|
528
|
+
useEffect(() => {
|
|
529
|
+
isMountedRef.current = true;
|
|
530
|
+
if (!enabled || !url) {
|
|
531
|
+
addLog(
|
|
532
|
+
"debug",
|
|
533
|
+
enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
|
|
534
|
+
);
|
|
535
|
+
setState("discovering");
|
|
536
|
+
return () => {
|
|
537
|
+
isMountedRef.current = false;
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
addLog("debug", "useMcp mounted, initiating connection.");
|
|
541
|
+
connectAttemptRef.current = 0;
|
|
542
|
+
if (!authProviderRef.current || authProviderRef.current.serverUrl !== url) {
|
|
543
|
+
authProviderRef.current = new BrowserOAuthClientProvider(url, {
|
|
544
|
+
storageKeyPrefix,
|
|
545
|
+
clientName,
|
|
546
|
+
clientUri,
|
|
547
|
+
callbackUrl,
|
|
548
|
+
preventAutoAuth,
|
|
549
|
+
onPopupWindow
|
|
550
|
+
});
|
|
551
|
+
addLog(
|
|
552
|
+
"debug",
|
|
553
|
+
"BrowserOAuthClientProvider initialized/updated on mount/option change."
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
connect();
|
|
557
|
+
return () => {
|
|
558
|
+
isMountedRef.current = false;
|
|
559
|
+
addLog("debug", "useMcp unmounting, disconnecting.");
|
|
560
|
+
disconnect(true);
|
|
561
|
+
};
|
|
562
|
+
}, [
|
|
563
|
+
url,
|
|
564
|
+
enabled,
|
|
565
|
+
storageKeyPrefix,
|
|
566
|
+
callbackUrl,
|
|
567
|
+
clientName,
|
|
568
|
+
clientUri,
|
|
569
|
+
clientConfig.name,
|
|
570
|
+
clientConfig.version
|
|
571
|
+
]);
|
|
572
|
+
useEffect(() => {
|
|
573
|
+
let retryTimeoutId = null;
|
|
574
|
+
if (state === "failed" && autoRetry && connectAttemptRef.current > 0) {
|
|
575
|
+
const delay = typeof autoRetry === "number" ? autoRetry : DEFAULT_RETRY_DELAY;
|
|
576
|
+
addLog("info", `Connection failed, auto-retrying in ${delay}ms...`);
|
|
577
|
+
retryTimeoutId = setTimeout(() => {
|
|
578
|
+
if (isMountedRef.current && stateRef.current === "failed") {
|
|
579
|
+
retry();
|
|
580
|
+
}
|
|
581
|
+
}, delay);
|
|
582
|
+
}
|
|
583
|
+
return () => {
|
|
584
|
+
if (retryTimeoutId) clearTimeout(retryTimeoutId);
|
|
585
|
+
};
|
|
586
|
+
}, [state, autoRetry, retry, addLog]);
|
|
587
|
+
return {
|
|
588
|
+
state,
|
|
589
|
+
tools,
|
|
590
|
+
resources,
|
|
591
|
+
resourceTemplates,
|
|
592
|
+
prompts,
|
|
593
|
+
serverInfo,
|
|
594
|
+
capabilities,
|
|
595
|
+
error,
|
|
596
|
+
log,
|
|
597
|
+
authUrl,
|
|
598
|
+
client: clientRef.current,
|
|
599
|
+
callTool,
|
|
600
|
+
readResource,
|
|
601
|
+
listResources,
|
|
602
|
+
listPrompts,
|
|
603
|
+
getPrompt,
|
|
604
|
+
retry,
|
|
605
|
+
disconnect,
|
|
606
|
+
authenticate,
|
|
607
|
+
clearStorage
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
__name(useMcp, "useMcp");
|
|
611
|
+
|
|
612
|
+
// src/react/useWidget.ts
|
|
613
|
+
import {
|
|
614
|
+
useCallback as useCallback2,
|
|
615
|
+
useEffect as useEffect2,
|
|
616
|
+
useMemo,
|
|
617
|
+
useState as useState2,
|
|
618
|
+
useSyncExternalStore
|
|
619
|
+
} from "react";
|
|
620
|
+
|
|
621
|
+
// src/react/widget-types.ts
|
|
622
|
+
var SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
|
|
623
|
+
|
|
624
|
+
// src/react/useWidget.ts
|
|
625
|
+
function useOpenAiGlobal(key) {
|
|
626
|
+
return useSyncExternalStore(
|
|
627
|
+
(onChange) => {
|
|
628
|
+
const handleSetGlobal = /* @__PURE__ */ __name((event) => {
|
|
629
|
+
const customEvent = event;
|
|
630
|
+
const value = customEvent.detail.globals[key];
|
|
631
|
+
if (value === void 0) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
onChange();
|
|
635
|
+
}, "handleSetGlobal");
|
|
636
|
+
if (typeof window !== "undefined") {
|
|
637
|
+
window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
|
|
638
|
+
}
|
|
639
|
+
return () => {
|
|
640
|
+
if (typeof window !== "undefined") {
|
|
641
|
+
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
},
|
|
645
|
+
() => typeof window !== "undefined" && window.openai ? window.openai[key] : void 0
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
__name(useOpenAiGlobal, "useOpenAiGlobal");
|
|
649
|
+
function useWidget(defaultProps) {
|
|
650
|
+
const [isOpenAiAvailable, setIsOpenAiAvailable] = useState2(
|
|
651
|
+
() => typeof window !== "undefined" && !!window.openai
|
|
652
|
+
);
|
|
653
|
+
useEffect2(() => {
|
|
654
|
+
if (typeof window !== "undefined" && window.openai) {
|
|
655
|
+
setIsOpenAiAvailable(true);
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const checkInterval = setInterval(() => {
|
|
659
|
+
if (typeof window !== "undefined" && window.openai) {
|
|
660
|
+
setIsOpenAiAvailable(true);
|
|
661
|
+
clearInterval(checkInterval);
|
|
662
|
+
}
|
|
663
|
+
}, 100);
|
|
664
|
+
const handleSetGlobals = /* @__PURE__ */ __name(() => {
|
|
665
|
+
if (typeof window !== "undefined" && window.openai) {
|
|
666
|
+
setIsOpenAiAvailable(true);
|
|
667
|
+
clearInterval(checkInterval);
|
|
668
|
+
}
|
|
669
|
+
}, "handleSetGlobals");
|
|
670
|
+
if (typeof window !== "undefined") {
|
|
671
|
+
window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
|
|
672
|
+
}
|
|
673
|
+
const timeout = setTimeout(() => {
|
|
674
|
+
clearInterval(checkInterval);
|
|
675
|
+
if (typeof window !== "undefined") {
|
|
676
|
+
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
|
|
677
|
+
}
|
|
678
|
+
}, 5e3);
|
|
679
|
+
return () => {
|
|
680
|
+
clearInterval(checkInterval);
|
|
681
|
+
clearTimeout(timeout);
|
|
682
|
+
if (typeof window !== "undefined") {
|
|
683
|
+
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
}, []);
|
|
687
|
+
const provider = useMemo(() => {
|
|
688
|
+
return isOpenAiAvailable ? "openai" : "mcp-ui";
|
|
689
|
+
}, [isOpenAiAvailable]);
|
|
690
|
+
const urlParams = useMemo(() => {
|
|
691
|
+
const urlParams2 = new URLSearchParams(window?.location?.search);
|
|
692
|
+
if (urlParams2.has("mcpUseParams")) {
|
|
693
|
+
return JSON.parse(urlParams2.get("mcpUseParams"));
|
|
694
|
+
}
|
|
695
|
+
return {
|
|
696
|
+
toolInput: {},
|
|
697
|
+
toolOutput: {},
|
|
698
|
+
toolId: ""
|
|
699
|
+
};
|
|
700
|
+
}, [window?.location?.search]);
|
|
701
|
+
const toolInput = provider === "openai" ? useOpenAiGlobal("toolInput") : urlParams.toolInput;
|
|
702
|
+
const toolOutput = provider === "openai" ? useOpenAiGlobal("toolOutput") : urlParams.toolOutput;
|
|
703
|
+
const toolResponseMetadata = useOpenAiGlobal("toolResponseMetadata");
|
|
704
|
+
const widgetState = useOpenAiGlobal("widgetState");
|
|
705
|
+
const theme = useOpenAiGlobal("theme");
|
|
706
|
+
const displayMode = useOpenAiGlobal("displayMode");
|
|
707
|
+
const safeArea = useOpenAiGlobal("safeArea");
|
|
708
|
+
const maxHeight = useOpenAiGlobal("maxHeight");
|
|
709
|
+
const userAgent = useOpenAiGlobal("userAgent");
|
|
710
|
+
const locale = useOpenAiGlobal("locale");
|
|
711
|
+
const [localWidgetState, setLocalWidgetState] = useState2(null);
|
|
712
|
+
useEffect2(() => {
|
|
713
|
+
if (widgetState !== void 0) {
|
|
714
|
+
setLocalWidgetState(widgetState);
|
|
715
|
+
}
|
|
716
|
+
}, [widgetState]);
|
|
717
|
+
const callTool = useCallback2(
|
|
718
|
+
async (name, args) => {
|
|
719
|
+
if (!window.openai?.callTool) {
|
|
720
|
+
throw new Error("window.openai.callTool is not available");
|
|
721
|
+
}
|
|
722
|
+
return window.openai.callTool(name, args);
|
|
723
|
+
},
|
|
724
|
+
[]
|
|
725
|
+
);
|
|
726
|
+
const sendFollowUpMessage = useCallback2(
|
|
727
|
+
async (prompt) => {
|
|
728
|
+
if (!window.openai?.sendFollowUpMessage) {
|
|
729
|
+
throw new Error("window.openai.sendFollowUpMessage is not available");
|
|
730
|
+
}
|
|
731
|
+
return window.openai.sendFollowUpMessage({ prompt });
|
|
732
|
+
},
|
|
733
|
+
[]
|
|
734
|
+
);
|
|
735
|
+
const openExternal = useCallback2((href) => {
|
|
736
|
+
if (!window.openai?.openExternal) {
|
|
737
|
+
throw new Error("window.openai.openExternal is not available");
|
|
738
|
+
}
|
|
739
|
+
window.openai.openExternal({ href });
|
|
740
|
+
}, []);
|
|
741
|
+
const requestDisplayMode = useCallback2(
|
|
742
|
+
async (mode) => {
|
|
743
|
+
if (!window.openai?.requestDisplayMode) {
|
|
744
|
+
throw new Error("window.openai.requestDisplayMode is not available");
|
|
745
|
+
}
|
|
746
|
+
return window.openai.requestDisplayMode({ mode });
|
|
747
|
+
},
|
|
748
|
+
[]
|
|
749
|
+
);
|
|
750
|
+
const setState = useCallback2(
|
|
751
|
+
async (state) => {
|
|
752
|
+
const newState = typeof state === "function" ? state(localWidgetState) : state;
|
|
753
|
+
if (!window.openai?.setWidgetState) {
|
|
754
|
+
throw new Error("window.openai.setWidgetState is not available");
|
|
755
|
+
}
|
|
756
|
+
setLocalWidgetState(newState);
|
|
757
|
+
return window.openai.setWidgetState(newState);
|
|
758
|
+
},
|
|
759
|
+
[localWidgetState]
|
|
760
|
+
);
|
|
761
|
+
return {
|
|
762
|
+
// Props and state (with defaults)
|
|
763
|
+
props: toolInput || defaultProps || {},
|
|
764
|
+
output: toolOutput ?? null,
|
|
765
|
+
metadata: toolResponseMetadata ?? null,
|
|
766
|
+
state: localWidgetState,
|
|
767
|
+
setState,
|
|
768
|
+
// Layout and theme (with safe defaults)
|
|
769
|
+
theme: theme || "light",
|
|
770
|
+
displayMode: displayMode || "inline",
|
|
771
|
+
safeArea: safeArea || { insets: { top: 0, bottom: 0, left: 0, right: 0 } },
|
|
772
|
+
maxHeight: maxHeight || 600,
|
|
773
|
+
userAgent: userAgent || {
|
|
774
|
+
device: { type: "desktop" },
|
|
775
|
+
capabilities: { hover: true, touch: false }
|
|
776
|
+
},
|
|
777
|
+
locale: locale || "en",
|
|
778
|
+
// Actions
|
|
779
|
+
callTool,
|
|
780
|
+
sendFollowUpMessage,
|
|
781
|
+
openExternal,
|
|
782
|
+
requestDisplayMode,
|
|
783
|
+
// Availability
|
|
784
|
+
isAvailable: isOpenAiAvailable
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
__name(useWidget, "useWidget");
|
|
788
|
+
function useWidgetProps(defaultProps) {
|
|
789
|
+
const { props } = useWidget(defaultProps);
|
|
790
|
+
return props;
|
|
791
|
+
}
|
|
792
|
+
__name(useWidgetProps, "useWidgetProps");
|
|
793
|
+
function useWidgetTheme() {
|
|
794
|
+
const { theme } = useWidget();
|
|
795
|
+
return theme;
|
|
796
|
+
}
|
|
797
|
+
__name(useWidgetTheme, "useWidgetTheme");
|
|
798
|
+
function useWidgetState(defaultState) {
|
|
799
|
+
const { state, setState } = useWidget();
|
|
800
|
+
useEffect2(() => {
|
|
801
|
+
if (state === null && defaultState !== void 0 && window.openai?.setWidgetState) {
|
|
802
|
+
setState(defaultState);
|
|
803
|
+
}
|
|
804
|
+
}, []);
|
|
805
|
+
return [state, setState];
|
|
806
|
+
}
|
|
807
|
+
__name(useWidgetState, "useWidgetState");
|
|
808
|
+
|
|
809
|
+
// src/react/WidgetFullscreenWrapper.tsx
|
|
810
|
+
import React, { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
811
|
+
function WidgetFullscreenWrapper({
|
|
812
|
+
children,
|
|
813
|
+
className = "",
|
|
814
|
+
position = "top-right",
|
|
815
|
+
attachTo,
|
|
816
|
+
showLabels = true
|
|
817
|
+
}) {
|
|
818
|
+
const { displayMode, requestDisplayMode, theme, safeArea, isAvailable } = useWidget();
|
|
819
|
+
const [isHovered, setIsHovered] = useState3(false);
|
|
820
|
+
const containerRef = useRef2(null);
|
|
821
|
+
const isFullscreen = displayMode === "fullscreen" && isAvailable;
|
|
822
|
+
const isPip = displayMode === "pip" && isAvailable;
|
|
823
|
+
const isDark = theme === "dark";
|
|
824
|
+
const buttonBg = isDark ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.7)";
|
|
825
|
+
const buttonBgHover = isDark ? "rgba(255, 255, 255, 0.2)" : "rgba(0, 0, 0, 0.9)";
|
|
826
|
+
const buttonColor = "white";
|
|
827
|
+
const getPositionStyles = /* @__PURE__ */ __name(() => {
|
|
828
|
+
const baseOffset = 16;
|
|
829
|
+
const topOffset = safeArea?.insets?.top ? `${Math.max(baseOffset, safeArea.insets.top + 8)}px` : `${baseOffset}px`;
|
|
830
|
+
const rightOffset = safeArea?.insets?.right ? `${Math.max(baseOffset, safeArea.insets.right + 8)}px` : `${baseOffset}px`;
|
|
831
|
+
const bottomOffset = safeArea?.insets?.bottom ? `${Math.max(baseOffset, safeArea.insets.bottom + 8)}px` : `${baseOffset}px`;
|
|
832
|
+
const leftOffset = safeArea?.insets?.left ? `${Math.max(baseOffset, safeArea.insets.left + 8)}px` : `${baseOffset}px`;
|
|
833
|
+
const styles = {
|
|
834
|
+
position: "absolute",
|
|
835
|
+
zIndex: 1e3,
|
|
836
|
+
display: "flex",
|
|
837
|
+
gap: "8px",
|
|
838
|
+
opacity: isHovered ? 1 : 0,
|
|
839
|
+
transition: "opacity 0.2s ease-in-out",
|
|
840
|
+
pointerEvents: isHovered ? "auto" : "none"
|
|
841
|
+
};
|
|
842
|
+
switch (position) {
|
|
843
|
+
case "top-left":
|
|
844
|
+
styles.top = topOffset;
|
|
845
|
+
styles.left = leftOffset;
|
|
846
|
+
break;
|
|
847
|
+
case "top-center":
|
|
848
|
+
styles.top = topOffset;
|
|
849
|
+
styles.left = "50%";
|
|
850
|
+
styles.transform = "translateX(-50%)";
|
|
851
|
+
break;
|
|
852
|
+
case "top-right":
|
|
853
|
+
styles.top = topOffset;
|
|
854
|
+
styles.right = rightOffset;
|
|
855
|
+
break;
|
|
856
|
+
case "center-left":
|
|
857
|
+
styles.top = "50%";
|
|
858
|
+
styles.left = leftOffset;
|
|
859
|
+
styles.transform = "translateY(-50%)";
|
|
860
|
+
break;
|
|
861
|
+
case "center-right":
|
|
862
|
+
styles.top = "50%";
|
|
863
|
+
styles.right = rightOffset;
|
|
864
|
+
styles.transform = "translateY(-50%)";
|
|
865
|
+
break;
|
|
866
|
+
case "bottom-left":
|
|
867
|
+
styles.bottom = bottomOffset;
|
|
868
|
+
styles.left = leftOffset;
|
|
869
|
+
break;
|
|
870
|
+
case "bottom-center":
|
|
871
|
+
styles.bottom = bottomOffset;
|
|
872
|
+
styles.left = "50%";
|
|
873
|
+
styles.transform = "translateX(-50%)";
|
|
874
|
+
break;
|
|
875
|
+
case "bottom-right":
|
|
876
|
+
styles.bottom = bottomOffset;
|
|
877
|
+
styles.right = rightOffset;
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
styles.top = topOffset;
|
|
881
|
+
styles.right = rightOffset;
|
|
882
|
+
break;
|
|
883
|
+
}
|
|
884
|
+
return styles;
|
|
885
|
+
}, "getPositionStyles");
|
|
886
|
+
useEffect3(() => {
|
|
887
|
+
if (!attachTo) return;
|
|
888
|
+
const handleMouseEnter = /* @__PURE__ */ __name(() => setIsHovered(true), "handleMouseEnter");
|
|
889
|
+
const handleMouseLeave = /* @__PURE__ */ __name(() => setIsHovered(false), "handleMouseLeave");
|
|
890
|
+
attachTo.addEventListener("mouseenter", handleMouseEnter);
|
|
891
|
+
attachTo.addEventListener("mouseleave", handleMouseLeave);
|
|
892
|
+
return () => {
|
|
893
|
+
attachTo.removeEventListener("mouseenter", handleMouseEnter);
|
|
894
|
+
attachTo.removeEventListener("mouseleave", handleMouseLeave);
|
|
895
|
+
};
|
|
896
|
+
}, [attachTo]);
|
|
897
|
+
const handleFullscreen = /* @__PURE__ */ __name(async () => {
|
|
898
|
+
try {
|
|
899
|
+
await requestDisplayMode("fullscreen");
|
|
900
|
+
} catch (error) {
|
|
901
|
+
console.error("Failed to go fullscreen:", error);
|
|
902
|
+
}
|
|
903
|
+
}, "handleFullscreen");
|
|
904
|
+
const handlePip = /* @__PURE__ */ __name(async () => {
|
|
905
|
+
try {
|
|
906
|
+
await requestDisplayMode("pip");
|
|
907
|
+
} catch (error) {
|
|
908
|
+
console.error("Failed to go pip:", error);
|
|
909
|
+
}
|
|
910
|
+
}, "handlePip");
|
|
911
|
+
const getTooltipStyles = /* @__PURE__ */ __name(() => {
|
|
912
|
+
const baseStyles = {
|
|
913
|
+
position: "absolute",
|
|
914
|
+
padding: "4px 8px",
|
|
915
|
+
backgroundColor: isDark ? "rgba(0, 0, 0, 0.9)" : "rgba(0, 0, 0, 0.9)",
|
|
916
|
+
color: "white",
|
|
917
|
+
borderRadius: "4px",
|
|
918
|
+
fontSize: "12px",
|
|
919
|
+
whiteSpace: "nowrap",
|
|
920
|
+
pointerEvents: "none",
|
|
921
|
+
transition: "opacity 0.2s ease-in-out"
|
|
922
|
+
};
|
|
923
|
+
switch (position) {
|
|
924
|
+
case "top-right":
|
|
925
|
+
return {
|
|
926
|
+
...baseStyles,
|
|
927
|
+
top: "100%",
|
|
928
|
+
right: "0",
|
|
929
|
+
marginTop: "8px"
|
|
930
|
+
};
|
|
931
|
+
case "top-left":
|
|
932
|
+
return {
|
|
933
|
+
...baseStyles,
|
|
934
|
+
top: "100%",
|
|
935
|
+
left: "0",
|
|
936
|
+
marginTop: "8px"
|
|
937
|
+
};
|
|
938
|
+
case "top-center":
|
|
939
|
+
return {
|
|
940
|
+
...baseStyles,
|
|
941
|
+
top: "100%",
|
|
942
|
+
left: "50%",
|
|
943
|
+
transform: "translateX(-50%)",
|
|
944
|
+
marginTop: "8px"
|
|
945
|
+
};
|
|
946
|
+
case "bottom-right":
|
|
947
|
+
return {
|
|
948
|
+
...baseStyles,
|
|
949
|
+
bottom: "100%",
|
|
950
|
+
right: "0",
|
|
951
|
+
marginBottom: "8px"
|
|
952
|
+
};
|
|
953
|
+
case "bottom-left":
|
|
954
|
+
return {
|
|
955
|
+
...baseStyles,
|
|
956
|
+
bottom: "100%",
|
|
957
|
+
left: "0",
|
|
958
|
+
marginBottom: "8px"
|
|
959
|
+
};
|
|
960
|
+
case "bottom-center":
|
|
961
|
+
return {
|
|
962
|
+
...baseStyles,
|
|
963
|
+
bottom: "100%",
|
|
964
|
+
left: "50%",
|
|
965
|
+
transform: "translateX(-50%)",
|
|
966
|
+
marginBottom: "8px"
|
|
967
|
+
};
|
|
968
|
+
case "center-left":
|
|
969
|
+
return {
|
|
970
|
+
...baseStyles,
|
|
971
|
+
left: "100%",
|
|
972
|
+
top: "50%",
|
|
973
|
+
transform: "translateY(-50%)",
|
|
974
|
+
marginLeft: "8px"
|
|
975
|
+
};
|
|
976
|
+
case "center-right":
|
|
977
|
+
return {
|
|
978
|
+
...baseStyles,
|
|
979
|
+
right: "100%",
|
|
980
|
+
top: "50%",
|
|
981
|
+
transform: "translateY(-50%)",
|
|
982
|
+
marginRight: "8px"
|
|
983
|
+
};
|
|
984
|
+
default:
|
|
985
|
+
return {
|
|
986
|
+
...baseStyles,
|
|
987
|
+
top: "100%",
|
|
988
|
+
right: "0",
|
|
989
|
+
marginTop: "8px"
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
}, "getTooltipStyles");
|
|
993
|
+
const IconButton = /* @__PURE__ */ __name(({
|
|
994
|
+
onClick,
|
|
995
|
+
label,
|
|
996
|
+
children: icon
|
|
997
|
+
}) => {
|
|
998
|
+
const [isButtonHovered, setIsButtonHovered] = useState3(false);
|
|
999
|
+
const tooltipStyles = getTooltipStyles();
|
|
1000
|
+
return /* @__PURE__ */ React.createElement(
|
|
1001
|
+
"button",
|
|
1002
|
+
{
|
|
1003
|
+
style: {
|
|
1004
|
+
padding: "8px",
|
|
1005
|
+
backgroundColor: buttonBg,
|
|
1006
|
+
color: buttonColor,
|
|
1007
|
+
border: "none",
|
|
1008
|
+
borderRadius: "8px",
|
|
1009
|
+
cursor: "pointer",
|
|
1010
|
+
display: "flex",
|
|
1011
|
+
alignItems: "center",
|
|
1012
|
+
justifyContent: "center",
|
|
1013
|
+
width: "32px",
|
|
1014
|
+
height: "32px",
|
|
1015
|
+
transition: "background-color 0.2s",
|
|
1016
|
+
backdropFilter: "blur(8px)",
|
|
1017
|
+
WebkitBackdropFilter: "blur(8px)",
|
|
1018
|
+
boxShadow: isDark ? "0 2px 8px rgba(0, 0, 0, 0.3)" : "0 2px 8px rgba(0, 0, 0, 0.2)",
|
|
1019
|
+
position: "relative"
|
|
1020
|
+
},
|
|
1021
|
+
onMouseEnter: (e) => {
|
|
1022
|
+
e.currentTarget.style.backgroundColor = buttonBgHover;
|
|
1023
|
+
setIsButtonHovered(true);
|
|
1024
|
+
},
|
|
1025
|
+
onMouseLeave: (e) => {
|
|
1026
|
+
e.currentTarget.style.backgroundColor = buttonBg;
|
|
1027
|
+
setIsButtonHovered(false);
|
|
1028
|
+
},
|
|
1029
|
+
onClick,
|
|
1030
|
+
"aria-label": label
|
|
1031
|
+
},
|
|
1032
|
+
/* @__PURE__ */ React.createElement(
|
|
1033
|
+
"svg",
|
|
1034
|
+
{
|
|
1035
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1036
|
+
width: "16",
|
|
1037
|
+
height: "16",
|
|
1038
|
+
viewBox: "0 0 24 24",
|
|
1039
|
+
fill: "none",
|
|
1040
|
+
stroke: "currentColor",
|
|
1041
|
+
strokeWidth: "2",
|
|
1042
|
+
strokeLinecap: "round",
|
|
1043
|
+
strokeLinejoin: "round",
|
|
1044
|
+
style: { display: "block" }
|
|
1045
|
+
},
|
|
1046
|
+
icon
|
|
1047
|
+
),
|
|
1048
|
+
showLabels && /* @__PURE__ */ React.createElement(
|
|
1049
|
+
"span",
|
|
1050
|
+
{
|
|
1051
|
+
style: {
|
|
1052
|
+
...tooltipStyles,
|
|
1053
|
+
opacity: isButtonHovered ? 1 : 0
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
label
|
|
1057
|
+
)
|
|
1058
|
+
);
|
|
1059
|
+
}, "IconButton");
|
|
1060
|
+
return /* @__PURE__ */ React.createElement(
|
|
1061
|
+
"div",
|
|
1062
|
+
{
|
|
1063
|
+
ref: containerRef,
|
|
1064
|
+
className,
|
|
1065
|
+
style: {
|
|
1066
|
+
position: "relative",
|
|
1067
|
+
height: "fit-content"
|
|
1068
|
+
},
|
|
1069
|
+
onMouseEnter: () => !attachTo && setIsHovered(true),
|
|
1070
|
+
onMouseLeave: () => !attachTo && setIsHovered(false)
|
|
1071
|
+
},
|
|
1072
|
+
!isFullscreen && !isPip && /* @__PURE__ */ React.createElement("div", { style: getPositionStyles() }, /* @__PURE__ */ React.createElement(IconButton, { onClick: handleFullscreen, label: "Fullscreen" }, /* @__PURE__ */ React.createElement("path", { d: "M15 3h6v6" }), /* @__PURE__ */ React.createElement("path", { d: "m21 3-7 7" }), /* @__PURE__ */ React.createElement("path", { d: "m3 21 7-7" }), /* @__PURE__ */ React.createElement("path", { d: "M9 21H3v-6" })), /* @__PURE__ */ React.createElement(IconButton, { onClick: handlePip, label: "Picture in Picture" }, /* @__PURE__ */ React.createElement("path", { d: "M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4" }), /* @__PURE__ */ React.createElement("rect", { width: "10", height: "7", x: "12", y: "13", rx: "2" }))),
|
|
1073
|
+
children
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
__name(WidgetFullscreenWrapper, "WidgetFullscreenWrapper");
|
|
1077
|
+
|
|
1078
|
+
// src/react/WidgetDebugger.tsx
|
|
1079
|
+
import React2, { useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
|
|
1080
|
+
function WidgetDebugger({
|
|
1081
|
+
children,
|
|
1082
|
+
className = "",
|
|
1083
|
+
position = "top-right",
|
|
1084
|
+
attachTo,
|
|
1085
|
+
showLabels = true
|
|
1086
|
+
}) {
|
|
1087
|
+
const {
|
|
1088
|
+
props,
|
|
1089
|
+
output,
|
|
1090
|
+
metadata,
|
|
1091
|
+
state,
|
|
1092
|
+
theme,
|
|
1093
|
+
displayMode,
|
|
1094
|
+
safeArea,
|
|
1095
|
+
maxHeight,
|
|
1096
|
+
userAgent,
|
|
1097
|
+
locale,
|
|
1098
|
+
isAvailable,
|
|
1099
|
+
callTool,
|
|
1100
|
+
sendFollowUpMessage,
|
|
1101
|
+
openExternal,
|
|
1102
|
+
requestDisplayMode,
|
|
1103
|
+
setState
|
|
1104
|
+
} = useWidget();
|
|
1105
|
+
const [isHovered, setIsHovered] = useState4(false);
|
|
1106
|
+
const [isOverlayOpen, setIsOverlayOpen] = useState4(false);
|
|
1107
|
+
const containerRef = useRef3(null);
|
|
1108
|
+
const overlayRef = useRef3(null);
|
|
1109
|
+
const [windowOpenAiKeys, setWindowOpenAiKeys] = useState4([]);
|
|
1110
|
+
const [actionResult, setActionResult] = useState4("");
|
|
1111
|
+
const [toolName, setToolName] = useState4("get-my-city");
|
|
1112
|
+
const [toolArgs, setToolArgs] = useState4("{}");
|
|
1113
|
+
const [followUpMessage, setFollowUpMessage] = useState4(
|
|
1114
|
+
"Test follow-up message"
|
|
1115
|
+
);
|
|
1116
|
+
const [externalUrl, setExternalUrl] = useState4(
|
|
1117
|
+
"https://docs.mcp-use.com"
|
|
1118
|
+
);
|
|
1119
|
+
const isFullscreen = displayMode === "fullscreen" && isAvailable;
|
|
1120
|
+
const isPip = displayMode === "pip" && isAvailable;
|
|
1121
|
+
useEffect4(() => {
|
|
1122
|
+
const timeoutId = setTimeout(() => {
|
|
1123
|
+
if (typeof window !== "undefined" && window.openai) {
|
|
1124
|
+
try {
|
|
1125
|
+
const keys = Object.keys(window.openai);
|
|
1126
|
+
setWindowOpenAiKeys(keys);
|
|
1127
|
+
} catch (e) {
|
|
1128
|
+
setWindowOpenAiKeys([]);
|
|
1129
|
+
}
|
|
1130
|
+
} else {
|
|
1131
|
+
setWindowOpenAiKeys([]);
|
|
1132
|
+
}
|
|
1133
|
+
}, 100);
|
|
1134
|
+
return () => clearTimeout(timeoutId);
|
|
1135
|
+
}, []);
|
|
1136
|
+
const isDark = theme === "dark";
|
|
1137
|
+
const buttonBg = isDark ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.7)";
|
|
1138
|
+
const buttonBgHover = isDark ? "rgba(255, 255, 255, 0.2)" : "rgba(0, 0, 0, 0.9)";
|
|
1139
|
+
const buttonColor = "white";
|
|
1140
|
+
const getPositionStyles = /* @__PURE__ */ __name(() => {
|
|
1141
|
+
const baseOffset = 16;
|
|
1142
|
+
const topOffset = safeArea?.insets?.top ? `${Math.max(baseOffset, safeArea.insets.top + 8)}px` : `${baseOffset}px`;
|
|
1143
|
+
const rightOffset = safeArea?.insets?.right ? `${Math.max(baseOffset, safeArea.insets.right + 8)}px` : `${baseOffset}px`;
|
|
1144
|
+
const bottomOffset = safeArea?.insets?.bottom ? `${Math.max(baseOffset, safeArea.insets.bottom + 8)}px` : `${baseOffset}px`;
|
|
1145
|
+
const leftOffset = safeArea?.insets?.left ? `${Math.max(baseOffset, safeArea.insets.left + 8)}px` : `${baseOffset}px`;
|
|
1146
|
+
const styles = {
|
|
1147
|
+
position: "absolute",
|
|
1148
|
+
zIndex: 1e3,
|
|
1149
|
+
display: "flex",
|
|
1150
|
+
gap: "8px",
|
|
1151
|
+
opacity: isHovered ? 1 : 0,
|
|
1152
|
+
transition: "opacity 0.2s ease-in-out",
|
|
1153
|
+
pointerEvents: isHovered ? "auto" : "none"
|
|
1154
|
+
};
|
|
1155
|
+
switch (position) {
|
|
1156
|
+
case "top-left":
|
|
1157
|
+
styles.top = topOffset;
|
|
1158
|
+
styles.left = leftOffset;
|
|
1159
|
+
break;
|
|
1160
|
+
case "top-center":
|
|
1161
|
+
styles.top = topOffset;
|
|
1162
|
+
styles.left = "50%";
|
|
1163
|
+
styles.transform = "translateX(-50%)";
|
|
1164
|
+
break;
|
|
1165
|
+
case "top-right":
|
|
1166
|
+
styles.top = topOffset;
|
|
1167
|
+
styles.right = rightOffset;
|
|
1168
|
+
if (!isFullscreen && !isPip) {
|
|
1169
|
+
styles.right = `calc(${rightOffset} + 80px)`;
|
|
1170
|
+
}
|
|
1171
|
+
break;
|
|
1172
|
+
case "center-left":
|
|
1173
|
+
styles.top = "50%";
|
|
1174
|
+
styles.left = leftOffset;
|
|
1175
|
+
styles.transform = "translateY(-50%)";
|
|
1176
|
+
break;
|
|
1177
|
+
case "center-right":
|
|
1178
|
+
styles.top = "50%";
|
|
1179
|
+
styles.right = rightOffset;
|
|
1180
|
+
styles.transform = "translateY(-50%)";
|
|
1181
|
+
break;
|
|
1182
|
+
case "bottom-left":
|
|
1183
|
+
styles.bottom = bottomOffset;
|
|
1184
|
+
styles.left = leftOffset;
|
|
1185
|
+
break;
|
|
1186
|
+
case "bottom-center":
|
|
1187
|
+
styles.bottom = bottomOffset;
|
|
1188
|
+
styles.left = "50%";
|
|
1189
|
+
styles.transform = "translateX(-50%)";
|
|
1190
|
+
break;
|
|
1191
|
+
case "bottom-right":
|
|
1192
|
+
styles.bottom = bottomOffset;
|
|
1193
|
+
styles.right = rightOffset;
|
|
1194
|
+
break;
|
|
1195
|
+
default:
|
|
1196
|
+
styles.top = topOffset;
|
|
1197
|
+
styles.right = rightOffset;
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
return styles;
|
|
1201
|
+
}, "getPositionStyles");
|
|
1202
|
+
useEffect4(() => {
|
|
1203
|
+
if (!attachTo) return;
|
|
1204
|
+
const handleMouseEnter = /* @__PURE__ */ __name(() => setIsHovered(true), "handleMouseEnter");
|
|
1205
|
+
const handleMouseLeave = /* @__PURE__ */ __name(() => setIsHovered(false), "handleMouseLeave");
|
|
1206
|
+
attachTo.addEventListener("mouseenter", handleMouseEnter);
|
|
1207
|
+
attachTo.addEventListener("mouseleave", handleMouseLeave);
|
|
1208
|
+
return () => {
|
|
1209
|
+
attachTo.removeEventListener("mouseenter", handleMouseEnter);
|
|
1210
|
+
attachTo.removeEventListener("mouseleave", handleMouseLeave);
|
|
1211
|
+
};
|
|
1212
|
+
}, [attachTo]);
|
|
1213
|
+
useEffect4(() => {
|
|
1214
|
+
if (!isOverlayOpen) return;
|
|
1215
|
+
const handleClickOutside = /* @__PURE__ */ __name((event) => {
|
|
1216
|
+
if (overlayRef.current && !overlayRef.current.contains(event.target)) {
|
|
1217
|
+
setIsOverlayOpen(false);
|
|
1218
|
+
}
|
|
1219
|
+
}, "handleClickOutside");
|
|
1220
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1221
|
+
return () => {
|
|
1222
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1223
|
+
};
|
|
1224
|
+
}, [isOverlayOpen]);
|
|
1225
|
+
useEffect4(() => {
|
|
1226
|
+
if (isOverlayOpen) {
|
|
1227
|
+
document.body.style.overflow = "hidden";
|
|
1228
|
+
} else {
|
|
1229
|
+
document.body.style.overflow = "";
|
|
1230
|
+
}
|
|
1231
|
+
return () => {
|
|
1232
|
+
document.body.style.overflow = "";
|
|
1233
|
+
};
|
|
1234
|
+
}, [isOverlayOpen]);
|
|
1235
|
+
const handleToggleOverlay = /* @__PURE__ */ __name(() => {
|
|
1236
|
+
setIsOverlayOpen(!isOverlayOpen);
|
|
1237
|
+
}, "handleToggleOverlay");
|
|
1238
|
+
const handleCallTool = /* @__PURE__ */ __name(async () => {
|
|
1239
|
+
try {
|
|
1240
|
+
setActionResult("Calling tool...");
|
|
1241
|
+
const args = toolArgs.trim() ? JSON.parse(toolArgs) : {};
|
|
1242
|
+
const result = await callTool(toolName, args);
|
|
1243
|
+
setActionResult(`Success: ${JSON.stringify(result, null, 2)}`);
|
|
1244
|
+
} catch (error) {
|
|
1245
|
+
setActionResult(`Error: ${error.message}`);
|
|
1246
|
+
}
|
|
1247
|
+
}, "handleCallTool");
|
|
1248
|
+
const handleSendFollowUpMessage = /* @__PURE__ */ __name(async () => {
|
|
1249
|
+
try {
|
|
1250
|
+
setActionResult("Sending follow-up message...");
|
|
1251
|
+
await sendFollowUpMessage(followUpMessage);
|
|
1252
|
+
setActionResult("Follow-up message sent successfully");
|
|
1253
|
+
} catch (error) {
|
|
1254
|
+
setActionResult(`Error: ${error.message}`);
|
|
1255
|
+
}
|
|
1256
|
+
}, "handleSendFollowUpMessage");
|
|
1257
|
+
const handleOpenExternal = /* @__PURE__ */ __name(() => {
|
|
1258
|
+
try {
|
|
1259
|
+
openExternal(externalUrl);
|
|
1260
|
+
setActionResult(`Opened external link: ${externalUrl}`);
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
setActionResult(`Error: ${error.message}`);
|
|
1263
|
+
}
|
|
1264
|
+
}, "handleOpenExternal");
|
|
1265
|
+
const handleRequestDisplayMode = /* @__PURE__ */ __name(async (mode) => {
|
|
1266
|
+
try {
|
|
1267
|
+
setActionResult(`Requesting display mode: ${mode}...`);
|
|
1268
|
+
const result = await requestDisplayMode(mode);
|
|
1269
|
+
setActionResult(`Display mode granted: ${result.mode}`);
|
|
1270
|
+
} catch (error) {
|
|
1271
|
+
setActionResult(`Error: ${error.message}`);
|
|
1272
|
+
}
|
|
1273
|
+
}, "handleRequestDisplayMode");
|
|
1274
|
+
const handleSetState = /* @__PURE__ */ __name(async () => {
|
|
1275
|
+
try {
|
|
1276
|
+
const newState = state ? { ...state, debugTimestamp: (/* @__PURE__ */ new Date()).toISOString() } : { debugTimestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
1277
|
+
setActionResult("Setting state...");
|
|
1278
|
+
await setState(newState);
|
|
1279
|
+
setActionResult(`State updated: ${JSON.stringify(newState, null, 2)}`);
|
|
1280
|
+
} catch (error) {
|
|
1281
|
+
setActionResult(`Error: ${error.message}`);
|
|
1282
|
+
}
|
|
1283
|
+
}, "handleSetState");
|
|
1284
|
+
const getTooltipStyles = /* @__PURE__ */ __name(() => {
|
|
1285
|
+
const baseStyles = {
|
|
1286
|
+
position: "absolute",
|
|
1287
|
+
padding: "4px 8px",
|
|
1288
|
+
backgroundColor: "rgba(0, 0, 0, 0.9)",
|
|
1289
|
+
color: "white",
|
|
1290
|
+
borderRadius: "4px",
|
|
1291
|
+
fontSize: "12px",
|
|
1292
|
+
whiteSpace: "nowrap",
|
|
1293
|
+
pointerEvents: "none",
|
|
1294
|
+
transition: "opacity 0.2s ease-in-out"
|
|
1295
|
+
};
|
|
1296
|
+
switch (position) {
|
|
1297
|
+
case "top-right":
|
|
1298
|
+
return {
|
|
1299
|
+
...baseStyles,
|
|
1300
|
+
top: "100%",
|
|
1301
|
+
right: "0",
|
|
1302
|
+
marginTop: "8px"
|
|
1303
|
+
};
|
|
1304
|
+
case "top-left":
|
|
1305
|
+
return {
|
|
1306
|
+
...baseStyles,
|
|
1307
|
+
top: "100%",
|
|
1308
|
+
left: "0",
|
|
1309
|
+
marginTop: "8px"
|
|
1310
|
+
};
|
|
1311
|
+
case "top-center":
|
|
1312
|
+
return {
|
|
1313
|
+
...baseStyles,
|
|
1314
|
+
top: "100%",
|
|
1315
|
+
left: "50%",
|
|
1316
|
+
transform: "translateX(-50%)",
|
|
1317
|
+
marginTop: "8px"
|
|
1318
|
+
};
|
|
1319
|
+
case "bottom-right":
|
|
1320
|
+
return {
|
|
1321
|
+
...baseStyles,
|
|
1322
|
+
bottom: "100%",
|
|
1323
|
+
right: "0",
|
|
1324
|
+
marginBottom: "8px"
|
|
1325
|
+
};
|
|
1326
|
+
case "bottom-left":
|
|
1327
|
+
return {
|
|
1328
|
+
...baseStyles,
|
|
1329
|
+
bottom: "100%",
|
|
1330
|
+
left: "0",
|
|
1331
|
+
marginBottom: "8px"
|
|
1332
|
+
};
|
|
1333
|
+
case "bottom-center":
|
|
1334
|
+
return {
|
|
1335
|
+
...baseStyles,
|
|
1336
|
+
bottom: "100%",
|
|
1337
|
+
left: "50%",
|
|
1338
|
+
transform: "translateX(-50%)",
|
|
1339
|
+
marginBottom: "8px"
|
|
1340
|
+
};
|
|
1341
|
+
case "center-left":
|
|
1342
|
+
return {
|
|
1343
|
+
...baseStyles,
|
|
1344
|
+
left: "100%",
|
|
1345
|
+
top: "50%",
|
|
1346
|
+
transform: "translateY(-50%)",
|
|
1347
|
+
marginLeft: "8px"
|
|
1348
|
+
};
|
|
1349
|
+
case "center-right":
|
|
1350
|
+
return {
|
|
1351
|
+
...baseStyles,
|
|
1352
|
+
right: "100%",
|
|
1353
|
+
top: "50%",
|
|
1354
|
+
transform: "translateY(-50%)",
|
|
1355
|
+
marginRight: "8px"
|
|
1356
|
+
};
|
|
1357
|
+
default:
|
|
1358
|
+
return {
|
|
1359
|
+
...baseStyles,
|
|
1360
|
+
top: "100%",
|
|
1361
|
+
right: "0",
|
|
1362
|
+
marginTop: "8px"
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
}, "getTooltipStyles");
|
|
1366
|
+
const IconButton = /* @__PURE__ */ __name(({
|
|
1367
|
+
onClick,
|
|
1368
|
+
label,
|
|
1369
|
+
children: icon
|
|
1370
|
+
}) => {
|
|
1371
|
+
const [isButtonHovered, setIsButtonHovered] = useState4(false);
|
|
1372
|
+
const tooltipStyles = getTooltipStyles();
|
|
1373
|
+
return /* @__PURE__ */ React2.createElement(
|
|
1374
|
+
"button",
|
|
1375
|
+
{
|
|
1376
|
+
style: {
|
|
1377
|
+
padding: "8px",
|
|
1378
|
+
backgroundColor: buttonBg,
|
|
1379
|
+
color: buttonColor,
|
|
1380
|
+
border: "none",
|
|
1381
|
+
borderRadius: "8px",
|
|
1382
|
+
cursor: "pointer",
|
|
1383
|
+
display: "flex",
|
|
1384
|
+
alignItems: "center",
|
|
1385
|
+
justifyContent: "center",
|
|
1386
|
+
width: "32px",
|
|
1387
|
+
height: "32px",
|
|
1388
|
+
transition: "background-color 0.2s",
|
|
1389
|
+
backdropFilter: "blur(8px)",
|
|
1390
|
+
WebkitBackdropFilter: "blur(8px)",
|
|
1391
|
+
boxShadow: isDark ? "0 2px 8px rgba(0, 0, 0, 0.3)" : "0 2px 8px rgba(0, 0, 0, 0.2)",
|
|
1392
|
+
position: "relative"
|
|
1393
|
+
},
|
|
1394
|
+
onMouseEnter: (e) => {
|
|
1395
|
+
e.currentTarget.style.backgroundColor = buttonBgHover;
|
|
1396
|
+
setIsButtonHovered(true);
|
|
1397
|
+
},
|
|
1398
|
+
onMouseLeave: (e) => {
|
|
1399
|
+
e.currentTarget.style.backgroundColor = buttonBg;
|
|
1400
|
+
setIsButtonHovered(false);
|
|
1401
|
+
},
|
|
1402
|
+
onClick,
|
|
1403
|
+
"aria-label": label
|
|
1404
|
+
},
|
|
1405
|
+
/* @__PURE__ */ React2.createElement(
|
|
1406
|
+
"svg",
|
|
1407
|
+
{
|
|
1408
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1409
|
+
width: "16",
|
|
1410
|
+
height: "16",
|
|
1411
|
+
viewBox: "0 0 24 24",
|
|
1412
|
+
fill: "none",
|
|
1413
|
+
stroke: "currentColor",
|
|
1414
|
+
strokeWidth: "2",
|
|
1415
|
+
strokeLinecap: "round",
|
|
1416
|
+
strokeLinejoin: "round",
|
|
1417
|
+
style: { display: "block" }
|
|
1418
|
+
},
|
|
1419
|
+
icon
|
|
1420
|
+
),
|
|
1421
|
+
showLabels && /* @__PURE__ */ React2.createElement(
|
|
1422
|
+
"span",
|
|
1423
|
+
{
|
|
1424
|
+
style: {
|
|
1425
|
+
...tooltipStyles,
|
|
1426
|
+
opacity: isButtonHovered ? 1 : 0
|
|
1427
|
+
}
|
|
1428
|
+
},
|
|
1429
|
+
label
|
|
1430
|
+
)
|
|
1431
|
+
);
|
|
1432
|
+
}, "IconButton");
|
|
1433
|
+
const formatValue = /* @__PURE__ */ __name((value) => {
|
|
1434
|
+
if (value === null) return "null";
|
|
1435
|
+
if (value === void 0) return "undefined";
|
|
1436
|
+
if (typeof value === "object") {
|
|
1437
|
+
try {
|
|
1438
|
+
return JSON.stringify(value, null, 2);
|
|
1439
|
+
} catch {
|
|
1440
|
+
return String(value);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return String(value);
|
|
1444
|
+
}, "formatValue");
|
|
1445
|
+
const formatUserAgent = /* @__PURE__ */ __name((ua) => {
|
|
1446
|
+
if (!ua) return "N/A";
|
|
1447
|
+
return `${ua.device?.type || "unknown"}`;
|
|
1448
|
+
}, "formatUserAgent");
|
|
1449
|
+
const formatSafeArea = /* @__PURE__ */ __name((sa) => {
|
|
1450
|
+
if (!sa?.insets) return "N/A";
|
|
1451
|
+
const { top, bottom, left, right } = sa.insets;
|
|
1452
|
+
return `T:${top} B:${bottom} L:${left} R:${right}`;
|
|
1453
|
+
}, "formatSafeArea");
|
|
1454
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
|
|
1455
|
+
"div",
|
|
1456
|
+
{
|
|
1457
|
+
ref: containerRef,
|
|
1458
|
+
className,
|
|
1459
|
+
style: {
|
|
1460
|
+
position: "relative",
|
|
1461
|
+
height: "fit-content"
|
|
1462
|
+
},
|
|
1463
|
+
onMouseEnter: () => !attachTo && setIsHovered(true),
|
|
1464
|
+
onMouseLeave: () => !attachTo && setIsHovered(false)
|
|
1465
|
+
},
|
|
1466
|
+
/* @__PURE__ */ React2.createElement("div", { style: getPositionStyles() }, /* @__PURE__ */ React2.createElement(IconButton, { onClick: handleToggleOverlay, label: "Debug Info" }, /* @__PURE__ */ React2.createElement("path", { d: "M12 20v-9" }), /* @__PURE__ */ React2.createElement("path", { d: "M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z" }), /* @__PURE__ */ React2.createElement("path", { d: "M14.12 3.88 16 2" }), /* @__PURE__ */ React2.createElement("path", { d: "M21 21a4 4 0 0 0-3.81-4" }), /* @__PURE__ */ React2.createElement("path", { d: "M21 5a4 4 0 0 1-3.55 3.97" }), /* @__PURE__ */ React2.createElement("path", { d: "M22 13h-4" }), /* @__PURE__ */ React2.createElement("path", { d: "M3 21a4 4 0 0 1 3.81-4" }), /* @__PURE__ */ React2.createElement("path", { d: "M3 5a4 4 0 0 0 3.55 3.97" }), /* @__PURE__ */ React2.createElement("path", { d: "M6 13H2" }), /* @__PURE__ */ React2.createElement("path", { d: "m8 2 1.88 1.88" }), /* @__PURE__ */ React2.createElement("path", { d: "M9 7.13V6a3 3 0 1 1 6 0v1.13" }))),
|
|
1467
|
+
children
|
|
1468
|
+
), isOverlayOpen && /* @__PURE__ */ React2.createElement(
|
|
1469
|
+
"div",
|
|
1470
|
+
{
|
|
1471
|
+
ref: overlayRef,
|
|
1472
|
+
style: {
|
|
1473
|
+
position: "fixed",
|
|
1474
|
+
top: 0,
|
|
1475
|
+
left: 0,
|
|
1476
|
+
right: 0,
|
|
1477
|
+
bottom: 0,
|
|
1478
|
+
backgroundColor: "#000000",
|
|
1479
|
+
color: "#ffffff",
|
|
1480
|
+
fontFamily: "monospace",
|
|
1481
|
+
fontSize: "12px",
|
|
1482
|
+
zIndex: 1e4,
|
|
1483
|
+
overflow: "auto",
|
|
1484
|
+
padding: "16px"
|
|
1485
|
+
},
|
|
1486
|
+
onClick: (e) => {
|
|
1487
|
+
if (e.target === overlayRef.current) {
|
|
1488
|
+
setIsOverlayOpen(false);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
},
|
|
1492
|
+
/* @__PURE__ */ React2.createElement(
|
|
1493
|
+
"button",
|
|
1494
|
+
{
|
|
1495
|
+
onClick: () => setIsOverlayOpen(false),
|
|
1496
|
+
style: {
|
|
1497
|
+
position: "absolute",
|
|
1498
|
+
top: "16px",
|
|
1499
|
+
right: "16px",
|
|
1500
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
1501
|
+
color: "#ffffff",
|
|
1502
|
+
border: "none",
|
|
1503
|
+
borderRadius: "4px",
|
|
1504
|
+
width: "32px",
|
|
1505
|
+
height: "32px",
|
|
1506
|
+
cursor: "pointer",
|
|
1507
|
+
display: "flex",
|
|
1508
|
+
alignItems: "center",
|
|
1509
|
+
justifyContent: "center",
|
|
1510
|
+
fontSize: "18px",
|
|
1511
|
+
lineHeight: 1
|
|
1512
|
+
},
|
|
1513
|
+
"aria-label": "Close"
|
|
1514
|
+
},
|
|
1515
|
+
"\xD7"
|
|
1516
|
+
),
|
|
1517
|
+
/* @__PURE__ */ React2.createElement(
|
|
1518
|
+
"div",
|
|
1519
|
+
{
|
|
1520
|
+
style: { maxWidth: "1200px", margin: "0 auto", paddingTop: "40px" }
|
|
1521
|
+
},
|
|
1522
|
+
/* @__PURE__ */ React2.createElement(
|
|
1523
|
+
"h1",
|
|
1524
|
+
{
|
|
1525
|
+
style: {
|
|
1526
|
+
fontSize: "18px",
|
|
1527
|
+
fontWeight: "bold",
|
|
1528
|
+
marginBottom: "16px",
|
|
1529
|
+
borderBottom: "1px solid #333",
|
|
1530
|
+
paddingBottom: "8px"
|
|
1531
|
+
}
|
|
1532
|
+
},
|
|
1533
|
+
"Debug Info"
|
|
1534
|
+
),
|
|
1535
|
+
/* @__PURE__ */ React2.createElement(
|
|
1536
|
+
"table",
|
|
1537
|
+
{
|
|
1538
|
+
style: {
|
|
1539
|
+
width: "100%",
|
|
1540
|
+
borderCollapse: "collapse",
|
|
1541
|
+
borderSpacing: 0
|
|
1542
|
+
}
|
|
1543
|
+
},
|
|
1544
|
+
/* @__PURE__ */ React2.createElement("tbody", null, /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1545
|
+
"td",
|
|
1546
|
+
{
|
|
1547
|
+
style: {
|
|
1548
|
+
padding: "8px",
|
|
1549
|
+
fontWeight: "bold",
|
|
1550
|
+
width: "200px",
|
|
1551
|
+
verticalAlign: "top"
|
|
1552
|
+
}
|
|
1553
|
+
},
|
|
1554
|
+
"Props"
|
|
1555
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1556
|
+
"td",
|
|
1557
|
+
{
|
|
1558
|
+
style: {
|
|
1559
|
+
padding: "8px",
|
|
1560
|
+
whiteSpace: "pre-wrap",
|
|
1561
|
+
wordBreak: "break-all"
|
|
1562
|
+
}
|
|
1563
|
+
},
|
|
1564
|
+
formatValue(props)
|
|
1565
|
+
)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1566
|
+
"td",
|
|
1567
|
+
{
|
|
1568
|
+
style: {
|
|
1569
|
+
padding: "8px",
|
|
1570
|
+
fontWeight: "bold",
|
|
1571
|
+
width: "200px",
|
|
1572
|
+
verticalAlign: "top"
|
|
1573
|
+
}
|
|
1574
|
+
},
|
|
1575
|
+
"Output"
|
|
1576
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1577
|
+
"td",
|
|
1578
|
+
{
|
|
1579
|
+
style: {
|
|
1580
|
+
padding: "8px",
|
|
1581
|
+
whiteSpace: "pre-wrap",
|
|
1582
|
+
wordBreak: "break-all"
|
|
1583
|
+
}
|
|
1584
|
+
},
|
|
1585
|
+
formatValue(output)
|
|
1586
|
+
)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1587
|
+
"td",
|
|
1588
|
+
{
|
|
1589
|
+
style: {
|
|
1590
|
+
padding: "8px",
|
|
1591
|
+
fontWeight: "bold",
|
|
1592
|
+
width: "200px",
|
|
1593
|
+
verticalAlign: "top"
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
"Metadata"
|
|
1597
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1598
|
+
"td",
|
|
1599
|
+
{
|
|
1600
|
+
style: {
|
|
1601
|
+
padding: "8px",
|
|
1602
|
+
whiteSpace: "pre-wrap",
|
|
1603
|
+
wordBreak: "break-all"
|
|
1604
|
+
}
|
|
1605
|
+
},
|
|
1606
|
+
formatValue(metadata)
|
|
1607
|
+
)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1608
|
+
"td",
|
|
1609
|
+
{
|
|
1610
|
+
style: {
|
|
1611
|
+
padding: "8px",
|
|
1612
|
+
fontWeight: "bold",
|
|
1613
|
+
width: "200px",
|
|
1614
|
+
verticalAlign: "top"
|
|
1615
|
+
}
|
|
1616
|
+
},
|
|
1617
|
+
"State"
|
|
1618
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1619
|
+
"td",
|
|
1620
|
+
{
|
|
1621
|
+
style: {
|
|
1622
|
+
padding: "8px",
|
|
1623
|
+
whiteSpace: "pre-wrap",
|
|
1624
|
+
wordBreak: "break-all"
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
formatValue(state)
|
|
1628
|
+
)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1629
|
+
"td",
|
|
1630
|
+
{
|
|
1631
|
+
style: {
|
|
1632
|
+
padding: "8px",
|
|
1633
|
+
fontWeight: "bold",
|
|
1634
|
+
width: "200px",
|
|
1635
|
+
verticalAlign: "top"
|
|
1636
|
+
}
|
|
1637
|
+
},
|
|
1638
|
+
"Theme"
|
|
1639
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, theme)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1640
|
+
"td",
|
|
1641
|
+
{
|
|
1642
|
+
style: {
|
|
1643
|
+
padding: "8px",
|
|
1644
|
+
fontWeight: "bold",
|
|
1645
|
+
width: "200px",
|
|
1646
|
+
verticalAlign: "top"
|
|
1647
|
+
}
|
|
1648
|
+
},
|
|
1649
|
+
"Display Mode"
|
|
1650
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, displayMode)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1651
|
+
"td",
|
|
1652
|
+
{
|
|
1653
|
+
style: {
|
|
1654
|
+
padding: "8px",
|
|
1655
|
+
fontWeight: "bold",
|
|
1656
|
+
width: "200px",
|
|
1657
|
+
verticalAlign: "top"
|
|
1658
|
+
}
|
|
1659
|
+
},
|
|
1660
|
+
"Locale"
|
|
1661
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, locale)), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1662
|
+
"td",
|
|
1663
|
+
{
|
|
1664
|
+
style: {
|
|
1665
|
+
padding: "8px",
|
|
1666
|
+
fontWeight: "bold",
|
|
1667
|
+
width: "200px",
|
|
1668
|
+
verticalAlign: "top"
|
|
1669
|
+
}
|
|
1670
|
+
},
|
|
1671
|
+
"Max Height"
|
|
1672
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, maxHeight, "px")), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1673
|
+
"td",
|
|
1674
|
+
{
|
|
1675
|
+
style: {
|
|
1676
|
+
padding: "8px",
|
|
1677
|
+
fontWeight: "bold",
|
|
1678
|
+
width: "200px",
|
|
1679
|
+
verticalAlign: "top"
|
|
1680
|
+
}
|
|
1681
|
+
},
|
|
1682
|
+
"User Agent"
|
|
1683
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, formatUserAgent(userAgent))), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1684
|
+
"td",
|
|
1685
|
+
{
|
|
1686
|
+
style: {
|
|
1687
|
+
padding: "8px",
|
|
1688
|
+
fontWeight: "bold",
|
|
1689
|
+
width: "200px",
|
|
1690
|
+
verticalAlign: "top"
|
|
1691
|
+
}
|
|
1692
|
+
},
|
|
1693
|
+
"Safe Area"
|
|
1694
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, formatSafeArea(safeArea))), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1695
|
+
"td",
|
|
1696
|
+
{
|
|
1697
|
+
style: {
|
|
1698
|
+
padding: "8px",
|
|
1699
|
+
fontWeight: "bold",
|
|
1700
|
+
width: "200px",
|
|
1701
|
+
verticalAlign: "top"
|
|
1702
|
+
}
|
|
1703
|
+
},
|
|
1704
|
+
"API Available"
|
|
1705
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, isAvailable ? "Yes" : "No")), /* @__PURE__ */ React2.createElement("tr", { style: { borderBottom: "1px solid #333" } }, /* @__PURE__ */ React2.createElement(
|
|
1706
|
+
"td",
|
|
1707
|
+
{
|
|
1708
|
+
style: {
|
|
1709
|
+
padding: "8px",
|
|
1710
|
+
fontWeight: "bold",
|
|
1711
|
+
width: "200px",
|
|
1712
|
+
verticalAlign: "top"
|
|
1713
|
+
}
|
|
1714
|
+
},
|
|
1715
|
+
"window.openai Keys"
|
|
1716
|
+
), /* @__PURE__ */ React2.createElement("td", { style: { padding: "8px" } }, windowOpenAiKeys.length > 0 ? windowOpenAiKeys.join(", ") : "N/A")))
|
|
1717
|
+
),
|
|
1718
|
+
/* @__PURE__ */ React2.createElement(
|
|
1719
|
+
"h2",
|
|
1720
|
+
{
|
|
1721
|
+
style: {
|
|
1722
|
+
fontSize: "16px",
|
|
1723
|
+
fontWeight: "bold",
|
|
1724
|
+
marginTop: "32px",
|
|
1725
|
+
marginBottom: "16px",
|
|
1726
|
+
borderBottom: "1px solid #333",
|
|
1727
|
+
paddingBottom: "8px"
|
|
1728
|
+
}
|
|
1729
|
+
},
|
|
1730
|
+
"Actions"
|
|
1731
|
+
),
|
|
1732
|
+
/* @__PURE__ */ React2.createElement(
|
|
1733
|
+
"div",
|
|
1734
|
+
{
|
|
1735
|
+
style: { display: "flex", flexDirection: "column", gap: "12px" }
|
|
1736
|
+
},
|
|
1737
|
+
/* @__PURE__ */ React2.createElement(
|
|
1738
|
+
"div",
|
|
1739
|
+
{
|
|
1740
|
+
style: { display: "flex", gap: "8px", alignItems: "center" }
|
|
1741
|
+
},
|
|
1742
|
+
/* @__PURE__ */ React2.createElement(
|
|
1743
|
+
"input",
|
|
1744
|
+
{
|
|
1745
|
+
type: "text",
|
|
1746
|
+
value: toolName,
|
|
1747
|
+
onChange: (e) => setToolName(e.target.value),
|
|
1748
|
+
placeholder: "Tool name",
|
|
1749
|
+
style: {
|
|
1750
|
+
padding: "6px 8px",
|
|
1751
|
+
backgroundColor: "#1a1a1a",
|
|
1752
|
+
color: "#ffffff",
|
|
1753
|
+
border: "1px solid #333",
|
|
1754
|
+
borderRadius: "4px",
|
|
1755
|
+
fontFamily: "monospace",
|
|
1756
|
+
fontSize: "12px",
|
|
1757
|
+
width: "150px"
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
),
|
|
1761
|
+
/* @__PURE__ */ React2.createElement(
|
|
1762
|
+
"input",
|
|
1763
|
+
{
|
|
1764
|
+
type: "text",
|
|
1765
|
+
value: toolArgs,
|
|
1766
|
+
onChange: (e) => setToolArgs(e.target.value),
|
|
1767
|
+
placeholder: '{"key": "value"}',
|
|
1768
|
+
style: {
|
|
1769
|
+
padding: "6px 8px",
|
|
1770
|
+
backgroundColor: "#1a1a1a",
|
|
1771
|
+
color: "#ffffff",
|
|
1772
|
+
border: "1px solid #333",
|
|
1773
|
+
borderRadius: "4px",
|
|
1774
|
+
fontFamily: "monospace",
|
|
1775
|
+
fontSize: "12px",
|
|
1776
|
+
flex: 1
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
),
|
|
1780
|
+
/* @__PURE__ */ React2.createElement(
|
|
1781
|
+
"button",
|
|
1782
|
+
{
|
|
1783
|
+
onClick: handleCallTool,
|
|
1784
|
+
style: {
|
|
1785
|
+
padding: "6px 12px",
|
|
1786
|
+
backgroundColor: "#333",
|
|
1787
|
+
color: "#ffffff",
|
|
1788
|
+
border: "1px solid #555",
|
|
1789
|
+
borderRadius: "4px",
|
|
1790
|
+
cursor: "pointer",
|
|
1791
|
+
fontFamily: "monospace",
|
|
1792
|
+
fontSize: "12px"
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1795
|
+
"Call Tool"
|
|
1796
|
+
)
|
|
1797
|
+
),
|
|
1798
|
+
/* @__PURE__ */ React2.createElement(
|
|
1799
|
+
"div",
|
|
1800
|
+
{
|
|
1801
|
+
style: { display: "flex", gap: "8px", alignItems: "center" }
|
|
1802
|
+
},
|
|
1803
|
+
/* @__PURE__ */ React2.createElement(
|
|
1804
|
+
"input",
|
|
1805
|
+
{
|
|
1806
|
+
type: "text",
|
|
1807
|
+
value: followUpMessage,
|
|
1808
|
+
onChange: (e) => setFollowUpMessage(e.target.value),
|
|
1809
|
+
placeholder: "Follow-up message",
|
|
1810
|
+
style: {
|
|
1811
|
+
padding: "6px 8px",
|
|
1812
|
+
backgroundColor: "#1a1a1a",
|
|
1813
|
+
color: "#ffffff",
|
|
1814
|
+
border: "1px solid #333",
|
|
1815
|
+
borderRadius: "4px",
|
|
1816
|
+
fontFamily: "monospace",
|
|
1817
|
+
fontSize: "12px",
|
|
1818
|
+
flex: 1
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
),
|
|
1822
|
+
/* @__PURE__ */ React2.createElement(
|
|
1823
|
+
"button",
|
|
1824
|
+
{
|
|
1825
|
+
onClick: handleSendFollowUpMessage,
|
|
1826
|
+
style: {
|
|
1827
|
+
padding: "6px 12px",
|
|
1828
|
+
backgroundColor: "#333",
|
|
1829
|
+
color: "#ffffff",
|
|
1830
|
+
border: "1px solid #555",
|
|
1831
|
+
borderRadius: "4px",
|
|
1832
|
+
cursor: "pointer",
|
|
1833
|
+
fontFamily: "monospace",
|
|
1834
|
+
fontSize: "12px"
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
"Send Follow-Up"
|
|
1838
|
+
)
|
|
1839
|
+
),
|
|
1840
|
+
/* @__PURE__ */ React2.createElement(
|
|
1841
|
+
"div",
|
|
1842
|
+
{
|
|
1843
|
+
style: { display: "flex", gap: "8px", alignItems: "center" }
|
|
1844
|
+
},
|
|
1845
|
+
/* @__PURE__ */ React2.createElement(
|
|
1846
|
+
"input",
|
|
1847
|
+
{
|
|
1848
|
+
type: "text",
|
|
1849
|
+
value: externalUrl,
|
|
1850
|
+
onChange: (e) => setExternalUrl(e.target.value),
|
|
1851
|
+
placeholder: "External URL",
|
|
1852
|
+
style: {
|
|
1853
|
+
padding: "6px 8px",
|
|
1854
|
+
backgroundColor: "#1a1a1a",
|
|
1855
|
+
color: "#ffffff",
|
|
1856
|
+
border: "1px solid #333",
|
|
1857
|
+
borderRadius: "4px",
|
|
1858
|
+
fontFamily: "monospace",
|
|
1859
|
+
fontSize: "12px",
|
|
1860
|
+
flex: 1
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
),
|
|
1864
|
+
/* @__PURE__ */ React2.createElement(
|
|
1865
|
+
"button",
|
|
1866
|
+
{
|
|
1867
|
+
onClick: handleOpenExternal,
|
|
1868
|
+
style: {
|
|
1869
|
+
padding: "6px 12px",
|
|
1870
|
+
backgroundColor: "#333",
|
|
1871
|
+
color: "#ffffff",
|
|
1872
|
+
border: "1px solid #555",
|
|
1873
|
+
borderRadius: "4px",
|
|
1874
|
+
cursor: "pointer",
|
|
1875
|
+
fontFamily: "monospace",
|
|
1876
|
+
fontSize: "12px"
|
|
1877
|
+
}
|
|
1878
|
+
},
|
|
1879
|
+
"Open Link"
|
|
1880
|
+
)
|
|
1881
|
+
),
|
|
1882
|
+
/* @__PURE__ */ React2.createElement(
|
|
1883
|
+
"div",
|
|
1884
|
+
{
|
|
1885
|
+
style: { display: "flex", gap: "8px", alignItems: "center" }
|
|
1886
|
+
},
|
|
1887
|
+
/* @__PURE__ */ React2.createElement("span", { style: { width: "150px", fontSize: "12px" } }, "Display Mode:"),
|
|
1888
|
+
/* @__PURE__ */ React2.createElement(
|
|
1889
|
+
"button",
|
|
1890
|
+
{
|
|
1891
|
+
onClick: () => handleRequestDisplayMode("inline"),
|
|
1892
|
+
style: {
|
|
1893
|
+
padding: "6px 12px",
|
|
1894
|
+
backgroundColor: "#333",
|
|
1895
|
+
color: "#ffffff",
|
|
1896
|
+
border: "1px solid #555",
|
|
1897
|
+
borderRadius: "4px",
|
|
1898
|
+
cursor: "pointer",
|
|
1899
|
+
fontFamily: "monospace",
|
|
1900
|
+
fontSize: "12px",
|
|
1901
|
+
flex: 1
|
|
1902
|
+
}
|
|
1903
|
+
},
|
|
1904
|
+
"Inline"
|
|
1905
|
+
),
|
|
1906
|
+
/* @__PURE__ */ React2.createElement(
|
|
1907
|
+
"button",
|
|
1908
|
+
{
|
|
1909
|
+
onClick: () => handleRequestDisplayMode("pip"),
|
|
1910
|
+
style: {
|
|
1911
|
+
padding: "6px 12px",
|
|
1912
|
+
backgroundColor: "#333",
|
|
1913
|
+
color: "#ffffff",
|
|
1914
|
+
border: "1px solid #555",
|
|
1915
|
+
borderRadius: "4px",
|
|
1916
|
+
cursor: "pointer",
|
|
1917
|
+
fontFamily: "monospace",
|
|
1918
|
+
fontSize: "12px",
|
|
1919
|
+
flex: 1
|
|
1920
|
+
}
|
|
1921
|
+
},
|
|
1922
|
+
"PiP"
|
|
1923
|
+
),
|
|
1924
|
+
/* @__PURE__ */ React2.createElement(
|
|
1925
|
+
"button",
|
|
1926
|
+
{
|
|
1927
|
+
onClick: () => handleRequestDisplayMode("fullscreen"),
|
|
1928
|
+
style: {
|
|
1929
|
+
padding: "6px 12px",
|
|
1930
|
+
backgroundColor: "#333",
|
|
1931
|
+
color: "#ffffff",
|
|
1932
|
+
border: "1px solid #555",
|
|
1933
|
+
borderRadius: "4px",
|
|
1934
|
+
cursor: "pointer",
|
|
1935
|
+
fontFamily: "monospace",
|
|
1936
|
+
fontSize: "12px",
|
|
1937
|
+
flex: 1
|
|
1938
|
+
}
|
|
1939
|
+
},
|
|
1940
|
+
"Fullscreen"
|
|
1941
|
+
)
|
|
1942
|
+
),
|
|
1943
|
+
/* @__PURE__ */ React2.createElement(
|
|
1944
|
+
"div",
|
|
1945
|
+
{
|
|
1946
|
+
style: { display: "flex", gap: "8px", alignItems: "center" }
|
|
1947
|
+
},
|
|
1948
|
+
/* @__PURE__ */ React2.createElement(
|
|
1949
|
+
"button",
|
|
1950
|
+
{
|
|
1951
|
+
onClick: handleSetState,
|
|
1952
|
+
style: {
|
|
1953
|
+
padding: "6px 12px",
|
|
1954
|
+
backgroundColor: "#333",
|
|
1955
|
+
color: "#ffffff",
|
|
1956
|
+
border: "1px solid #555",
|
|
1957
|
+
borderRadius: "4px",
|
|
1958
|
+
cursor: "pointer",
|
|
1959
|
+
fontFamily: "monospace",
|
|
1960
|
+
fontSize: "12px"
|
|
1961
|
+
}
|
|
1962
|
+
},
|
|
1963
|
+
"Set State (Add Timestamp)"
|
|
1964
|
+
)
|
|
1965
|
+
),
|
|
1966
|
+
actionResult && /* @__PURE__ */ React2.createElement(
|
|
1967
|
+
"div",
|
|
1968
|
+
{
|
|
1969
|
+
style: {
|
|
1970
|
+
marginTop: "8px",
|
|
1971
|
+
padding: "8px",
|
|
1972
|
+
backgroundColor: "#1a1a1a",
|
|
1973
|
+
border: "1px solid #333",
|
|
1974
|
+
borderRadius: "4px",
|
|
1975
|
+
whiteSpace: "pre-wrap",
|
|
1976
|
+
wordBreak: "break-all",
|
|
1977
|
+
fontSize: "11px",
|
|
1978
|
+
maxHeight: "200px",
|
|
1979
|
+
overflow: "auto"
|
|
1980
|
+
}
|
|
1981
|
+
},
|
|
1982
|
+
/* @__PURE__ */ React2.createElement(
|
|
1983
|
+
"div",
|
|
1984
|
+
{
|
|
1985
|
+
style: {
|
|
1986
|
+
fontWeight: "bold",
|
|
1987
|
+
marginBottom: "4px",
|
|
1988
|
+
color: "#aaa"
|
|
1989
|
+
}
|
|
1990
|
+
},
|
|
1991
|
+
"Result:"
|
|
1992
|
+
),
|
|
1993
|
+
actionResult,
|
|
1994
|
+
/* @__PURE__ */ React2.createElement(
|
|
1995
|
+
"button",
|
|
1996
|
+
{
|
|
1997
|
+
onClick: () => setActionResult(""),
|
|
1998
|
+
style: {
|
|
1999
|
+
marginTop: "8px",
|
|
2000
|
+
padding: "4px 8px",
|
|
2001
|
+
backgroundColor: "#333",
|
|
2002
|
+
color: "#ffffff",
|
|
2003
|
+
border: "1px solid #555",
|
|
2004
|
+
borderRadius: "4px",
|
|
2005
|
+
cursor: "pointer",
|
|
2006
|
+
fontFamily: "monospace",
|
|
2007
|
+
fontSize: "11px"
|
|
2008
|
+
}
|
|
2009
|
+
},
|
|
2010
|
+
"Clear"
|
|
2011
|
+
)
|
|
2012
|
+
)
|
|
2013
|
+
)
|
|
2014
|
+
)
|
|
2015
|
+
));
|
|
2016
|
+
}
|
|
2017
|
+
__name(WidgetDebugger, "WidgetDebugger");
|
|
2018
|
+
|
|
2019
|
+
export {
|
|
2020
|
+
useMcp,
|
|
2021
|
+
useWidget,
|
|
2022
|
+
useWidgetProps,
|
|
2023
|
+
useWidgetTheme,
|
|
2024
|
+
useWidgetState,
|
|
2025
|
+
WidgetFullscreenWrapper,
|
|
2026
|
+
WidgetDebugger
|
|
2027
|
+
};
|