@assistant-ui/react 0.15.24 → 0.15.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useToolCallElapsed.d.ts +3 -1
- package/dist/hooks/useToolCallElapsed.d.ts.map +1 -1
- package/dist/hooks/useToolCallElapsed.js +8 -8
- package/dist/hooks/useToolCallElapsed.js.map +1 -1
- package/dist/index.d.ts +39 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +3 -2
- 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 +56 -46
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/mcp-apps/csp.d.ts +4 -0
- package/dist/mcp-apps/csp.d.ts.map +1 -0
- package/dist/mcp-apps/csp.js +93 -0
- package/dist/mcp-apps/csp.js.map +1 -0
- package/dist/mcp-apps/types.d.ts +1 -0
- package/dist/mcp-apps/types.d.ts.map +1 -1
- package/dist/mcp-apps/types.js.map +1 -1
- package/dist/model-context/makeAssistantVisible.d.ts +1 -0
- package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
- package/dist/model-context/makeAssistantVisible.js +31 -12
- package/dist/model-context/makeAssistantVisible.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.d.ts +1 -0
- package/dist/primitives/assistantModal/AssistantModalRoot.d.ts.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.js.map +1 -1
- package/dist/primitives/attachment.d.ts +3 -1
- package/dist/primitives/attachment.d.ts.map +1 -1
- package/dist/primitives/attachment.js.map +1 -1
- package/dist/primitives/composer/ComposerCancel.d.ts +5 -1
- package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerCancel.js +14 -1
- package/dist/primitives/composer/ComposerCancel.js.map +1 -1
- package/dist/primitives/composer/ComposerInput.d.ts +15 -1
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +5 -4
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerRoot.js +24 -19
- package/dist/primitives/composer/ComposerRoot.js.map +1 -1
- package/dist/primitives/composer/composerInputSelector.d.ts +3 -0
- package/dist/primitives/composer/composerInputSelector.d.ts.map +1 -0
- package/dist/primitives/composer/composerInputSelector.js +7 -0
- package/dist/primitives/composer/composerInputSelector.js.map +1 -0
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts +11 -11
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +62 -60
- package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +6 -6
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +3 -3
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts +9 -9
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +7 -7
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +5 -5
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
- package/dist/primitives/composer/trigger/index.d.ts +1 -1
- package/dist/primitives/composer/useComposerCancelWithFocus.d.ts +2 -0
- package/dist/primitives/composer/useComposerCancelWithFocus.d.ts.map +1 -0
- package/dist/primitives/composer/useComposerCancelWithFocus.js +42 -0
- package/dist/primitives/composer/useComposerCancelWithFocus.js.map +1 -0
- package/dist/primitives/composer.d.ts +55 -15
- package/dist/primitives/composer.d.ts.map +1 -1
- package/dist/primitives/composer.js +8 -1
- package/dist/primitives/composer.js.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.d.ts +8 -1
- package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js +58 -278
- package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +5 -2
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
- package/dist/primitives/thread/ThreadLoadEarlier.d.ts +19 -0
- package/dist/primitives/thread/ThreadLoadEarlier.d.ts.map +1 -0
- package/dist/primitives/thread/ThreadLoadEarlier.js +36 -0
- package/dist/primitives/thread/ThreadLoadEarlier.js.map +1 -0
- package/dist/primitives/thread/ThreadMessages.d.ts +1 -1
- package/dist/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadMessages.js +2 -2
- package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +4 -3
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +2 -2
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +195 -17
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/thread.d.ts +2 -0
- package/dist/primitives/thread.d.ts.map +1 -1
- package/dist/primitives/thread.js +5 -2
- package/dist/primitives/thread.js.map +1 -1
- package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
- package/dist/sandbox-host/SandboxHost.js +9 -3
- package/dist/sandbox-host/SandboxHost.js.map +1 -1
- package/dist/unstable/useComposerInput.d.ts +7 -4
- package/dist/unstable/useComposerInput.d.ts.map +1 -1
- package/dist/unstable/useComposerInput.js +4 -4
- package/dist/unstable/useComposerInput.js.map +1 -1
- package/dist/unstable/useComposerInputHistory.d.ts +3 -2
- package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
- package/dist/unstable/useComposerInputHistory.js +2 -2
- package/dist/unstable/useComposerInputHistory.js.map +1 -1
- package/dist/unstable/useLiveCompletionAdapter.d.ts +3 -2
- package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
- package/dist/unstable/useLiveCompletionAdapter.js +8 -7
- package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
- package/dist/unstable/useMentionAdapter.d.ts +12 -3
- package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
- package/dist/unstable/useMentionAdapter.js +2 -2
- package/dist/unstable/useMentionAdapter.js.map +1 -1
- package/dist/unstable/useMessageStallDetection.d.ts +4 -2
- package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
- package/dist/unstable/useMessageStallDetection.js +12 -8
- package/dist/unstable/useMessageStallDetection.js.map +1 -1
- package/dist/unstable/useSlashCommandAdapter.d.ts +5 -2
- package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
- package/dist/unstable/useSlashCommandAdapter.js +5 -4
- package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
- package/dist/unstable/webmcp/useWebMcpProvider.d.ts +4 -0
- package/dist/unstable/webmcp/useWebMcpProvider.d.ts.map +1 -1
- package/dist/unstable/webmcp/useWebMcpProvider.js +2 -0
- package/dist/unstable/webmcp/useWebMcpProvider.js.map +1 -1
- package/dist/utils/getSelectionMessageId.d.ts.map +1 -1
- package/dist/utils/getSelectionMessageId.js +31 -8
- package/dist/utils/getSelectionMessageId.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.js +2 -22
- package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
- package/dist/utils/smooth/useSmooth.js +6 -6
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/dist/utils/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/utils/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/utils/useIsomorphicLayoutEffect.js +6 -0
- package/dist/utils/useIsomorphicLayoutEffect.js.map +1 -0
- package/package.json +12 -11
- package/src/hooks/useToolCallElapsed.test.tsx +37 -0
- package/src/hooks/useToolCallElapsed.ts +10 -7
- package/src/index.ts +47 -5
- package/src/mcp-apps/McpAppRenderer.tsx +3 -9
- package/src/mcp-apps/app-frame.test.tsx +38 -0
- package/src/mcp-apps/app-frame.tsx +5 -8
- package/src/mcp-apps/csp.test.ts +112 -0
- package/src/mcp-apps/csp.ts +124 -0
- package/src/mcp-apps/types.ts +1 -0
- package/src/model-context/frame/AssistantFrame.test.ts +45 -0
- package/src/model-context/frame/SPEC_AssistantFrame.md +1 -0
- package/src/model-context/makeAssistantVisible.test.tsx +315 -5
- package/src/model-context/makeAssistantVisible.tsx +43 -7
- package/src/primitives/assistantModal/AssistantModalRoot.tsx +1 -0
- package/src/primitives/attachment.ts +4 -1
- package/src/primitives/composer/ComposerCancel.focus.test.tsx +307 -0
- package/src/primitives/composer/ComposerCancel.ts +8 -1
- package/src/primitives/composer/ComposerInput.tsx +20 -2
- package/src/primitives/composer/ComposerRoot.tsx +6 -5
- package/src/primitives/composer/composerInputSelector.ts +4 -0
- package/src/primitives/composer/trigger/TriggerPopover.tsx +11 -11
- package/src/primitives/composer/trigger/TriggerPopoverAction.tsx +10 -13
- package/src/primitives/composer/trigger/TriggerPopoverCategories.tsx +2 -2
- package/src/primitives/composer/trigger/TriggerPopoverDirective.tsx +11 -14
- package/src/primitives/composer/trigger/TriggerPopoverExports.test.ts +61 -0
- package/src/primitives/composer/trigger/TriggerPopoverItems.tsx +3 -3
- package/src/primitives/composer/trigger/TriggerPopoverRootContext.tsx +8 -8
- package/src/primitives/composer/useComposerCancelWithFocus.ts +57 -0
- package/src/primitives/composer.ts +70 -15
- package/src/primitives/message/MessagePartsGrouped.test.tsx +106 -2
- package/src/primitives/message/MessagePartsGrouped.tsx +36 -134
- package/src/primitives/message/MessageRoot.test.tsx +125 -2
- package/src/primitives/selectionToolbar/SelectionToolbarRoot.test.tsx +20 -12
- package/src/primitives/selectionToolbar/SelectionToolbarRoot.tsx +6 -2
- package/src/primitives/thread/ThreadLoadEarlier.tsx +35 -0
- package/src/primitives/thread/ThreadMessages.tsx +1 -0
- package/src/primitives/thread/ThreadViewport.tsx +3 -3
- package/src/primitives/thread/topAnchor/useTopAnchorReserve.ts +2 -2
- package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +922 -68
- package/src/primitives/thread/useThreadViewportAutoScroll.ts +330 -56
- package/src/primitives/thread.ts +2 -0
- package/src/sandbox-host/SandboxHost.test.tsx +34 -0
- package/src/sandbox-host/SandboxHost.tsx +11 -12
- package/src/tests/toolCallTiming.test.tsx +19 -2
- package/src/unstable/useComposerInput.ts +7 -4
- package/src/unstable/useComposerInputHistory.ts +3 -2
- package/src/unstable/useLiveCompletionAdapter.ts +9 -14
- package/src/unstable/useMentionAdapter.ts +12 -3
- package/src/unstable/useMessageStallDetection.test.tsx +40 -0
- package/src/unstable/useMessageStallDetection.ts +14 -8
- package/src/unstable/useSlashCommandAdapter.ts +8 -4
- package/src/unstable/webmcp/useWebMcpProvider.ts +4 -0
- package/src/utils/getSelectionMessageId.test.ts +231 -0
- package/src/utils/getSelectionMessageId.ts +45 -7
- package/src/utils/hooks/useOnResizeContent.ts +2 -29
- package/src/utils/smooth/useSmooth.test.tsx +16 -5
- package/src/utils/smooth/useSmooth.ts +7 -7
- package/src/utils/useIsomorphicLayoutEffect.test.tsx +21 -0
- package/src/utils/useIsomorphicLayoutEffect.ts +9 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { useIsomorphicLayoutEffect } from "../utils/useIsomorphicLayoutEffect.js";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
3
4
|
//#region src/unstable/useLiveCompletionAdapter.ts
|
|
4
5
|
/** Sentinel that no real query (including the empty string) equals, so the first query always fetches. */
|
|
5
6
|
const NO_QUERY = "\0";
|
|
6
7
|
/**
|
|
7
|
-
* @deprecated Under active development and may change without notice.
|
|
8
|
-
*
|
|
9
8
|
* Bridges an async completion source (a server search, a gateway RPC) into the
|
|
10
9
|
* synchronous `Unstable_TriggerAdapter` that `ComposerTriggerPopover` consumes.
|
|
11
10
|
* `search(query)` returns the last fetched items synchronously and schedules a
|
|
@@ -16,6 +15,8 @@ const NO_QUERY = "\0";
|
|
|
16
15
|
* `isLoading` is `true` while a fetch is in flight. Pass it to the popover's
|
|
17
16
|
* `isLoading` prop to render a loading state.
|
|
18
17
|
*
|
|
18
|
+
* @deprecated Experimental since 2026-06-15. Not scheduled for removal; the API may change in any release.
|
|
19
|
+
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```tsx
|
|
21
22
|
* const mentions = unstable_useLiveCompletionAdapter({
|
|
@@ -39,7 +40,7 @@ function unstable_useLiveCompletionAdapter(options) {
|
|
|
39
40
|
});
|
|
40
41
|
const [isLoading, setIsLoading] = useState(false);
|
|
41
42
|
const fetcherRef = useRef(fetcher);
|
|
42
|
-
|
|
43
|
+
useIsomorphicLayoutEffect(() => {
|
|
43
44
|
fetcherRef.current = fetcher;
|
|
44
45
|
}, [fetcher]);
|
|
45
46
|
const timerRef = useRef(null);
|
|
@@ -107,7 +108,7 @@ function unstable_useLiveCompletionAdapter(options) {
|
|
|
107
108
|
rearmPendingRetry
|
|
108
109
|
]);
|
|
109
110
|
const scheduleFetchRef = useRef(scheduleFetch);
|
|
110
|
-
|
|
111
|
+
useIsomorphicLayoutEffect(() => {
|
|
111
112
|
scheduleFetchRef.current = scheduleFetch;
|
|
112
113
|
}, [scheduleFetch]);
|
|
113
114
|
const invalidatePending = useCallback(() => {
|
|
@@ -118,7 +119,7 @@ function unstable_useLiveCompletionAdapter(options) {
|
|
|
118
119
|
setIsLoading(false);
|
|
119
120
|
}, [cancelTimer, rearmPendingRetry]);
|
|
120
121
|
const cacheKeyRef = useRef(cacheKey);
|
|
121
|
-
|
|
122
|
+
useIsomorphicLayoutEffect(() => {
|
|
122
123
|
if (cacheKeyRef.current === cacheKey) return;
|
|
123
124
|
cacheKeyRef.current = cacheKey;
|
|
124
125
|
invalidatePending();
|
|
@@ -139,7 +140,7 @@ function unstable_useLiveCompletionAdapter(options) {
|
|
|
139
140
|
failed: false
|
|
140
141
|
});
|
|
141
142
|
}, [enabled, invalidatePending]);
|
|
142
|
-
|
|
143
|
+
useIsomorphicLayoutEffect(() => {
|
|
143
144
|
inactiveRef.current = false;
|
|
144
145
|
const deferredQuery = deferredQueryRef.current;
|
|
145
146
|
deferredQueryRef.current = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLiveCompletionAdapter.js","names":["useCallback","useEffect","useLayoutEffect","useMemo","useRef","useState","Unstable_TriggerAdapter","Unstable_TriggerItem","Unstable_UseLiveCompletionAdapterOptions","fetcher","query","Promise","cacheKey","debounceMs","enabled","NO_QUERY","unstable_useLiveCompletionAdapter","options","adapter","isLoading","state","setState","items","failed","setIsLoading","fetcherRef","current","timerRef","ReturnType","setTimeout","tokenRef","pendingQueryRef","retryableQueryRef","pendingRetryQueryRef","inactiveRef","deferredQueryRef","cancelTimer","clearTimeout","rearmPendingRetry","scheduleFetch","token","resolve","then","scheduleFetchRef","invalidatePending","cacheKeyRef","s","deferredQuery","categories","categoryItems","search","queueMicrotask"],"sources":["../../src/unstable/useLiveCompletionAdapter.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n Unstable_TriggerAdapter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\n\nexport type Unstable_UseLiveCompletionAdapterOptions = {\n /**\n * Fetches the items for a query from an async source. Called debounced; the\n * resolved items are cached and returned synchronously to the popover on the\n * next render.\n */\n readonly fetcher: (query: string) => Promise<readonly Unstable_TriggerItem[]>;\n /**\n * Identifies the fetcher's data source. Change this when switching accounts,\n * workspaces, or another boundary that should invalidate cached results.\n */\n readonly cacheKey?: string | number | undefined;\n /** Debounce applied before a fetch fires, in milliseconds. @default 60 */\n readonly debounceMs?: number | undefined;\n /** When `false`, no fetch is scheduled and the adapter stays empty. @default true */\n readonly enabled?: boolean | undefined;\n};\n\n/** Sentinel that no real query (including the empty string) equals, so the first query always fetches. */\nconst NO_QUERY = \"\\u0000\";\n\n/**\n * @deprecated Under active development and may change without notice.\n *\n * Bridges an async completion source (a server search, a gateway RPC) into the\n * synchronous `Unstable_TriggerAdapter` that `ComposerTriggerPopover` consumes.\n * `search(query)` returns the last fetched items synchronously and schedules a\n * debounced fetch when the query changes; when results arrive the returned\n * `adapter` identity changes, which re-runs the popover's lookup so the fresh\n * items render. This is a search-only adapter (`categories` are empty).\n *\n * `isLoading` is `true` while a fetch is in flight. Pass it to the popover's\n * `isLoading` prop to render a loading state.\n *\n * @example\n * ```tsx\n * const mentions = unstable_useLiveCompletionAdapter({\n * fetcher: (query) => searchUsers(query),\n * });\n *\n * <ComposerTriggerPopover\n * char=\"@\"\n * adapter={mentions.adapter}\n * isLoading={mentions.isLoading}\n * directive={{ onInserted }}\n * />\n * ```\n */\nexport function unstable_useLiveCompletionAdapter(\n options: Unstable_UseLiveCompletionAdapterOptions,\n): { adapter: Unstable_TriggerAdapter; isLoading: boolean } {\n const { fetcher, cacheKey, debounceMs = 60, enabled = true } = options;\n\n const [state, setState] = useState<{\n query: string;\n items: readonly Unstable_TriggerItem[];\n failed: boolean;\n }>({ query: NO_QUERY, items: [], failed: false });\n const [isLoading, setIsLoading] = useState(false);\n\n const fetcherRef = useRef(fetcher);\n // The debounce timer must only observe fetchers from committed renders.\n useLayoutEffect(() => {\n fetcherRef.current = fetcher;\n }, [fetcher]);\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const tokenRef = useRef(0);\n const pendingQueryRef = useRef<string | null>(null);\n const retryableQueryRef = useRef<string | null>(null);\n const pendingRetryQueryRef = useRef<string | null>(null);\n const inactiveRef = useRef(true);\n const deferredQueryRef = useRef<string | null>(null);\n\n const cancelTimer = useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const rearmPendingRetry = useCallback(() => {\n const query = pendingRetryQueryRef.current;\n if (query === null) return;\n retryableQueryRef.current = query;\n pendingRetryQueryRef.current = null;\n }, []);\n\n const scheduleFetch = useCallback(\n (query: string) => {\n if (!enabled) return;\n if (inactiveRef.current) {\n deferredQueryRef.current = query;\n return;\n }\n if (pendingQueryRef.current === query) return;\n rearmPendingRetry();\n if (retryableQueryRef.current === query) {\n retryableQueryRef.current = null;\n pendingRetryQueryRef.current = query;\n }\n pendingQueryRef.current = query;\n cancelTimer();\n const token = ++tokenRef.current;\n setIsLoading(true);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n Promise.resolve()\n .then(() => fetcherRef.current(query))\n .then(\n (items) => {\n if (token !== tokenRef.current) return;\n pendingRetryQueryRef.current = null;\n setState({ query, items, failed: false });\n setIsLoading(false);\n },\n () => {\n if (token !== tokenRef.current) return;\n pendingQueryRef.current = null;\n pendingRetryQueryRef.current = null;\n setState({ query, items: [], failed: true });\n setIsLoading(false);\n },\n );\n }, debounceMs);\n },\n [enabled, debounceMs, cancelTimer, rearmPendingRetry],\n );\n\n const scheduleFetchRef = useRef(scheduleFetch);\n useLayoutEffect(() => {\n scheduleFetchRef.current = scheduleFetch;\n }, [scheduleFetch]);\n\n const invalidatePending = useCallback(() => {\n rearmPendingRetry();\n cancelTimer();\n pendingQueryRef.current = null;\n tokenRef.current += 1;\n setIsLoading(false);\n }, [cancelTimer, rearmPendingRetry]);\n\n const cacheKeyRef = useRef(cacheKey);\n useLayoutEffect(() => {\n if (cacheKeyRef.current === cacheKey) return;\n cacheKeyRef.current = cacheKey;\n invalidatePending();\n retryableQueryRef.current = null;\n pendingRetryQueryRef.current = null;\n setState({ query: NO_QUERY, items: [], failed: false });\n }, [cacheKey, invalidatePending]);\n\n useEffect(() => {\n if (enabled) return;\n invalidatePending();\n setState((s) =>\n s.query === NO_QUERY ? s : { query: NO_QUERY, items: [], failed: false },\n );\n }, [enabled, invalidatePending]);\n\n // Render-time searches can outlive an abandoned render, so they only arm\n // request work after this hook commits.\n useLayoutEffect(() => {\n inactiveRef.current = false;\n const deferredQuery = deferredQueryRef.current;\n deferredQueryRef.current = null;\n if (deferredQuery !== null) scheduleFetchRef.current(deferredQuery);\n return () => {\n inactiveRef.current = true;\n invalidatePending();\n };\n }, [invalidatePending]);\n\n // Arm retries only after the failed state commits. Arming during rejection\n // would let the failure render immediately schedule another request.\n useEffect(() => {\n retryableQueryRef.current = state.failed ? state.query : null;\n }, [state]);\n\n const adapter = useMemo<Unstable_TriggerAdapter>(\n () => ({\n categories: () => [],\n categoryItems: () => [],\n search: (query: string) => {\n // search() runs inside the popover's render; defer state updates with\n // queueMicrotask so they are not dispatched while another component renders.\n if (query !== state.query || retryableQueryRef.current === query) {\n queueMicrotask(() => scheduleFetch(query));\n } else {\n queueMicrotask(() => {\n if (\n deferredQueryRef.current !== null &&\n deferredQueryRef.current !== query\n ) {\n deferredQueryRef.current = null;\n }\n if (\n pendingQueryRef.current !== null &&\n pendingQueryRef.current !== query\n ) {\n invalidatePending();\n }\n });\n }\n return state.items;\n },\n }),\n [state, scheduleFetch, invalidatePending],\n );\n\n return { adapter, isLoading };\n}\n"],"mappings":";;;;AAkCA,MAAMe,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BjB,SAAgBC,kCACdC,SAC0D;CAC1D,MAAM,EAAER,SAASG,UAAUC,aAAa,IAAIC,UAAU,SAASG;CAE/D,MAAM,CAACG,OAAOC,YAAYhB,SAIvB;EAAEK,OAAOK;EAAUO,OAAO,CAAA;EAAIC,QAAQ;CAAM,CAAC;CAChD,MAAM,CAACJ,WAAWK,gBAAgBnB,SAAS,KAAK;CAEhD,MAAMoB,aAAarB,OAAOK,OAAO;CAEjCP,sBAAsB;EACpBuB,WAAWC,UAAUjB;CACvB,GAAG,CAACA,OAAO,CAAC;CAEZ,MAAMkB,WAAWvB,OAA6C,IAAI;CAClE,MAAM0B,WAAW1B,OAAO,CAAC;CACzB,MAAM2B,kBAAkB3B,OAAsB,IAAI;CAClD,MAAM4B,oBAAoB5B,OAAsB,IAAI;CACpD,MAAM6B,uBAAuB7B,OAAsB,IAAI;CACvD,MAAM8B,cAAc9B,OAAO,IAAI;CAC/B,MAAM+B,mBAAmB/B,OAAsB,IAAI;CAEnD,MAAMgC,cAAcpC,kBAAkB;EACpC,IAAI2B,SAASD,YAAY,MAAM;GAC7BW,aAAaV,SAASD,OAAO;GAC7BC,SAASD,UAAU;EACrB;CACF,GAAG,CAAA,CAAE;CAEL,MAAMY,oBAAoBtC,kBAAkB;EAC1C,MAAMU,QAAQuB,qBAAqBP;EACnC,IAAIhB,UAAU,MAAM;EACpBsB,kBAAkBN,UAAUhB;EAC5BuB,qBAAqBP,UAAU;CACjC,GAAG,CAAA,CAAE;CAEL,MAAMa,gBAAgBvC,aACnBU,UAAkB;EACjB,IAAI,CAACI,SAAS;EACd,IAAIoB,YAAYR,SAAS;GACvBS,iBAAiBT,UAAUhB;GAC3B;EACF;EACA,IAAIqB,gBAAgBL,YAAYhB,OAAO;EACvC4B,kBAAkB;EAClB,IAAIN,kBAAkBN,YAAYhB,OAAO;GACvCsB,kBAAkBN,UAAU;GAC5BO,qBAAqBP,UAAUhB;EACjC;EACAqB,gBAAgBL,UAAUhB;EAC1B0B,YAAY;EACZ,MAAMI,QAAQ,EAAEV,SAASJ;EACzBF,aAAa,IAAI;EACjBG,SAASD,UAAUG,iBAAiB;GAClCF,SAASD,UAAU;GACnBf,QAAQ8B,QAAQ,CAAC,CACdC,WAAWjB,WAAWC,QAAQhB,KAAK,CAAC,CAAC,CACrCgC,MACEpB,UAAU;IACT,IAAIkB,UAAUV,SAASJ,SAAS;IAChCO,qBAAqBP,UAAU;IAC/BL,SAAS;KAAEX;KAAOY;KAAOC,QAAQ;IAAM,CAAC;IACxCC,aAAa,KAAK;GACpB,SACM;IACJ,IAAIgB,UAAUV,SAASJ,SAAS;IAChCK,gBAAgBL,UAAU;IAC1BO,qBAAqBP,UAAU;IAC/BL,SAAS;KAAEX;KAAOY,OAAO,CAAA;KAAIC,QAAQ;IAAK,CAAC;IAC3CC,aAAa,KAAK;GACpB,CACF;EACJ,GAAGX,UAAU;CACf,GACA;EAACC;EAASD;EAAYuB;EAAaE;CAAiB,CACtD;CAEA,MAAMK,mBAAmBvC,OAAOmC,aAAa;CAC7CrC,sBAAsB;EACpByC,iBAAiBjB,UAAUa;CAC7B,GAAG,CAACA,aAAa,CAAC;CAElB,MAAMK,oBAAoB5C,kBAAkB;EAC1CsC,kBAAkB;EAClBF,YAAY;EACZL,gBAAgBL,UAAU;EAC1BI,SAASJ,WAAW;EACpBF,aAAa,KAAK;CACpB,GAAG,CAACY,aAAaE,iBAAiB,CAAC;CAEnC,MAAMO,cAAczC,OAAOQ,QAAQ;CACnCV,sBAAsB;EACpB,IAAI2C,YAAYnB,YAAYd,UAAU;EACtCiC,YAAYnB,UAAUd;EACtBgC,kBAAkB;EAClBZ,kBAAkBN,UAAU;EAC5BO,qBAAqBP,UAAU;EAC/BL,SAAS;GAAEX,OAAOK;GAAUO,OAAO,CAAA;GAAIC,QAAQ;EAAM,CAAC;CACxD,GAAG,CAACX,UAAUgC,iBAAiB,CAAC;CAEhC3C,gBAAgB;EACd,IAAIa,SAAS;EACb8B,kBAAkB;EAClBvB,UAAUyB,MACRA,EAAEpC,UAAUK,WAAW+B,IAAI;GAAEpC,OAAOK;GAAUO,OAAO,CAAA;GAAIC,QAAQ;EAAM,CACzE;CACF,GAAG,CAACT,SAAS8B,iBAAiB,CAAC;CAI/B1C,sBAAsB;EACpBgC,YAAYR,UAAU;EACtB,MAAMqB,gBAAgBZ,iBAAiBT;EACvCS,iBAAiBT,UAAU;EAC3B,IAAIqB,kBAAkB,MAAMJ,iBAAiBjB,QAAQqB,aAAa;EAClE,aAAa;GACXb,YAAYR,UAAU;GACtBkB,kBAAkB;EACpB;CACF,GAAG,CAACA,iBAAiB,CAAC;CAItB3C,gBAAgB;EACd+B,kBAAkBN,UAAUN,MAAMG,SAASH,MAAMV,QAAQ;CAC3D,GAAG,CAACU,KAAK,CAAC;CAiCV,OAAO;EAAEF,SA/BOf,eACP;GACL6C,kBAAkB,CAAA;GAClBC,qBAAqB,CAAA;GACrBC,SAASxC,UAAkB;IAGzB,IAAIA,UAAUU,MAAMV,SAASsB,kBAAkBN,YAAYhB,OACzDyC,qBAAqBZ,cAAc7B,KAAK,CAAC;SAEzCyC,qBAAqB;KACnB,IACEhB,iBAAiBT,YAAY,QAC7BS,iBAAiBT,YAAYhB,OAE7ByB,iBAAiBT,UAAU;KAE7B,IACEK,gBAAgBL,YAAY,QAC5BK,gBAAgBL,YAAYhB,OAE5BkC,kBAAkB;IAEtB,CAAC;IAEH,OAAOxB,MAAME;GACf;EACF,IACA;GAACF;GAAOmB;GAAeK;EAAiB,CAGjC1B;EAASC;CAAU;AAC9B"}
|
|
1
|
+
{"version":3,"file":"useLiveCompletionAdapter.js","names":["useCallback","useEffect","useMemo","useRef","useState","useIsomorphicLayoutEffect","Unstable_TriggerAdapter","Unstable_TriggerItem","Unstable_UseLiveCompletionAdapterOptions","fetcher","query","Promise","cacheKey","debounceMs","enabled","NO_QUERY","unstable_useLiveCompletionAdapter","options","adapter","isLoading","state","setState","items","failed","setIsLoading","fetcherRef","current","timerRef","ReturnType","setTimeout","tokenRef","pendingQueryRef","retryableQueryRef","pendingRetryQueryRef","inactiveRef","deferredQueryRef","cancelTimer","clearTimeout","rearmPendingRetry","scheduleFetch","token","resolve","then","scheduleFetchRef","invalidatePending","cacheKeyRef","s","deferredQuery","categories","categoryItems","search","queueMicrotask"],"sources":["../../src/unstable/useLiveCompletionAdapter.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"../utils/useIsomorphicLayoutEffect\";\nimport type {\n Unstable_TriggerAdapter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\n\n/** @deprecated Experimental since 2026-06-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_UseLiveCompletionAdapterOptions = {\n /**\n * Fetches the items for a query from an async source. Called debounced; the\n * resolved items are cached and returned synchronously to the popover on the\n * next render.\n */\n readonly fetcher: (query: string) => Promise<readonly Unstable_TriggerItem[]>;\n /**\n * Identifies the fetcher's data source. Change this when switching accounts,\n * workspaces, or another boundary that should invalidate cached results.\n */\n readonly cacheKey?: string | number | undefined;\n /** Debounce applied before a fetch fires, in milliseconds. @default 60 */\n readonly debounceMs?: number | undefined;\n /** When `false`, no fetch is scheduled and the adapter stays empty. @default true */\n readonly enabled?: boolean | undefined;\n};\n\n/** Sentinel that no real query (including the empty string) equals, so the first query always fetches. */\nconst NO_QUERY = \"\\u0000\";\n\n/**\n * Bridges an async completion source (a server search, a gateway RPC) into the\n * synchronous `Unstable_TriggerAdapter` that `ComposerTriggerPopover` consumes.\n * `search(query)` returns the last fetched items synchronously and schedules a\n * debounced fetch when the query changes; when results arrive the returned\n * `adapter` identity changes, which re-runs the popover's lookup so the fresh\n * items render. This is a search-only adapter (`categories` are empty).\n *\n * `isLoading` is `true` while a fetch is in flight. Pass it to the popover's\n * `isLoading` prop to render a loading state.\n *\n * @deprecated Experimental since 2026-06-15. Not scheduled for removal; the API may change in any release.\n *\n * @example\n * ```tsx\n * const mentions = unstable_useLiveCompletionAdapter({\n * fetcher: (query) => searchUsers(query),\n * });\n *\n * <ComposerTriggerPopover\n * char=\"@\"\n * adapter={mentions.adapter}\n * isLoading={mentions.isLoading}\n * directive={{ onInserted }}\n * />\n * ```\n */\nexport function unstable_useLiveCompletionAdapter(\n options: Unstable_UseLiveCompletionAdapterOptions,\n): { adapter: Unstable_TriggerAdapter; isLoading: boolean } {\n const { fetcher, cacheKey, debounceMs = 60, enabled = true } = options;\n\n const [state, setState] = useState<{\n query: string;\n items: readonly Unstable_TriggerItem[];\n failed: boolean;\n }>({ query: NO_QUERY, items: [], failed: false });\n const [isLoading, setIsLoading] = useState(false);\n\n const fetcherRef = useRef(fetcher);\n // The debounce timer must only observe fetchers from committed renders.\n useIsomorphicLayoutEffect(() => {\n fetcherRef.current = fetcher;\n }, [fetcher]);\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const tokenRef = useRef(0);\n const pendingQueryRef = useRef<string | null>(null);\n const retryableQueryRef = useRef<string | null>(null);\n const pendingRetryQueryRef = useRef<string | null>(null);\n const inactiveRef = useRef(true);\n const deferredQueryRef = useRef<string | null>(null);\n\n const cancelTimer = useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const rearmPendingRetry = useCallback(() => {\n const query = pendingRetryQueryRef.current;\n if (query === null) return;\n retryableQueryRef.current = query;\n pendingRetryQueryRef.current = null;\n }, []);\n\n const scheduleFetch = useCallback(\n (query: string) => {\n if (!enabled) return;\n if (inactiveRef.current) {\n deferredQueryRef.current = query;\n return;\n }\n if (pendingQueryRef.current === query) return;\n rearmPendingRetry();\n if (retryableQueryRef.current === query) {\n retryableQueryRef.current = null;\n pendingRetryQueryRef.current = query;\n }\n pendingQueryRef.current = query;\n cancelTimer();\n const token = ++tokenRef.current;\n setIsLoading(true);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n Promise.resolve()\n .then(() => fetcherRef.current(query))\n .then(\n (items) => {\n if (token !== tokenRef.current) return;\n pendingRetryQueryRef.current = null;\n setState({ query, items, failed: false });\n setIsLoading(false);\n },\n () => {\n if (token !== tokenRef.current) return;\n pendingQueryRef.current = null;\n pendingRetryQueryRef.current = null;\n setState({ query, items: [], failed: true });\n setIsLoading(false);\n },\n );\n }, debounceMs);\n },\n [enabled, debounceMs, cancelTimer, rearmPendingRetry],\n );\n\n const scheduleFetchRef = useRef(scheduleFetch);\n useIsomorphicLayoutEffect(() => {\n scheduleFetchRef.current = scheduleFetch;\n }, [scheduleFetch]);\n\n const invalidatePending = useCallback(() => {\n rearmPendingRetry();\n cancelTimer();\n pendingQueryRef.current = null;\n tokenRef.current += 1;\n setIsLoading(false);\n }, [cancelTimer, rearmPendingRetry]);\n\n const cacheKeyRef = useRef(cacheKey);\n useIsomorphicLayoutEffect(() => {\n if (cacheKeyRef.current === cacheKey) return;\n cacheKeyRef.current = cacheKey;\n invalidatePending();\n retryableQueryRef.current = null;\n pendingRetryQueryRef.current = null;\n setState({ query: NO_QUERY, items: [], failed: false });\n }, [cacheKey, invalidatePending]);\n\n useEffect(() => {\n if (enabled) return;\n invalidatePending();\n setState((s) =>\n s.query === NO_QUERY ? s : { query: NO_QUERY, items: [], failed: false },\n );\n }, [enabled, invalidatePending]);\n\n // Render-time searches can outlive an abandoned render, so they only arm\n // request work after this hook commits.\n useIsomorphicLayoutEffect(() => {\n inactiveRef.current = false;\n const deferredQuery = deferredQueryRef.current;\n deferredQueryRef.current = null;\n if (deferredQuery !== null) scheduleFetchRef.current(deferredQuery);\n return () => {\n inactiveRef.current = true;\n invalidatePending();\n };\n }, [invalidatePending]);\n\n // Arm retries only after the failed state commits. Arming during rejection\n // would let the failure render immediately schedule another request.\n useEffect(() => {\n retryableQueryRef.current = state.failed ? state.query : null;\n }, [state]);\n\n const adapter = useMemo<Unstable_TriggerAdapter>(\n () => ({\n categories: () => [],\n categoryItems: () => [],\n search: (query: string) => {\n // search() runs inside the popover's render; defer state updates with\n // queueMicrotask so they are not dispatched while another component renders.\n if (query !== state.query || retryableQueryRef.current === query) {\n queueMicrotask(() => scheduleFetch(query));\n } else {\n queueMicrotask(() => {\n if (\n deferredQueryRef.current !== null &&\n deferredQueryRef.current !== query\n ) {\n deferredQueryRef.current = null;\n }\n if (\n pendingQueryRef.current !== null &&\n pendingQueryRef.current !== query\n ) {\n invalidatePending();\n }\n });\n }\n return state.items;\n },\n }),\n [state, scheduleFetch, invalidatePending],\n );\n\n return { adapter, isLoading };\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { type FC } from "react";
|
|
2
2
|
import type { Unstable_DirectiveFormatter, Unstable_TriggerAdapter, Unstable_TriggerItem } from "@assistant-ui/core";
|
|
3
3
|
import type { ReadonlyJSONObject } from "assistant-stream/utils";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Icon component shape consumed by `ComposerTriggerPopover`'s `iconMap`.
|
|
6
|
+
*
|
|
7
|
+
* @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release.
|
|
8
|
+
*/
|
|
5
9
|
export type Unstable_IconComponent = FC<{
|
|
6
10
|
className?: string;
|
|
7
11
|
}>;
|
|
12
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
8
13
|
export type Unstable_Mention = {
|
|
9
14
|
readonly id: string;
|
|
10
15
|
readonly type: string;
|
|
@@ -14,11 +19,13 @@ export type Unstable_Mention = {
|
|
|
14
19
|
readonly icon?: string | undefined;
|
|
15
20
|
readonly metadata?: ReadonlyJSONObject | undefined;
|
|
16
21
|
};
|
|
22
|
+
/** @deprecated Experimental since 2026-03-16. Not scheduled for removal; the API may change in any release. */
|
|
17
23
|
export type Unstable_MentionCategory = {
|
|
18
24
|
readonly id: string;
|
|
19
25
|
readonly label: string;
|
|
20
26
|
readonly items: readonly Unstable_Mention[];
|
|
21
27
|
};
|
|
28
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
22
29
|
export type Unstable_ModelContextToolsOptions = {
|
|
23
30
|
/**
|
|
24
31
|
* Wrap tools in a dedicated category. Selects drill-down mode on its own
|
|
@@ -33,6 +40,7 @@ export type Unstable_ModelContextToolsOptions = {
|
|
|
33
40
|
/** Default icon key for each tool. */
|
|
34
41
|
readonly icon?: string;
|
|
35
42
|
};
|
|
43
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
36
44
|
export type Unstable_UseMentionAdapterOptions = {
|
|
37
45
|
/**
|
|
38
46
|
* Flat mention list. Ignored when `categories` is set, and keeps the
|
|
@@ -60,17 +68,18 @@ export type Unstable_UseMentionAdapterOptions = {
|
|
|
60
68
|
/** Fallback icon when no entry in `iconMap` matches. */
|
|
61
69
|
readonly fallbackIcon?: Unstable_IconComponent;
|
|
62
70
|
};
|
|
71
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
63
72
|
export type Unstable_MentionDirective = {
|
|
64
73
|
readonly formatter: Unstable_DirectiveFormatter;
|
|
65
74
|
readonly onInserted?: ((item: Unstable_TriggerItem) => void) | undefined;
|
|
66
75
|
};
|
|
67
76
|
/**
|
|
68
|
-
* @deprecated Under active development and might change without notice.
|
|
69
|
-
*
|
|
70
77
|
* Creates a spreadable `{ adapter, directive }` bundle for `@` mentions.
|
|
71
78
|
* Supports tools registered in model context, explicit items, or both —
|
|
72
79
|
* flat or categorized.
|
|
73
80
|
*
|
|
81
|
+
* @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release.
|
|
82
|
+
*
|
|
74
83
|
* @example
|
|
75
84
|
* ```tsx
|
|
76
85
|
* const mention = unstable_useMentionAdapter();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMentionAdapter.d.ts","sourceRoot":"","sources":["../../src/unstable/useMentionAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAEzC,OAAO,KAAK,EACV,2BAA2B,EAC3B,uBAAuB,EAEvB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAQjE
|
|
1
|
+
{"version":3,"file":"useMentionAdapter.d.ts","sourceRoot":"","sources":["../../src/unstable/useMentionAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,12 +29,12 @@ const toolMentionSource = {
|
|
|
29
29
|
isEqual: shallowEqualRecords
|
|
30
30
|
};
|
|
31
31
|
/**
|
|
32
|
-
* @deprecated Under active development and might change without notice.
|
|
33
|
-
*
|
|
34
32
|
* Creates a spreadable `{ adapter, directive }` bundle for `@` mentions.
|
|
35
33
|
* Supports tools registered in model context, explicit items, or both —
|
|
36
34
|
* flat or categorized.
|
|
37
35
|
*
|
|
36
|
+
* @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release.
|
|
37
|
+
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```tsx
|
|
40
40
|
* const mention = unstable_useMentionAdapter();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMentionAdapter.js","names":["useMemo","FC","useAui","Unstable_DirectiveFormatter","Unstable_TriggerAdapter","Unstable_TriggerCategory","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","ReadonlyJSONObject","matchesTriggerItemQuery","shallowEqualRecords","useModelContextSnapshot","ModelContextSnapshotSource","Unstable_IconComponent","className","Unstable_Mention","id","type","label","description","icon","metadata","Unstable_MentionCategory","items","Unstable_ModelContextToolsOptions","category","formatLabel","toolName","Unstable_UseMentionAdapterOptions","categories","includeModelContextTools","formatter","onInserted","item","iconMap","Record","fallbackIcon","Unstable_MentionDirective","EMPTY_TOOL_MENTIONS","Readonly","Object","freeze","toolMentionSource","empty","read","aui","tools","thread","getModelContext","mentions","create","name","tool","entries","subscribe","onChange","unsubscribeContext","on","unsubscribeSelection","scope","event","isEqual","unstable_useMentionAdapter","options","adapter","directive","includeTools","toolsConfig","undefined","wantsTools","isCategorized","toolMentions","defaultIcon","toolItems","map","toTriggerItem","groups","cat","allGroups","length","categoryItems","find","g","search","query","lower","toLowerCase","flatMap","filter","flatItems","seen","Set","i","flatPool","t","has","m"],"sources":["../../src/unstable/useMentionAdapter.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, type FC } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerAdapter,\n Unstable_TriggerCategory,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport { matchesTriggerItemQuery } from \"../primitives/composer/trigger/matchesTriggerItemQuery\";\nimport {\n shallowEqualRecords,\n useModelContextSnapshot,\n type ModelContextSnapshotSource,\n} from \"./useModelContextSnapshot\";\n\n/** Icon component shape consumed by `ComposerTriggerPopover`'s `iconMap`. */\nexport type Unstable_IconComponent = FC<{ className?: string }>;\n\nexport type Unstable_Mention = {\n readonly id: string;\n readonly type: string;\n readonly label: string;\n readonly description?: string | undefined;\n /** Shortcut for `metadata.icon`; merged with `metadata` if both are given. */\n readonly icon?: string | undefined;\n readonly metadata?: ReadonlyJSONObject | undefined;\n};\n\nexport type Unstable_MentionCategory = {\n readonly id: string;\n readonly label: string;\n readonly items: readonly Unstable_Mention[];\n};\n\nexport type Unstable_ModelContextToolsOptions = {\n /**\n * Wrap tools in a dedicated category. Selects drill-down mode on its own\n * when `categories` is unset and `items` is omitted.\n */\n readonly category?: { readonly id: string; readonly label: string };\n /** Format tool name for display. */\n readonly formatLabel?: (toolName: string) => string;\n /** Default icon key for each tool. */\n readonly icon?: string;\n};\n\nexport type Unstable_UseMentionAdapterOptions = {\n /**\n * Flat mention list. Ignored when `categories` is set, and keeps the\n * adapter flat when a tool `category` is configured.\n */\n readonly items?: readonly Unstable_Mention[];\n /** Categorized mentions for drill-down navigation. */\n readonly categories?: readonly Unstable_MentionCategory[];\n /**\n * How tools registered in model context integrate.\n * - `false`: exclude.\n * - `true`: include (default when no `items`/`categories`; as a category\n * if `categories` is set, flat otherwise).\n * - object: explicit config; `category` also selects drill-down mode.\n *\n * Omitted → defaults to `true` iff neither `items` nor `categories`.\n */\n readonly includeModelContextTools?:\n | boolean\n | Unstable_ModelContextToolsOptions;\n /** Directive formatter. @default unstable_defaultDirectiveFormatter */\n readonly formatter?: Unstable_DirectiveFormatter;\n /** Fires after an item is inserted into the composer. */\n readonly onInserted?: (item: Unstable_TriggerItem) => void;\n /** Maps `metadata.icon` / `category.id` string keys to React components. */\n readonly iconMap?: Record<string, Unstable_IconComponent>;\n /** Fallback icon when no entry in `iconMap` matches. */\n readonly fallbackIcon?: Unstable_IconComponent;\n};\n\nexport type Unstable_MentionDirective = {\n readonly formatter: Unstable_DirectiveFormatter;\n readonly onInserted?: ((item: Unstable_TriggerItem) => void) | undefined;\n};\n\nconst EMPTY_TOOL_MENTIONS: Readonly<Record<string, string | undefined>> =\n Object.freeze({});\n\n// The description is copied out rather than reached through the tool, so a\n// provider that returns a stable tool object and edits it in place is observed.\nconst toolMentionSource: ModelContextSnapshotSource<\n Readonly<Record<string, string | undefined>>\n> = {\n empty: EMPTY_TOOL_MENTIONS,\n read: (aui) => {\n const tools = aui.thread.getModelContext().tools;\n if (!tools) return EMPTY_TOOL_MENTIONS;\n const mentions = Object.create(null) as Record<string, string | undefined>;\n for (const [name, tool] of Object.entries(tools)) {\n mentions[name] = tool.description;\n }\n return mentions;\n },\n subscribe: (aui, onChange) => {\n const unsubscribeContext = aui.on(\"thread.modelContextUpdate\", onChange);\n // Rebinding the thread event subject to a new thread does not replay it,\n // so a switch between threads carrying different providers is its own\n // refresh trigger. Subscribed globally because a composer can render\n // without a thread list scope.\n const unsubscribeSelection = aui.on(\n { scope: \"*\", event: \"threads.selectionChanged\" },\n onChange,\n );\n return () => {\n unsubscribeContext();\n unsubscribeSelection();\n };\n },\n isEqual: shallowEqualRecords,\n};\n\n/**\n * @deprecated Under active development and might change without notice.\n *\n * Creates a spreadable `{ adapter, directive }` bundle for `@` mentions.\n * Supports tools registered in model context, explicit items, or both —\n * flat or categorized.\n *\n * @example\n * ```tsx\n * const mention = unstable_useMentionAdapter();\n * <ComposerTriggerPopover char=\"@\" {...mention} />\n * ```\n */\nexport function unstable_useMentionAdapter(\n options?: Unstable_UseMentionAdapterOptions,\n): {\n adapter: Unstable_TriggerAdapter;\n directive: Unstable_MentionDirective;\n iconMap?: Record<string, Unstable_IconComponent>;\n fallbackIcon?: Unstable_IconComponent;\n} {\n const aui = useAui();\n\n const items = options?.items;\n const categories = options?.categories;\n const includeTools =\n options?.includeModelContextTools ?? (!items && !categories);\n const toolsConfig =\n typeof includeTools === \"object\" ? includeTools : undefined;\n const wantsTools = includeTools !== false;\n const formatter = options?.formatter;\n const onInserted = options?.onInserted;\n const isCategorized =\n categories !== undefined ||\n (toolsConfig?.category !== undefined && items === undefined);\n const toolMentions = useModelContextSnapshot(\n aui,\n wantsTools,\n toolMentionSource,\n );\n\n const adapter = useMemo<Unstable_TriggerAdapter>(() => {\n const formatLabel = toolsConfig?.formatLabel;\n const defaultIcon = toolsConfig?.icon;\n const toolItems = wantsTools\n ? Object.entries(toolMentions).map(([name, description]) =>\n toTriggerItem({\n id: name,\n type: \"tool\",\n label: formatLabel ? formatLabel(name) : name,\n description,\n icon: defaultIcon,\n }),\n )\n : [];\n\n // Categorized: drill-down mode\n if (isCategorized) {\n const groups = (categories ?? []).map((cat) => ({\n id: cat.id,\n label: cat.label,\n items: cat.items.map(toTriggerItem),\n }));\n const allGroups =\n toolItems.length > 0\n ? [\n ...groups,\n {\n id: toolsConfig?.category?.id ?? \"tools\",\n label: toolsConfig?.category?.label ?? \"Tools\",\n items: toolItems,\n },\n ]\n : groups;\n\n return {\n categories: () => allGroups.map(({ id, label }) => ({ id, label })),\n categoryItems: (id) => allGroups.find((g) => g.id === id)?.items ?? [],\n search: (query) => {\n const lower = query.toLowerCase();\n return allGroups\n .flatMap((g) => g.items)\n .filter((item) => matchesTriggerItemQuery(item, lower));\n },\n };\n }\n\n // Flat: items + (optionally) tools, all in one search pool\n const flatItems = (items ?? []).map(toTriggerItem);\n // Dedupe by id — explicit items win.\n const seen = new Set(flatItems.map((i) => i.id));\n const flatPool = [\n ...flatItems,\n ...toolItems.filter((t) => !seen.has(t.id)),\n ];\n\n return {\n categories: (): readonly Unstable_TriggerCategory[] => [],\n categoryItems: () => [],\n search: (query) => {\n const lower = query.toLowerCase();\n return flatPool.filter((item) => matchesTriggerItemQuery(item, lower));\n },\n };\n }, [items, categories, wantsTools, toolsConfig, isCategorized, toolMentions]);\n\n const directive = useMemo<Unstable_MentionDirective>(\n () => ({\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n ...(onInserted ? { onInserted } : {}),\n }),\n [formatter, onInserted],\n );\n\n return {\n adapter,\n directive,\n ...(options?.iconMap ? { iconMap: options.iconMap } : {}),\n ...(options?.fallbackIcon ? { fallbackIcon: options.fallbackIcon } : {}),\n };\n}\n\nfunction toTriggerItem(m: Unstable_Mention): Unstable_TriggerItem {\n const metadata =\n m.icon !== undefined ? { ...(m.metadata ?? {}), icon: m.icon } : m.metadata;\n return {\n id: m.id,\n type: m.type,\n label: m.label,\n ...(m.description !== undefined ? { description: m.description } : {}),\n ...(metadata !== undefined ? { metadata } : {}),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useMentionAdapter.js","names":["useMemo","FC","useAui","Unstable_DirectiveFormatter","Unstable_TriggerAdapter","Unstable_TriggerCategory","Unstable_TriggerItem","unstable_defaultDirectiveFormatter","ReadonlyJSONObject","matchesTriggerItemQuery","shallowEqualRecords","useModelContextSnapshot","ModelContextSnapshotSource","Unstable_IconComponent","className","Unstable_Mention","id","type","label","description","icon","metadata","Unstable_MentionCategory","items","Unstable_ModelContextToolsOptions","category","formatLabel","toolName","Unstable_UseMentionAdapterOptions","categories","includeModelContextTools","formatter","onInserted","item","iconMap","Record","fallbackIcon","Unstable_MentionDirective","EMPTY_TOOL_MENTIONS","Readonly","Object","freeze","toolMentionSource","empty","read","aui","tools","thread","getModelContext","mentions","create","name","tool","entries","subscribe","onChange","unsubscribeContext","on","unsubscribeSelection","scope","event","isEqual","unstable_useMentionAdapter","options","adapter","directive","includeTools","toolsConfig","undefined","wantsTools","isCategorized","toolMentions","defaultIcon","toolItems","map","toTriggerItem","groups","cat","allGroups","length","categoryItems","find","g","search","query","lower","toLowerCase","flatMap","filter","flatItems","seen","Set","i","flatPool","t","has","m"],"sources":["../../src/unstable/useMentionAdapter.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, type FC } from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n Unstable_DirectiveFormatter,\n Unstable_TriggerAdapter,\n Unstable_TriggerCategory,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport { unstable_defaultDirectiveFormatter } from \"@assistant-ui/core\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport { matchesTriggerItemQuery } from \"../primitives/composer/trigger/matchesTriggerItemQuery\";\nimport {\n shallowEqualRecords,\n useModelContextSnapshot,\n type ModelContextSnapshotSource,\n} from \"./useModelContextSnapshot\";\n\n/**\n * Icon component shape consumed by `ComposerTriggerPopover`'s `iconMap`.\n *\n * @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release.\n */\nexport type Unstable_IconComponent = FC<{ className?: string }>;\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_Mention = {\n readonly id: string;\n readonly type: string;\n readonly label: string;\n readonly description?: string | undefined;\n /** Shortcut for `metadata.icon`; merged with `metadata` if both are given. */\n readonly icon?: string | undefined;\n readonly metadata?: ReadonlyJSONObject | undefined;\n};\n\n/** @deprecated Experimental since 2026-03-16. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_MentionCategory = {\n readonly id: string;\n readonly label: string;\n readonly items: readonly Unstable_Mention[];\n};\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_ModelContextToolsOptions = {\n /**\n * Wrap tools in a dedicated category. Selects drill-down mode on its own\n * when `categories` is unset and `items` is omitted.\n */\n readonly category?: { readonly id: string; readonly label: string };\n /** Format tool name for display. */\n readonly formatLabel?: (toolName: string) => string;\n /** Default icon key for each tool. */\n readonly icon?: string;\n};\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_UseMentionAdapterOptions = {\n /**\n * Flat mention list. Ignored when `categories` is set, and keeps the\n * adapter flat when a tool `category` is configured.\n */\n readonly items?: readonly Unstable_Mention[];\n /** Categorized mentions for drill-down navigation. */\n readonly categories?: readonly Unstable_MentionCategory[];\n /**\n * How tools registered in model context integrate.\n * - `false`: exclude.\n * - `true`: include (default when no `items`/`categories`; as a category\n * if `categories` is set, flat otherwise).\n * - object: explicit config; `category` also selects drill-down mode.\n *\n * Omitted → defaults to `true` iff neither `items` nor `categories`.\n */\n readonly includeModelContextTools?:\n | boolean\n | Unstable_ModelContextToolsOptions;\n /** Directive formatter. @default unstable_defaultDirectiveFormatter */\n readonly formatter?: Unstable_DirectiveFormatter;\n /** Fires after an item is inserted into the composer. */\n readonly onInserted?: (item: Unstable_TriggerItem) => void;\n /** Maps `metadata.icon` / `category.id` string keys to React components. */\n readonly iconMap?: Record<string, Unstable_IconComponent>;\n /** Fallback icon when no entry in `iconMap` matches. */\n readonly fallbackIcon?: Unstable_IconComponent;\n};\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_MentionDirective = {\n readonly formatter: Unstable_DirectiveFormatter;\n readonly onInserted?: ((item: Unstable_TriggerItem) => void) | undefined;\n};\n\nconst EMPTY_TOOL_MENTIONS: Readonly<Record<string, string | undefined>> =\n Object.freeze({});\n\n// The description is copied out rather than reached through the tool, so a\n// provider that returns a stable tool object and edits it in place is observed.\nconst toolMentionSource: ModelContextSnapshotSource<\n Readonly<Record<string, string | undefined>>\n> = {\n empty: EMPTY_TOOL_MENTIONS,\n read: (aui) => {\n const tools = aui.thread.getModelContext().tools;\n if (!tools) return EMPTY_TOOL_MENTIONS;\n const mentions = Object.create(null) as Record<string, string | undefined>;\n for (const [name, tool] of Object.entries(tools)) {\n mentions[name] = tool.description;\n }\n return mentions;\n },\n subscribe: (aui, onChange) => {\n const unsubscribeContext = aui.on(\"thread.modelContextUpdate\", onChange);\n // Rebinding the thread event subject to a new thread does not replay it,\n // so a switch between threads carrying different providers is its own\n // refresh trigger. Subscribed globally because a composer can render\n // without a thread list scope.\n const unsubscribeSelection = aui.on(\n { scope: \"*\", event: \"threads.selectionChanged\" },\n onChange,\n );\n return () => {\n unsubscribeContext();\n unsubscribeSelection();\n };\n },\n isEqual: shallowEqualRecords,\n};\n\n/**\n * Creates a spreadable `{ adapter, directive }` bundle for `@` mentions.\n * Supports tools registered in model context, explicit items, or both —\n * flat or categorized.\n *\n * @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release.\n *\n * @example\n * ```tsx\n * const mention = unstable_useMentionAdapter();\n * <ComposerTriggerPopover char=\"@\" {...mention} />\n * ```\n */\nexport function unstable_useMentionAdapter(\n options?: Unstable_UseMentionAdapterOptions,\n): {\n adapter: Unstable_TriggerAdapter;\n directive: Unstable_MentionDirective;\n iconMap?: Record<string, Unstable_IconComponent>;\n fallbackIcon?: Unstable_IconComponent;\n} {\n const aui = useAui();\n\n const items = options?.items;\n const categories = options?.categories;\n const includeTools =\n options?.includeModelContextTools ?? (!items && !categories);\n const toolsConfig =\n typeof includeTools === \"object\" ? includeTools : undefined;\n const wantsTools = includeTools !== false;\n const formatter = options?.formatter;\n const onInserted = options?.onInserted;\n const isCategorized =\n categories !== undefined ||\n (toolsConfig?.category !== undefined && items === undefined);\n const toolMentions = useModelContextSnapshot(\n aui,\n wantsTools,\n toolMentionSource,\n );\n\n const adapter = useMemo<Unstable_TriggerAdapter>(() => {\n const formatLabel = toolsConfig?.formatLabel;\n const defaultIcon = toolsConfig?.icon;\n const toolItems = wantsTools\n ? Object.entries(toolMentions).map(([name, description]) =>\n toTriggerItem({\n id: name,\n type: \"tool\",\n label: formatLabel ? formatLabel(name) : name,\n description,\n icon: defaultIcon,\n }),\n )\n : [];\n\n // Categorized: drill-down mode\n if (isCategorized) {\n const groups = (categories ?? []).map((cat) => ({\n id: cat.id,\n label: cat.label,\n items: cat.items.map(toTriggerItem),\n }));\n const allGroups =\n toolItems.length > 0\n ? [\n ...groups,\n {\n id: toolsConfig?.category?.id ?? \"tools\",\n label: toolsConfig?.category?.label ?? \"Tools\",\n items: toolItems,\n },\n ]\n : groups;\n\n return {\n categories: () => allGroups.map(({ id, label }) => ({ id, label })),\n categoryItems: (id) => allGroups.find((g) => g.id === id)?.items ?? [],\n search: (query) => {\n const lower = query.toLowerCase();\n return allGroups\n .flatMap((g) => g.items)\n .filter((item) => matchesTriggerItemQuery(item, lower));\n },\n };\n }\n\n // Flat: items + (optionally) tools, all in one search pool\n const flatItems = (items ?? []).map(toTriggerItem);\n // Dedupe by id — explicit items win.\n const seen = new Set(flatItems.map((i) => i.id));\n const flatPool = [\n ...flatItems,\n ...toolItems.filter((t) => !seen.has(t.id)),\n ];\n\n return {\n categories: (): readonly Unstable_TriggerCategory[] => [],\n categoryItems: () => [],\n search: (query) => {\n const lower = query.toLowerCase();\n return flatPool.filter((item) => matchesTriggerItemQuery(item, lower));\n },\n };\n }, [items, categories, wantsTools, toolsConfig, isCategorized, toolMentions]);\n\n const directive = useMemo<Unstable_MentionDirective>(\n () => ({\n formatter: formatter ?? unstable_defaultDirectiveFormatter,\n ...(onInserted ? { onInserted } : {}),\n }),\n [formatter, onInserted],\n );\n\n return {\n adapter,\n directive,\n ...(options?.iconMap ? { iconMap: options.iconMap } : {}),\n ...(options?.fallbackIcon ? { fallbackIcon: options.fallbackIcon } : {}),\n };\n}\n\nfunction toTriggerItem(m: Unstable_Mention): Unstable_TriggerItem {\n const metadata =\n m.icon !== undefined ? { ...(m.metadata ?? {}), icon: m.icon } : m.metadata;\n return {\n id: m.id,\n type: m.type,\n label: m.label,\n ...(m.description !== undefined ? { description: m.description } : {}),\n ...(metadata !== undefined ? { metadata } : {}),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release. */
|
|
1
2
|
export type Unstable_MessageStallDetectionOptions = {
|
|
2
3
|
/**
|
|
3
4
|
* Milliseconds of unchanged message content before the message counts as
|
|
@@ -6,6 +7,7 @@ export type Unstable_MessageStallDetectionOptions = {
|
|
|
6
7
|
*/
|
|
7
8
|
thresholdMs?: number | undefined;
|
|
8
9
|
};
|
|
10
|
+
/** @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release. */
|
|
9
11
|
export type Unstable_MessageStallDetection = {
|
|
10
12
|
/** True while the message is running and its content has not changed for at least `thresholdMs`. */
|
|
11
13
|
stalled: boolean;
|
|
@@ -13,8 +15,6 @@ export type Unstable_MessageStallDetection = {
|
|
|
13
15
|
stalledForMs: number;
|
|
14
16
|
};
|
|
15
17
|
/**
|
|
16
|
-
* @deprecated Under active development and might change without notice.
|
|
17
|
-
*
|
|
18
18
|
* Detects mid-run output stalls on the current message: while the message is
|
|
19
19
|
* running, watches its text, reasoning, and tool-argument values plus tool-result
|
|
20
20
|
* availability and reports a stall once they stop changing for `thresholdMs`.
|
|
@@ -22,6 +22,8 @@ export type Unstable_MessageStallDetection = {
|
|
|
22
22
|
* provider stalls, after the first tokens have already streamed.
|
|
23
23
|
*
|
|
24
24
|
* Must be used inside a message scope.
|
|
25
|
+
*
|
|
26
|
+
* @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release.
|
|
25
27
|
*/
|
|
26
28
|
export declare function unstable_useMessageStallDetection(options?: Unstable_MessageStallDetectionOptions): Unstable_MessageStallDetection;
|
|
27
29
|
//# sourceMappingURL=useMessageStallDetection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageStallDetection.d.ts","sourceRoot":"","sources":["../../src/unstable/useMessageStallDetection.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,qCAAqC,GAAG;IAClD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,qCAAqC,GAC9C,8BAA8B,
|
|
1
|
+
{"version":3,"file":"useMessageStallDetection.d.ts","sourceRoot":"","sources":["../../src/unstable/useMessageStallDetection.ts"],"names":[],"mappings":"AAMA,+GAA+G;AAC/G,MAAM,MAAM,qCAAqC,GAAG;IAClD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,+GAA+G;AAC/G,MAAM,MAAM,8BAA8B,GAAG;IAC3C,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,qCAAqC,GAC9C,8BAA8B,CAkEhC"}
|
|
@@ -4,8 +4,6 @@ import { useAuiState } from "@assistant-ui/store";
|
|
|
4
4
|
import { useShallowSelector } from "@assistant-ui/store/internal";
|
|
5
5
|
//#region src/unstable/useMessageStallDetection.ts
|
|
6
6
|
/**
|
|
7
|
-
* @deprecated Under active development and might change without notice.
|
|
8
|
-
*
|
|
9
7
|
* Detects mid-run output stalls on the current message: while the message is
|
|
10
8
|
* running, watches its text, reasoning, and tool-argument values plus tool-result
|
|
11
9
|
* availability and reports a stall once they stop changing for `thresholdMs`.
|
|
@@ -13,6 +11,8 @@ import { useShallowSelector } from "@assistant-ui/store/internal";
|
|
|
13
11
|
* provider stalls, after the first tokens have already streamed.
|
|
14
12
|
*
|
|
15
13
|
* Must be used inside a message scope.
|
|
14
|
+
*
|
|
15
|
+
* @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release.
|
|
16
16
|
*/
|
|
17
17
|
function unstable_useMessageStallDetection(options) {
|
|
18
18
|
const thresholdMs = options?.thresholdMs ?? 2e3;
|
|
@@ -25,9 +25,9 @@ function unstable_useMessageStallDetection(options) {
|
|
|
25
25
|
return values;
|
|
26
26
|
}));
|
|
27
27
|
const running = activity[0] === true;
|
|
28
|
-
const lastActivityRef = useRef(
|
|
28
|
+
const lastActivityRef = useRef(0);
|
|
29
29
|
const [stalled, setStalled] = useState(false);
|
|
30
|
-
const [,
|
|
30
|
+
const [now, setNow] = useState(0);
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
if (!running) return void 0;
|
|
33
33
|
lastActivityRef.current = Date.now();
|
|
@@ -37,13 +37,17 @@ function unstable_useMessageStallDetection(options) {
|
|
|
37
37
|
setStalled(false);
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
+
const stall = () => {
|
|
41
|
+
setNow(Date.now());
|
|
42
|
+
setStalled(true);
|
|
43
|
+
};
|
|
40
44
|
const sinceActivity = Date.now() - lastActivityRef.current;
|
|
41
45
|
if (sinceActivity >= thresholdMs) {
|
|
42
|
-
|
|
46
|
+
stall();
|
|
43
47
|
return;
|
|
44
48
|
}
|
|
45
49
|
setStalled(false);
|
|
46
|
-
const id = setTimeout(
|
|
50
|
+
const id = setTimeout(stall, thresholdMs - sinceActivity);
|
|
47
51
|
return () => clearTimeout(id);
|
|
48
52
|
}, [
|
|
49
53
|
running,
|
|
@@ -52,7 +56,7 @@ function unstable_useMessageStallDetection(options) {
|
|
|
52
56
|
]);
|
|
53
57
|
useEffect(() => {
|
|
54
58
|
if (!stalled) return void 0;
|
|
55
|
-
const id = setInterval(() =>
|
|
59
|
+
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
56
60
|
return () => clearInterval(id);
|
|
57
61
|
}, [stalled]);
|
|
58
62
|
if (!stalled) return {
|
|
@@ -61,7 +65,7 @@ function unstable_useMessageStallDetection(options) {
|
|
|
61
65
|
};
|
|
62
66
|
return {
|
|
63
67
|
stalled: true,
|
|
64
|
-
stalledForMs: Math.max(0,
|
|
68
|
+
stalledForMs: Math.max(0, now - lastActivityRef.current)
|
|
65
69
|
};
|
|
66
70
|
}
|
|
67
71
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageStallDetection.js","names":["useEffect","useRef","useState","useAuiState","useShallowSelector","Unstable_MessageStallDetectionOptions","thresholdMs","Unstable_MessageStallDetection","stalled","stalledForMs","unstable_useMessageStallDetection","options","activity","s","running","message","status","type","values","content","length","part","push","text","argsText","result","undefined","lastActivityRef","
|
|
1
|
+
{"version":3,"file":"useMessageStallDetection.js","names":["useEffect","useRef","useState","useAuiState","useShallowSelector","Unstable_MessageStallDetectionOptions","thresholdMs","Unstable_MessageStallDetection","stalled","stalledForMs","unstable_useMessageStallDetection","options","activity","s","running","message","status","type","values","content","length","part","push","text","argsText","result","undefined","lastActivityRef","setStalled","now","setNow","current","Date","stall","sinceActivity","id","setTimeout","clearTimeout","setInterval","clearInterval","Math","max"],"sources":["../../src/unstable/useMessageStallDetection.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallowSelector } from \"@assistant-ui/store/internal\";\n\n/** @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_MessageStallDetectionOptions = {\n /**\n * Milliseconds of unchanged message content before the message counts as\n * stalled.\n * @default 2000\n */\n thresholdMs?: number | undefined;\n};\n\n/** @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_MessageStallDetection = {\n /** True while the message is running and its content has not changed for at least `thresholdMs`. */\n stalled: boolean;\n /** Milliseconds since the last observed content change. `0` while not stalled. */\n stalledForMs: number;\n};\n\n/**\n * Detects mid-run output stalls on the current message: while the message is\n * running, watches its text, reasoning, and tool-argument values plus tool-result\n * availability and reports a stall once they stop changing for `thresholdMs`.\n * Useful for re-surfacing a \"still working\" indicator during tool think-time or\n * provider stalls, after the first tokens have already streamed.\n *\n * Must be used inside a message scope.\n *\n * @deprecated Experimental since 2026-06-13. Not scheduled for removal; the API may change in any release.\n */\nexport function unstable_useMessageStallDetection(\n options?: Unstable_MessageStallDetectionOptions,\n): Unstable_MessageStallDetection {\n const thresholdMs = options?.thresholdMs ?? 2000;\n\n const activity = useAuiState(\n useShallowSelector((s) => {\n const running = s.message.status?.type === \"running\";\n if (!running) return [false];\n\n const values: unknown[] = [true, s.message.content.length];\n\n for (const part of s.message.content) {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n values.push(part.type, part.text);\n } else if (part.type === \"tool-call\") {\n values.push(part.type, part.argsText, part.result !== undefined);\n } else {\n values.push(part.type);\n }\n }\n return values;\n }),\n );\n\n const running = activity[0] === true;\n const lastActivityRef = useRef(0);\n const [stalled, setStalled] = useState(false);\n const [now, setNow] = useState(0);\n\n useEffect(() => {\n if (!running) return undefined;\n lastActivityRef.current = Date.now();\n return undefined;\n }, [running, activity]);\n\n useEffect(() => {\n if (!running) {\n setStalled(false);\n return undefined;\n }\n\n const stall = () => {\n setNow(Date.now());\n setStalled(true);\n };\n const sinceActivity = Date.now() - lastActivityRef.current;\n if (sinceActivity >= thresholdMs) {\n stall();\n return undefined;\n }\n\n setStalled(false);\n const id = setTimeout(stall, thresholdMs - sinceActivity);\n return () => clearTimeout(id);\n }, [running, activity, thresholdMs]);\n\n useEffect(() => {\n if (!stalled) return undefined;\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [stalled]);\n\n if (!stalled) return { stalled: false, stalledForMs: 0 };\n return {\n stalled: true,\n stalledForMs: Math.max(0, now - lastActivityRef.current),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmCA,SAAgBU,kCACdC,SACgC;CAChC,MAAML,cAAcK,SAASL,eAAe;CAE5C,MAAMM,WAAWT,YACfC,oBAAoBS,MAAM;EAExB,IAAI,EADYA,EAAEE,QAAQC,QAAQC,SAAS,YAC7B,OAAO,CAAC,KAAK;EAE3B,MAAMC,SAAoB,CAAC,MAAML,EAAEE,QAAQI,QAAQC,MAAM;EAEzD,KAAK,MAAMC,QAAQR,EAAEE,QAAQI,SAC3B,IAAIE,KAAKJ,SAAS,UAAUI,KAAKJ,SAAS,aACxCC,OAAOI,KAAKD,KAAKJ,MAAMI,KAAKE,IAAI;OAC3B,IAAIF,KAAKJ,SAAS,aACvBC,OAAOI,KAAKD,KAAKJ,MAAMI,KAAKG,UAAUH,KAAKI,WAAWC,KAAAA,CAAS;OAE/DR,OAAOI,KAAKD,KAAKJ,IAAI;EAGzB,OAAOC;CACT,CAAC,CACH;CAEA,MAAMJ,UAAUF,SAAS,OAAO;CAChC,MAAMe,kBAAkB1B,OAAO,CAAC;CAChC,MAAM,CAACO,SAASoB,cAAc1B,SAAS,KAAK;CAC5C,MAAM,CAAC2B,KAAKC,UAAU5B,SAAS,CAAC;CAEhCF,gBAAgB;EACd,IAAI,CAACc,SAAS,OAAOY,KAAAA;EACrBC,gBAAgBI,UAAUC,KAAKH,IAAI;CAErC,GAAG,CAACf,SAASF,QAAQ,CAAC;CAEtBZ,gBAAgB;EACd,IAAI,CAACc,SAAS;GACZc,WAAW,KAAK;GAChB;EACF;EAEA,MAAMK,cAAc;GAClBH,OAAOE,KAAKH,IAAI,CAAC;GACjBD,WAAW,IAAI;EACjB;EACA,MAAMM,gBAAgBF,KAAKH,IAAI,IAAIF,gBAAgBI;EACnD,IAAIG,iBAAiB5B,aAAa;GAChC2B,MAAM;GACN;EACF;EAEAL,WAAW,KAAK;EAChB,MAAMO,KAAKC,WAAWH,OAAO3B,cAAc4B,aAAa;EACxD,aAAaG,aAAaF,EAAE;CAC9B,GAAG;EAACrB;EAASF;EAAUN;CAAW,CAAC;CAEnCN,gBAAgB;EACd,IAAI,CAACQ,SAAS,OAAOkB,KAAAA;EACrB,MAAMS,KAAKG,kBAAkBR,OAAOE,KAAKH,IAAI,CAAC,GAAG,GAAI;EACrD,aAAaU,cAAcJ,EAAE;CAC/B,GAAG,CAAC3B,OAAO,CAAC;CAEZ,IAAI,CAACA,SAAS,OAAO;EAAEA,SAAS;EAAOC,cAAc;CAAE;CACvD,OAAO;EACLD,SAAS;EACTC,cAAc+B,KAAKC,IAAI,GAAGZ,MAAMF,gBAAgBI,OAAO;CACzD;AACF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Unstable_TriggerAdapter, Unstable_TriggerItem } from "@assistant-ui/core";
|
|
2
2
|
import type { Unstable_IconComponent } from "./useMentionAdapter.js";
|
|
3
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
3
4
|
export type Unstable_SlashCommand = {
|
|
4
5
|
readonly id: string;
|
|
5
6
|
readonly label?: string | undefined;
|
|
@@ -7,6 +8,7 @@ export type Unstable_SlashCommand = {
|
|
|
7
8
|
readonly icon?: string | undefined;
|
|
8
9
|
readonly execute: () => void;
|
|
9
10
|
};
|
|
11
|
+
/** @deprecated Experimental since 2026-04-06. Not scheduled for removal; the API may change in any release. */
|
|
10
12
|
export type Unstable_UseSlashCommandAdapterOptions = {
|
|
11
13
|
readonly commands: readonly Unstable_SlashCommand[];
|
|
12
14
|
/** Strip the trigger text from the composer after executing. @default false */
|
|
@@ -16,18 +18,19 @@ export type Unstable_UseSlashCommandAdapterOptions = {
|
|
|
16
18
|
/** Fallback icon when no entry in `iconMap` matches. */
|
|
17
19
|
readonly fallbackIcon?: Unstable_IconComponent;
|
|
18
20
|
};
|
|
21
|
+
/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */
|
|
19
22
|
export type Unstable_SlashCommandAction = {
|
|
20
23
|
readonly onExecute: (item: Unstable_TriggerItem) => void;
|
|
21
24
|
readonly removeOnExecute?: boolean | undefined;
|
|
22
25
|
};
|
|
23
26
|
/**
|
|
24
|
-
* @deprecated Under active development and may change without notice.
|
|
25
|
-
*
|
|
26
27
|
* Bundles slash command definitions (with inline `execute` callbacks) into
|
|
27
28
|
* `{adapter, action}` that plug directly into `ComposerTriggerPopover`.
|
|
28
29
|
* `execute` stays in the hook closure and is never attached to the returned
|
|
29
30
|
* `TriggerItem`, keeping items serializable.
|
|
30
31
|
*
|
|
32
|
+
* @deprecated Experimental since 2026-04-06. Not scheduled for removal; the API may change in any release.
|
|
33
|
+
*
|
|
31
34
|
* @example
|
|
32
35
|
* ```tsx
|
|
33
36
|
* const slash = unstable_useSlashCommandAdapter({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlashCommandAdapter.d.ts","sourceRoot":"","sources":["../../src/unstable/useSlashCommandAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useSlashCommandAdapter.d.ts","sourceRoot":"","sources":["../../src/unstable/useSlashCommandAdapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,+BAA4B;AAGlE,+GAA+G;AAC/G,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,+GAA+G;AAC/G,MAAM,MAAM,sCAAsC,GAAG;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/C,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC1D,wDAAwD;IACxD,QAAQ,CAAC,YAAY,CAAC,EAAE,sBAAsB,CAAC;CAChD,CAAC;AAEF,+GAA+G;AAC/G,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,sCAAsC,GAC9C;IACD,OAAO,EAAE,uBAAuB,CAAC;IACjC,MAAM,EAAE,2BAA2B,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,sBAAsB,CAAC;CACvC,CAiDA"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useIsomorphicLayoutEffect } from "../utils/useIsomorphicLayoutEffect.js";
|
|
2
3
|
import { matchesTriggerItemQuery } from "../primitives/composer/trigger/matchesTriggerItemQuery.js";
|
|
3
|
-
import {
|
|
4
|
+
import { useMemo, useRef } from "@assistant-ui/tap/react-shim";
|
|
4
5
|
//#region src/unstable/useSlashCommandAdapter.ts
|
|
5
6
|
/**
|
|
6
|
-
* @deprecated Under active development and may change without notice.
|
|
7
|
-
*
|
|
8
7
|
* Bundles slash command definitions (with inline `execute` callbacks) into
|
|
9
8
|
* `{adapter, action}` that plug directly into `ComposerTriggerPopover`.
|
|
10
9
|
* `execute` stays in the hook closure and is never attached to the returned
|
|
11
10
|
* `TriggerItem`, keeping items serializable.
|
|
12
11
|
*
|
|
12
|
+
* @deprecated Experimental since 2026-04-06. Not scheduled for removal; the API may change in any release.
|
|
13
|
+
*
|
|
13
14
|
* @example
|
|
14
15
|
* ```tsx
|
|
15
16
|
* const slash = unstable_useSlashCommandAdapter({
|
|
@@ -28,7 +29,7 @@ function unstable_useSlashCommandAdapter(options) {
|
|
|
28
29
|
const committedItemsRef = useRef(void 0);
|
|
29
30
|
const nextItems = commands.map(toItem);
|
|
30
31
|
const items = areTriggerItemsEqual(committedItemsRef.current, nextItems) ? committedItemsRef.current : nextItems;
|
|
31
|
-
|
|
32
|
+
useIsomorphicLayoutEffect(() => {
|
|
32
33
|
commandsRef.current = commands;
|
|
33
34
|
committedItemsRef.current = items;
|
|
34
35
|
}, [commands, items]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlashCommandAdapter.js","names":["
|
|
1
|
+
{"version":3,"file":"useSlashCommandAdapter.js","names":["useMemo","useRef","useIsomorphicLayoutEffect","Unstable_TriggerAdapter","Unstable_TriggerItem","Unstable_IconComponent","matchesTriggerItemQuery","Unstable_SlashCommand","id","label","description","icon","execute","Unstable_UseSlashCommandAdapterOptions","commands","removeOnExecute","iconMap","Record","fallbackIcon","Unstable_SlashCommandAction","onExecute","item","unstable_useSlashCommandAdapter","options","adapter","action","commandsRef","committedItemsRef","undefined","nextItems","map","toItem","items","areTriggerItemsEqual","current","categories","categoryItems","search","query","lower","toLowerCase","filter","find","c","cmd","type","metadata","previous","next","length","every","index","nextItem"],"sources":["../../src/unstable/useSlashCommandAdapter.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useRef } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"../utils/useIsomorphicLayoutEffect\";\nimport type {\n Unstable_TriggerAdapter,\n Unstable_TriggerItem,\n} from \"@assistant-ui/core\";\nimport type { Unstable_IconComponent } from \"./useMentionAdapter\";\nimport { matchesTriggerItemQuery } from \"../primitives/composer/trigger/matchesTriggerItemQuery\";\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_SlashCommand = {\n readonly id: string;\n readonly label?: string | undefined;\n readonly description?: string | undefined;\n readonly icon?: string | undefined;\n readonly execute: () => void;\n};\n\n/** @deprecated Experimental since 2026-04-06. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_UseSlashCommandAdapterOptions = {\n readonly commands: readonly Unstable_SlashCommand[];\n /** Strip the trigger text from the composer after executing. @default false */\n readonly removeOnExecute?: boolean | undefined;\n /** Maps `metadata.icon` / `category.id` string keys to React components. */\n readonly iconMap?: Record<string, Unstable_IconComponent>;\n /** Fallback icon when no entry in `iconMap` matches. */\n readonly fallbackIcon?: Unstable_IconComponent;\n};\n\n/** @deprecated Experimental since 2026-04-15. Not scheduled for removal; the API may change in any release. */\nexport type Unstable_SlashCommandAction = {\n readonly onExecute: (item: Unstable_TriggerItem) => void;\n readonly removeOnExecute?: boolean | undefined;\n};\n\n/**\n * Bundles slash command definitions (with inline `execute` callbacks) into\n * `{adapter, action}` that plug directly into `ComposerTriggerPopover`.\n * `execute` stays in the hook closure and is never attached to the returned\n * `TriggerItem`, keeping items serializable.\n *\n * @deprecated Experimental since 2026-04-06. Not scheduled for removal; the API may change in any release.\n *\n * @example\n * ```tsx\n * const slash = unstable_useSlashCommandAdapter({\n * commands: [\n * { id: \"summarize\", execute: () => runSummarize(), icon: \"FileText\" },\n * { id: \"translate\", execute: () => runTranslate(), icon: \"Languages\" },\n * ],\n * });\n *\n * <ComposerTriggerPopover char=\"/\" {...slash} />\n * ```\n */\nexport function unstable_useSlashCommandAdapter(\n options: Unstable_UseSlashCommandAdapterOptions,\n): {\n adapter: Unstable_TriggerAdapter;\n action: Unstable_SlashCommandAction;\n iconMap?: Record<string, Unstable_IconComponent>;\n fallbackIcon?: Unstable_IconComponent;\n} {\n const { commands, removeOnExecute } = options;\n\n const commandsRef = useRef(commands);\n const committedItemsRef = useRef<readonly Unstable_TriggerItem[]>(undefined);\n const nextItems = commands.map(toItem);\n // A referential cache, never state: `items` is always structurally equal to\n // `nextItems`, so the render-time read cannot change what the adapter shows.\n const items = areTriggerItemsEqual(committedItemsRef.current, nextItems)\n ? committedItemsRef.current\n : nextItems;\n\n // The adapter's callbacks must only observe commands from committed renders.\n useIsomorphicLayoutEffect(() => {\n commandsRef.current = commands;\n committedItemsRef.current = items;\n }, [commands, items]);\n\n const adapter = useMemo<Unstable_TriggerAdapter>(\n () => ({\n categories: () => [],\n categoryItems: () => [],\n search: (query: string) => {\n const lower = query.toLowerCase();\n return items.filter((item) => matchesTriggerItemQuery(item, lower));\n },\n }),\n [items],\n );\n\n const action = useMemo<Unstable_SlashCommandAction>(\n () => ({\n onExecute: (item) => {\n commandsRef.current.find((c) => c.id === item.id)?.execute();\n },\n ...(removeOnExecute !== undefined ? { removeOnExecute } : {}),\n }),\n [removeOnExecute],\n );\n\n return useMemo(\n () => ({\n adapter,\n action,\n ...(options.iconMap ? { iconMap: options.iconMap } : {}),\n ...(options.fallbackIcon ? { fallbackIcon: options.fallbackIcon } : {}),\n }),\n [adapter, action, options.iconMap, options.fallbackIcon],\n );\n}\n\nfunction toItem(cmd: Unstable_SlashCommand): Unstable_TriggerItem {\n return {\n id: cmd.id,\n type: \"command\",\n label: cmd.label ?? `/${cmd.id}`,\n ...(cmd.description !== undefined ? { description: cmd.description } : {}),\n ...(cmd.icon !== undefined ? { metadata: { icon: cmd.icon } } : {}),\n };\n}\n\nfunction areTriggerItemsEqual(\n previous: readonly Unstable_TriggerItem[] | undefined,\n next: readonly Unstable_TriggerItem[],\n): previous is readonly Unstable_TriggerItem[] {\n if (!previous || previous.length !== next.length) return false;\n\n return previous.every((item, index) => {\n const nextItem = next[index];\n return (\n nextItem !== undefined &&\n item.id === nextItem.id &&\n item.label === nextItem.label &&\n item.description === nextItem.description &&\n item.metadata?.icon === nextItem.metadata?.icon\n );\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,SAAgBsB,gCACdC,SAMA;CACA,MAAM,EAAET,UAAUC,oBAAoBQ;CAEtC,MAAMG,cAAczB,OAAOa,QAAQ;CACnC,MAAMa,oBAAoB1B,OAAwC2B,KAAAA,CAAS;CAC3E,MAAMC,YAAYf,SAASgB,IAAIC,MAAM;CAGrC,MAAMC,QAAQC,qBAAqBN,kBAAkBO,SAASL,SAAS,IACnEF,kBAAkBO,UAClBL;CAGJ3B,gCAAgC;EAC9BwB,YAAYQ,UAAUpB;EACtBa,kBAAkBO,UAAUF;CAC9B,GAAG,CAAClB,UAAUkB,KAAK,CAAC;CAEpB,MAAMR,UAAUxB,eACP;EACLmC,kBAAkB,CAAA;EAClBC,qBAAqB,CAAA;EACrBC,SAASC,UAAkB;GACzB,MAAMC,QAAQD,MAAME,YAAY;GAChC,OAAOR,MAAMS,QAAQpB,SAASf,wBAAwBe,MAAMkB,KAAK,CAAC;EACpE;CACF,IACA,CAACP,KAAK,CACR;CAEA,MAAMP,SAASzB,eACN;EACLoB,YAAYC,SAAS;GACnBK,YAAYQ,QAAQQ,MAAMC,MAAMA,EAAEnC,OAAOa,KAAKb,EAAE,CAAC,EAAEI,QAAQ;EAC7D;EACA,GAAIG,oBAAoBa,KAAAA,IAAY,EAAEb,gBAAgB,IAAI,CAAC;CAC7D,IACA,CAACA,eAAe,CAClB;CAEA,OAAOf,eACE;EACLwB;EACAC;EACA,GAAIF,QAAQP,UAAU,EAAEA,SAASO,QAAQP,QAAQ,IAAI,CAAC;EACtD,GAAIO,QAAQL,eAAe,EAAEA,cAAcK,QAAQL,aAAa,IAAI,CAAC;CACvE,IACA;EAACM;EAASC;EAAQF,QAAQP;EAASO,QAAQL;CAAY,CACzD;AACF;AAEA,SAASa,OAAOa,KAAkD;CAChE,OAAO;EACLpC,IAAIoC,IAAIpC;EACRqC,MAAM;EACNpC,OAAOmC,IAAInC,SAAS,IAAImC,IAAIpC;EAC5B,GAAIoC,IAAIlC,gBAAgBkB,KAAAA,IAAY,EAAElB,aAAakC,IAAIlC,YAAY,IAAI,CAAC;EACxE,GAAIkC,IAAIjC,SAASiB,KAAAA,IAAY,EAAEkB,UAAU,EAAEnC,MAAMiC,IAAIjC,KAAK,EAAE,IAAI,CAAC;CACnE;AACF;AAEA,SAASsB,qBACPc,UACAC,MAC6C;CAC7C,IAAI,CAACD,YAAYA,SAASE,WAAWD,KAAKC,QAAQ,OAAO;CAEzD,OAAOF,SAASG,OAAO7B,MAAM8B,UAAU;EACrC,MAAMC,WAAWJ,KAAKG;EACtB,OACEC,aAAaxB,KAAAA,KACbP,KAAKb,OAAO4C,SAAS5C,MACrBa,KAAKZ,UAAU2C,SAAS3C,SACxBY,KAAKX,gBAAgB0C,SAAS1C,eAC9BW,KAAKyB,UAAUnC,SAASyC,SAASN,UAAUnC;CAE/C,CAAC;AACH"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Tool } from "assistant-stream";
|
|
2
|
+
/** @deprecated Experimental since 2026-08-29. Not scheduled for removal; the API may change in any release. */
|
|
2
3
|
export type Unstable_WebMcpProviderOptions = {
|
|
3
4
|
filter?: (name: string, tool: Tool<any, any>) => boolean;
|
|
4
5
|
};
|
|
6
|
+
/** @deprecated Experimental since 2026-08-29. Not scheduled for removal; the API may change in any release. */
|
|
5
7
|
export type Unstable_WebMcpProviderResult = {
|
|
6
8
|
status: "unsupported" | "active";
|
|
7
9
|
registeredToolNames: readonly string[];
|
|
@@ -13,6 +15,8 @@ export type Unstable_WebMcpProviderResult = {
|
|
|
13
15
|
* Returns `status: "unsupported"` when the page exposes no
|
|
14
16
|
* `document.modelContext` (or `navigator.modelContext`), and the sorted names
|
|
15
17
|
* of the tools currently registered with the host.
|
|
18
|
+
*
|
|
19
|
+
* @deprecated Experimental since 2026-08-29. Not scheduled for removal; the API may change in any release.
|
|
16
20
|
*/
|
|
17
21
|
export declare const unstable_useWebMcpProvider: (options?: Unstable_WebMcpProviderOptions) => Unstable_WebMcpProviderResult;
|
|
18
22
|
//# sourceMappingURL=useWebMcpProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebMcpProvider.d.ts","sourceRoot":"","sources":["../../../src/unstable/webmcp/useWebMcpProvider.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAU7C,MAAM,MAAM,8BAA8B,GAAG;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,aAAa,GAAG,QAAQ,CAAC;IACjC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AA8FF
|
|
1
|
+
{"version":3,"file":"useWebMcpProvider.d.ts","sourceRoot":"","sources":["../../../src/unstable/webmcp/useWebMcpProvider.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAU7C,+GAA+G;AAC/G,MAAM,MAAM,8BAA8B,GAAG;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;CAC1D,CAAC;AAEF,+GAA+G;AAC/G,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,aAAa,GAAG,QAAQ,CAAC;IACjC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AA8FF;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,GACrC,UAAS,8BAAmC,KAC3C,6BAyCF,CAAC"}
|
|
@@ -80,6 +80,8 @@ const useWebMcpRegistry = (t0) => {
|
|
|
80
80
|
* Returns `status: "unsupported"` when the page exposes no
|
|
81
81
|
* `document.modelContext` (or `navigator.modelContext`), and the sorted names
|
|
82
82
|
* of the tools currently registered with the host.
|
|
83
|
+
*
|
|
84
|
+
* @deprecated Experimental since 2026-08-29. Not scheduled for removal; the API may change in any release.
|
|
83
85
|
*/
|
|
84
86
|
const unstable_useWebMcpProvider = (options = {}) => {
|
|
85
87
|
const aui = useAui();
|