@assistant-ui/react 0.14.14 → 0.14.15
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 +5 -1
- package/dist/client/ExternalThread.d.ts +2 -12
- package/dist/client/ExternalThread.d.ts.map +1 -1
- package/dist/client/ExternalThread.js +30 -29
- package/dist/client/ExternalThread.js.map +1 -1
- package/dist/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/client/InMemoryThreadList.js +11 -10
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/client/SingleThreadList.d.ts.map +1 -1
- package/dist/client/SingleThreadList.js +9 -8
- package/dist/client/SingleThreadList.js.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.js +1 -1
- package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
- package/dist/context/react/ThreadViewportContext.js +1 -1
- package/dist/context/react/utils/createContextHook.js +1 -1
- package/dist/context/react/utils/ensureBinding.js.map +1 -1
- package/dist/context/react/utils/useRuntimeState.js +1 -1
- package/dist/context/stores/ThreadViewport.js.map +1 -1
- package/dist/devtools/DevToolsHooks.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -1
- package/dist/legacy-runtime/cloud/auiV0.js +1 -1
- package/dist/legacy-runtime/hooks/AssistantContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/AttachmentContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ComposerContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/MessageContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/MessagePartContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadContext.js +1 -1
- package/dist/legacy-runtime/hooks/ThreadContext.js.map +1 -1
- package/dist/legacy-runtime/hooks/ThreadListItemContext.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/commandQueue.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useConvertedState.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useLatestRef.js +1 -1
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +7 -7
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js +5 -4
- package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -1
- package/dist/mcp-apps/app-frame.d.ts +1 -1
- package/dist/mcp-apps/app-frame.d.ts.map +1 -1
- package/dist/mcp-apps/app-frame.js +82 -104
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/mcp-apps/bridge.d.ts +3 -3
- package/dist/mcp-apps/bridge.d.ts.map +1 -1
- package/dist/mcp-apps/bridge.js +35 -10
- package/dist/mcp-apps/bridge.js.map +1 -1
- package/dist/mcp-apps/types.d.ts +2 -12
- package/dist/mcp-apps/types.d.ts.map +1 -1
- package/dist/mcp-apps/types.js.map +1 -1
- package/dist/model-context/frame/useAssistantFrameHost.js +1 -1
- package/dist/model-context/makeAssistantVisible.js +1 -1
- package/dist/model-context/makeAssistantVisible.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -1
- package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -1
- package/dist/primitives/actionBar/ActionBarRoot.js +1 -1
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -1
- package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -1
- package/dist/primitives/assistantModal/AssistantModalContent.js +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -1
- package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -1
- package/dist/primitives/attachment/AttachmentRemove.js +1 -1
- package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
- package/dist/primitives/attachment/AttachmentRoot.js +1 -1
- package/dist/primitives/attachment/AttachmentThumb.js +1 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
- package/dist/primitives/composer/ComposerDictationTranscript.js +1 -1
- package/dist/primitives/composer/ComposerInput.js +1 -1
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.js +1 -1
- package/dist/primitives/composer/ComposerQuote.js +1 -1
- package/dist/primitives/composer/ComposerQuote.js.map +1 -1
- package/dist/primitives/composer/ComposerRoot.js +1 -1
- package/dist/primitives/composer/ComposerSend.js +1 -1
- package/dist/primitives/composer/ComposerStopDictation.js +1 -1
- package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +2 -2
- package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js +8 -7
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -1
- package/dist/primitives/composer/trigger/triggerDetectionResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerDetectionResource.js +5 -4
- package/dist/primitives/composer/trigger/triggerDetectionResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js +8 -7
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.js +13 -12
- package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.js +7 -6
- package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
- package/dist/primitives/error/ErrorMessage.js +1 -1
- package/dist/primitives/error/ErrorRoot.js +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
- package/dist/primitives/message/MessageRoot.js +1 -1
- package/dist/primitives/message/MessageRoot.js.map +1 -1
- package/dist/primitives/messagePart/MessagePartImage.js +1 -1
- package/dist/primitives/messagePart/MessagePartText.js +1 -1
- package/dist/primitives/queueItem/QueueItemRemove.js +1 -1
- package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.js +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemText.js +1 -1
- package/dist/primitives/reasoning/useScrollLock.js +1 -1
- package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionDescription.js +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.js +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.js +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
- package/dist/primitives/thread/ThreadRoot.js +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +1 -1
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -1
- package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -1
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/threadList/ThreadListNew.js +1 -1
- package/dist/primitives/threadList/ThreadListRoot.js +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -1
- package/dist/sandbox-host/SandboxHost.d.ts +50 -0
- package/dist/sandbox-host/SandboxHost.d.ts.map +1 -0
- package/dist/sandbox-host/SandboxHost.js +85 -0
- package/dist/sandbox-host/SandboxHost.js.map +1 -0
- package/dist/unstable/useMentionAdapter.js +1 -1
- package/dist/unstable/useMentionAdapter.js.map +1 -1
- package/dist/unstable/useSlashCommandAdapter.js +1 -1
- package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
- package/dist/utils/Primitive.js +1 -1
- package/dist/utils/createActionButton.js +1 -1
- package/dist/utils/createActionButton.js.map +1 -1
- package/dist/utils/hooks/useManagedRef.js +1 -1
- package/dist/utils/hooks/useMediaQuery.js +1 -1
- package/dist/utils/hooks/useMediaQuery.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.js +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.js +1 -1
- package/dist/utils/hooks/useSizeHandle.js +1 -1
- package/dist/utils/json/is-json.js.map +1 -1
- package/dist/utils/smooth/SmoothContext.js +1 -1
- package/dist/utils/smooth/SmoothContext.js.map +1 -1
- package/dist/utils/smooth/useSmooth.js +1 -1
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/dist/utils/useToolArgsFieldStatus.d.ts +2 -2
- package/dist/utils/useToolArgsFieldStatus.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/client/ExternalThread.ts +484 -515
- package/src/client/InMemoryThreadList.ts +153 -162
- package/src/client/SingleThreadList.ts +87 -84
- package/src/context/providers/ThreadViewportProvider.tsx +2 -2
- package/src/index.ts +8 -1
- package/src/mcp-apps/McpAppRenderer.tsx +28 -35
- package/src/mcp-apps/McpAppsRemoteHost.ts +25 -24
- package/src/mcp-apps/app-frame.tsx +100 -141
- package/src/mcp-apps/bridge.test.ts +100 -60
- package/src/mcp-apps/bridge.ts +43 -21
- package/src/mcp-apps/types.ts +2 -12
- package/src/primitives/composer/trigger/TriggerPopover.tsx +1 -1
- package/src/primitives/composer/trigger/TriggerPopoverResource.ts +75 -76
- package/src/primitives/composer/trigger/triggerDetectionResource.ts +6 -5
- package/src/primitives/composer/trigger/triggerKeyboardResource.ts +9 -13
- package/src/primitives/composer/trigger/triggerNavigationResource.ts +14 -19
- package/src/primitives/composer/trigger/triggerSelectionResource.ts +8 -7
- package/src/sandbox-host/SandboxHost.test.tsx +231 -0
- package/src/sandbox-host/SandboxHost.tsx +185 -0
- package/src/tests/local-runtime-queue.test.tsx +305 -0
package/src/mcp-apps/bridge.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SandboxHostFrame } from "../sandbox-host/SandboxHost";
|
|
2
2
|
import {
|
|
3
3
|
MCP_APP_PROTOCOL_VERSION,
|
|
4
4
|
type McpAppBridgeHandlers,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type McpAppJsonRpcRequest,
|
|
11
11
|
type McpAppJsonRpcResponse,
|
|
12
12
|
} from "./types";
|
|
13
|
+
import { isRecord } from "../utils/json/is-json";
|
|
13
14
|
|
|
14
15
|
const VALID_DISPLAY_MODES = [
|
|
15
16
|
"inline",
|
|
@@ -17,20 +18,17 @@ const VALID_DISPLAY_MODES = [
|
|
|
17
18
|
"pip",
|
|
18
19
|
] as const satisfies readonly McpAppDisplayMode[];
|
|
19
20
|
|
|
20
|
-
export type McpAppBridgeFrame =
|
|
21
|
-
RenderedFrame,
|
|
22
|
-
"iframe" | "origin" | "sendMessage"
|
|
23
|
-
>;
|
|
21
|
+
export type McpAppBridgeFrame = SandboxHostFrame;
|
|
24
22
|
|
|
25
23
|
export type CreateMcpAppBridgeOptions = {
|
|
26
24
|
frame: McpAppBridgeFrame;
|
|
27
25
|
handlers?: McpAppBridgeHandlers | undefined;
|
|
28
26
|
hostInfo?: McpAppHostInfo | undefined;
|
|
29
27
|
hostContext?: McpAppHostContext | undefined;
|
|
30
|
-
targetWindow?: Window | undefined;
|
|
31
28
|
};
|
|
32
29
|
|
|
33
30
|
export type McpAppBridge = {
|
|
31
|
+
onMessage: (event: MessageEvent) => void;
|
|
34
32
|
dispose: () => void;
|
|
35
33
|
notifyToolInput: (input: unknown) => void;
|
|
36
34
|
notifyToolResult: (result: unknown) => void;
|
|
@@ -90,13 +88,8 @@ export function createMcpAppBridge(
|
|
|
90
88
|
handlers = {},
|
|
91
89
|
hostInfo = DEFAULT_HOST_INFO,
|
|
92
90
|
hostContext = {},
|
|
93
|
-
targetWindow = typeof window !== "undefined" ? window : undefined,
|
|
94
91
|
} = opts;
|
|
95
92
|
|
|
96
|
-
if (!targetWindow) {
|
|
97
|
-
throw new Error("createMcpAppBridge requires a window context");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
93
|
const post = (msg: McpAppJsonRpcMessage) => {
|
|
101
94
|
frame.sendMessage(msg);
|
|
102
95
|
};
|
|
@@ -136,10 +129,15 @@ export function createMcpAppBridge(
|
|
|
136
129
|
|
|
137
130
|
switch (normalizeMethod(req.method)) {
|
|
138
131
|
case "ui/initialize": {
|
|
132
|
+
const requestedProtocolVersion =
|
|
133
|
+
isRecord(params) && typeof params.protocolVersion === "string"
|
|
134
|
+
? params.protocolVersion
|
|
135
|
+
: MCP_APP_PROTOCOL_VERSION;
|
|
139
136
|
respond(req.id, {
|
|
140
137
|
result: {
|
|
141
|
-
protocolVersion:
|
|
138
|
+
protocolVersion: requestedProtocolVersion,
|
|
142
139
|
host: hostInfo,
|
|
140
|
+
hostInfo,
|
|
143
141
|
hostContext,
|
|
144
142
|
capabilities: {
|
|
145
143
|
tools: handlers.callTool ? {} : undefined,
|
|
@@ -154,6 +152,18 @@ export function createMcpAppBridge(
|
|
|
154
152
|
updateModelContext: !!handlers.updateModelContext,
|
|
155
153
|
},
|
|
156
154
|
},
|
|
155
|
+
hostCapabilities: {
|
|
156
|
+
...(handlers.openLink ? { openLinks: {} } : {}),
|
|
157
|
+
...(handlers.callTool ? { serverTools: {} } : {}),
|
|
158
|
+
...(handlers.readResource || handlers.listResources
|
|
159
|
+
? { serverResources: {} }
|
|
160
|
+
: {}),
|
|
161
|
+
...(handlers.updateModelContext
|
|
162
|
+
? { updateModelContext: { text: {} } }
|
|
163
|
+
: {}),
|
|
164
|
+
...(handlers.sendMessage ? { message: { text: {} } } : {}),
|
|
165
|
+
...(handlers.onLog ? { logging: {} } : {}),
|
|
166
|
+
},
|
|
157
167
|
},
|
|
158
168
|
});
|
|
159
169
|
return;
|
|
@@ -405,11 +415,9 @@ export function createMcpAppBridge(
|
|
|
405
415
|
}
|
|
406
416
|
};
|
|
407
417
|
|
|
408
|
-
//
|
|
409
|
-
//
|
|
418
|
+
// The host applies the cross-origin guard before delegating; this only
|
|
419
|
+
// validates the JSON-RPC envelope.
|
|
410
420
|
const onMessage = (event: MessageEvent) => {
|
|
411
|
-
if (event.source !== frame.iframe.contentWindow) return;
|
|
412
|
-
if (event.origin !== frame.origin) return;
|
|
413
421
|
if (!isJsonRpcMessage(event.data)) return;
|
|
414
422
|
|
|
415
423
|
const msg = event.data;
|
|
@@ -420,18 +428,20 @@ export function createMcpAppBridge(
|
|
|
420
428
|
}
|
|
421
429
|
};
|
|
422
430
|
|
|
423
|
-
targetWindow.addEventListener("message", onMessage);
|
|
424
|
-
|
|
425
431
|
return {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
},
|
|
432
|
+
onMessage,
|
|
433
|
+
dispose: () => {},
|
|
429
434
|
notifyToolInput: (input: unknown) => {
|
|
430
435
|
post({
|
|
431
436
|
jsonrpc: "2.0",
|
|
432
437
|
method: "notifications/tools/call/input",
|
|
433
438
|
params: { input },
|
|
434
439
|
});
|
|
440
|
+
post({
|
|
441
|
+
jsonrpc: "2.0",
|
|
442
|
+
method: "ui/notifications/tool-input",
|
|
443
|
+
params: isRecord(input) ? { arguments: input } : {},
|
|
444
|
+
});
|
|
435
445
|
},
|
|
436
446
|
notifyToolResult: (result: unknown) => {
|
|
437
447
|
post({
|
|
@@ -439,6 +449,13 @@ export function createMcpAppBridge(
|
|
|
439
449
|
method: "notifications/tools/call/result",
|
|
440
450
|
params: { result },
|
|
441
451
|
});
|
|
452
|
+
post({
|
|
453
|
+
jsonrpc: "2.0",
|
|
454
|
+
method: "ui/notifications/tool-result",
|
|
455
|
+
params: isRecord(result)
|
|
456
|
+
? result
|
|
457
|
+
: { content: [{ type: "text", text: String(result) }] },
|
|
458
|
+
});
|
|
442
459
|
},
|
|
443
460
|
notifyHostContextChanged: (ctx: McpAppHostContext) => {
|
|
444
461
|
post({
|
|
@@ -446,6 +463,11 @@ export function createMcpAppBridge(
|
|
|
446
463
|
method: "notifications/host_context/changed",
|
|
447
464
|
params: ctx,
|
|
448
465
|
});
|
|
466
|
+
post({
|
|
467
|
+
jsonrpc: "2.0",
|
|
468
|
+
method: "ui/notifications/host-context-changed",
|
|
469
|
+
params: ctx,
|
|
470
|
+
});
|
|
449
471
|
},
|
|
450
472
|
};
|
|
451
473
|
}
|
package/src/mcp-apps/types.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { CSSProperties } from "react";
|
|
2
1
|
import type {
|
|
3
2
|
McpAppMetadata,
|
|
4
3
|
ToolCallMessagePartMcpMetadata,
|
|
5
4
|
} from "@assistant-ui/core";
|
|
6
|
-
import type {
|
|
5
|
+
import type { SandboxHostConfig } from "../sandbox-host/SandboxHost";
|
|
7
6
|
|
|
8
7
|
export type { McpAppMetadata, ToolCallMessagePartMcpMetadata };
|
|
9
8
|
|
|
@@ -97,16 +96,7 @@ export type McpAppBridgeHandlers = {
|
|
|
97
96
|
onError?: (error: Error) => void;
|
|
98
97
|
};
|
|
99
98
|
|
|
100
|
-
export type McpAppSandboxConfig =
|
|
101
|
-
sandbox?: SandboxOption[];
|
|
102
|
-
useShadowDom?: boolean;
|
|
103
|
-
enableBrowserCaching?: boolean;
|
|
104
|
-
salt?: string;
|
|
105
|
-
product?: string;
|
|
106
|
-
className?: string;
|
|
107
|
-
style?: CSSProperties;
|
|
108
|
-
unsafeDocumentWrite?: boolean;
|
|
109
|
-
};
|
|
99
|
+
export type McpAppSandboxConfig = SandboxHostConfig;
|
|
110
100
|
|
|
111
101
|
export type McpAppFrameProps = {
|
|
112
102
|
app: McpAppMetadata;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
4
|
-
import { useResource } from "@assistant-ui/tap
|
|
4
|
+
import { useResource } from "@assistant-ui/tap";
|
|
5
5
|
import type { Unstable_TriggerAdapter } from "@assistant-ui/core";
|
|
6
6
|
import {
|
|
7
7
|
createContext,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffectEvent } from "react";
|
|
2
|
+
import { useResource, resource } from "@assistant-ui/tap";
|
|
2
3
|
import type {
|
|
3
4
|
Unstable_TriggerAdapter,
|
|
4
5
|
Unstable_TriggerCategory,
|
|
@@ -50,88 +51,86 @@ export type TriggerPopoverResourceOutput = {
|
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
/** Composes detection, navigation, keyboard, and selection sub-resources. */
|
|
53
|
-
export const TriggerPopoverResource = resource(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const open =
|
|
75
|
-
detection.trigger !== null &&
|
|
76
|
-
adapter !== undefined &&
|
|
77
|
-
behavior !== undefined;
|
|
54
|
+
export const TriggerPopoverResource = resource(function TriggerPopoverResource({
|
|
55
|
+
adapter,
|
|
56
|
+
text,
|
|
57
|
+
triggerChar,
|
|
58
|
+
behavior,
|
|
59
|
+
aui,
|
|
60
|
+
popoverId,
|
|
61
|
+
}: {
|
|
62
|
+
adapter: Unstable_TriggerAdapter | undefined;
|
|
63
|
+
text: string;
|
|
64
|
+
triggerChar: string;
|
|
65
|
+
behavior: TriggerBehavior | undefined;
|
|
66
|
+
aui: AssistantClient;
|
|
67
|
+
/** Stable ID for accessible element IDs (pass React's useId() from component layer). */
|
|
68
|
+
popoverId: string;
|
|
69
|
+
}): TriggerPopoverResourceOutput {
|
|
70
|
+
const detection = useResource(
|
|
71
|
+
TriggerDetectionResource({ text, triggerChar }),
|
|
72
|
+
);
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
open,
|
|
84
|
-
}),
|
|
85
|
-
);
|
|
74
|
+
const open =
|
|
75
|
+
detection.trigger !== null &&
|
|
76
|
+
adapter !== undefined &&
|
|
77
|
+
behavior !== undefined;
|
|
86
78
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
const navigation = useResource(
|
|
80
|
+
TriggerNavigationResource({
|
|
81
|
+
adapter,
|
|
82
|
+
query: detection.query,
|
|
83
|
+
open,
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
trigger: detection.trigger,
|
|
95
|
-
aui,
|
|
96
|
-
triggerChar,
|
|
97
|
-
setCursorPosition: detection.setCursorPosition,
|
|
98
|
-
onSelected,
|
|
99
|
-
}),
|
|
100
|
-
);
|
|
87
|
+
const onSelected = useEffectEvent(() => {
|
|
88
|
+
navigation.goBack();
|
|
89
|
+
});
|
|
101
90
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
goBack: navigation.goBack,
|
|
113
|
-
close: selection.close,
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
91
|
+
const selection = useResource(
|
|
92
|
+
TriggerSelectionResource({
|
|
93
|
+
behavior,
|
|
94
|
+
trigger: detection.trigger,
|
|
95
|
+
aui,
|
|
96
|
+
triggerChar,
|
|
97
|
+
setCursorPosition: detection.setCursorPosition,
|
|
98
|
+
onSelected,
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
116
101
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
activeCategoryId: navigation.activeCategoryId,
|
|
121
|
-
categories: navigation.categories,
|
|
122
|
-
items: navigation.items,
|
|
123
|
-
highlightedIndex: keyboard.highlightedIndex,
|
|
102
|
+
const keyboard = useResource(
|
|
103
|
+
TriggerKeyboardResource({
|
|
104
|
+
navigableList: navigation.navigableList,
|
|
124
105
|
isSearchMode: navigation.isSearchMode,
|
|
106
|
+
activeCategoryId: navigation.activeCategoryId,
|
|
107
|
+
query: detection.query,
|
|
125
108
|
popoverId,
|
|
126
|
-
|
|
109
|
+
open,
|
|
110
|
+
selectItem: selection.selectItem,
|
|
127
111
|
selectCategory: navigation.selectCategory,
|
|
128
112
|
goBack: navigation.goBack,
|
|
129
|
-
selectItem: selection.selectItem,
|
|
130
113
|
close: selection.close,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
open,
|
|
119
|
+
query: detection.query,
|
|
120
|
+
activeCategoryId: navigation.activeCategoryId,
|
|
121
|
+
categories: navigation.categories,
|
|
122
|
+
items: navigation.items,
|
|
123
|
+
highlightedIndex: keyboard.highlightedIndex,
|
|
124
|
+
isSearchMode: navigation.isSearchMode,
|
|
125
|
+
popoverId,
|
|
126
|
+
highlightedItemId: keyboard.highlightedItemId,
|
|
127
|
+
selectCategory: navigation.selectCategory,
|
|
128
|
+
goBack: navigation.goBack,
|
|
129
|
+
selectItem: selection.selectItem,
|
|
130
|
+
close: selection.close,
|
|
131
|
+
highlightIndex: keyboard.highlightIndex,
|
|
132
|
+
handleKeyDown: keyboard.handleKeyDown,
|
|
133
|
+
setCursorPosition: detection.setCursorPosition,
|
|
134
|
+
registerSelectItemOverride: selection.registerSelectItemOverride,
|
|
135
|
+
};
|
|
136
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import { resource } from "@assistant-ui/tap";
|
|
2
3
|
import { detectTrigger } from "./detectTrigger";
|
|
3
4
|
|
|
4
5
|
/** Detected trigger position within the composer text. */
|
|
@@ -18,16 +19,16 @@ export type TriggerDetectionResourceOutput = {
|
|
|
18
19
|
|
|
19
20
|
/** Tracks cursor position and derives the active trigger + query from composer text. */
|
|
20
21
|
export const TriggerDetectionResource = resource(
|
|
21
|
-
({
|
|
22
|
+
function TriggerDetectionResource({
|
|
22
23
|
text,
|
|
23
24
|
triggerChar,
|
|
24
25
|
}: {
|
|
25
26
|
text: string;
|
|
26
27
|
triggerChar: string;
|
|
27
|
-
}): TriggerDetectionResourceOutput
|
|
28
|
-
const [cursorPosition, setCursorPosition] =
|
|
28
|
+
}): TriggerDetectionResourceOutput {
|
|
29
|
+
const [cursorPosition, setCursorPosition] = useState(text.length);
|
|
29
30
|
|
|
30
|
-
const trigger =
|
|
31
|
+
const trigger = useMemo(() => {
|
|
31
32
|
const pos = Math.min(cursorPosition, text.length);
|
|
32
33
|
return detectTrigger(text, triggerChar, pos);
|
|
33
34
|
}, [cursorPosition, text, triggerChar]);
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
tapEffect,
|
|
4
|
-
tapEffectEvent,
|
|
5
|
-
tapState,
|
|
6
|
-
} from "@assistant-ui/tap";
|
|
1
|
+
import { useEffect, useEffectEvent, useState } from "react";
|
|
2
|
+
import { resource } from "@assistant-ui/tap";
|
|
7
3
|
import type {
|
|
8
4
|
Unstable_TriggerCategory,
|
|
9
5
|
Unstable_TriggerItem,
|
|
@@ -39,7 +35,7 @@ export type TriggerKeyboardResourceOutput = {
|
|
|
39
35
|
* category drill-in, back, and close to the callbacks supplied by the parent.
|
|
40
36
|
*/
|
|
41
37
|
export const TriggerKeyboardResource = resource(
|
|
42
|
-
({
|
|
38
|
+
function TriggerKeyboardResource({
|
|
43
39
|
navigableList,
|
|
44
40
|
isSearchMode,
|
|
45
41
|
activeCategoryId,
|
|
@@ -61,24 +57,24 @@ export const TriggerKeyboardResource = resource(
|
|
|
61
57
|
selectCategory: (categoryId: string) => void;
|
|
62
58
|
goBack: () => void;
|
|
63
59
|
close: () => void;
|
|
64
|
-
}): TriggerKeyboardResourceOutput
|
|
65
|
-
const [highlightedIndex, setHighlightedIndex] =
|
|
60
|
+
}): TriggerKeyboardResourceOutput {
|
|
61
|
+
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
useEffect(() => {
|
|
68
64
|
setHighlightedIndex(0);
|
|
69
65
|
}, [navigableList]);
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
useEffect(() => {
|
|
72
68
|
setHighlightedIndex(0);
|
|
73
69
|
}, [isSearchMode, activeCategoryId]);
|
|
74
70
|
|
|
75
|
-
const highlightIndex =
|
|
71
|
+
const highlightIndex = useEffectEvent((index: number) => {
|
|
76
72
|
if (index < 0 || index >= navigableList.length) return;
|
|
77
73
|
if (index === highlightedIndex) return;
|
|
78
74
|
setHighlightedIndex(index);
|
|
79
75
|
});
|
|
80
76
|
|
|
81
|
-
const handleKeyDown =
|
|
77
|
+
const handleKeyDown = useEffectEvent(
|
|
82
78
|
(e: TriggerPopoverKeyEvent): boolean => {
|
|
83
79
|
if (!open) return false;
|
|
84
80
|
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
tapEffect,
|
|
4
|
-
tapEffectEvent,
|
|
5
|
-
tapMemo,
|
|
6
|
-
tapState,
|
|
7
|
-
} from "@assistant-ui/tap";
|
|
1
|
+
import { useEffect, useEffectEvent, useMemo, useState } from "react";
|
|
2
|
+
import { resource } from "@assistant-ui/tap";
|
|
8
3
|
import type {
|
|
9
4
|
Unstable_TriggerAdapter,
|
|
10
5
|
Unstable_TriggerCategory,
|
|
@@ -44,7 +39,7 @@ export type TriggerNavigationResourceOutput = {
|
|
|
44
39
|
* adapter + current query. Pure derivation — no side effects on the composer.
|
|
45
40
|
*/
|
|
46
41
|
export const TriggerNavigationResource = resource(
|
|
47
|
-
({
|
|
42
|
+
function TriggerNavigationResource({
|
|
48
43
|
adapter,
|
|
49
44
|
query,
|
|
50
45
|
open,
|
|
@@ -52,28 +47,28 @@ export const TriggerNavigationResource = resource(
|
|
|
52
47
|
adapter: Unstable_TriggerAdapter | undefined;
|
|
53
48
|
query: string;
|
|
54
49
|
open: boolean;
|
|
55
|
-
}): TriggerNavigationResourceOutput
|
|
56
|
-
const [activeCategoryId, setActiveCategoryId] =
|
|
50
|
+
}): TriggerNavigationResourceOutput {
|
|
51
|
+
const [activeCategoryId, setActiveCategoryId] = useState<string | null>(
|
|
57
52
|
null,
|
|
58
53
|
);
|
|
59
54
|
|
|
60
|
-
|
|
55
|
+
useEffect(() => {
|
|
61
56
|
if (!open) setActiveCategoryId(null);
|
|
62
57
|
}, [open]);
|
|
63
58
|
|
|
64
|
-
const categories =
|
|
59
|
+
const categories = useMemo<readonly Unstable_TriggerCategory[]>(() => {
|
|
65
60
|
if (!open || !adapter) return [];
|
|
66
61
|
return adapter.categories();
|
|
67
62
|
}, [open, adapter]);
|
|
68
63
|
|
|
69
64
|
const effectiveActiveCategoryId = open ? activeCategoryId : null;
|
|
70
65
|
|
|
71
|
-
const allItems =
|
|
66
|
+
const allItems = useMemo<readonly Unstable_TriggerItem[]>(() => {
|
|
72
67
|
if (!effectiveActiveCategoryId || !adapter) return [];
|
|
73
68
|
return adapter.categoryItems(effectiveActiveCategoryId);
|
|
74
69
|
}, [effectiveActiveCategoryId, adapter]);
|
|
75
70
|
|
|
76
|
-
const searchResults =
|
|
71
|
+
const searchResults = useMemo<
|
|
77
72
|
readonly Unstable_TriggerItem[] | null
|
|
78
73
|
>(() => {
|
|
79
74
|
if (!open || !adapter || effectiveActiveCategoryId) return null;
|
|
@@ -96,7 +91,7 @@ export const TriggerNavigationResource = resource(
|
|
|
96
91
|
|
|
97
92
|
const isSearchMode = searchResults !== null;
|
|
98
93
|
|
|
99
|
-
const filteredCategories =
|
|
94
|
+
const filteredCategories = useMemo(() => {
|
|
100
95
|
if (isSearchMode) return [];
|
|
101
96
|
if (!query) return categories;
|
|
102
97
|
const lower = query.toLowerCase();
|
|
@@ -105,14 +100,14 @@ export const TriggerNavigationResource = resource(
|
|
|
105
100
|
);
|
|
106
101
|
}, [categories, query, isSearchMode]);
|
|
107
102
|
|
|
108
|
-
const filteredItems =
|
|
103
|
+
const filteredItems = useMemo(() => {
|
|
109
104
|
if (isSearchMode) return searchResults ?? [];
|
|
110
105
|
if (!query) return allItems;
|
|
111
106
|
const lower = query.toLowerCase();
|
|
112
107
|
return allItems.filter((item) => matchesQuery(item, lower));
|
|
113
108
|
}, [allItems, query, isSearchMode, searchResults]);
|
|
114
109
|
|
|
115
|
-
const navigableList =
|
|
110
|
+
const navigableList = useMemo(() => {
|
|
116
111
|
if (isSearchMode) return searchResults ?? [];
|
|
117
112
|
if (effectiveActiveCategoryId) return filteredItems;
|
|
118
113
|
return filteredCategories;
|
|
@@ -124,11 +119,11 @@ export const TriggerNavigationResource = resource(
|
|
|
124
119
|
filteredCategories,
|
|
125
120
|
]);
|
|
126
121
|
|
|
127
|
-
const selectCategory =
|
|
122
|
+
const selectCategory = useEffectEvent((categoryId: string) => {
|
|
128
123
|
setActiveCategoryId(categoryId);
|
|
129
124
|
});
|
|
130
125
|
|
|
131
|
-
const goBack =
|
|
126
|
+
const goBack = useEffectEvent(() => {
|
|
132
127
|
setActiveCategoryId(null);
|
|
133
128
|
});
|
|
134
129
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffectEvent, useRef } from "react";
|
|
2
|
+
import { resource } from "@assistant-ui/tap";
|
|
2
3
|
import type {
|
|
3
4
|
Unstable_DirectiveFormatter,
|
|
4
5
|
Unstable_TriggerItem,
|
|
@@ -33,7 +34,7 @@ export type TriggerSelectionResourceOutput = {
|
|
|
33
34
|
|
|
34
35
|
/** Owns composer text mutation + behavior dispatch on item selection. */
|
|
35
36
|
export const TriggerSelectionResource = resource(
|
|
36
|
-
({
|
|
37
|
+
function TriggerSelectionResource({
|
|
37
38
|
behavior,
|
|
38
39
|
trigger,
|
|
39
40
|
aui,
|
|
@@ -48,12 +49,12 @@ export const TriggerSelectionResource = resource(
|
|
|
48
49
|
setCursorPosition: (pos: number) => void;
|
|
49
50
|
/** Called after a successful selection so the parent can reset nav state. */
|
|
50
51
|
onSelected: () => void;
|
|
51
|
-
}): TriggerSelectionResourceOutput
|
|
52
|
+
}): TriggerSelectionResourceOutput {
|
|
52
53
|
// Select-item override: lets Lexical's DirectivePlugin intercept selection
|
|
53
54
|
// and drive its own node insertion.
|
|
54
|
-
const selectItemOverrideRef =
|
|
55
|
+
const selectItemOverrideRef = useRef<SelectItemOverride | null>(null);
|
|
55
56
|
|
|
56
|
-
const registerSelectItemOverride =
|
|
57
|
+
const registerSelectItemOverride = useEffectEvent(
|
|
57
58
|
(fn: SelectItemOverride) => {
|
|
58
59
|
selectItemOverrideRef.current = fn;
|
|
59
60
|
return () => {
|
|
@@ -64,7 +65,7 @@ export const TriggerSelectionResource = resource(
|
|
|
64
65
|
},
|
|
65
66
|
);
|
|
66
67
|
|
|
67
|
-
const selectItem =
|
|
68
|
+
const selectItem = useEffectEvent((item: Unstable_TriggerItem) => {
|
|
68
69
|
if (!trigger || !behavior) return;
|
|
69
70
|
|
|
70
71
|
if (selectItemOverrideRef.current?.(item)) {
|
|
@@ -105,7 +106,7 @@ export const TriggerSelectionResource = resource(
|
|
|
105
106
|
onSelected();
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
const close =
|
|
109
|
+
const close = useEffectEvent(() => {
|
|
109
110
|
onSelected();
|
|
110
111
|
// Move cursor before the trigger so trigger detection deactivates
|
|
111
112
|
if (trigger) {
|