@tooluminati/react-troubleshooting 0.1.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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/dist/WebMcpErrorBoundary.d.ts +8 -0
  3. package/dist/WebMcpErrorBoundary.d.ts.map +1 -0
  4. package/dist/WebMcpErrorBoundary.js +29 -0
  5. package/dist/WebMcpTroubleshootingContext.d.ts +12 -0
  6. package/dist/WebMcpTroubleshootingContext.d.ts.map +1 -0
  7. package/dist/WebMcpTroubleshootingContext.js +9 -0
  8. package/dist/WebMcpTroubleshootingPanel.d.ts +9 -0
  9. package/dist/WebMcpTroubleshootingPanel.d.ts.map +1 -0
  10. package/dist/WebMcpTroubleshootingPanel.js +170 -0
  11. package/dist/WebMcpTroubleshootingProvider.d.ts +23 -0
  12. package/dist/WebMcpTroubleshootingProvider.d.ts.map +1 -0
  13. package/dist/WebMcpTroubleshootingProvider.js +106 -0
  14. package/dist/declarative-form.d.ts +23 -0
  15. package/dist/declarative-form.d.ts.map +1 -0
  16. package/dist/declarative-form.js +33 -0
  17. package/dist/index.cjs +833 -0
  18. package/dist/index.d.ts +11 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +822 -0
  21. package/dist/panel-visibility.d.ts +8 -0
  22. package/dist/panel-visibility.d.ts.map +1 -0
  23. package/dist/panel-visibility.js +23 -0
  24. package/dist/useFormSubmitBlockers.d.ts +11 -0
  25. package/dist/useFormSubmitBlockers.d.ts.map +1 -0
  26. package/dist/useFormSubmitBlockers.js +35 -0
  27. package/dist/useTanStackQueryWebMcpTools.d.ts +9 -0
  28. package/dist/useTanStackQueryWebMcpTools.d.ts.map +1 -0
  29. package/dist/useTanStackQueryWebMcpTools.js +16 -0
  30. package/dist/useTroubleshootingPanel.d.ts +14 -0
  31. package/dist/useTroubleshootingPanel.d.ts.map +1 -0
  32. package/dist/useTroubleshootingPanel.js +29 -0
  33. package/dist/webmcp-declarative-attributes.d.ts +20 -0
  34. package/dist/webmcp-declarative-attributes.d.ts.map +1 -0
  35. package/dist/webmcp-declarative-attributes.js +2 -0
  36. package/package.json +67 -0
