@assistant-ui/react 0.14.13 → 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 +24 -13
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/client/SingleThreadList.d.ts.map +1 -1
- package/dist/client/SingleThreadList.js +12 -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.d.ts +14 -0
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js +101 -0
- package/dist/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.js.map +1 -0
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +13 -2
- 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.d.ts +2 -2
- package/dist/unstable/useMentionAdapter.js +2 -2
- 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/package.json +21 -20
- package/src/client/ExternalThread.ts +484 -515
- package/src/client/InMemoryThreadList.ts +154 -142
- package/src/client/SingleThreadList.ts +88 -81
- package/src/context/providers/ThreadViewportProvider.tsx +2 -2
- package/src/index.ts +18 -3
- package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.test.ts +426 -0
- package/src/legacy-runtime/runtime-cores/assistant-transport/replayBoundaryStream.ts +146 -0
- package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.ts +16 -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/unstable/useMentionAdapter.ts +2 -2
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createMcpAppBridge,
|
|
5
|
+
type McpAppBridge,
|
|
6
|
+
type McpAppBridgeFrame,
|
|
7
|
+
} from "./bridge";
|
|
4
8
|
import type {
|
|
5
9
|
McpAppJsonRpcMessage,
|
|
6
10
|
McpAppJsonRpcRequest,
|
|
@@ -24,13 +28,8 @@ function makeFrame() {
|
|
|
24
28
|
return { frame, captured };
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
data: message,
|
|
30
|
-
origin: frame.origin,
|
|
31
|
-
source: frame.iframe.contentWindow,
|
|
32
|
-
});
|
|
33
|
-
window.dispatchEvent(event);
|
|
31
|
+
function deliver(bridge: McpAppBridge, message: McpAppJsonRpcMessage) {
|
|
32
|
+
bridge.onMessage(new MessageEvent("message", { data: message }));
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
async function flush() {
|
|
@@ -55,7 +54,7 @@ describe("createMcpAppBridge", () => {
|
|
|
55
54
|
id: 1,
|
|
56
55
|
method: "ui/initialize",
|
|
57
56
|
};
|
|
58
|
-
|
|
57
|
+
deliver(bridge, req);
|
|
59
58
|
await flush();
|
|
60
59
|
|
|
61
60
|
expect(captured).toHaveLength(1);
|
|
@@ -69,6 +68,34 @@ describe("createMcpAppBridge", () => {
|
|
|
69
68
|
expect(result["capabilities"]["ui"]["sendMessage"]).toBe(true);
|
|
70
69
|
expect(result["capabilities"]["ui"]["openLink"]).toBe(false);
|
|
71
70
|
|
|
71
|
+
expect(result["hostInfo"]).toEqual({ name: "test-host", version: "9.9.9" });
|
|
72
|
+
expect(result["hostCapabilities"]).toEqual({
|
|
73
|
+
serverTools: {},
|
|
74
|
+
message: { text: {} },
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
bridge.dispose();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("echoes the requested protocolVersion in the ui/initialize result", async () => {
|
|
81
|
+
const { frame, captured } = makeFrame();
|
|
82
|
+
const bridge = createMcpAppBridge({ frame });
|
|
83
|
+
|
|
84
|
+
deliver(bridge, {
|
|
85
|
+
jsonrpc: "2.0",
|
|
86
|
+
id: 1,
|
|
87
|
+
method: "ui/initialize",
|
|
88
|
+
params: { protocolVersion: "2026-01-26" },
|
|
89
|
+
});
|
|
90
|
+
await flush();
|
|
91
|
+
|
|
92
|
+
const result = (captured[0] as McpAppJsonRpcResponse).result as Record<
|
|
93
|
+
string,
|
|
94
|
+
any
|
|
95
|
+
>;
|
|
96
|
+
expect(result["protocolVersion"]).toBe("2026-01-26");
|
|
97
|
+
expect(result["hostCapabilities"]).toEqual({});
|
|
98
|
+
|
|
72
99
|
bridge.dispose();
|
|
73
100
|
});
|
|
74
101
|
|
|
@@ -77,7 +104,7 @@ describe("createMcpAppBridge", () => {
|
|
|
77
104
|
const callTool = vi.fn().mockResolvedValue({ ok: true });
|
|
78
105
|
const bridge = createMcpAppBridge({ frame, handlers: { callTool } });
|
|
79
106
|
|
|
80
|
-
|
|
107
|
+
deliver(bridge, {
|
|
81
108
|
jsonrpc: "2.0",
|
|
82
109
|
id: 7,
|
|
83
110
|
method: "tools/call",
|
|
@@ -105,7 +132,7 @@ describe("createMcpAppBridge", () => {
|
|
|
105
132
|
handlers: { callTool, allowedTools: ["search"] },
|
|
106
133
|
});
|
|
107
134
|
|
|
108
|
-
|
|
135
|
+
deliver(bridge, {
|
|
109
136
|
jsonrpc: "2.0",
|
|
110
137
|
id: 2,
|
|
111
138
|
method: "tools/call",
|
|
@@ -123,7 +150,7 @@ describe("createMcpAppBridge", () => {
|
|
|
123
150
|
const { frame, captured } = makeFrame();
|
|
124
151
|
const bridge = createMcpAppBridge({ frame });
|
|
125
152
|
|
|
126
|
-
|
|
153
|
+
deliver(bridge, {
|
|
127
154
|
jsonrpc: "2.0",
|
|
128
155
|
id: 3,
|
|
129
156
|
method: "tools/call",
|
|
@@ -141,7 +168,7 @@ describe("createMcpAppBridge", () => {
|
|
|
141
168
|
const callTool = vi.fn();
|
|
142
169
|
const bridge = createMcpAppBridge({ frame, handlers: { callTool } });
|
|
143
170
|
|
|
144
|
-
|
|
171
|
+
deliver(bridge, {
|
|
145
172
|
jsonrpc: "2.0",
|
|
146
173
|
id: 11,
|
|
147
174
|
method: "tools/call",
|
|
@@ -162,7 +189,7 @@ describe("createMcpAppBridge", () => {
|
|
|
162
189
|
handlers: { requestDisplayMode },
|
|
163
190
|
});
|
|
164
191
|
|
|
165
|
-
|
|
192
|
+
deliver(bridge, {
|
|
166
193
|
jsonrpc: "2.0",
|
|
167
194
|
id: 13,
|
|
168
195
|
method: "requestDisplayMode",
|
|
@@ -180,7 +207,7 @@ describe("createMcpAppBridge", () => {
|
|
|
180
207
|
const openLink = vi.fn();
|
|
181
208
|
const bridge = createMcpAppBridge({ frame, handlers: { openLink } });
|
|
182
209
|
|
|
183
|
-
|
|
210
|
+
deliver(bridge, {
|
|
184
211
|
jsonrpc: "2.0",
|
|
185
212
|
id: 12,
|
|
186
213
|
method: "openLink",
|
|
@@ -202,12 +229,12 @@ describe("createMcpAppBridge", () => {
|
|
|
202
229
|
handlers: { onSizeChange, onInitialized },
|
|
203
230
|
});
|
|
204
231
|
|
|
205
|
-
|
|
232
|
+
deliver(bridge, {
|
|
206
233
|
jsonrpc: "2.0",
|
|
207
234
|
method: "notifications/size_changed",
|
|
208
235
|
params: { width: 320, height: 240 },
|
|
209
236
|
});
|
|
210
|
-
|
|
237
|
+
deliver(bridge, {
|
|
211
238
|
jsonrpc: "2.0",
|
|
212
239
|
method: "notifications/initialized",
|
|
213
240
|
});
|
|
@@ -217,7 +244,7 @@ describe("createMcpAppBridge", () => {
|
|
|
217
244
|
bridge.dispose();
|
|
218
245
|
});
|
|
219
246
|
|
|
220
|
-
it("notifyToolInput / notifyToolResult / notifyHostContextChanged post
|
|
247
|
+
it("notifyToolInput / notifyToolResult / notifyHostContextChanged post both legacy and 2026-01-26 notifications", () => {
|
|
221
248
|
const { frame, captured } = makeFrame();
|
|
222
249
|
const bridge = createMcpAppBridge({ frame });
|
|
223
250
|
|
|
@@ -231,16 +258,62 @@ describe("createMcpAppBridge", () => {
|
|
|
231
258
|
method: "notifications/tools/call/input",
|
|
232
259
|
params: { input: { a: 1 } },
|
|
233
260
|
},
|
|
261
|
+
{
|
|
262
|
+
jsonrpc: "2.0",
|
|
263
|
+
method: "ui/notifications/tool-input",
|
|
264
|
+
params: { arguments: { a: 1 } },
|
|
265
|
+
},
|
|
234
266
|
{
|
|
235
267
|
jsonrpc: "2.0",
|
|
236
268
|
method: "notifications/tools/call/result",
|
|
237
269
|
params: { result: { ok: 1 } },
|
|
238
270
|
},
|
|
271
|
+
{
|
|
272
|
+
jsonrpc: "2.0",
|
|
273
|
+
method: "ui/notifications/tool-result",
|
|
274
|
+
params: { ok: 1 },
|
|
275
|
+
},
|
|
239
276
|
{
|
|
240
277
|
jsonrpc: "2.0",
|
|
241
278
|
method: "notifications/host_context/changed",
|
|
242
279
|
params: { theme: "light" },
|
|
243
280
|
},
|
|
281
|
+
{
|
|
282
|
+
jsonrpc: "2.0",
|
|
283
|
+
method: "ui/notifications/host-context-changed",
|
|
284
|
+
params: { theme: "light" },
|
|
285
|
+
},
|
|
286
|
+
]);
|
|
287
|
+
bridge.dispose();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("wraps non-object and array tool results in a valid content block for the spec dialect", () => {
|
|
291
|
+
const { frame, captured } = makeFrame();
|
|
292
|
+
const bridge = createMcpAppBridge({ frame });
|
|
293
|
+
|
|
294
|
+
bridge.notifyToolResult("done");
|
|
295
|
+
bridge.notifyToolResult([1, 2]);
|
|
296
|
+
bridge.notifyToolInput(null);
|
|
297
|
+
|
|
298
|
+
const spec = captured.filter((c) =>
|
|
299
|
+
(c as { method?: string }).method?.startsWith("ui/notifications/"),
|
|
300
|
+
);
|
|
301
|
+
expect(spec).toEqual([
|
|
302
|
+
{
|
|
303
|
+
jsonrpc: "2.0",
|
|
304
|
+
method: "ui/notifications/tool-result",
|
|
305
|
+
params: { content: [{ type: "text", text: "done" }] },
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
jsonrpc: "2.0",
|
|
309
|
+
method: "ui/notifications/tool-result",
|
|
310
|
+
params: { content: [{ type: "text", text: "1,2" }] },
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
jsonrpc: "2.0",
|
|
314
|
+
method: "ui/notifications/tool-input",
|
|
315
|
+
params: {},
|
|
316
|
+
},
|
|
244
317
|
]);
|
|
245
318
|
bridge.dispose();
|
|
246
319
|
});
|
|
@@ -254,13 +327,13 @@ describe("createMcpAppBridge", () => {
|
|
|
254
327
|
handlers: { readResource, listResources },
|
|
255
328
|
});
|
|
256
329
|
|
|
257
|
-
|
|
330
|
+
deliver(bridge, {
|
|
258
331
|
jsonrpc: "2.0",
|
|
259
332
|
id: 20,
|
|
260
333
|
method: "resources/read",
|
|
261
334
|
params: { uri: "ui://app/x" },
|
|
262
335
|
});
|
|
263
|
-
|
|
336
|
+
deliver(bridge, {
|
|
264
337
|
jsonrpc: "2.0",
|
|
265
338
|
id: 21,
|
|
266
339
|
method: "resources/list",
|
|
@@ -279,13 +352,13 @@ describe("createMcpAppBridge", () => {
|
|
|
279
352
|
const { frame, captured } = makeFrame();
|
|
280
353
|
const bridge = createMcpAppBridge({ frame });
|
|
281
354
|
|
|
282
|
-
|
|
355
|
+
deliver(bridge, {
|
|
283
356
|
jsonrpc: "2.0",
|
|
284
357
|
id: 22,
|
|
285
358
|
method: "resources/read",
|
|
286
359
|
params: { uri: "ui://x" },
|
|
287
360
|
});
|
|
288
|
-
|
|
361
|
+
deliver(bridge, { jsonrpc: "2.0", id: 23, method: "resources/list" });
|
|
289
362
|
await flush();
|
|
290
363
|
|
|
291
364
|
expect((captured[0] as McpAppJsonRpcResponse).error?.code).toBe(-32601);
|
|
@@ -302,13 +375,13 @@ describe("createMcpAppBridge", () => {
|
|
|
302
375
|
handlers: { sendMessage, updateModelContext },
|
|
303
376
|
});
|
|
304
377
|
|
|
305
|
-
|
|
378
|
+
deliver(bridge, {
|
|
306
379
|
jsonrpc: "2.0",
|
|
307
380
|
id: 30,
|
|
308
381
|
method: "sendMessage",
|
|
309
382
|
params: { text: "hi" },
|
|
310
383
|
});
|
|
311
|
-
|
|
384
|
+
deliver(bridge, {
|
|
312
385
|
jsonrpc: "2.0",
|
|
313
386
|
id: 31,
|
|
314
387
|
method: "updateModelContext",
|
|
@@ -334,17 +407,17 @@ describe("createMcpAppBridge", () => {
|
|
|
334
407
|
handlers: { onLog, onError, onRequestTeardown },
|
|
335
408
|
});
|
|
336
409
|
|
|
337
|
-
|
|
410
|
+
deliver(bridge, {
|
|
338
411
|
jsonrpc: "2.0",
|
|
339
412
|
method: "notifications/log",
|
|
340
413
|
params: { level: "info", message: "hello" },
|
|
341
414
|
});
|
|
342
|
-
|
|
415
|
+
deliver(bridge, {
|
|
343
416
|
jsonrpc: "2.0",
|
|
344
417
|
method: "notifications/error",
|
|
345
418
|
params: { message: "kaboom" },
|
|
346
419
|
});
|
|
347
|
-
|
|
420
|
+
deliver(bridge, {
|
|
348
421
|
jsonrpc: "2.0",
|
|
349
422
|
method: "notifications/request_teardown",
|
|
350
423
|
params: { reason: "done" },
|
|
@@ -355,37 +428,4 @@ describe("createMcpAppBridge", () => {
|
|
|
355
428
|
expect(onRequestTeardown).toHaveBeenCalledWith({ reason: "done" });
|
|
356
429
|
bridge.dispose();
|
|
357
430
|
});
|
|
358
|
-
|
|
359
|
-
it("ignores messages from wrong origin or wrong source", async () => {
|
|
360
|
-
const { frame, captured } = makeFrame();
|
|
361
|
-
const callTool = vi.fn();
|
|
362
|
-
const bridge = createMcpAppBridge({ frame, handlers: { callTool } });
|
|
363
|
-
|
|
364
|
-
const msg: McpAppJsonRpcMessage = {
|
|
365
|
-
jsonrpc: "2.0",
|
|
366
|
-
id: 1,
|
|
367
|
-
method: "tools/call",
|
|
368
|
-
params: { name: "search" },
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
window.dispatchEvent(
|
|
372
|
-
new MessageEvent("message", {
|
|
373
|
-
data: msg,
|
|
374
|
-
origin: "https://attacker.example",
|
|
375
|
-
source: frame.iframe.contentWindow,
|
|
376
|
-
}),
|
|
377
|
-
);
|
|
378
|
-
window.dispatchEvent(
|
|
379
|
-
new MessageEvent("message", {
|
|
380
|
-
data: msg,
|
|
381
|
-
origin: frame.origin,
|
|
382
|
-
source: window,
|
|
383
|
-
}),
|
|
384
|
-
);
|
|
385
|
-
await flush();
|
|
386
|
-
|
|
387
|
-
expect(callTool).not.toHaveBeenCalled();
|
|
388
|
-
expect(captured).toHaveLength(0);
|
|
389
|
-
bridge.dispose();
|
|
390
|
-
});
|
|
391
431
|
});
|
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
|
+
});
|