open-mcp-app 0.0.9 → 0.0.10

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.
@@ -418,26 +418,17 @@ interface HostProviderProps {
418
418
  onThemeChange?: (theme: "light" | "dark") => void;
419
419
  /** Called when host requests teardown (MCP Apps only) */
420
420
  onTeardown?: () => Promise<void> | void;
421
+ /**
422
+ * Capture browser `console.*` calls and `window.onerror`/`unhandledrejection`
423
+ * events, routing them through the SDK's `log()` as `notifications/message`.
424
+ *
425
+ * Filters out `console.debug` by default (MCP transport noise).
426
+ * Batches events and flushes every 2 seconds or on page unload.
427
+ *
428
+ * @default false
429
+ */
430
+ captureConsole?: boolean;
421
431
  }
422
- /**
423
- * Provides the host client to child components.
424
- *
425
- * Creates a single host client instance that is shared across all children.
426
- * The client connects on mount and disconnects on unmount.
427
- *
428
- * @example
429
- * ```tsx
430
- * import { HostProvider } from 'open-mcp-app/react';
431
- *
432
- * function App() {
433
- * return (
434
- * <HostProvider name="my-app" version="1.0.0">
435
- * <MyWidget />
436
- * </HostProvider>
437
- * );
438
- * }
439
- * ```
440
- */
441
- declare function HostProvider({ name, version, children, onToolInput, onThemeChange, onTeardown, }: HostProviderProps): react_jsx_runtime.JSX.Element;
432
+ declare function HostProvider({ name, version, children, onToolInput, onThemeChange, onTeardown, captureConsole, }: HostProviderProps): react_jsx_runtime.JSX.Element;
442
433
 
443
434
  export { ContentBlock, CreatureIcon, type CreatureIconProps, DisplayMode, Environment, ExpHostApi, HostContext, HostProvider, type HostProviderProps, type Logger, type ToolCallFunction, type ToolCallState, type ToolCallStatus, type ToolCallTuple, ToolResult, type UseHostConfig, type UseHostReturn, type UseToolResultReturn, type UseViewsReturn, type UseWebSocketConfig, type UseWebSocketReturn, type Views, WebSocketStatus, WidgetState, useHost, useToolResult, useViews, useWebSocket };
@@ -10731,13 +10731,83 @@ var HostContext = createContext(null);
10731
10731
  function useHostClientOptional() {
10732
10732
  return useContext(HostContext);
10733
10733
  }
10734
+ var CONSOLE_LEVEL_MAP = {
10735
+ log: "info",
10736
+ info: "info",
10737
+ warn: "warning",
10738
+ error: "error"
10739
+ };
10740
+ var FLUSH_INTERVAL_MS = 2e3;
10741
+ var MAX_BUFFER = 50;
10742
+ function setupConsoleCapture(client) {
10743
+ const originals = {};
10744
+ let buffer = [];
10745
+ let destroyed = false;
10746
+ const flush = () => {
10747
+ if (buffer.length === 0 || !client.getState().isReady) return;
10748
+ const batch = buffer;
10749
+ buffer = [];
10750
+ for (const entry of batch) {
10751
+ try {
10752
+ client.log(entry.level, entry.message);
10753
+ } catch {
10754
+ }
10755
+ }
10756
+ };
10757
+ const enqueue = (level, message) => {
10758
+ if (destroyed) return;
10759
+ buffer.push({ level, message });
10760
+ if (buffer.length >= MAX_BUFFER) flush();
10761
+ };
10762
+ if (typeof console !== "undefined") {
10763
+ for (const method of Object.keys(CONSOLE_LEVEL_MAP)) {
10764
+ const original = console[method];
10765
+ if (typeof original !== "function") continue;
10766
+ originals[method] = original;
10767
+ console[method] = (...args) => {
10768
+ original.call(console, ...args);
10769
+ const level = CONSOLE_LEVEL_MAP[method] ?? "info";
10770
+ const message = args.map((a2) => typeof a2 === "string" ? a2 : JSON.stringify(a2)).join(" ");
10771
+ enqueue(level, message);
10772
+ };
10773
+ }
10774
+ }
10775
+ let onError = null;
10776
+ let onRejection = null;
10777
+ if (typeof window !== "undefined") {
10778
+ onError = (event) => {
10779
+ enqueue("error", event.message || "Unknown error");
10780
+ };
10781
+ onRejection = (event) => {
10782
+ const reason = event.reason;
10783
+ enqueue("error", reason instanceof Error ? reason.message : String(reason));
10784
+ };
10785
+ window.addEventListener("error", onError);
10786
+ window.addEventListener("unhandledrejection", onRejection);
10787
+ }
10788
+ const timer = setInterval(flush, FLUSH_INTERVAL_MS);
10789
+ return () => {
10790
+ if (destroyed) return;
10791
+ destroyed = true;
10792
+ clearInterval(timer);
10793
+ flush();
10794
+ for (const [method, original] of Object.entries(originals)) {
10795
+ if (original) console[method] = original;
10796
+ }
10797
+ if (typeof window !== "undefined") {
10798
+ if (onError) window.removeEventListener("error", onError);
10799
+ if (onRejection) window.removeEventListener("unhandledrejection", onRejection);
10800
+ }
10801
+ };
10802
+ }
10734
10803
  function HostProvider({
10735
10804
  name,
10736
10805
  version,
10737
10806
  children,
10738
10807
  onToolInput,
10739
10808
  onThemeChange,
10740
- onTeardown
10809
+ onTeardown,
10810
+ captureConsole
10741
10811
  }) {
10742
10812
  const clientRef = useRef(null);
10743
10813
  if (!clientRef.current) {
@@ -10767,6 +10837,10 @@ function HostProvider({
10767
10837
  client.disconnect();
10768
10838
  };
10769
10839
  }, [client]);
10840
+ useEffect(() => {
10841
+ if (!captureConsole) return;
10842
+ return setupConsoleCapture(client);
10843
+ }, [client, captureConsole]);
10770
10844
  return /* @__PURE__ */ jsx(HostContext.Provider, { value: client, children });
10771
10845
  }
10772
10846