package/dist/index.js ADDED
@@ -0,0 +1,822 @@
1
+ // src/webmcp-declarative-attributes.ts
2
+ import "react";
3
+
4
+ // src/WebMcpTroubleshootingProvider.tsx
5
+ import {
6
+ useEffect as useEffect2,
7
+ useMemo as useMemo2,
8
+ useRef
9
+ } from "react";
10
+ import {
11
+ ClientErrorBuffer,
12
+ TroubleshootingTimelineBuffer,
13
+ createErrorCollector,
14
+ createFetchFailureTracker,
15
+ createActionAvailabilityTool,
16
+ createListActionsTool,
17
+ createMountedFormsRegistry,
18
+ createMountedFormsSummaryTool,
19
+ createRecentClientErrorsTool,
20
+ createTimelineFromErrorBuffer,
21
+ createTroubleshootingPanelViewModel,
22
+ createTroubleshootingTimelineTool,
23
+ createWebMcpEnvironmentSummary,
24
+ createWebMcpEnvironmentTool,
25
+ createWebMcpLifecycleCollector,
26
+ createWorkflowBlockersTool,
27
+ discoverDeclarativeForms,
28
+ formSummaryFromMounted,
29
+ isPanelEnabledByDefault,
30
+ isPanelUrlOverrideEnabled
31
+ } from "@tooluminati/diagnostics";
32
+ import {
33
+ WebMcpProvider,
34
+ useWebMcpRegistry
35
+ } from "@tooluminati/react";
36
+
37
+ // src/WebMcpTroubleshootingContext.tsx
38
+ import { createContext, useContext } from "react";
39
+ var WebMcpTroubleshootingContext = createContext(null);
40
+ function useWebMcpTroubleshootingContext() {
41
+ const value = useContext(WebMcpTroubleshootingContext);
42
+ if (!value) {
43
+ throw new Error(
44
+ "useWebMcpTroubleshootingContext requires WebMcpTroubleshootingProvider."
45
+ );
46
+ }
47
+ return value;
48
+ }
49
+
50
+ // src/WebMcpTroubleshootingPanel.tsx
51
+ import { useEffect, useMemo, useState } from "react";
52
+ import {
53
+ filterPanelEvents,
54
+ serializeTroubleshootingDiagnostics
55
+ } from "@tooluminati/diagnostics";
56
+ import { jsx, jsxs } from "react/jsx-runtime";
57
+ var PALETTE = {
58
+ surface: "#0a0e1a",
59
+ navy: "#17316A",
60
+ amber: "#FECD10",
61
+ cyan: "#0AADF2",
62
+ red: "#FF5C6C"
63
+ };
64
+ var positionStyle = {
65
+ br: { right: "26px", bottom: "26px" },
66
+ bl: { left: "26px", bottom: "26px" },
67
+ tr: { right: "26px", top: "26px" },
68
+ tl: { left: "26px", top: "26px" }
69
+ };
70
+ function WebMcpTroubleshootingPanel({
71
+ position = "br",
72
+ startCollapsed,
73
+ onCopyDiagnostics
74
+ }) {
75
+ const { viewModel, visibility, isPanelEnabled } = useWebMcpTroubleshootingContext();
76
+ const [snapshot, setSnapshot] = useState(
77
+ () => viewModel.refresh()
78
+ );
79
+ const [filter, setFilter] = useState("all");
80
+ const [openChecks, setOpenChecks] = useState({});
81
+ const [openEvents, setOpenEvents] = useState({});
82
+ const [openErrors, setOpenErrors] = useState({});
83
+ const [copied, setCopied] = useState(false);
84
+ const [spinning, setSpinning] = useState(false);
85
+ useEffect(() => {
86
+ if (startCollapsed) {
87
+ visibility.setCollapsed(true);
88
+ }
89
+ }, [startCollapsed, visibility]);
90
+ useEffect(() => {
91
+ const refresh2 = () => setSnapshot(viewModel.refresh());
92
+ refresh2();
93
+ const unsubVm = viewModel.subscribe(refresh2);
94
+ const unsubVis = visibility.subscribe(refresh2);
95
+ return () => {
96
+ unsubVm();
97
+ unsubVis();
98
+ };
99
+ }, [viewModel, visibility]);
100
+ const filteredEvents = useMemo(
101
+ () => filterPanelEvents(snapshot.events, filter),
102
+ [snapshot.events, filter]
103
+ );
104
+ if (!isPanelEnabled || !visibility.visible) {
105
+ return null;
106
+ }
107
+ const pos = positionStyle[position];
108
+ const supportColor = snapshot.supported ? PALETTE.cyan : PALETTE.red;
109
+ const collapsed = visibility.collapsed;
110
+ const refresh = () => {
111
+ setSpinning(true);
112
+ setSnapshot(viewModel.refresh());
113
+ window.setTimeout(() => setSpinning(false), 650);
114
+ };
115
+ const copyDiagnostics = async () => {
116
+ const json = serializeTroubleshootingDiagnostics(snapshot);
117
+ if (onCopyDiagnostics) {
118
+ onCopyDiagnostics(json);
119
+ } else if (navigator.clipboard) {
120
+ await navigator.clipboard.writeText(json);
121
+ }
122
+ setCopied(true);
123
+ window.setTimeout(() => setCopied(false), 1500);
124
+ };
125
+ if (collapsed) {
126
+ return /* @__PURE__ */ jsxs(
127
+ "button",
128
+ {
129
+ type: "button",
130
+ "aria-label": "Expand WebMCP troubleshooting panel",
131
+ "data-testid": "webmcp-troubleshooting-badge",
132
+ onClick: () => visibility.setCollapsed(false),
133
+ style: {
134
+ position: "fixed",
135
+ ...pos,
136
+ zIndex: 99990,
137
+ display: "flex",
138
+ alignItems: "center",
139
+ gap: 11,
140
+ padding: "11px 15px 11px 13px",
141
+ background: "#0d1322",
142
+ border: "1px solid #1f2940",
143
+ borderRadius: 13,
144
+ cursor: "pointer",
145
+ boxShadow: "0 14px 40px rgba(0,0,0,.5)",
146
+ fontFamily: "'IBM Plex Sans', system-ui, sans-serif"
147
+ },
148
+ children: [
149
+ /* @__PURE__ */ jsx(BrandMark, {}),
150
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", flexDirection: "column", lineHeight: 1.15 }, children: [
151
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 600, color: "#e7ecf6" }, children: "WebMCP" }),
152
+ /* @__PURE__ */ jsx(
153
+ "span",
154
+ {
155
+ style: {
156
+ fontFamily: "'IBM Plex Mono', monospace",
157
+ fontSize: 10,
158
+ color: supportColor
159
+ },
160
+ children: snapshot.supported ? "supported" : "unsupported"
161
+ }
162
+ )
163
+ ] }),
164
+ /* @__PURE__ */ jsxs(
165
+ "span",
166
+ {
167
+ style: {
168
+ display: "flex",
169
+ alignItems: "center",
170
+ gap: 6,
171
+ paddingLeft: 11,
172
+ marginLeft: 3,
173
+ borderLeft: "1px solid #20293f"
174
+ },
175
+ children: [
176
+ /* @__PURE__ */ jsx(
177
+ "span",
178
+ {
179
+ style: {
180
+ fontFamily: "'IBM Plex Mono', monospace",
181
+ fontSize: 12,
182
+ color: "#aeb7cb"
183
+ },
184
+ children: snapshot.toolCount
185
+ }
186
+ ),
187
+ snapshot.issueCount > 0 ? /* @__PURE__ */ jsx(
188
+ "span",
189
+ {
190
+ style: {
191
+ width: 8,
192
+ height: 8,
193
+ borderRadius: "50%",
194
+ background: snapshot.errors.length > 0 ? PALETTE.red : PALETTE.amber
195
+ }
196
+ }
197
+ ) : null
198
+ ]
199
+ }
200
+ )
201
+ ]
202
+ }
203
+ );
204
+ }
205
+ return /* @__PURE__ */ jsxs(
206
+ "div",
207
+ {
208
+ "aria-label": "WebMCP troubleshooting panel",
209
+ "data-testid": "webmcp-troubleshooting-panel",
210
+ style: {
211
+ position: "fixed",
212
+ ...pos,
213
+ zIndex: 99990,
214
+ width: 412,
215
+ maxHeight: "calc(100vh - 52px)",
216
+ display: "flex",
217
+ flexDirection: "column",
218
+ background: PALETTE.surface,
219
+ border: "1px solid #1c2438",
220
+ borderRadius: 15,
221
+ boxShadow: "0 26px 70px rgba(0,0,0,.62)",
222
+ overflow: "hidden",
223
+ fontFamily: "'IBM Plex Sans', system-ui, sans-serif",
224
+ color: "#eef2fa"
225
+ },
226
+ children: [
227
+ /* @__PURE__ */ jsxs(
228
+ "header",
229
+ {
230
+ style: {
231
+ display: "flex",
232
+ alignItems: "center",
233
+ gap: 11,
234
+ padding: "13px 14px",
235
+ borderBottom: "1px solid #161d2e"
236
+ },
237
+ children: [
238
+ /* @__PURE__ */ jsx(BrandMark, {}),
239
+ /* @__PURE__ */ jsxs("div", { style: { marginRight: "auto", lineHeight: 1.2 }, children: [
240
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13.5, fontWeight: 600 }, children: "WebMCP Troubleshooting" }),
241
+ /* @__PURE__ */ jsx(
242
+ "div",
243
+ {
244
+ style: {
245
+ fontFamily: "'IBM Plex Mono', monospace",
246
+ fontSize: 9.5,
247
+ letterSpacing: 1.6,
248
+ color: "#5f6a82",
249
+ textTransform: "uppercase"
250
+ },
251
+ children: "Tooluminati \xB7 dev panel"
252
+ }
253
+ )
254
+ ] }),
255
+ /* @__PURE__ */ jsx(PanelButton, { title: "Re-run checks", onClick: refresh, children: /* @__PURE__ */ jsx("span", { style: { display: "inline-block", animation: spinning ? "tlmSpin .65s linear" : "none" }, children: "\u27F3" }) }),
256
+ /* @__PURE__ */ jsx(PanelButton, { onClick: () => void copyDiagnostics(), children: /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 11, color: copied ? PALETTE.cyan : "#9aa5bd" }, children: copied ? "Copied \u2713" : "Copy JSON" }) }),
257
+ /* @__PURE__ */ jsx(PanelButton, { title: "Minimize", onClick: () => visibility.setCollapsed(true), children: "\u2013" })
258
+ ]
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsxs(
262
+ "div",
263
+ {
264
+ style: {
265
+ display: "grid",
266
+ gridTemplateColumns: "1fr 1fr 1fr",
267
+ gap: 1,
268
+ background: "#161d2e"
269
+ },
270
+ children: [
271
+ /* @__PURE__ */ jsx(StatTile, { label: "WebMCP", value: snapshot.supported ? "Supported" : "Unsupported", color: supportColor }),
272
+ /* @__PURE__ */ jsx(StatTile, { label: "Tools", value: String(snapshot.toolCount), color: snapshot.toolCount > 0 ? "#eef2fa" : PALETTE.amber }),
273
+ /* @__PURE__ */ jsx(StatTile, { label: "Issues", value: String(snapshot.issueCount), color: snapshot.errors.length ? PALETTE.red : snapshot.issueCount ? PALETTE.amber : PALETTE.cyan })
274
+ ]
275
+ }
276
+ ),
277
+ /* @__PURE__ */ jsxs("div", { style: { overflow: "auto", flex: 1, minHeight: 0 }, children: [
278
+ /* @__PURE__ */ jsx(Section, { title: "Environment", children: snapshot.checks.map((check) => /* @__PURE__ */ jsx(
279
+ Row,
280
+ {
281
+ open: openChecks[check.id] ?? false,
282
+ onToggle: () => setOpenChecks((s) => ({ ...s, [check.id]: !s[check.id] })),
283
+ hint: check.guidance,
284
+ label: check.label,
285
+ value: check.value,
286
+ status: check.status
287
+ },
288
+ check.id
289
+ )) }),
290
+ /* @__PURE__ */ jsxs(Section, { title: "Timeline", meta: `${snapshot.events.length} captured`, children: [
291
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, padding: "0 12px 8px" }, children: ["all", "failures", "blocked", "tools", "nav"].map((chip) => /* @__PURE__ */ jsx(
292
+ "button",
293
+ {
294
+ type: "button",
295
+ onClick: () => setFilter(chip),
296
+ style: {
297
+ fontFamily: "'IBM Plex Mono', monospace",
298
+ fontSize: 10.5,
299
+ padding: "4px 9px",
300
+ borderRadius: 20,
301
+ cursor: "pointer",
302
+ border: `1px solid ${filter === chip ? PALETTE.cyan : "#1f2840"}`,
303
+ background: filter === chip ? "rgba(10,173,242,.13)" : "#0d1322",
304
+ color: filter === chip ? "#5EC8F7" : "#8893a8"
305
+ },
306
+ children: chip
307
+ },
308
+ chip
309
+ )) }),
310
+ filteredEvents.length === 0 ? /* @__PURE__ */ jsx(EmptyRow, { label: snapshot.events.length === 0 ? "No timeline activity yet" : "No events in this filter" }) : filteredEvents.map((event) => /* @__PURE__ */ jsx(
311
+ Row,
312
+ {
313
+ open: openEvents[event.id] ?? false,
314
+ onToggle: () => setOpenEvents((s) => ({ ...s, [event.id]: !s[event.id] })),
315
+ hint: event.detail ?? event.guidance,
316
+ meta: event.metadata ? JSON.stringify(event.metadata, null, 2) : void 0,
317
+ label: event.title,
318
+ value: event.time,
319
+ tag: event.category.slice(0, 4).toUpperCase()
320
+ },
321
+ event.id
322
+ ))
323
+ ] }),
324
+ /* @__PURE__ */ jsx(Section, { title: "Client Errors", meta: snapshot.errors.length ? `${snapshot.errors.length} captured` : "clean", children: snapshot.errors.length === 0 ? /* @__PURE__ */ jsx(EmptyRow, { label: "No errors captured this session", ok: true }) : snapshot.errors.map((error) => /* @__PURE__ */ jsx(
325
+ Row,
326
+ {
327
+ open: openErrors[error.id] ?? false,
328
+ onToggle: () => setOpenErrors((s) => ({ ...s, [error.id]: !s[error.id] })),
329
+ hint: error.guidance,
330
+ meta: error.stack,
331
+ label: error.message,
332
+ value: error.time,
333
+ tag: "ERR",
334
+ error: true
335
+ },
336
+ error.id
337
+ )) })
338
+ ] }),
339
+ /* @__PURE__ */ jsxs(
340
+ "footer",
341
+ {
342
+ style: {
343
+ display: "flex",
344
+ alignItems: "center",
345
+ gap: 8,
346
+ padding: "9px 14px",
347
+ borderTop: "1px solid #161d2e",
348
+ background: "#0c1120"
349
+ },
350
+ children: [
351
+ /* @__PURE__ */ jsx("span", { style: { width: 6, height: 6, borderRadius: "50%", background: PALETTE.cyan } }),
352
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10.5, color: "#6b768c" }, children: [
353
+ "Live \xB7 ",
354
+ snapshot.panelState
355
+ ] })
356
+ ]
357
+ }
358
+ ),
359
+ /* @__PURE__ */ jsx("style", { children: `@keyframes tlmSpin { to { transform: rotate(360deg); } }` })
360
+ ]
361
+ }
362
+ );
363
+ }
364
+ function BrandMark() {
365
+ return /* @__PURE__ */ jsxs("span", { style: { position: "relative", width: 26, height: 26, display: "inline-flex", alignItems: "center", justifyContent: "center" }, children: [
366
+ /* @__PURE__ */ jsx("span", { style: { width: 0, height: 0, borderLeft: "13px solid transparent", borderRight: "13px solid transparent", borderBottom: "22px solid #17316A", position: "absolute", top: 1 } }),
367
+ /* @__PURE__ */ jsx("span", { style: { position: "relative", width: 7, height: 7, borderRadius: "50%", background: "#FECD10", marginTop: 6, boxShadow: "0 0 8px #FECD10" } })
368
+ ] });
369
+ }
370
+ function PanelButton({ children, onClick, title }) {
371
+ return /* @__PURE__ */ jsx("button", { type: "button", title, onClick, style: { display: "inline-flex", alignItems: "center", justifyContent: "center", minWidth: 30, height: 30, borderRadius: 8, background: "#121a2b", border: "1px solid #1f2840", color: "#9aa5bd", cursor: "pointer" }, children });
372
+ }
373
+ function StatTile({ label, value, color }) {
374
+ return /* @__PURE__ */ jsxs("div", { style: { background: "#0a0e1a", padding: "12px 13px" }, children: [
375
+ /* @__PURE__ */ jsx("div", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 9.5, letterSpacing: 1, color: "#5f6a82", textTransform: "uppercase" }, children: label }),
376
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 14, fontWeight: 600, color }, children: value })
377
+ ] });
378
+ }
379
+ function Section({ title, meta, children }) {
380
+ return /* @__PURE__ */ jsxs("div", { style: { paddingBottom: 8 }, children: [
381
+ /* @__PURE__ */ jsxs("div", { style: { padding: "13px 14px 6px", display: "flex", alignItems: "center", gap: 8 }, children: [
382
+ /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, letterSpacing: 1.5, color: "#7b8aa6", textTransform: "uppercase", fontWeight: 600 }, children: title }),
383
+ meta ? /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, color: "#4f5870" }, children: meta }) : null
384
+ ] }),
385
+ /* @__PURE__ */ jsx("div", { style: { padding: "0 12px" }, children })
386
+ ] });
387
+ }
388
+ function Row({
389
+ label,
390
+ value,
391
+ hint,
392
+ meta,
393
+ tag,
394
+ status,
395
+ open,
396
+ onToggle,
397
+ error
398
+ }) {
399
+ const expandable = Boolean(hint || meta);
400
+ return /* @__PURE__ */ jsxs("div", { style: { borderRadius: 8, overflow: "hidden", marginBottom: 3, background: open ? "#0e1424" : error ? "rgba(255,92,108,.05)" : "#0b0f1c", borderLeft: error ? `2px solid #FF5C6C` : void 0 }, children: [
401
+ /* @__PURE__ */ jsxs("button", { type: "button", onClick: expandable ? onToggle : void 0, style: { width: "100%", display: "flex", alignItems: "center", gap: 9, padding: "7px 10px", background: "transparent", border: 0, cursor: expandable ? "pointer" : "default", color: "inherit", textAlign: "left" }, children: [
402
+ tag ? /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 8.5, fontWeight: 600, padding: "2px 5px", borderRadius: 4, color: error ? "#FF8088" : "#5EC8F7", background: error ? "rgba(255,92,108,.12)" : "rgba(10,173,242,.13)" }, children: tag }) : null,
403
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: label }),
404
+ value ? /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, color: status === "warn" ? "#FFD86B" : status === "fail" ? "#FF8088" : "#58627a" }, children: value }) : null,
405
+ expandable ? /* @__PURE__ */ jsx("span", { style: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 11, color: "#586279" }, children: open ? "\u25BE" : "\u25B8" }) : null
406
+ ] }),
407
+ open && hint ? /* @__PURE__ */ jsx("div", { style: { padding: "0 12px 11px 36px", fontSize: 11.5, lineHeight: 1.55, color: "#9aa5bd" }, children: hint }) : null,
408
+ open && meta ? /* @__PURE__ */ jsx("pre", { style: { margin: "0 12px 11px", fontFamily: "'IBM Plex Mono', monospace", fontSize: 10.5, color: "#6b768c", background: "#070b14", border: "1px solid #161d2e", borderRadius: 6, padding: "7px 9px", whiteSpace: "pre-wrap" }, children: meta }) : null
409
+ ] });
410
+ }
411
+ function EmptyRow({ label, ok }) {
412
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px 10px", fontSize: 12, color: "#586279", fontFamily: "'IBM Plex Mono', monospace" }, children: [
413
+ ok ? "\u2713 " : "",
414
+ label
415
+ ] });
416
+ }
417
+
418
+ // src/panel-visibility.ts
419
+ import {
420
+ createTroubleshootingPanelVisibilityController
421
+ } from "@tooluminati/diagnostics";
422
+ var controller;
423
+ function getPanelVisibilityController() {
424
+ if (!controller) {
425
+ controller = createTroubleshootingPanelVisibilityController();
426
+ }
427
+ return controller;
428
+ }
429
+ function wirePanelVisibilityController(next) {
430
+ controller = next;
431
+ }
432
+ function showWebMcpTroubleshootingPanel() {
433
+ getPanelVisibilityController().show();
434
+ }
435
+ function hideWebMcpTroubleshootingPanel() {
436
+ getPanelVisibilityController().hide();
437
+ }
438
+ function toggleWebMcpTroubleshootingPanel() {
439
+ getPanelVisibilityController().toggle();
440
+ }
441
+ function resetPanelVisibilityController() {
442
+ controller = void 0;
443
+ }
444
+
445
+ // src/WebMcpTroubleshootingProvider.tsx
446
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
447
+ function WebMcpTroubleshootingInner({
448
+ children,
449
+ timeline,
450
+ errors,
451
+ mountedForms,
452
+ trackFetchFailures,
453
+ panel,
454
+ panelEnabled,
455
+ registryRef
456
+ }) {
457
+ const registry = useWebMcpRegistry();
458
+ useEffect2(() => {
459
+ registryRef.current = registry;
460
+ }, [registry, registryRef]);
461
+ const visibility = useMemo2(() => {
462
+ const controller2 = getPanelVisibilityController();
463
+ wirePanelVisibilityController(controller2);
464
+ if (panel?.startCollapsed) {
465
+ controller2.setCollapsed(true);
466
+ }
467
+ return controller2;
468
+ }, [panel?.startCollapsed]);
469
+ const viewModel = useMemo2(
470
+ () => createTroubleshootingPanelViewModel(
471
+ {
472
+ timeline,
473
+ errors,
474
+ environment: () => createWebMcpEnvironmentSummary({ registry }),
475
+ registry
476
+ },
477
+ {
478
+ pollMs: panel?.pollMs ?? 2e3,
479
+ registry,
480
+ ...panel?.eventLimit !== void 0 ? { eventLimit: panel.eventLimit } : {}
481
+ }
482
+ ),
483
+ [timeline, errors, registry, panel?.eventLimit, panel?.pollMs]
484
+ );
485
+ useEffect2(() => {
486
+ const cleanups = [
487
+ createErrorCollector({ buffer: errors }),
488
+ createTimelineFromErrorBuffer(errors, timeline),
489
+ createWebMcpLifecycleCollector({ buffer: timeline })
490
+ ];
491
+ if (trackFetchFailures) {
492
+ cleanups.push(createFetchFailureTracker({ buffer: timeline }));
493
+ }
494
+ return () => {
495
+ for (const cleanup of cleanups) {
496
+ cleanup();
497
+ }
498
+ viewModel.dispose();
499
+ };
500
+ }, [errors, timeline, trackFetchFailures, viewModel]);
501
+ const shouldRenderPanel = panelEnabled && panel?.render !== false && (panel?.render === true || panel?.render === "auto" || panel?.render === void 0);
502
+ const contextValue = useMemo2(
503
+ () => ({
504
+ timeline,
505
+ errors,
506
+ mountedForms,
507
+ viewModel,
508
+ visibility,
509
+ isPanelEnabled: panelEnabled
510
+ }),
511
+ [timeline, errors, mountedForms, viewModel, visibility, panelEnabled]
512
+ );
513
+ return /* @__PURE__ */ jsxs2(WebMcpTroubleshootingContext.Provider, { value: contextValue, children: [
514
+ children,
515
+ shouldRenderPanel ? /* @__PURE__ */ jsx2(
516
+ WebMcpTroubleshootingPanel,
517
+ {
518
+ position: panel?.position ?? "br",
519
+ ...panel?.startCollapsed !== void 0 ? { startCollapsed: panel.startCollapsed } : {},
520
+ ...panel?.eventLimit !== void 0 ? { eventLimit: panel.eventLimit } : {},
521
+ pollMs: panel?.pollMs ?? 2e3
522
+ }
523
+ ) : null
524
+ ] });
525
+ }
526
+ function WebMcpTroubleshootingProvider({
527
+ children,
528
+ actionProvider,
529
+ querySummaries,
530
+ trackFetchFailures = true,
531
+ panel,
532
+ tools = [],
533
+ extraTools = [],
534
+ ...providerProps
535
+ }) {
536
+ const timeline = useMemo2(() => new TroubleshootingTimelineBuffer(), []);
537
+ const errors = useMemo2(
538
+ () => new ClientErrorBuffer({ includeStacks: true }),
539
+ []
540
+ );
541
+ const mountedForms = useMemo2(() => createMountedFormsRegistry(), []);
542
+ const registryRef = useRef(void 0);
543
+ const actionProviderRef = useRef(actionProvider);
544
+ const querySummariesRef = useRef(querySummaries);
545
+ actionProviderRef.current = actionProvider;
546
+ querySummariesRef.current = querySummaries;
547
+ useEffect2(() => () => resetPanelVisibilityController(), []);
548
+ const panelEnabled = isPanelEnabledByDefault(panel?.enabled) || isPanelUrlOverrideEnabled(panel?.allowUrlOverride);
549
+ const liveActionProvider = useMemo2(
550
+ () => ({
551
+ getActionAvailability: (actionId) => actionProviderRef.current?.getActionAvailability(actionId),
552
+ listActions: () => actionProviderRef.current?.listActions?.() ?? []
553
+ }),
554
+ []
555
+ );
556
+ const diagnosticTools = useMemo2(
557
+ () => [
558
+ createTroubleshootingTimelineTool(timeline),
559
+ createWebMcpEnvironmentTool(
560
+ () => createWebMcpEnvironmentSummary({ registry: registryRef.current })
561
+ ),
562
+ createRecentClientErrorsTool(errors),
563
+ createMountedFormsSummaryTool(mountedForms),
564
+ createWorkflowBlockersTool({
565
+ ...actionProvider ? { actionProvider: liveActionProvider } : {},
566
+ formSummaries: () => mountedForms.list().map(formSummaryFromMounted),
567
+ declarativeFormSummaries: () => discoverDeclarativeForms(),
568
+ recentErrors: () => errors.list(),
569
+ querySummaries: () => querySummariesRef.current?.() ?? []
570
+ }),
571
+ ...actionProvider ? [
572
+ createActionAvailabilityTool(liveActionProvider),
573
+ createListActionsTool(liveActionProvider)
574
+ ] : [],
575
+ ...tools,
576
+ ...extraTools
577
+ ],
578
+ [timeline, errors, mountedForms, actionProvider, liveActionProvider, tools, extraTools]
579
+ );
580
+ return /* @__PURE__ */ jsx2(WebMcpProvider, { ...providerProps, tools: diagnosticTools, children: /* @__PURE__ */ jsx2(
581
+ WebMcpTroubleshootingInner,
582
+ {
583
+ timeline,
584
+ errors,
585
+ mountedForms,
586
+ trackFetchFailures,
587
+ panelEnabled,
588
+ registryRef,
589
+ ...actionProvider ? { actionProvider } : {},
590
+ ...querySummaries ? { querySummaries } : {},
591
+ ...panel ? { panel } : {},
592
+ children
593
+ }
594
+ ) });
595
+ }
596
+
597
+ // src/WebMcpErrorBoundary.tsx
598
+ import { Component } from "react";
599
+ import { jsx as jsx3 } from "react/jsx-runtime";
600
+ var Boundary = class extends Component {
601
+ state = { hasError: false };
602
+ static getDerivedStateFromError() {
603
+ return { hasError: true };
604
+ }
605
+ componentDidCatch(error, info) {
606
+ this.props.errors.push({
607
+ message: error.message,
608
+ source: this.props.source ?? info.componentStack?.split("\n")[1]?.trim() ?? "react",
609
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
610
+ ...error.stack ? { stack: error.stack } : {}
611
+ });
612
+ }
613
+ render() {
614
+ if (this.state.hasError) {
615
+ return this.props.fallback ?? null;
616
+ }
617
+ return this.props.children;
618
+ }
619
+ };
620
+ function WebMcpErrorBoundary({
621
+ children,
622
+ fallback,
623
+ source
624
+ }) {
625
+ const { errors, timeline } = useWebMcpTroubleshootingContext();
626
+ return /* @__PURE__ */ jsx3(
627
+ Boundary,
628
+ {
629
+ errors,
630
+ timeline,
631
+ fallback,
632
+ ...source ? { source } : {},
633
+ children
634
+ }
635
+ );
636
+ }
637
+
638
+ // src/useTanStackQueryWebMcpTools.ts
639
+ import { useMemo as useMemo3 } from "react";
640
+ import { useWebMcpTools } from "@tooluminati/react";
641
+ import {
642
+ createQueryCacheSummaryTool
643
+ } from "@tooluminati/state";
644
+ function useTanStackQueryWebMcpTools(queryClient, options) {
645
+ const {
646
+ allowKeys,
647
+ includeDataShape,
648
+ includeData,
649
+ name
650
+ } = options;
651
+ const tool = useMemo3(() => {
652
+ return createQueryCacheSummaryTool({
653
+ queryClient,
654
+ allowKeys,
655
+ ...includeDataShape !== void 0 ? { includeDataShape } : {},
656
+ ...includeData !== void 0 ? { includeData } : {},
657
+ ...name ? { name } : {}
658
+ });
659
+ }, [queryClient, allowKeys, includeDataShape, includeData, name]);
660
+ useWebMcpTools([tool], [tool], { source: "diagnostic" });
661
+ }
662
+
663
+ // src/useFormSubmitBlockers.ts
664
+ import { useMemo as useMemo4 } from "react";
665
+ import { useWebMcpTool } from "@tooluminati/react";
666
+ import { createActionAvailabilityTool as createActionAvailabilityTool2 } from "@tooluminati/diagnostics";
667
+ function createFormSubmitBlockersProvider(options) {
668
+ return {
669
+ getActionAvailability(actionId) {
670
+ if (actionId !== options.actionId) {
671
+ return void 0;
672
+ }
673
+ const summary = options.getFormSummary();
674
+ const reasons = [
675
+ ...summary.errors.map((e) => `${e.path}: ${e.message}`),
676
+ ...options.getExtraReasons?.() ?? []
677
+ ];
678
+ if (summary.submitting) {
679
+ reasons.push("Form is submitting.");
680
+ }
681
+ return {
682
+ actionId,
683
+ label: options.label,
684
+ available: reasons.length === 0,
685
+ reasons
686
+ };
687
+ },
688
+ listActions() {
689
+ const action = createFormSubmitBlockersProvider(
690
+ options
691
+ ).getActionAvailability(options.actionId);
692
+ return action ? [action] : [];
693
+ }
694
+ };
695
+ }
696
+ function useFormSubmitBlockers(options) {
697
+ const provider = useMemo4(
698
+ () => createFormSubmitBlockersProvider(options),
699
+ [options]
700
+ );
701
+ useWebMcpTool(createActionAvailabilityTool2(provider), [provider]);
702
+ return provider;
703
+ }
704
+
705
+ // src/declarative-form.tsx
706
+ import { jsx as jsx4 } from "react/jsx-runtime";
707
+ function WebMcpForm({
708
+ toolName,
709
+ toolDescription,
710
+ toolAutoSubmit,
711
+ children,
712
+ ...props
713
+ }) {
714
+ return /* @__PURE__ */ jsx4(
715
+ "form",
716
+ {
717
+ ...props,
718
+ toolname: toolName,
719
+ tooldescription: toolDescription,
720
+ ...toolAutoSubmit ? { toolautosubmit: "" } : {},
721
+ children
722
+ }
723
+ );
724
+ }
725
+ function WebMcpInput(props) {
726
+ const { toolParamDescription, ...rest } = props;
727
+ return /* @__PURE__ */ jsx4(
728
+ "input",
729
+ {
730
+ ...rest,
731
+ ...toolParamDescription ? { toolparamdescription: toolParamDescription } : {}
732
+ }
733
+ );
734
+ }
735
+ function WebMcpSelect(props) {
736
+ const { toolParamDescription, ...rest } = props;
737
+ return /* @__PURE__ */ jsx4(
738
+ "select",
739
+ {
740
+ ...rest,
741
+ ...toolParamDescription ? { toolparamdescription: toolParamDescription } : {}
742
+ }
743
+ );
744
+ }
745
+ function WebMcpTextarea(props) {
746
+ const { toolParamDescription, ...rest } = props;
747
+ return /* @__PURE__ */ jsx4(
748
+ "textarea",
749
+ {
750
+ ...rest,
751
+ ...toolParamDescription ? { toolparamdescription: toolParamDescription } : {}
752
+ }
753
+ );
754
+ }
755
+ function useAgentInvokedSubmit(handler) {
756
+ return (event) => {
757
+ const submitEvent = event.nativeEvent;
758
+ if (submitEvent.agentInvoked) {
759
+ handler(event);
760
+ }
761
+ };
762
+ }
763
+ function useDeclarativeFormToolEvents(_options = {}) {
764
+ }
765
+
766
+ // src/useTroubleshootingPanel.ts
767
+ import { useEffect as useEffect3, useState as useState2 } from "react";
768
+ import {
769
+ serializeTroubleshootingDiagnostics as serializeTroubleshootingDiagnostics2
770
+ } from "@tooluminati/diagnostics";
771
+ function useTroubleshootingPanel() {
772
+ const { viewModel } = useWebMcpTroubleshootingContext();
773
+ const [snapshot, setSnapshot] = useState2(
774
+ () => viewModel.refresh()
775
+ );
776
+ useEffect3(() => {
777
+ const refresh = () => setSnapshot(viewModel.refresh());
778
+ refresh();
779
+ return viewModel.subscribe(refresh);
780
+ }, [viewModel]);
781
+ return {
782
+ snapshot,
783
+ panelState: snapshot.panelState,
784
+ refresh: () => setSnapshot(viewModel.refresh()),
785
+ copyDiagnostics: () => serializeTroubleshootingDiagnostics2(snapshot)
786
+ };
787
+ }
788
+ function useTroubleshootingPanelVisibility() {
789
+ const { visibility, isPanelEnabled } = useWebMcpTroubleshootingContext();
790
+ const [, bump] = useState2(0);
791
+ useEffect3(() => visibility.subscribe(() => bump((n) => n + 1)), [visibility]);
792
+ return {
793
+ visibility,
794
+ isPanelEnabled,
795
+ visible: visibility.visible,
796
+ collapsed: visibility.collapsed
797
+ };
798
+ }
799
+ export {
800
+ WebMcpErrorBoundary,
801
+ WebMcpForm,
802
+ WebMcpInput,
803
+ WebMcpSelect,
804
+ WebMcpTextarea,
805
+ WebMcpTroubleshootingContext,
806
+ WebMcpTroubleshootingPanel,
807
+ WebMcpTroubleshootingProvider,
808
+ createFormSubmitBlockersProvider,
809
+ getPanelVisibilityController,
810
+ hideWebMcpTroubleshootingPanel,
811
+ resetPanelVisibilityController,
812
+ showWebMcpTroubleshootingPanel,
813
+ toggleWebMcpTroubleshootingPanel,
814
+ useAgentInvokedSubmit,
815
+ useDeclarativeFormToolEvents,
816
+ useFormSubmitBlockers,
817
+ useTanStackQueryWebMcpTools,
818
+ useTroubleshootingPanel,
819
+ useTroubleshootingPanelVisibility,
820
+ useWebMcpTroubleshootingContext,
821
+ wirePanelVisibilityController
822
+ };