@assistant-ui/react 0.15.17 → 0.15.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -2
- package/dist/mcp-apps/McpAppRenderer.d.ts +30 -8
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +91 -47
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/app-frame.d.ts.map +1 -1
- package/dist/mcp-apps/app-frame.js +41 -22
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/mcp-apps/bridge.js +2 -3
- package/dist/mcp-apps/bridge.js.map +1 -1
- package/dist/mcp-apps/index.d.ts +2 -2
- package/dist/primitives/composer/ComposerInputPluginContext.d.ts +1 -2
- package/dist/primitives/composer/ComposerInputPluginContext.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.js +1 -6
- package/dist/primitives/composer/ComposerInputPluginContext.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +46 -15
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +40 -10
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js.map +1 -1
- package/dist/primitives/composer/trigger/matchesTriggerItemQuery.d.ts +6 -0
- package/dist/primitives/composer/trigger/matchesTriggerItemQuery.d.ts.map +1 -0
- package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js +9 -0
- package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js.map +1 -0
- package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.js +3 -5
- package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
- package/dist/primitives/messagePart/MessagePartText.d.ts +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +3 -3
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
- package/dist/sandbox-host/SandboxHost.js +14 -5
- package/dist/sandbox-host/SandboxHost.js.map +1 -1
- package/dist/unstable/useMentionAdapter.d.ts +9 -3
- package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
- package/dist/unstable/useMentionAdapter.js +50 -43
- package/dist/unstable/useMentionAdapter.js.map +1 -1
- package/dist/unstable/useModelContextSnapshot.d.ts +34 -0
- package/dist/unstable/useModelContextSnapshot.d.ts.map +1 -0
- package/dist/unstable/useModelContextSnapshot.js +61 -0
- package/dist/unstable/useModelContextSnapshot.js.map +1 -0
- package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
- package/dist/unstable/useSlashCommandAdapter.js +2 -8
- package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
- package/dist/unstable/webmcp/WebMcpRegistrationResource.d.ts +14 -0
- package/dist/unstable/webmcp/WebMcpRegistrationResource.d.ts.map +1 -0
- package/dist/unstable/webmcp/WebMcpRegistrationResource.js +85 -0
- package/dist/unstable/webmcp/WebMcpRegistrationResource.js.map +1 -0
- package/dist/unstable/webmcp/convertTools.d.ts +21 -0
- package/dist/unstable/webmcp/convertTools.d.ts.map +1 -0
- package/dist/unstable/webmcp/convertTools.js +110 -0
- package/dist/unstable/webmcp/convertTools.js.map +1 -0
- package/dist/unstable/webmcp/useWebMcpProvider.d.ts +21 -0
- package/dist/unstable/webmcp/useWebMcpProvider.d.ts.map +1 -0
- package/dist/unstable/webmcp/useWebMcpProvider.js +105 -0
- package/dist/unstable/webmcp/useWebMcpProvider.js.map +1 -0
- package/dist/unstable/webmcp/webmcp-host.d.ts +39 -0
- package/dist/unstable/webmcp/webmcp-host.d.ts.map +1 -0
- package/dist/unstable/webmcp/webmcp-host.js +29 -0
- package/dist/unstable/webmcp/webmcp-host.js.map +1 -0
- package/dist/utils/Primitive.d.ts +4 -4
- package/package.json +12 -12
- package/src/index.ts +13 -0
- package/src/mcp-apps/McpAppRenderer.test.tsx +253 -5
- package/src/mcp-apps/McpAppRenderer.tsx +147 -52
- package/src/mcp-apps/app-frame.test.tsx +248 -1
- package/src/mcp-apps/app-frame.tsx +51 -5
- package/src/mcp-apps/bridge.ts +7 -2
- package/src/mcp-apps/index.ts +5 -1
- package/src/primitives/composer/ComposerInputPluginContext.tsx +0 -10
- package/src/primitives/composer/trigger/TriggerPopoverAction.tsx +4 -2
- package/src/primitives/composer/trigger/TriggerPopoverBehavior.test.tsx +109 -0
- package/src/primitives/composer/trigger/TriggerPopoverDirective.tsx +4 -2
- package/src/primitives/composer/trigger/matchesTriggerItemQuery.test.ts +52 -0
- package/src/primitives/composer/trigger/matchesTriggerItemQuery.ts +13 -0
- package/src/primitives/composer/trigger/triggerNavigationResource.ts +3 -10
- package/src/primitives/thread/useThreadViewportAutoScroll.ts +7 -6
- package/src/sandbox-host/SandboxHost.test.tsx +120 -2
- package/src/sandbox-host/SandboxHost.tsx +26 -6
- package/src/unstable/useComposerInputHistory.test.tsx +2 -1
- package/src/unstable/useMentionAdapter.test.tsx +337 -0
- package/src/unstable/useMentionAdapter.ts +94 -57
- package/src/unstable/useModelContextSnapshot.test.tsx +132 -0
- package/src/unstable/useModelContextSnapshot.ts +67 -0
- package/src/unstable/useSlashCommandAdapter.ts +2 -9
- package/src/unstable/webmcp/WebMcpRegistrationResource.ts +92 -0
- package/src/unstable/webmcp/__tests__/webmcp.fake.tsx +168 -0
- package/src/unstable/webmcp/convertTools.test.ts +393 -0
- package/src/unstable/webmcp/convertTools.ts +180 -0
- package/src/unstable/webmcp/useWebMcpProvider.test.tsx +466 -0
- package/src/unstable/webmcp/useWebMcpProvider.ts +150 -0
- package/src/unstable/webmcp/webmcp-host.test.ts +142 -0
- package/src/unstable/webmcp/webmcp-host.ts +83 -0
- package/dist/utils/invokeCallbackSafely.d.ts +0 -5
- package/dist/utils/invokeCallbackSafely.d.ts.map +0 -1
- package/dist/utils/invokeCallbackSafely.js +0 -15
- package/dist/utils/invokeCallbackSafely.js.map +0 -1
- package/dist/utils/useToolArgsFieldStatus.d.ts +0 -19
- package/dist/utils/useToolArgsFieldStatus.d.ts.map +0 -1
- package/dist/utils/useToolArgsFieldStatus.js +0 -23
- package/dist/utils/useToolArgsFieldStatus.js.map +0 -1
- package/src/utils/invokeCallbackSafely.ts +0 -11
- package/src/utils/useToolArgsFieldStatus.ts +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-frame.js","names":["c","_c","MutableRefObject","useEffect","useLayoutEffect","useRef","McpAppBridge","createMcpAppBridge","SandboxHost","SandboxBridge","SandboxHostApi","SandboxHostFrame","McpAppBridgeHandlers","McpAppFrameProps","McpAppHostContext","DEFAULT_PRODUCT","INIT_TIMEOUT_MS","DEFAULT_MAX_HEIGHT","useBridgeNotify","value","bridgeRef","widgetReadyRef","pendingRef","lastSentRef","notify","$","t0","current","undefined","t1","LiveSnapshot","handlers","hostInfo","hostContext","input","output","buildLiveHandlers","initial","liveRef","live","has","key","K","out","Object","defineProperty","get","allowedTools","enumerable","configurable","liveCall","NonNullable","p","fn","Error","callTool","readResource","listResources","openLink","sendMessage","updateModelContext","requestDisplayMode","onSizeChange","onInitialized","onRequestTeardown","onLog","onError","e","McpAppFrame","app","resource","sandbox","maxHeight","lastSentInputRef","lastSentOutputRef","lastSentHostContextRef","pendingInputRef","pendingOutputRef","pendingHostContextRef","t2","t3","t4","t5","Symbol","for","frame","host","initTimeoutId","flushPending","b","notifyToolInput","notifyToolResult","notifyHostContextChanged","liveHandlers","liveOnInitialized","wrappedHandlers","clearTimeout","height","setHeight","setTimeout","bridge","onMessage","dispose","createBridge","_temp","_temp2","_temp3","t6","html","t7","serverId","uri","t8","product","t9","t10","err","t11","meta","prefersBorder","t12","resourceUri","t13","b_2","v_1","v","b_1","v_0","b_0"],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type MutableRefObject,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n if (value === undefined) return;\n if (lastSentRef.current === value) return;\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify is assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n if (has(\"allowedTools\")) {\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n }\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => live()?.onSizeChange?.(p);\n out.onInitialized = () => live()?.onInitialized?.();\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n });\n useLayoutEffect(() => {\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n }, [handlers, hostInfo, hostContext, input, output]);\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const liveHandlers = buildLiveHandlers(current.handlers, liveRef);\n const liveOnInitialized = liveHandlers.onInitialized;\n const wrappedHandlers: McpAppBridgeHandlers = {\n ...liveHandlers,\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n liveOnInitialized?.();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n liveHandlers.onSizeChange?.(p);\n },\n };\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response; subsequent\n // changes flow through useBridgeNotify's pending path.\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={\n app.serverId ? `${app.serverId} ${resource.uri}` : resource.uri\n }\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-frame.js","names":["c","_c","MutableRefObject","useEffect","useLayoutEffect","useRef","McpAppBridge","createMcpAppBridge","SandboxHost","SandboxBridge","SandboxHostApi","SandboxHostFrame","McpAppBridgeHandlers","McpAppFrameProps","McpAppHostContext","isRecord","DEFAULT_PRODUCT","INIT_TIMEOUT_MS","DEFAULT_MAX_HEIGHT","isPlainObject","value","Record","prototype","Object","getPrototypeOf","isSameHostContext","a","b","depth","is","Array","isArray","length","every","item","index","aKeys","keys","key","hasOwn","useBridgeNotify","bridgeRef","widgetReadyRef","pendingRef","lastSentRef","notify","t0","$","isEqual","undefined","t1","current","t2","LiveSnapshot","handlers","hostInfo","hostContext","input","output","buildLiveHandlers","initial","liveRef","live","has","K","out","defineProperty","get","allowedTools","enumerable","configurable","liveCall","NonNullable","p","fn","Error","callTool","readResource","listResources","openLink","sendMessage","updateModelContext","requestDisplayMode","onSizeChange","onInitialized","onRequestTeardown","onLog","onError","e","McpAppFrame","app","resource","sandbox","maxHeight","lastSentInputRef","lastSentOutputRef","lastSentHostContextRef","pendingInputRef","pendingOutputRef","pendingHostContextRef","t3","t4","t5","Symbol","for","frame","host","initTimeoutId","flushPending","notifyToolInput","notifyToolResult","notifyHostContextChanged","liveHandlers","liveOnInitialized","wrappedHandlers","clearTimeout","height","setHeight","setTimeout","bridge","onMessage","dispose","createBridge","_temp","_temp2","_temp3","t6","html","t7","serverId","uri","t8","product","t9","t10","err","t11","meta","prefersBorder","t12","resourceUri","t13","b_2","v_1","v","b_1","v_0","b_0"],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type MutableRefObject,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\n// Only a plain object can be compared by its own keys. Structured clone carries\n// a Date, Map, or class instance to the widget intact, and those expose no\n// enumerable keys, so walking them would report two different values as equal.\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!isRecord(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || prototype === Object.prototype;\n};\n\n// Hosts commonly rebuild an equal context object on every render, and the\n// widget cannot tell a repeated notification apart from a real change. The\n// open index signature on McpAppHostContext admits values JSON rejects (an\n// undefined property value is enough), so leaves the walk cannot compare fall\n// back to identity rather than failing the whole comparison.\nconst isSameHostContext = (a: unknown, b: unknown, depth = 0): boolean => {\n if (Object.is(a, b)) return true;\n if (depth > 100) return false;\n if (Array.isArray(a) || Array.isArray(b)) {\n return (\n Array.isArray(a) &&\n Array.isArray(b) &&\n a.length === b.length &&\n a.every((item, index) => isSameHostContext(item, b[index], depth + 1))\n );\n }\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const aKeys = Object.keys(a);\n return (\n aKeys.length === Object.keys(b).length &&\n aKeys.every(\n (key) =>\n Object.hasOwn(b, key) && isSameHostContext(a[key], b[key], depth + 1),\n )\n );\n};\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n isEqual: (sent: T | undefined, next: T) => boolean = Object.is,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n // Nothing to deliver, either because there is no value or because the\n // widget already holds it; a queued value here is superseded and would\n // otherwise flush after initialization as a stale update.\n if (value === undefined || isEqual(lastSentRef.current, value)) {\n pendingRef.current = undefined;\n return;\n }\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify and isEqual are assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n if (has(\"allowedTools\")) {\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n }\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => live()?.onSizeChange?.(p);\n out.onInitialized = () => live()?.onInitialized?.();\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n });\n useLayoutEffect(() => {\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n }, [handlers, hostInfo, hostContext, input, output]);\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const liveHandlers = buildLiveHandlers(current.handlers, liveRef);\n const liveOnInitialized = liveHandlers.onInitialized;\n const wrappedHandlers: McpAppBridgeHandlers = {\n ...liveHandlers,\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n liveOnInitialized?.();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n liveHandlers.onSizeChange?.(p);\n },\n };\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response, where the\n // bridge defaults it to {}; recording that same normalized value keeps the\n // first later change from repeating what the widget already holds.\n lastSentHostContextRef.current = current.hostContext ?? {};\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n isSameHostContext,\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={\n app.serverId ? `${app.serverId} ${resource.uri}` : resource.uri\n }\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":"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"}
|
package/dist/mcp-apps/bridge.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { invokeCallbackSafely } from "../utils/invokeCallbackSafely.js";
|
|
2
1
|
import "./types.js";
|
|
3
|
-
import { isRecord } from "@assistant-ui/core/internal";
|
|
2
|
+
import { invokeUserCallback, isRecord } from "@assistant-ui/core/internal";
|
|
4
3
|
//#region src/mcp-apps/bridge.ts
|
|
5
4
|
const VALID_DISPLAY_MODES = [
|
|
6
5
|
"inline",
|
|
@@ -60,7 +59,7 @@ function createMcpAppBridge(opts) {
|
|
|
60
59
|
} });
|
|
61
60
|
};
|
|
62
61
|
const reportError = (error) => {
|
|
63
|
-
|
|
62
|
+
invokeUserCallback("assistant-ui", "MCP App onError", handlers.onError?.bind(handlers), error);
|
|
64
63
|
};
|
|
65
64
|
const handleRequest = async (req) => {
|
|
66
65
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","names":["SandboxHostFrame","invokeCallbackSafely","MCP_APP_PROTOCOL_VERSION","McpAppBridgeHandlers","McpAppDisplayMode","McpAppHostContext","McpAppHostInfo","McpAppJsonRpcMessage","McpAppJsonRpcNotification","McpAppJsonRpcRequest","McpAppJsonRpcResponse","isRecord","VALID_DISPLAY_MODES","const","McpAppBridgeFrame","CreateMcpAppBridgeOptions","frame","handlers","hostInfo","hostContext","McpAppBridge","onMessage","event","MessageEvent","dispose","notifyToolInput","input","notifyToolResult","result","notifyHostContextChanged","DEFAULT_HOST_INFO","name","version","METHOD_ALIASES","Record","normalizeMethod","method","JSONRPC_ERROR","parseError","invalidRequest","methodNotFound","invalidParams","internalError","isJsonRpcMessage","value","v","jsonrpc","isRequest","msg","isNotification","createMcpAppBridge","opts","post","sendMessage","respond","id","payload","error","code","message","data","res","errorResponse","undefined","reportError","Error","onError","handleRequest","req","params","requestedProtocolVersion","protocolVersion","host","capabilities","tools","callTool","resources","readResource","listResources","ui","openLink","requestDisplayMode","updateModelContext","hostCapabilities","openLinks","serverTools","serverResources","text","onLog","logging","callParams","arguments","allowedTools","includes","callArgs","Array","isArray","readParams","uri","linkParams","url","linkProtocol","URL","protocol","modeParams","mode","err","String","handleNotification","note","onInitialized","p","width","height","onSizeChange","onRequestTeardown","content","type","ctx"],"sources":["../../src/mcp-apps/bridge.ts"],"sourcesContent":["import type { SandboxHostFrame } from \"../sandbox-host/SandboxHost\";\nimport { invokeCallbackSafely } from \"../utils/invokeCallbackSafely\";\nimport {\n MCP_APP_PROTOCOL_VERSION,\n type McpAppBridgeHandlers,\n type McpAppDisplayMode,\n type McpAppHostContext,\n type McpAppHostInfo,\n type McpAppJsonRpcMessage,\n type McpAppJsonRpcNotification,\n type McpAppJsonRpcRequest,\n type McpAppJsonRpcResponse,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst VALID_DISPLAY_MODES = [\n \"inline\",\n \"fullscreen\",\n \"pip\",\n] as const satisfies readonly McpAppDisplayMode[];\n\nexport type McpAppBridgeFrame = SandboxHostFrame;\n\nexport type CreateMcpAppBridgeOptions = {\n frame: McpAppBridgeFrame;\n handlers?: McpAppBridgeHandlers | undefined;\n hostInfo?: McpAppHostInfo | undefined;\n hostContext?: McpAppHostContext | undefined;\n};\n\nexport type McpAppBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n notifyToolInput: (input: unknown) => void;\n notifyToolResult: (result: unknown) => void;\n notifyHostContextChanged: (hostContext: McpAppHostContext) => void;\n};\n\nconst DEFAULT_HOST_INFO: McpAppHostInfo = {\n name: \"assistant-ui\",\n version: \"0.1\",\n};\n\n// Accept both the legacy method names and the MCP-UI 2026-01-26 names that\n// `ui/*` capable widgets (e.g. xmcp's host-bridge) emit. Normalize on input\n// so downstream switch statements only need to know the legacy names.\nconst METHOD_ALIASES: Record<string, string> = {\n \"ui/notifications/initialized\": \"notifications/initialized\",\n \"ui/notifications/size-changed\": \"notifications/size_changed\",\n \"ui/request-display-mode\": \"requestDisplayMode\",\n \"ui/open-link\": \"openLink\",\n \"ui/update-model-context\": \"updateModelContext\",\n \"ui/message\": \"sendMessage\",\n \"notifications/message\": \"notifications/log\",\n};\n\nconst normalizeMethod = (method: string): string =>\n METHOD_ALIASES[method] ?? method;\n\nconst JSONRPC_ERROR = {\n parseError: -32700,\n invalidRequest: -32600,\n methodNotFound: -32601,\n invalidParams: -32602,\n internalError: -32603,\n} as const;\n\nfunction isJsonRpcMessage(value: unknown): value is McpAppJsonRpcMessage {\n if (!value || typeof value !== \"object\") return false;\n const v = value as Record<string, unknown>;\n return v.jsonrpc === \"2.0\" && typeof v.method === \"string\";\n}\n\nfunction isRequest(msg: McpAppJsonRpcMessage): msg is McpAppJsonRpcRequest {\n return \"id\" in msg;\n}\n\nfunction isNotification(\n msg: McpAppJsonRpcMessage,\n): msg is McpAppJsonRpcNotification {\n return !(\"id\" in msg);\n}\n\nexport function createMcpAppBridge(\n opts: CreateMcpAppBridgeOptions,\n): McpAppBridge {\n const {\n frame,\n handlers = {},\n hostInfo = DEFAULT_HOST_INFO,\n hostContext = {},\n } = opts;\n\n const post = (msg: McpAppJsonRpcMessage) => {\n frame.sendMessage(msg);\n };\n\n const respond = (\n id: McpAppJsonRpcRequest[\"id\"],\n payload:\n | { result: unknown }\n | { error: { code: number; message: string; data?: unknown } },\n ) => {\n const res: McpAppJsonRpcResponse = {\n jsonrpc: \"2.0\",\n id,\n ...payload,\n };\n post(res);\n };\n\n const errorResponse = (\n id: McpAppJsonRpcRequest[\"id\"],\n code: number,\n message: string,\n data?: unknown,\n ) => {\n respond(id, {\n error: {\n code,\n message,\n ...(data !== undefined ? { data } : {}),\n },\n });\n };\n\n const reportError = (error: Error) => {\n invokeCallbackSafely(() => handlers.onError?.(error), \"MCP App onError\");\n };\n\n const handleRequest = async (req: McpAppJsonRpcRequest) => {\n try {\n const params = req.params;\n\n switch (normalizeMethod(req.method)) {\n case \"ui/initialize\": {\n const requestedProtocolVersion =\n isRecord(params) && typeof params.protocolVersion === \"string\"\n ? params.protocolVersion\n : MCP_APP_PROTOCOL_VERSION;\n respond(req.id, {\n result: {\n protocolVersion: requestedProtocolVersion,\n host: hostInfo,\n hostInfo,\n hostContext,\n capabilities: {\n tools: handlers.callTool ? {} : undefined,\n resources:\n handlers.readResource || handlers.listResources\n ? {}\n : undefined,\n ui: {\n sendMessage: !!handlers.sendMessage,\n openLink: !!handlers.openLink,\n requestDisplayMode: !!handlers.requestDisplayMode,\n updateModelContext: !!handlers.updateModelContext,\n },\n },\n hostCapabilities: {\n ...(handlers.openLink ? { openLinks: {} } : {}),\n ...(handlers.callTool ? { serverTools: {} } : {}),\n ...(handlers.readResource || handlers.listResources\n ? { serverResources: {} }\n : {}),\n ...(handlers.updateModelContext\n ? { updateModelContext: { text: {} } }\n : {}),\n ...(handlers.sendMessage ? { message: { text: {} } } : {}),\n ...(handlers.onLog ? { logging: {} } : {}),\n },\n },\n });\n return;\n }\n\n case \"tools/call\": {\n if (!handlers.callTool) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"tools/call is not supported by this host\",\n );\n return;\n }\n const callParams = (params ?? {}) as {\n name?: unknown;\n arguments?: unknown;\n };\n if (typeof callParams.name !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call requires a string 'name'\",\n );\n return;\n }\n if (\n handlers.allowedTools &&\n !handlers.allowedTools.includes(callParams.name)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n `tool '${callParams.name}' is not allowed for this app`,\n );\n return;\n }\n let callArgs: Record<string, unknown> | undefined;\n if (callParams.arguments !== undefined) {\n if (\n callParams.arguments === null ||\n typeof callParams.arguments !== \"object\" ||\n Array.isArray(callParams.arguments)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call 'arguments' must be an object\",\n );\n return;\n }\n callArgs = callParams.arguments as Record<string, unknown>;\n }\n const result = await handlers.callTool({\n name: callParams.name,\n ...(callArgs !== undefined ? { arguments: callArgs } : {}),\n });\n respond(req.id, { result });\n return;\n }\n\n case \"resources/read\": {\n if (!handlers.readResource) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/read is not supported by this host\",\n );\n return;\n }\n const readParams = (params ?? {}) as { uri?: unknown };\n if (typeof readParams.uri !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"resources/read requires a string 'uri'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.readResource({ uri: readParams.uri }),\n });\n return;\n }\n\n case \"resources/list\": {\n if (!handlers.listResources) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/list is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.listResources(params)) ?? null,\n });\n return;\n }\n\n case \"openLink\": {\n if (!handlers.openLink) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"openLink is not supported by this host\",\n );\n return;\n }\n const linkParams = (params ?? {}) as { url?: unknown };\n if (typeof linkParams.url !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a string 'url'\",\n );\n return;\n }\n let linkProtocol: string;\n try {\n linkProtocol = new URL(linkParams.url).protocol;\n } catch {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a valid URL\",\n );\n return;\n }\n if (linkProtocol !== \"https:\" && linkProtocol !== \"http:\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink only accepts http(s) URLs\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.openLink({ url: linkParams.url }),\n });\n return;\n }\n\n case \"sendMessage\": {\n if (!handlers.sendMessage) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"sendMessage is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.sendMessage(params)) ?? null,\n });\n return;\n }\n\n case \"updateModelContext\": {\n if (!handlers.updateModelContext) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"updateModelContext is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.updateModelContext(params)) ?? null,\n });\n return;\n }\n\n case \"requestDisplayMode\": {\n if (!handlers.requestDisplayMode) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"requestDisplayMode is not supported by this host\",\n );\n return;\n }\n const modeParams = (params ?? {}) as { mode?: unknown };\n if (\n typeof modeParams.mode !== \"string\" ||\n !VALID_DISPLAY_MODES.includes(modeParams.mode as McpAppDisplayMode)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"requestDisplayMode requires a valid 'mode'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.requestDisplayMode({\n mode: modeParams.mode as McpAppDisplayMode,\n }),\n });\n return;\n }\n\n default: {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n `Unknown method: ${req.method}`,\n );\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n errorResponse(req.id, JSONRPC_ERROR.internalError, error.message);\n }\n };\n\n const handleNotification = (note: McpAppJsonRpcNotification) => {\n try {\n switch (normalizeMethod(note.method)) {\n case \"notifications/initialized\": {\n handlers.onInitialized?.();\n return;\n }\n case \"notifications/size_changed\": {\n const p = (note.params ?? {}) as { width?: number; height?: number };\n handlers.onSizeChange?.({\n ...(typeof p.width === \"number\" ? { width: p.width } : {}),\n ...(typeof p.height === \"number\" ? { height: p.height } : {}),\n });\n return;\n }\n case \"notifications/log\": {\n handlers.onLog?.(note.params);\n return;\n }\n case \"notifications/request_teardown\": {\n handlers.onRequestTeardown?.(note.params);\n return;\n }\n case \"notifications/error\": {\n const p = (note.params ?? {}) as { message?: string };\n reportError(\n new Error(\n typeof p.message === \"string\" ? p.message : \"Widget error\",\n ),\n );\n return;\n }\n default:\n return;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n }\n };\n\n // The host applies the cross-origin guard before delegating; this only\n // validates the JSON-RPC envelope.\n const onMessage = (event: MessageEvent) => {\n if (!isJsonRpcMessage(event.data)) return;\n\n const msg = event.data;\n if (isRequest(msg)) {\n void handleRequest(msg);\n } else if (isNotification(msg)) {\n handleNotification(msg);\n }\n };\n\n return {\n onMessage,\n dispose: () => {},\n notifyToolInput: (input: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/input\",\n params: { input },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-input\",\n params: isRecord(input) ? { arguments: input } : {},\n });\n },\n notifyToolResult: (result: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/result\",\n params: { result },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-result\",\n params: isRecord(result)\n ? result\n : { content: [{ type: \"text\", text: String(result) }] },\n });\n },\n notifyHostContextChanged: (ctx: McpAppHostContext) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/host_context/changed\",\n params: ctx,\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/host-context-changed\",\n params: ctx,\n });\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bridge.js","names":["SandboxHostFrame","invokeUserCallback","MCP_APP_PROTOCOL_VERSION","McpAppBridgeHandlers","McpAppDisplayMode","McpAppHostContext","McpAppHostInfo","McpAppJsonRpcMessage","McpAppJsonRpcNotification","McpAppJsonRpcRequest","McpAppJsonRpcResponse","isRecord","VALID_DISPLAY_MODES","const","McpAppBridgeFrame","CreateMcpAppBridgeOptions","frame","handlers","hostInfo","hostContext","McpAppBridge","onMessage","event","MessageEvent","dispose","notifyToolInput","input","notifyToolResult","result","notifyHostContextChanged","DEFAULT_HOST_INFO","name","version","METHOD_ALIASES","Record","normalizeMethod","method","JSONRPC_ERROR","parseError","invalidRequest","methodNotFound","invalidParams","internalError","isJsonRpcMessage","value","v","jsonrpc","isRequest","msg","isNotification","createMcpAppBridge","opts","post","sendMessage","respond","id","payload","error","code","message","data","res","errorResponse","undefined","reportError","Error","onError","bind","handleRequest","req","params","requestedProtocolVersion","protocolVersion","host","capabilities","tools","callTool","resources","readResource","listResources","ui","openLink","requestDisplayMode","updateModelContext","hostCapabilities","openLinks","serverTools","serverResources","text","onLog","logging","callParams","arguments","allowedTools","includes","callArgs","Array","isArray","readParams","uri","linkParams","url","linkProtocol","URL","protocol","modeParams","mode","err","String","handleNotification","note","onInitialized","p","width","height","onSizeChange","onRequestTeardown","content","type","ctx"],"sources":["../../src/mcp-apps/bridge.ts"],"sourcesContent":["import type { SandboxHostFrame } from \"../sandbox-host/SandboxHost\";\nimport { invokeUserCallback } from \"@assistant-ui/core/internal\";\nimport {\n MCP_APP_PROTOCOL_VERSION,\n type McpAppBridgeHandlers,\n type McpAppDisplayMode,\n type McpAppHostContext,\n type McpAppHostInfo,\n type McpAppJsonRpcMessage,\n type McpAppJsonRpcNotification,\n type McpAppJsonRpcRequest,\n type McpAppJsonRpcResponse,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst VALID_DISPLAY_MODES = [\n \"inline\",\n \"fullscreen\",\n \"pip\",\n] as const satisfies readonly McpAppDisplayMode[];\n\nexport type McpAppBridgeFrame = SandboxHostFrame;\n\nexport type CreateMcpAppBridgeOptions = {\n frame: McpAppBridgeFrame;\n handlers?: McpAppBridgeHandlers | undefined;\n hostInfo?: McpAppHostInfo | undefined;\n hostContext?: McpAppHostContext | undefined;\n};\n\nexport type McpAppBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n notifyToolInput: (input: unknown) => void;\n notifyToolResult: (result: unknown) => void;\n notifyHostContextChanged: (hostContext: McpAppHostContext) => void;\n};\n\nconst DEFAULT_HOST_INFO: McpAppHostInfo = {\n name: \"assistant-ui\",\n version: \"0.1\",\n};\n\n// Accept both the legacy method names and the MCP-UI 2026-01-26 names that\n// `ui/*` capable widgets (e.g. xmcp's host-bridge) emit. Normalize on input\n// so downstream switch statements only need to know the legacy names.\nconst METHOD_ALIASES: Record<string, string> = {\n \"ui/notifications/initialized\": \"notifications/initialized\",\n \"ui/notifications/size-changed\": \"notifications/size_changed\",\n \"ui/request-display-mode\": \"requestDisplayMode\",\n \"ui/open-link\": \"openLink\",\n \"ui/update-model-context\": \"updateModelContext\",\n \"ui/message\": \"sendMessage\",\n \"notifications/message\": \"notifications/log\",\n};\n\nconst normalizeMethod = (method: string): string =>\n METHOD_ALIASES[method] ?? method;\n\nconst JSONRPC_ERROR = {\n parseError: -32700,\n invalidRequest: -32600,\n methodNotFound: -32601,\n invalidParams: -32602,\n internalError: -32603,\n} as const;\n\nfunction isJsonRpcMessage(value: unknown): value is McpAppJsonRpcMessage {\n if (!value || typeof value !== \"object\") return false;\n const v = value as Record<string, unknown>;\n return v.jsonrpc === \"2.0\" && typeof v.method === \"string\";\n}\n\nfunction isRequest(msg: McpAppJsonRpcMessage): msg is McpAppJsonRpcRequest {\n return \"id\" in msg;\n}\n\nfunction isNotification(\n msg: McpAppJsonRpcMessage,\n): msg is McpAppJsonRpcNotification {\n return !(\"id\" in msg);\n}\n\nexport function createMcpAppBridge(\n opts: CreateMcpAppBridgeOptions,\n): McpAppBridge {\n const {\n frame,\n handlers = {},\n hostInfo = DEFAULT_HOST_INFO,\n hostContext = {},\n } = opts;\n\n const post = (msg: McpAppJsonRpcMessage) => {\n frame.sendMessage(msg);\n };\n\n const respond = (\n id: McpAppJsonRpcRequest[\"id\"],\n payload:\n | { result: unknown }\n | { error: { code: number; message: string; data?: unknown } },\n ) => {\n const res: McpAppJsonRpcResponse = {\n jsonrpc: \"2.0\",\n id,\n ...payload,\n };\n post(res);\n };\n\n const errorResponse = (\n id: McpAppJsonRpcRequest[\"id\"],\n code: number,\n message: string,\n data?: unknown,\n ) => {\n respond(id, {\n error: {\n code,\n message,\n ...(data !== undefined ? { data } : {}),\n },\n });\n };\n\n const reportError = (error: Error) => {\n invokeUserCallback(\n \"assistant-ui\",\n \"MCP App onError\",\n handlers.onError?.bind(handlers),\n error,\n );\n };\n\n const handleRequest = async (req: McpAppJsonRpcRequest) => {\n try {\n const params = req.params;\n\n switch (normalizeMethod(req.method)) {\n case \"ui/initialize\": {\n const requestedProtocolVersion =\n isRecord(params) && typeof params.protocolVersion === \"string\"\n ? params.protocolVersion\n : MCP_APP_PROTOCOL_VERSION;\n respond(req.id, {\n result: {\n protocolVersion: requestedProtocolVersion,\n host: hostInfo,\n hostInfo,\n hostContext,\n capabilities: {\n tools: handlers.callTool ? {} : undefined,\n resources:\n handlers.readResource || handlers.listResources\n ? {}\n : undefined,\n ui: {\n sendMessage: !!handlers.sendMessage,\n openLink: !!handlers.openLink,\n requestDisplayMode: !!handlers.requestDisplayMode,\n updateModelContext: !!handlers.updateModelContext,\n },\n },\n hostCapabilities: {\n ...(handlers.openLink ? { openLinks: {} } : {}),\n ...(handlers.callTool ? { serverTools: {} } : {}),\n ...(handlers.readResource || handlers.listResources\n ? { serverResources: {} }\n : {}),\n ...(handlers.updateModelContext\n ? { updateModelContext: { text: {} } }\n : {}),\n ...(handlers.sendMessage ? { message: { text: {} } } : {}),\n ...(handlers.onLog ? { logging: {} } : {}),\n },\n },\n });\n return;\n }\n\n case \"tools/call\": {\n if (!handlers.callTool) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"tools/call is not supported by this host\",\n );\n return;\n }\n const callParams = (params ?? {}) as {\n name?: unknown;\n arguments?: unknown;\n };\n if (typeof callParams.name !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call requires a string 'name'\",\n );\n return;\n }\n if (\n handlers.allowedTools &&\n !handlers.allowedTools.includes(callParams.name)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n `tool '${callParams.name}' is not allowed for this app`,\n );\n return;\n }\n let callArgs: Record<string, unknown> | undefined;\n if (callParams.arguments !== undefined) {\n if (\n callParams.arguments === null ||\n typeof callParams.arguments !== \"object\" ||\n Array.isArray(callParams.arguments)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call 'arguments' must be an object\",\n );\n return;\n }\n callArgs = callParams.arguments as Record<string, unknown>;\n }\n const result = await handlers.callTool({\n name: callParams.name,\n ...(callArgs !== undefined ? { arguments: callArgs } : {}),\n });\n respond(req.id, { result });\n return;\n }\n\n case \"resources/read\": {\n if (!handlers.readResource) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/read is not supported by this host\",\n );\n return;\n }\n const readParams = (params ?? {}) as { uri?: unknown };\n if (typeof readParams.uri !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"resources/read requires a string 'uri'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.readResource({ uri: readParams.uri }),\n });\n return;\n }\n\n case \"resources/list\": {\n if (!handlers.listResources) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/list is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.listResources(params)) ?? null,\n });\n return;\n }\n\n case \"openLink\": {\n if (!handlers.openLink) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"openLink is not supported by this host\",\n );\n return;\n }\n const linkParams = (params ?? {}) as { url?: unknown };\n if (typeof linkParams.url !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a string 'url'\",\n );\n return;\n }\n let linkProtocol: string;\n try {\n linkProtocol = new URL(linkParams.url).protocol;\n } catch {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a valid URL\",\n );\n return;\n }\n if (linkProtocol !== \"https:\" && linkProtocol !== \"http:\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink only accepts http(s) URLs\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.openLink({ url: linkParams.url }),\n });\n return;\n }\n\n case \"sendMessage\": {\n if (!handlers.sendMessage) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"sendMessage is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.sendMessage(params)) ?? null,\n });\n return;\n }\n\n case \"updateModelContext\": {\n if (!handlers.updateModelContext) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"updateModelContext is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.updateModelContext(params)) ?? null,\n });\n return;\n }\n\n case \"requestDisplayMode\": {\n if (!handlers.requestDisplayMode) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"requestDisplayMode is not supported by this host\",\n );\n return;\n }\n const modeParams = (params ?? {}) as { mode?: unknown };\n if (\n typeof modeParams.mode !== \"string\" ||\n !VALID_DISPLAY_MODES.includes(modeParams.mode as McpAppDisplayMode)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"requestDisplayMode requires a valid 'mode'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.requestDisplayMode({\n mode: modeParams.mode as McpAppDisplayMode,\n }),\n });\n return;\n }\n\n default: {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n `Unknown method: ${req.method}`,\n );\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n errorResponse(req.id, JSONRPC_ERROR.internalError, error.message);\n }\n };\n\n const handleNotification = (note: McpAppJsonRpcNotification) => {\n try {\n switch (normalizeMethod(note.method)) {\n case \"notifications/initialized\": {\n handlers.onInitialized?.();\n return;\n }\n case \"notifications/size_changed\": {\n const p = (note.params ?? {}) as { width?: number; height?: number };\n handlers.onSizeChange?.({\n ...(typeof p.width === \"number\" ? { width: p.width } : {}),\n ...(typeof p.height === \"number\" ? { height: p.height } : {}),\n });\n return;\n }\n case \"notifications/log\": {\n handlers.onLog?.(note.params);\n return;\n }\n case \"notifications/request_teardown\": {\n handlers.onRequestTeardown?.(note.params);\n return;\n }\n case \"notifications/error\": {\n const p = (note.params ?? {}) as { message?: string };\n reportError(\n new Error(\n typeof p.message === \"string\" ? p.message : \"Widget error\",\n ),\n );\n return;\n }\n default:\n return;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n }\n };\n\n // The host applies the cross-origin guard before delegating; this only\n // validates the JSON-RPC envelope.\n const onMessage = (event: MessageEvent) => {\n if (!isJsonRpcMessage(event.data)) return;\n\n const msg = event.data;\n if (isRequest(msg)) {\n void handleRequest(msg);\n } else if (isNotification(msg)) {\n handleNotification(msg);\n }\n };\n\n return {\n onMessage,\n dispose: () => {},\n notifyToolInput: (input: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/input\",\n params: { input },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-input\",\n params: isRecord(input) ? { arguments: input } : {},\n });\n },\n notifyToolResult: (result: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/result\",\n params: { result },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-result\",\n params: isRecord(result)\n ? result\n : { content: [{ type: \"text\", text: String(result) }] },\n });\n },\n notifyHostContextChanged: (ctx: McpAppHostContext) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/host_context/changed\",\n params: ctx,\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/host-context-changed\",\n params: ctx,\n });\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/mcp-apps/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpAppBridgeHandlers, McpAppDisplayMode, McpAppHostContext, McpAppHostInfo, McpAppMetadata, McpAppResource, McpAppResourceCSP, McpAppResourceMeta, McpAppSandboxConfig, McpAppToolCallParams, McpAppsHost, McpAppsRemoteHostOptions, ToolCallMessagePartMcpMetadata } from "./types.js";
|
|
2
|
-
import { McpAppRenderer, McpAppRendererOptions } from "./McpAppRenderer.js";
|
|
2
|
+
import { McpAppPartOptions, McpAppRenderer, McpAppRendererOptions } from "./McpAppRenderer.js";
|
|
3
3
|
import { McpAppsRemoteHost } from "./McpAppsRemoteHost.js";
|
|
4
4
|
import { getMcpAppFromToolPart } from "./utils.js";
|
|
5
|
-
export { type McpAppBridgeHandlers, type McpAppDisplayMode, type McpAppHostContext, type McpAppHostInfo, type McpAppMetadata, McpAppRenderer, type McpAppRendererOptions, type McpAppResource, type McpAppResourceCSP, type McpAppResourceMeta, type McpAppSandboxConfig, type McpAppToolCallParams, type McpAppsHost, McpAppsRemoteHost, type McpAppsRemoteHostOptions, type ToolCallMessagePartMcpMetadata, getMcpAppFromToolPart };
|
|
5
|
+
export { type McpAppBridgeHandlers, type McpAppDisplayMode, type McpAppHostContext, type McpAppHostInfo, type McpAppMetadata, type McpAppPartOptions, McpAppRenderer, type McpAppRendererOptions, type McpAppResource, type McpAppResourceCSP, type McpAppResourceMeta, type McpAppSandboxConfig, type McpAppToolCallParams, type McpAppsHost, McpAppsRemoteHost, type McpAppsRemoteHostOptions, type ToolCallMessagePartMcpMetadata, getMcpAppFromToolPart };
|
|
@@ -32,11 +32,10 @@ type ComposerInputPluginRegistry = {
|
|
|
32
32
|
register(plugin: ComposerInputPlugin, opts?: ComposerInputPluginRegisterOptions): () => void;
|
|
33
33
|
getPlugins(): readonly ComposerInputPlugin[];
|
|
34
34
|
};
|
|
35
|
-
declare const useComposerInputPluginRegistry: () => ComposerInputPluginRegistry;
|
|
36
35
|
declare const useComposerInputPluginRegistryOptional: () => ComposerInputPluginRegistry | null;
|
|
37
36
|
declare const ComposerInputPluginProvider: FC<{
|
|
38
37
|
children: ReactNode;
|
|
39
38
|
}>;
|
|
40
39
|
//#endregion
|
|
41
|
-
export { ComposerInputPlugin, ComposerInputPluginProvider, ComposerInputPluginRegisterOptions, ComposerInputPluginRegistry,
|
|
40
|
+
export { ComposerInputPlugin, ComposerInputPluginProvider, ComposerInputPluginRegisterOptions, ComposerInputPluginRegistry, useComposerInputPluginRegistryOptional };
|
|
42
41
|
//# sourceMappingURL=ComposerInputPluginContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposerInputPluginContext.d.ts","names":[],"sources":["../../../src/primitives/composer/ComposerInputPluginContext.tsx"],"mappings":";;;;;;;KAiBY;;EAEV,cAAc;aACH;aACA;aACA;aACA;aACA;MAAgB;;IACzB;;;EAIF,kBAAkB;;;KAIR;;;;;EAKV;;KAIU;EACV,SACE,QAAQ,qBACR,OAAO;EAET,uBAAuB;;cAMZ,
|
|
1
|
+
{"version":3,"file":"ComposerInputPluginContext.d.ts","names":[],"sources":["../../../src/primitives/composer/ComposerInputPluginContext.tsx"],"mappings":";;;;;;;KAiBY;;EAEV,cAAc;aACH;aACA;aACA;aACA;aACA;MAAgB;;IACzB;;;EAIF,kBAAkB;;;KAIR;;;;;EAKV;;KAIU;EACV,SACE,QAAQ,qBACR,OAAO;EAET,uBAAuB;;cAMZ,8CACP;cAIO,6BAA6B;EAAK,UAAU"}
|
|
@@ -4,11 +4,6 @@ import { createContext, useContext, useRef } from "@assistant-ui/tap/react-shim"
|
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/primitives/composer/ComposerInputPluginContext.tsx
|
|
6
6
|
const ComposerInputPluginRegistryContext = createContext(null);
|
|
7
|
-
const useComposerInputPluginRegistry = () => {
|
|
8
|
-
const ctx = useContext(ComposerInputPluginRegistryContext);
|
|
9
|
-
if (!ctx) throw new Error("useComposerInputPluginRegistry must be used within a ComposerInputPluginProvider");
|
|
10
|
-
return ctx;
|
|
11
|
-
};
|
|
12
7
|
const useComposerInputPluginRegistryOptional = () => {
|
|
13
8
|
return useContext(ComposerInputPluginRegistryContext);
|
|
14
9
|
};
|
|
@@ -85,6 +80,6 @@ function _temp2(t0) {
|
|
|
85
80
|
return plugin;
|
|
86
81
|
}
|
|
87
82
|
//#endregion
|
|
88
|
-
export { ComposerInputPluginProvider,
|
|
83
|
+
export { ComposerInputPluginProvider, useComposerInputPluginRegistryOptional };
|
|
89
84
|
|
|
90
85
|
//# sourceMappingURL=ComposerInputPluginContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposerInputPluginContext.js","names":["c","_c","createContext","useContext","useRef","useCallback","useMemo","ReactNode","FC","ComposerInputPlugin","handleKeyDown","e","key","shiftKey","ctrlKey","metaKey","nativeEvent","isComposing","preventDefault","setCursorPosition","pos","ComposerInputPluginRegisterOptions","priority","ComposerInputPluginRegistry","register","plugin","opts","getPlugins","ComposerInputPluginRegistryContext","
|
|
1
|
+
{"version":3,"file":"ComposerInputPluginContext.js","names":["c","_c","createContext","useContext","useRef","useCallback","useMemo","ReactNode","FC","ComposerInputPlugin","handleKeyDown","e","key","shiftKey","ctrlKey","metaKey","nativeEvent","isComposing","preventDefault","setCursorPosition","pos","ComposerInputPluginRegisterOptions","priority","ComposerInputPluginRegistry","register","plugin","opts","getPlugins","ComposerInputPluginRegistryContext","useComposerInputPluginRegistryOptional","ComposerInputPluginProvider","children","t0","$","t1","Symbol","for","Map","pluginsRef","t2","snapshotRef","t3","entries","Array","from","current","sort","_temp","map","_temp2","refreshSnapshot","t4","plugin_0","set","delete","t5","t6","registry","t7","a","b"],"sources":["../../../src/primitives/composer/ComposerInputPluginContext.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useRef,\n useCallback,\n useMemo,\n type ReactNode,\n type FC,\n} from \"react\";\n\n/**\n * A plugin that intercepts keyboard events and cursor changes in the composer\n * input. Used by trigger popover declarations to handle popover navigation\n * without ComposerInput knowing about specific triggers.\n */\nexport type ComposerInputPlugin = {\n /** Handle a key event. Return true if consumed (stops propagation to other plugins and default behavior). */\n handleKeyDown(e: {\n readonly key: string;\n readonly shiftKey: boolean;\n readonly ctrlKey?: boolean;\n readonly metaKey?: boolean;\n readonly nativeEvent?: { isComposing?: boolean };\n preventDefault(): void;\n }): boolean;\n\n /** Called on every cursor position change (selection change / text change). */\n setCursorPosition(pos: number): void;\n};\n\n/** Options for registering a plugin. */\nexport type ComposerInputPluginRegisterOptions = {\n /**\n * Relative priority. Plugins with higher priority receive events first.\n * @default 0\n */\n priority?: number;\n};\n\n// Ref-based registry: plugins are read imperatively at event time, so register/unregister does not trigger re-renders.\nexport type ComposerInputPluginRegistry = {\n register(\n plugin: ComposerInputPlugin,\n opts?: ComposerInputPluginRegisterOptions,\n ): () => void;\n getPlugins(): readonly ComposerInputPlugin[];\n};\n\nconst ComposerInputPluginRegistryContext =\n createContext<ComposerInputPluginRegistry | null>(null);\n\nexport const useComposerInputPluginRegistryOptional =\n (): ComposerInputPluginRegistry | null => {\n return useContext(ComposerInputPluginRegistryContext);\n };\n\nexport const ComposerInputPluginProvider: FC<{ children: ReactNode }> = ({\n children,\n}) => {\n const pluginsRef = useRef<Map<ComposerInputPlugin, number>>(new Map());\n const snapshotRef = useRef<readonly ComposerInputPlugin[]>([]);\n\n const refreshSnapshot = useCallback(() => {\n const entries = Array.from(pluginsRef.current.entries());\n // Sort by priority descending; stable insertion order for equal priorities.\n entries.sort((a, b) => b[1] - a[1]);\n snapshotRef.current = entries.map(([plugin]) => plugin);\n }, []);\n\n const register = useCallback(\n (\n plugin: ComposerInputPlugin,\n opts?: ComposerInputPluginRegisterOptions,\n ) => {\n const priority = opts?.priority ?? 0;\n pluginsRef.current.set(plugin, priority);\n refreshSnapshot();\n return () => {\n pluginsRef.current.delete(plugin);\n refreshSnapshot();\n };\n },\n [refreshSnapshot],\n );\n\n const getPlugins = useCallback(\n (): readonly ComposerInputPlugin[] => snapshotRef.current,\n [],\n );\n\n const registry = useMemo<ComposerInputPluginRegistry>(\n () => ({ register, getPlugins }),\n [register, getPlugins],\n );\n\n return (\n <ComposerInputPluginRegistryContext.Provider value={registry}>\n {children}\n </ComposerInputPluginRegistryContext.Provider>\n );\n};\n"],"mappings":";;;;;AAkDA,MAAM4B,qCACJ1B,cAAkD,IAAI;AAExD,MAAa2B,+CACX;CAAA,OACS1B,WAAWyB,kCAAkC;AAAC;AAGzD,MAAaE,+BAA2DE,OAAA;CAAA,MAAAC,IAAAhC,EAAA,CAAA;CAAC,MAAA,EAAA8B,aAAAC;CAExE,IAAAE;CAAA,IAAAD,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EAC6DF,qBAAA,IAAIG,IAAI;EAACJ,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAArE,MAAAK,aAAmBlC,OAAyC8B,EAAS;CAAE,IAAAK;CAAA,IAAAN,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EACZG,KAAA,CAAA;EAAEN,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAA7D,MAAAO,cAAoBpC,OAAuCmC,EAAE;CAAE,IAAAE;CAAA,IAAAR,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EAE3BK,WAAA;GAClC,MAAAC,UAAgBC,MAAKC,KAAMN,WAAUO,QAAQH,QAAS,CAAC;GAEvDA,QAAOI,KAAMC,KAAqB;GAClCP,YAAWK,UAAWH,QAAOM,IAAKC,MAAoB;EAAnC;EACpBhB,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CALD,MAAAiB,kBAAwBT;CAKjB,IAAAU;CAAA,IAAAlB,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EAGLe,MAAAC,UAAA1B,SAAA;GAIE,MAAAJ,WAAiBI,MAAIJ,YAAJ;GACjBgB,WAAUO,QAAQQ,IAAK5B,UAAQH,QAAQ;GACvC4B,gBAAgB;GAAC,aACV;IACLZ,WAAUO,QAAQS,OAAQ7B,QAAM;IAChCyB,gBAAgB;GAAC;EAClB;EACFjB,EAAA,KAAAkB;CAAA,OAAAA,KAAAlB,EAAA;CAZH,MAAAT,WAAiB2B;CAcf,IAAAI;CAAA,IAAAtB,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EAGAmB,WAAsCf,YAAWK;EAAQZ,EAAA,KAAAsB;CAAA,OAAAA,KAAAtB,EAAA;CAD3D,MAAAN,aAAmB4B;CAGjB,IAAAC;CAAA,IAAAvB,EAAA,OAAAE,OAAAC,IAAA,2BAAA,GAAA;EAGOoB,KAAA;GAAAhC;GAAAG;EAAuB;EAACM,EAAA,KAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CADjC,MAAAwB,WACSD;CAEP,IAAAE;CAAA,IAAAzB,EAAA,OAAAF,UAAA;EAGA2B,KAAA,oBAAA,mCAAA,UAAA;GAAoDD,OAAAA;GACjD1B;EACH,CAAA;EAA8CE,EAAA,KAAAF;EAAAE,EAAA,KAAAyB;CAAA,OAAAA,KAAAzB,EAAA;CAAA,OAF9CyB;AAE8C;AA1CsB,SAAAX,MAAAY,GAAAC,GAAA;CAAA,OAS7CA,EAAC,KAAMD,EAAC;AAAG;AATkC,SAAAV,OAAAjB,IAAA;CAUjC,MAAA,CAAAP,UAAAO;CAAQ,OAAKP;AAAM"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useTriggerBehaviorRegistration } from "./TriggerPopover.js";
|
|
3
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
3
4
|
import { unstable_defaultDirectiveFormatter } from "@assistant-ui/core";
|
|
4
|
-
import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
5
|
+
import { useEffect, useInsertionEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
5
6
|
//#region src/primitives/composer/trigger/TriggerPopoverAction.tsx
|
|
6
7
|
/**
|
|
7
8
|
* Configures a `<TriggerPopover>` to fire a handler when an item is selected,
|
|
@@ -20,23 +21,53 @@ import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
|
20
21
|
* </ComposerPrimitive.Unstable_TriggerPopover>
|
|
21
22
|
* ```
|
|
22
23
|
*/
|
|
23
|
-
const ComposerPrimitiveTriggerPopoverAction = (
|
|
24
|
+
const ComposerPrimitiveTriggerPopoverAction = (t0) => {
|
|
25
|
+
const $ = c(8);
|
|
26
|
+
const { formatter, onExecute, removeOnExecute } = t0;
|
|
24
27
|
const { register } = useTriggerBehaviorRegistration();
|
|
25
28
|
const onExecuteRef = useRef(onExecute);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
onExecute: (item) => onExecuteRef.current(item),
|
|
32
|
-
...removeOnExecute !== void 0 ? { removeOnExecute } : {}
|
|
29
|
+
let t1;
|
|
30
|
+
let t2;
|
|
31
|
+
if ($[0] !== onExecute) {
|
|
32
|
+
t1 = () => {
|
|
33
|
+
onExecuteRef.current = onExecute;
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
t2 = [onExecute];
|
|
36
|
+
$[0] = onExecute;
|
|
37
|
+
$[1] = t1;
|
|
38
|
+
$[2] = t2;
|
|
39
|
+
} else {
|
|
40
|
+
t1 = $[1];
|
|
41
|
+
t2 = $[2];
|
|
42
|
+
}
|
|
43
|
+
useInsertionEffect(t1, t2);
|
|
44
|
+
let t3;
|
|
45
|
+
let t4;
|
|
46
|
+
if ($[3] !== formatter || $[4] !== register || $[5] !== removeOnExecute) {
|
|
47
|
+
t3 = () => {
|
|
48
|
+
const behavior = {
|
|
49
|
+
kind: "action",
|
|
50
|
+
formatter: formatter ?? unstable_defaultDirectiveFormatter,
|
|
51
|
+
onExecute: (item) => onExecuteRef.current(item),
|
|
52
|
+
...removeOnExecute !== void 0 ? { removeOnExecute } : {}
|
|
53
|
+
};
|
|
54
|
+
return register(behavior);
|
|
55
|
+
};
|
|
56
|
+
t4 = [
|
|
57
|
+
register,
|
|
58
|
+
formatter,
|
|
59
|
+
removeOnExecute
|
|
60
|
+
];
|
|
61
|
+
$[3] = formatter;
|
|
62
|
+
$[4] = register;
|
|
63
|
+
$[5] = removeOnExecute;
|
|
64
|
+
$[6] = t3;
|
|
65
|
+
$[7] = t4;
|
|
66
|
+
} else {
|
|
67
|
+
t3 = $[6];
|
|
68
|
+
t4 = $[7];
|
|
69
|
+
}
|
|
70
|
+
useEffect(t3, t4);
|
|
40
71
|
return null;
|
|
41
72
|
};
|
|
42
73
|
ComposerPrimitiveTriggerPopoverAction.displayName = "ComposerPrimitive.TriggerPopoverAction";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TriggerPopoverAction.js","names":["Unstable_DirectiveFormatter","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","useEffect","useRef","FC","useTriggerBehaviorRegistration","TriggerBehavior","ComposerPrimitiveTriggerPopoverAction","Props","formatter","onExecute","item","removeOnExecute","register","onExecuteRef","current","behavior","kind","undefined","displayName"],"sources":["../../../../src/primitives/composer/trigger/TriggerPopoverAction.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport { useEffect, useRef, type FC } from \"react\";\nimport { useTriggerBehaviorRegistration } from \"./TriggerPopover\";\nimport type { TriggerBehavior } from \"./triggerSelectionResource\";\n\nexport namespace ComposerPrimitiveTriggerPopoverAction {\n export type Props = {\n /** Defaults to `unstable_defaultDirectiveFormatter`. */\n readonly formatter?: Unstable_DirectiveFormatter | undefined;\n /** Fires the moment an item is selected; runs regardless of `removeOnExecute`. */\n readonly onExecute: (item: Unstable_TriggerItem) => void;\n /** When true, strips the trigger text after executing. Defaults to `false` (keeps audit-trail chip). */\n readonly removeOnExecute?: boolean | undefined;\n };\n}\n\n/**\n * Configures a `<TriggerPopover>` to fire a handler when an item is selected,\n * optionally leaving a directive chip behind as an audit trail. Render exactly\n * one behavior sub-primitive per `<TriggerPopover>`.\n *\n * Exposed as `ComposerPrimitive.Unstable_TriggerPopover.Action`.\n *\n * @example\n * ```tsx\n * <ComposerPrimitive.Unstable_TriggerPopover char=\"/\" adapter={slashAdapter}>\n * <ComposerPrimitive.Unstable_TriggerPopover.Action\n * onExecute={(item) => commandHandlers[item.id]?.()}\n * removeOnExecute={false}\n * />\n * </ComposerPrimitive.Unstable_TriggerPopover>\n * ```\n */\nexport const ComposerPrimitiveTriggerPopoverAction: FC<\n ComposerPrimitiveTriggerPopoverAction.Props\n> = ({ formatter, onExecute, removeOnExecute }) => {\n const { register } = useTriggerBehaviorRegistration();\n const onExecuteRef = useRef(onExecute);\n onExecuteRef.current = onExecute;\n\n useEffect(() => {\n const behavior: TriggerBehavior = {\n kind: \"action\",\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n onExecute: (item) => onExecuteRef.current(item),\n ...(removeOnExecute !== undefined ? { removeOnExecute } : {}),\n };\n return register(behavior);\n }, [register, formatter, removeOnExecute]);\n\n return null;\n};\n\nComposerPrimitiveTriggerPopoverAction.displayName =\n \"ComposerPrimitive.TriggerPopoverAction\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TriggerPopoverAction.js","names":["c","_c","Unstable_DirectiveFormatter","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","useEffect","useInsertionEffect","useRef","FC","useTriggerBehaviorRegistration","TriggerBehavior","ComposerPrimitiveTriggerPopoverAction","Props","formatter","onExecute","item","removeOnExecute","t0","$","register","onExecuteRef","t1","t2","current","t3","t4","behavior","kind","undefined","displayName"],"sources":["../../../../src/primitives/composer/trigger/TriggerPopoverAction.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport { useEffect, useInsertionEffect, useRef, type FC } from \"react\";\nimport { useTriggerBehaviorRegistration } from \"./TriggerPopover\";\nimport type { TriggerBehavior } from \"./triggerSelectionResource\";\n\nexport namespace ComposerPrimitiveTriggerPopoverAction {\n export type Props = {\n /** Defaults to `unstable_defaultDirectiveFormatter`. */\n readonly formatter?: Unstable_DirectiveFormatter | undefined;\n /** Fires the moment an item is selected; runs regardless of `removeOnExecute`. */\n readonly onExecute: (item: Unstable_TriggerItem) => void;\n /** When true, strips the trigger text after executing. Defaults to `false` (keeps audit-trail chip). */\n readonly removeOnExecute?: boolean | undefined;\n };\n}\n\n/**\n * Configures a `<TriggerPopover>` to fire a handler when an item is selected,\n * optionally leaving a directive chip behind as an audit trail. Render exactly\n * one behavior sub-primitive per `<TriggerPopover>`.\n *\n * Exposed as `ComposerPrimitive.Unstable_TriggerPopover.Action`.\n *\n * @example\n * ```tsx\n * <ComposerPrimitive.Unstable_TriggerPopover char=\"/\" adapter={slashAdapter}>\n * <ComposerPrimitive.Unstable_TriggerPopover.Action\n * onExecute={(item) => commandHandlers[item.id]?.()}\n * removeOnExecute={false}\n * />\n * </ComposerPrimitive.Unstable_TriggerPopover>\n * ```\n */\nexport const ComposerPrimitiveTriggerPopoverAction: FC<\n ComposerPrimitiveTriggerPopoverAction.Props\n> = ({ formatter, onExecute, removeOnExecute }) => {\n const { register } = useTriggerBehaviorRegistration();\n const onExecuteRef = useRef(onExecute);\n useInsertionEffect(() => {\n onExecuteRef.current = onExecute;\n }, [onExecute]);\n\n useEffect(() => {\n const behavior: TriggerBehavior = {\n kind: \"action\",\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n onExecute: (item) => onExecuteRef.current(item),\n ...(removeOnExecute !== undefined ? { removeOnExecute } : {}),\n };\n return register(behavior);\n }, [register, formatter, removeOnExecute]);\n\n return null;\n};\n\nComposerPrimitiveTriggerPopoverAction.displayName =\n \"ComposerPrimitive.TriggerPopoverAction\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAaW,yCAETM,OAAA;CAAA,MAAAC,IAAAjB,EAAA,CAAA;CAAC,MAAA,EAAAY,WAAAC,WAAAE,oBAAAC;CACH,MAAA,EAAAE,aAAqBV,+BAA+B;CACpD,MAAAW,eAAqBb,OAAOO,SAAS;CAAE,IAAAO;CAAA,IAAAC;CAAA,IAAAJ,EAAA,OAAAJ,WAAA;EACpBO,WAAA;GACjBD,aAAYG,UAAWT;EAAH;EACnBQ,KAAA,CAACR,SAAS;EAACI,EAAA,KAAAJ;EAAAI,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAA;EAAAD,KAAAH,EAAA;EAAAI,KAAAJ,EAAA;CAAA;CAFdZ,mBAAmBe,IAEhBC,EAAW;CAAC,IAAAE;CAAA,IAAAC;CAAA,IAAAP,EAAA,OAAAL,aAAAK,EAAA,OAAAC,YAAAD,EAAA,OAAAF,iBAAA;EAELQ,WAAA;GACR,MAAAE,WAAkC;IAAAC,MAC1B;IAAQd,WACHA,aAAAT;IAA+CU,YAC/CC,SAAUK,aAAYG,QAASR,IAAI;IAAC,GAC3CC,oBAAoBY,KAAAA,IAApB,EAAAZ,gBAAuD,IAAvD,CAAuD;GAC7D;GAAE,OACKG,SAASO,QAAQ;EAAC;EACxBD,KAAA;GAACN;GAAUN;GAAWG;EAAe;EAACE,EAAA,KAAAL;EAAAK,EAAA,KAAAC;EAAAD,EAAA,KAAAF;EAAAE,EAAA,KAAAM;EAAAN,EAAA,KAAAO;CAAA,OAAA;EAAAD,KAAAN,EAAA;EAAAO,KAAAP,EAAA;CAAA;CARzCb,UAAUmB,IAQPC,EAAsC;CAAC,OAEnC;AAAI;AAGbd,sCAAsCkB,cACpC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useTriggerBehaviorRegistration } from "./TriggerPopover.js";
|
|
3
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
3
4
|
import { unstable_defaultDirectiveFormatter } from "@assistant-ui/core";
|
|
4
|
-
import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
5
|
+
import { useEffect, useInsertionEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
5
6
|
//#region src/primitives/composer/trigger/TriggerPopoverDirective.tsx
|
|
6
7
|
/**
|
|
7
8
|
* Configures a `<TriggerPopover>` to insert a directive chip when an item is
|
|
@@ -19,17 +20,46 @@ import { useEffect, useRef } from "@assistant-ui/tap/react-shim";
|
|
|
19
20
|
* </ComposerPrimitive.Unstable_TriggerPopover>
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
const ComposerPrimitiveTriggerPopoverDirective = (
|
|
23
|
+
const ComposerPrimitiveTriggerPopoverDirective = (t0) => {
|
|
24
|
+
const $ = c(7);
|
|
25
|
+
const { formatter, onInserted } = t0;
|
|
23
26
|
const { register } = useTriggerBehaviorRegistration();
|
|
24
27
|
const onInsertedRef = useRef(onInserted);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
let t1;
|
|
29
|
+
let t2;
|
|
30
|
+
if ($[0] !== onInserted) {
|
|
31
|
+
t1 = () => {
|
|
32
|
+
onInsertedRef.current = onInserted;
|
|
33
|
+
};
|
|
34
|
+
t2 = [onInserted];
|
|
35
|
+
$[0] = onInserted;
|
|
36
|
+
$[1] = t1;
|
|
37
|
+
$[2] = t2;
|
|
38
|
+
} else {
|
|
39
|
+
t1 = $[1];
|
|
40
|
+
t2 = $[2];
|
|
41
|
+
}
|
|
42
|
+
useInsertionEffect(t1, t2);
|
|
43
|
+
let t3;
|
|
44
|
+
let t4;
|
|
45
|
+
if ($[3] !== formatter || $[4] !== register) {
|
|
46
|
+
t3 = () => {
|
|
47
|
+
return register({
|
|
48
|
+
kind: "directive",
|
|
49
|
+
formatter: formatter ?? unstable_defaultDirectiveFormatter,
|
|
50
|
+
onInserted: (item) => onInsertedRef.current?.(item)
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
t4 = [register, formatter];
|
|
54
|
+
$[3] = formatter;
|
|
55
|
+
$[4] = register;
|
|
56
|
+
$[5] = t3;
|
|
57
|
+
$[6] = t4;
|
|
58
|
+
} else {
|
|
59
|
+
t3 = $[5];
|
|
60
|
+
t4 = $[6];
|
|
61
|
+
}
|
|
62
|
+
useEffect(t3, t4);
|
|
33
63
|
return null;
|
|
34
64
|
};
|
|
35
65
|
ComposerPrimitiveTriggerPopoverDirective.displayName = "ComposerPrimitive.TriggerPopoverDirective";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TriggerPopoverDirective.js","names":["Unstable_DirectiveFormatter","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","useEffect","useRef","FC","useTriggerBehaviorRegistration","TriggerBehavior","ComposerPrimitiveTriggerPopoverDirective","Props","formatter","onInserted","item","register","onInsertedRef","current","behavior","kind","displayName"],"sources":["../../../../src/primitives/composer/trigger/TriggerPopoverDirective.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport { useEffect, useRef, type FC } from \"react\";\nimport { useTriggerBehaviorRegistration } from \"./TriggerPopover\";\nimport type { TriggerBehavior } from \"./triggerSelectionResource\";\n\nexport namespace ComposerPrimitiveTriggerPopoverDirective {\n export type Props = {\n /** Defaults to `unstable_defaultDirectiveFormatter`. */\n readonly formatter?: Unstable_DirectiveFormatter | undefined;\n /** Fires after an item has been inserted into the composer. */\n readonly onInserted?: ((item: Unstable_TriggerItem) => void) | undefined;\n };\n}\n\n/**\n * Configures a `<TriggerPopover>` to insert a directive chip when an item is\n * selected. Render exactly one behavior sub-primitive per `<TriggerPopover>`.\n *\n * Exposed as `ComposerPrimitive.Unstable_TriggerPopover.Directive`.\n *\n * @example\n * ```tsx\n * <ComposerPrimitive.Unstable_TriggerPopover char=\"@\" adapter={mentionAdapter}>\n * <ComposerPrimitive.Unstable_TriggerPopover.Directive\n * formatter={unstable_defaultDirectiveFormatter}\n * onInserted={(item) => track(\"mention\", item.id)}\n * />\n * </ComposerPrimitive.Unstable_TriggerPopover>\n * ```\n */\nexport const ComposerPrimitiveTriggerPopoverDirective: FC<\n ComposerPrimitiveTriggerPopoverDirective.Props\n> = ({ formatter, onInserted }) => {\n const { register } = useTriggerBehaviorRegistration();\n const onInsertedRef = useRef(onInserted);\n onInsertedRef.current = onInserted;\n\n useEffect(() => {\n const behavior: TriggerBehavior = {\n kind: \"directive\",\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n onInserted: (item) => onInsertedRef.current?.(item),\n };\n return register(behavior);\n }, [register, formatter]);\n\n return null;\n};\n\nComposerPrimitiveTriggerPopoverDirective.displayName =\n \"ComposerPrimitive.TriggerPopoverDirective\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TriggerPopoverDirective.js","names":["c","_c","Unstable_DirectiveFormatter","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","useEffect","useInsertionEffect","useRef","FC","useTriggerBehaviorRegistration","TriggerBehavior","ComposerPrimitiveTriggerPopoverDirective","Props","formatter","onInserted","item","t0","$","register","onInsertedRef","t1","t2","current","t3","t4","behavior","kind","displayName"],"sources":["../../../../src/primitives/composer/trigger/TriggerPopoverDirective.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport { useEffect, useInsertionEffect, useRef, type FC } from \"react\";\nimport { useTriggerBehaviorRegistration } from \"./TriggerPopover\";\nimport type { TriggerBehavior } from \"./triggerSelectionResource\";\n\nexport namespace ComposerPrimitiveTriggerPopoverDirective {\n export type Props = {\n /** Defaults to `unstable_defaultDirectiveFormatter`. */\n readonly formatter?: Unstable_DirectiveFormatter | undefined;\n /** Fires after an item has been inserted into the composer. */\n readonly onInserted?: ((item: Unstable_TriggerItem) => void) | undefined;\n };\n}\n\n/**\n * Configures a `<TriggerPopover>` to insert a directive chip when an item is\n * selected. Render exactly one behavior sub-primitive per `<TriggerPopover>`.\n *\n * Exposed as `ComposerPrimitive.Unstable_TriggerPopover.Directive`.\n *\n * @example\n * ```tsx\n * <ComposerPrimitive.Unstable_TriggerPopover char=\"@\" adapter={mentionAdapter}>\n * <ComposerPrimitive.Unstable_TriggerPopover.Directive\n * formatter={unstable_defaultDirectiveFormatter}\n * onInserted={(item) => track(\"mention\", item.id)}\n * />\n * </ComposerPrimitive.Unstable_TriggerPopover>\n * ```\n */\nexport const ComposerPrimitiveTriggerPopoverDirective: FC<\n ComposerPrimitiveTriggerPopoverDirective.Props\n> = ({ formatter, onInserted }) => {\n const { register } = useTriggerBehaviorRegistration();\n const onInsertedRef = useRef(onInserted);\n useInsertionEffect(() => {\n onInsertedRef.current = onInserted;\n }, [onInserted]);\n\n useEffect(() => {\n const behavior: TriggerBehavior = {\n kind: \"directive\",\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n onInserted: (item) => onInsertedRef.current?.(item),\n };\n return register(behavior);\n }, [register, formatter]);\n\n return null;\n};\n\nComposerPrimitiveTriggerPopoverDirective.displayName =\n \"ComposerPrimitive.TriggerPopoverDirective\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAaW,4CAETK,OAAA;CAAA,MAAAC,IAAAhB,EAAA,CAAA;CAAC,MAAA,EAAAY,WAAAC,eAAAE;CACH,MAAA,EAAAE,aAAqBT,+BAA+B;CACpD,MAAAU,gBAAsBZ,OAAOO,UAAU;CAAE,IAAAM;CAAA,IAAAC;CAAA,IAAAJ,EAAA,OAAAH,YAAA;EACtBM,WAAA;GACjBD,cAAaG,UAAWR;EAAH;EACpBO,KAAA,CAACP,UAAU;EAACG,EAAA,KAAAH;EAAAG,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAA;EAAAD,KAAAH,EAAA;EAAAI,KAAAJ,EAAA;CAAA;CAFfX,mBAAmBc,IAEhBC,EAAY;CAAC,IAAAE;CAAA,IAAAC;CAAA,IAAAP,EAAA,OAAAJ,aAAAI,EAAA,OAAAC,UAAA;EAENK,WAAA;GAKN,OACKL,SAASO;IALkBC,MAC1B;IAAWb,WACNA,aAAAT;IAA+CU,aAC9CC,SAAUI,cAAaG,UAAWP,IAAI;GAEpCU,CAAQ;EAAC;EACxBD,KAAA,CAACN,UAAUL,SAAS;EAACI,EAAA,KAAAJ;EAAAI,EAAA,KAAAC;EAAAD,EAAA,KAAAM;EAAAN,EAAA,KAAAO;CAAA,OAAA;EAAAD,KAAAN,EAAA;EAAAO,KAAAP,EAAA;CAAA;CAPxBZ,UAAUkB,IAOPC,EAAqB;CAAC,OAElB;AAAI;AAGbb,yCAAyCgB,cACvC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Unstable_TriggerItem } from "@assistant-ui/core";
|
|
2
|
+
//#region src/primitives/composer/trigger/matchesTriggerItemQuery.d.ts
|
|
3
|
+
declare function matchesTriggerItemQuery(item: Unstable_TriggerItem, lowerQuery: string): boolean;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { matchesTriggerItemQuery };
|
|
6
|
+
//# sourceMappingURL=matchesTriggerItemQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchesTriggerItemQuery.d.ts","names":[],"sources":["../../../../src/primitives/composer/trigger/matchesTriggerItemQuery.ts"],"mappings":";;iBAEgB,wBACd,MAAM,sBACN"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/primitives/composer/trigger/matchesTriggerItemQuery.ts
|
|
2
|
+
function matchesTriggerItemQuery(item, lowerQuery) {
|
|
3
|
+
if (!lowerQuery) return true;
|
|
4
|
+
return item.id.toLowerCase().includes(lowerQuery) || item.label.toLowerCase().includes(lowerQuery) || (item.description?.toLowerCase().includes(lowerQuery) ?? false);
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { matchesTriggerItemQuery };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=matchesTriggerItemQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchesTriggerItemQuery.js","names":["Unstable_TriggerItem","matchesTriggerItemQuery","item","lowerQuery","id","toLowerCase","includes","label","description"],"sources":["../../../../src/primitives/composer/trigger/matchesTriggerItemQuery.ts"],"sourcesContent":["import type { Unstable_TriggerItem } from \"@assistant-ui/core\";\n\nexport function matchesTriggerItemQuery(\n item: Unstable_TriggerItem,\n lowerQuery: string,\n): boolean {\n if (!lowerQuery) return true;\n return (\n item.id.toLowerCase().includes(lowerQuery) ||\n item.label.toLowerCase().includes(lowerQuery) ||\n (item.description?.toLowerCase().includes(lowerQuery) ?? false)\n );\n}\n"],"mappings":";AAEA,SAAgBC,wBACdC,MACAC,YACS;CACT,IAAI,CAACA,YAAY,OAAO;CACxB,OACED,KAAKE,GAAGC,YAAY,CAAC,CAACC,SAASH,UAAU,KACzCD,KAAKK,MAAMF,YAAY,CAAC,CAACC,SAASH,UAAU,MAC3CD,KAAKM,aAAaH,YAAY,CAAC,CAACC,SAASH,UAAU,KAAK;AAE7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"triggerNavigationResource.d.ts","names":[],"sources":["../../../../src/primitives/composer/trigger/triggerNavigationResource.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"triggerNavigationResource.d.ts","names":[],"sources":["../../../../src/primitives/composer/trigger/triggerNavigationResource.ts"],"mappings":";;KASY;;WAED,qBAAqB;;WAErB,gBAAgB;;WAEhB;;WAEA;;WAEA,yBACL,2BACA;;EAGJ,eAAe;;EAEf;;cAoGW,uDAAyB,SAAA;EAxF3B,SAAA;EACF;EACD"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
+
import { matchesTriggerItemQuery } from "./matchesTriggerItemQuery.js";
|
|
1
2
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
2
3
|
import { useEffect, useEffectEvent, useState } from "@assistant-ui/tap/react-shim";
|
|
3
4
|
import { resource } from "@assistant-ui/tap";
|
|
4
5
|
//#region src/primitives/composer/trigger/triggerNavigationResource.ts
|
|
5
|
-
function matchesQuery(item, lower) {
|
|
6
|
-
return item.id.toLowerCase().includes(lower) || item.label.toLowerCase().includes(lower) || (item.description?.toLowerCase().includes(lower) ?? false);
|
|
7
|
-
}
|
|
8
6
|
/**
|
|
9
7
|
* Computes categories, items, search results, and navigation state from the
|
|
10
8
|
* adapter + current query. Pure derivation — no side effects on the composer.
|
|
@@ -95,7 +93,7 @@ const useTriggerNavigationResource = (t0) => {
|
|
|
95
93
|
if ($[13] !== adapter || $[14] !== categories || $[15] !== query) {
|
|
96
94
|
all = [];
|
|
97
95
|
const lower = query.toLowerCase();
|
|
98
|
-
for (const cat of categories) for (const item of adapter.categoryItems(cat.id)) if (
|
|
96
|
+
for (const cat of categories) for (const item of adapter.categoryItems(cat.id)) if (matchesTriggerItemQuery(item, lower)) all.push(item);
|
|
99
97
|
$[13] = adapter;
|
|
100
98
|
$[14] = categories;
|
|
101
99
|
$[15] = query;
|
|
@@ -150,7 +148,7 @@ const useTriggerNavigationResource = (t0) => {
|
|
|
150
148
|
let t8;
|
|
151
149
|
if ($[23] !== allItems || $[24] !== query) {
|
|
152
150
|
const lower_1 = query.toLowerCase();
|
|
153
|
-
t8 = allItems.filter((item_0) =>
|
|
151
|
+
t8 = allItems.filter((item_0) => matchesTriggerItemQuery(item_0, lower_1));
|
|
154
152
|
$[23] = allItems;
|
|
155
153
|
$[24] = query;
|
|
156
154
|
$[25] = t8;
|