@assistant-ui/mcp-docs-server 0.2.3 → 0.3.1
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 +16 -43
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -91
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +9 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +91 -0
- package/dist/proxy.js.map +1 -0
- package/package.json +8 -12
- package/src/index.ts +3 -115
- package/src/proxy.test.ts +385 -0
- package/src/proxy.ts +126 -0
- package/.docs/organized/code-examples/waterfall.md +0 -807
- package/.docs/organized/code-examples/with-a2a.md +0 -675
- package/.docs/organized/code-examples/with-ag-ui.md +0 -553
- package/.docs/organized/code-examples/with-ai-sdk-v7.md +0 -466
- package/.docs/organized/code-examples/with-artifacts.md +0 -815
- package/.docs/organized/code-examples/with-assistant-transport.md +0 -576
- package/.docs/organized/code-examples/with-browser-extension.md +0 -371
- package/.docs/organized/code-examples/with-chain-of-thought.md +0 -962
- package/.docs/organized/code-examples/with-cloud-standalone.md +0 -681
- package/.docs/organized/code-examples/with-cloud.md +0 -439
- package/.docs/organized/code-examples/with-custom-thread-list.md +0 -569
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +0 -527
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +0 -697
- package/.docs/organized/code-examples/with-eve.md +0 -405
- package/.docs/organized/code-examples/with-expo.md +0 -2246
- package/.docs/organized/code-examples/with-external-store.md +0 -421
- package/.docs/organized/code-examples/with-ffmpeg.md +0 -829
- package/.docs/organized/code-examples/with-generative-ui.md +0 -1810
- package/.docs/organized/code-examples/with-google-adk.md +0 -368
- package/.docs/organized/code-examples/with-heat-graph.md +0 -304
- package/.docs/organized/code-examples/with-image-generation.md +0 -463
- package/.docs/organized/code-examples/with-interactables.md +0 -733
- package/.docs/organized/code-examples/with-langchain.md +0 -446
- package/.docs/organized/code-examples/with-langgraph.md +0 -855
- package/.docs/organized/code-examples/with-livekit.md +0 -643
- package/.docs/organized/code-examples/with-mcp.md +0 -782
- package/.docs/organized/code-examples/with-nuxt.md +0 -2428
- package/.docs/organized/code-examples/with-opencode.md +0 -1974
- package/.docs/organized/code-examples/with-openui.md +0 -450
- package/.docs/organized/code-examples/with-pi.md +0 -2084
- package/.docs/organized/code-examples/with-react-hook-form.md +0 -727
- package/.docs/organized/code-examples/with-react-ink-web.md +0 -740
- package/.docs/organized/code-examples/with-react-ink.md +0 -473
- package/.docs/organized/code-examples/with-react-router.md +0 -936
- package/.docs/organized/code-examples/with-resumable-stream.md +0 -668
- package/.docs/organized/code-examples/with-store.md +0 -679
- package/.docs/organized/code-examples/with-svelte.md +0 -415
- package/.docs/organized/code-examples/with-sveltekit.md +0 -1061
- package/.docs/organized/code-examples/with-tanstack.md +0 -812
- package/.docs/organized/code-examples/with-tap-runtime.md +0 -813
- package/.docs/organized/code-examples/with-virtualized-thread.md +0 -681
- package/.docs/organized/code-examples/with-vue.md +0 -408
- package/.docs/raw/docs/(getting-started)/architecture.mdx +0 -146
- package/.docs/raw/docs/(getting-started)/base-ui.mdx +0 -39
- package/.docs/raw/docs/(getting-started)/cli.mdx +0 -542
- package/.docs/raw/docs/(getting-started)/devtools.mdx +0 -79
- package/.docs/raw/docs/(getting-started)/index.mdx +0 -23
- package/.docs/raw/docs/(getting-started)/installation.mdx +0 -483
- package/.docs/raw/docs/(getting-started)/llm.mdx +0 -211
- package/.docs/raw/docs/(getting-started)/rtl.mdx +0 -78
- package/.docs/raw/docs/(reference)/api-reference/adapters/attachments.mdx +0 -36
- package/.docs/raw/docs/(reference)/api-reference/adapters/feedback.mdx +0 -20
- package/.docs/raw/docs/(reference)/api-reference/adapters/index.mdx +0 -34
- package/.docs/raw/docs/(reference)/api-reference/adapters/model.mdx +0 -44
- package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +0 -59
- package/.docs/raw/docs/(reference)/api-reference/adapters/runtime.mdx +0 -20
- package/.docs/raw/docs/(reference)/api-reference/adapters/suggestions.mdx +0 -26
- package/.docs/raw/docs/(reference)/api-reference/context-providers/assistant-runtime-provider.mdx +0 -84
- package/.docs/raw/docs/(reference)/api-reference/context-providers/index.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/context-providers/scoped-providers.mdx +0 -64
- package/.docs/raw/docs/(reference)/api-reference/external-store/index.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +0 -57
- package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +0 -49
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/a2ui.mdx +0 -40
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +0 -56
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +0 -86
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +0 -39
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +0 -42
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +0 -84
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +0 -85
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/spec.mdx +0 -45
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +0 -93
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +0 -62
- package/.docs/raw/docs/(reference)/api-reference/hooks/composer-triggers.mdx +0 -129
- package/.docs/raw/docs/(reference)/api-reference/hooks/index.mdx +0 -31
- package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +0 -34
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +0 -350
- package/.docs/raw/docs/(reference)/api-reference/hooks/runtimes.mdx +0 -28
- package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +0 -97
- package/.docs/raw/docs/(reference)/api-reference/integrations/ai-sdk.mdx +0 -200
- package/.docs/raw/docs/(reference)/api-reference/integrations/cloud-ai-sdk.mdx +0 -24
- package/.docs/raw/docs/(reference)/api-reference/integrations/eve.mdx +0 -118
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +0 -28
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +0 -37
- package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +0 -50
- package/.docs/raw/docs/(reference)/api-reference/model-context/index.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/model-context/registry.mdx +0 -20
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +0 -566
- package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar-more.mdx +0 -152
- package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +0 -239
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +0 -208
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +0 -108
- package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +0 -99
- package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +0 -145
- package/.docs/raw/docs/(reference)/api-reference/primitives/chain-of-thought.mdx +0 -82
- package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +0 -637
- package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/primitives/error.mdx +0 -65
- package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +0 -73
- package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +0 -117
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +0 -339
- package/.docs/raw/docs/(reference)/api-reference/primitives/queue-item.mdx +0 -77
- package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +0 -88
- package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +0 -81
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item-more.mdx +0 -129
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +0 -138
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +0 -122
- package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +0 -289
- package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +0 -20
- package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +0 -24
- package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +0 -32
- package/.docs/raw/docs/(reference)/api-reference/runtimes/index.mdx +0 -43
- package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +0 -43
- package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +0 -24
- package/.docs/raw/docs/(reference)/api-reference/runtimes/queue-state.mdx +0 -20
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +0 -24
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +0 -24
- package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +0 -36
- package/.docs/raw/docs/(reference)/api-reference/tools/component-tools.mdx +0 -85
- package/.docs/raw/docs/(reference)/api-reference/tools/index.mdx +0 -45
- package/.docs/raw/docs/(reference)/api-reference/tools/interactables-legacy.mdx +0 -55
- package/.docs/raw/docs/(reference)/api-reference/tools/interactables.mdx +0 -151
- package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +0 -106
- package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -62
- package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +0 -178
- package/.docs/raw/docs/(reference)/api-reference/transport/assistant-transport.mdx +0 -48
- package/.docs/raw/docs/(reference)/api-reference/transport/frame.mdx +0 -62
- package/.docs/raw/docs/(reference)/api-reference/transport/index.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/utilities/index.mdx +0 -19
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +0 -152
- package/.docs/raw/docs/(reference)/api-reference/voice/index.mdx +0 -22
- package/.docs/raw/docs/(reference)/api-reference/voice/session.mdx +0 -54
- package/.docs/raw/docs/(reference)/api-reference/voice/speech-dictation.mdx +0 -36
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +0 -527
- package/.docs/raw/docs/cloud/ai-sdk.mdx +0 -604
- package/.docs/raw/docs/cloud/authorization.mdx +0 -252
- package/.docs/raw/docs/cloud/index.mdx +0 -46
- package/.docs/raw/docs/cloud/langgraph.mdx +0 -554
- package/.docs/raw/docs/copilots/assistant-frame.mdx +0 -411
- package/.docs/raw/docs/copilots/make-assistant-visible.mdx +0 -82
- package/.docs/raw/docs/copilots/model-context.mdx +0 -156
- package/.docs/raw/docs/copilots/motivation.mdx +0 -202
- package/.docs/raw/docs/copilots/use-assistant-instructions.mdx +0 -64
- package/.docs/raw/docs/guides/attachments.mdx +0 -619
- package/.docs/raw/docs/guides/branching.mdx +0 -76
- package/.docs/raw/docs/guides/chain-of-thought.mdx +0 -164
- package/.docs/raw/docs/guides/chatgpt-subscription.mdx +0 -108
- package/.docs/raw/docs/guides/context-api.mdx +0 -619
- package/.docs/raw/docs/guides/dictation.mdx +0 -298
- package/.docs/raw/docs/guides/editing.mdx +0 -102
- package/.docs/raw/docs/guides/electron.mdx +0 -369
- package/.docs/raw/docs/guides/headless-composer-input.mdx +0 -113
- package/.docs/raw/docs/guides/image-generation.mdx +0 -74
- package/.docs/raw/docs/guides/index.mdx +0 -117
- package/.docs/raw/docs/guides/input-history.mdx +0 -55
- package/.docs/raw/docs/guides/latex.mdx +0 -158
- package/.docs/raw/docs/guides/mentions.mdx +0 -575
- package/.docs/raw/docs/guides/message-timing.mdx +0 -215
- package/.docs/raw/docs/guides/quoting.mdx +0 -169
- package/.docs/raw/docs/guides/resumable-stream-deployment.mdx +0 -212
- package/.docs/raw/docs/guides/resumable-stream-stores.mdx +0 -152
- package/.docs/raw/docs/guides/resumable-streams.mdx +0 -292
- package/.docs/raw/docs/guides/slash-commands.mdx +0 -358
- package/.docs/raw/docs/guides/speech.mdx +0 -172
- package/.docs/raw/docs/guides/suggestions.mdx +0 -384
- package/.docs/raw/docs/guides/virtualization.mdx +0 -133
- package/.docs/raw/docs/guides/voice.mdx +0 -310
- package/.docs/raw/docs/ink/adapters.mdx +0 -99
- package/.docs/raw/docs/ink/custom-backend.mdx +0 -254
- package/.docs/raw/docs/ink/hooks.mdx +0 -469
- package/.docs/raw/docs/ink/index.mdx +0 -237
- package/.docs/raw/docs/ink/migration.mdx +0 -138
- package/.docs/raw/docs/ink/primitives.mdx +0 -1259
- package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +0 -528
- package/.docs/raw/docs/integrations/auth/better-auth.mdx +0 -188
- package/.docs/raw/docs/integrations/auth/clerk.mdx +0 -166
- package/.docs/raw/docs/integrations/auth/next-auth.mdx +0 -191
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +0 -88
- package/.docs/raw/docs/integrations/frameworks/cloudflare-agents.mdx +0 -283
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +0 -188
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +0 -57
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +0 -201
- package/.docs/raw/docs/integrations/gateways/index.mdx +0 -162
- package/.docs/raw/docs/integrations/index.mdx +0 -178
- package/.docs/raw/docs/integrations/observability/helicone.mdx +0 -129
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +0 -161
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +0 -151
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +0 -773
- package/.docs/raw/docs/migrations/deprecation-policy.mdx +0 -42
- package/.docs/raw/docs/migrations/index.mdx +0 -50
- package/.docs/raw/docs/migrations/react-compatibility.mdx +0 -74
- package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +0 -328
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +0 -236
- package/.docs/raw/docs/migrations/v0-11.mdx +0 -172
- package/.docs/raw/docs/migrations/v0-12.mdx +0 -302
- package/.docs/raw/docs/migrations/v0-14.mdx +0 -297
- package/.docs/raw/docs/migrations/v0-15.mdx +0 -270
- package/.docs/raw/docs/primitives/action-bar.mdx +0 -352
- package/.docs/raw/docs/primitives/assistant-modal.mdx +0 -216
- package/.docs/raw/docs/primitives/attachment.mdx +0 -217
- package/.docs/raw/docs/primitives/branch-picker.mdx +0 -222
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +0 -315
- package/.docs/raw/docs/primitives/composer.mdx +0 -659
- package/.docs/raw/docs/primitives/error.mdx +0 -142
- package/.docs/raw/docs/primitives/index.mdx +0 -99
- package/.docs/raw/docs/primitives/message.mdx +0 -618
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +0 -191
- package/.docs/raw/docs/primitives/suggestion.mdx +0 -254
- package/.docs/raw/docs/primitives/thread-list.mdx +0 -467
- package/.docs/raw/docs/primitives/thread.mdx +0 -509
- package/.docs/raw/docs/react-native/adapters.mdx +0 -94
- package/.docs/raw/docs/react-native/custom-backend.mdx +0 -207
- package/.docs/raw/docs/react-native/hooks.mdx +0 -339
- package/.docs/raw/docs/react-native/index.mdx +0 -289
- package/.docs/raw/docs/react-native/migration.mdx +0 -142
- package/.docs/raw/docs/react-native/primitives.mdx +0 -976
- package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +0 -399
- package/.docs/raw/docs/runtimes/a2a/overview.mdx +0 -60
- package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +0 -216
- package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +0 -124
- package/.docs/raw/docs/runtimes/ag-ui/overview.mdx +0 -70
- package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +0 -243
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +0 -267
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +0 -61
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +0 -122
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +0 -135
- package/.docs/raw/docs/runtimes/ai-sdk/v6-legacy.mdx +0 -636
- package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +0 -731
- package/.docs/raw/docs/runtimes/claude-managed-agents.mdx +0 -118
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +0 -265
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +0 -167
- package/.docs/raw/docs/runtimes/concepts/stability.mdx +0 -68
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +0 -513
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +0 -763
- package/.docs/raw/docs/runtimes/custom/data-stream.mdx +0 -339
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +0 -957
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +0 -902
- package/.docs/raw/docs/runtimes/custom/overview.mdx +0 -71
- package/.docs/raw/docs/runtimes/eve/overview.mdx +0 -151
- package/.docs/raw/docs/runtimes/eve/quickstart.mdx +0 -192
- package/.docs/raw/docs/runtimes/google-adk/api.mdx +0 -256
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +0 -784
- package/.docs/raw/docs/runtimes/google-adk/overview.mdx +0 -69
- package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +0 -229
- package/.docs/raw/docs/runtimes/langchain.mdx +0 -901
- package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +0 -181
- package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +0 -305
- package/.docs/raw/docs/runtimes/langgraph/interrupts.mdx +0 -104
- package/.docs/raw/docs/runtimes/langgraph/overview.mdx +0 -84
- package/.docs/raw/docs/runtimes/langgraph/quickstart.mdx +0 -496
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +0 -144
- package/.docs/raw/docs/runtimes/langgraph/threads.mdx +0 -113
- package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +0 -29
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +0 -93
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +0 -347
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +0 -393
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +0 -194
- package/.docs/raw/docs/runtimes/opencode/overview.mdx +0 -58
- package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +0 -119
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +0 -133
- package/.docs/raw/docs/tools/a2ui.mdx +0 -107
- package/.docs/raw/docs/tools/backend.mdx +0 -147
- package/.docs/raw/docs/tools/defining-tools.mdx +0 -574
- package/.docs/raw/docs/tools/dynamic-tools.mdx +0 -112
- package/.docs/raw/docs/tools/generative-ui-primitive.mdx +0 -180
- package/.docs/raw/docs/tools/generative-ui-slack.mdx +0 -167
- package/.docs/raw/docs/tools/generative-ui-teams.mdx +0 -160
- package/.docs/raw/docs/tools/generative-ui.mdx +0 -322
- package/.docs/raw/docs/tools/index.mdx +0 -72
- package/.docs/raw/docs/tools/interactables.mdx +0 -1084
- package/.docs/raw/docs/tools/mcp-apps.mdx +0 -363
- package/.docs/raw/docs/tools/mcp.mdx +0 -466
- package/.docs/raw/docs/tools/multi-agent.mdx +0 -237
- package/.docs/raw/docs/tools/openui.mdx +0 -175
- package/.docs/raw/docs/tools/tool-ui.mdx +0 -1020
- package/.docs/raw/docs/tools/user-managed-mcp.mdx +0 -428
- package/.docs/raw/docs/ui/assistant-modal.mdx +0 -166
- package/.docs/raw/docs/ui/assistant-sidebar.mdx +0 -89
- package/.docs/raw/docs/ui/attachment.mdx +0 -279
- package/.docs/raw/docs/ui/composer-trigger-popover.mdx +0 -247
- package/.docs/raw/docs/ui/context-display.mdx +0 -148
- package/.docs/raw/docs/ui/directive-text.mdx +0 -114
- package/.docs/raw/docs/ui/file.mdx +0 -159
- package/.docs/raw/docs/ui/follow-up-suggestions.mdx +0 -82
- package/.docs/raw/docs/ui/image.mdx +0 -102
- package/.docs/raw/docs/ui/markdown.mdx +0 -103
- package/.docs/raw/docs/ui/mcp-config.mdx +0 -107
- package/.docs/raw/docs/ui/mermaid.mdx +0 -92
- package/.docs/raw/docs/ui/message-timing.mdx +0 -93
- package/.docs/raw/docs/ui/model-selector.mdx +0 -455
- package/.docs/raw/docs/ui/part-grouping.mdx +0 -614
- package/.docs/raw/docs/ui/quote.mdx +0 -211
- package/.docs/raw/docs/ui/reasoning.mdx +0 -214
- package/.docs/raw/docs/ui/scrollbar.mdx +0 -77
- package/.docs/raw/docs/ui/sources.mdx +0 -186
- package/.docs/raw/docs/ui/streamdown.mdx +0 -392
- package/.docs/raw/docs/ui/syntax-highlighting.mdx +0 -205
- package/.docs/raw/docs/ui/thread-list.mdx +0 -411
- package/.docs/raw/docs/ui/thread.mdx +0 -559
- package/.docs/raw/docs/ui/tool-fallback.mdx +0 -141
- package/.docs/raw/docs/ui/tool-group.mdx +0 -240
- package/.docs/raw/docs/ui/voice.mdx +0 -173
- package/.docs/raw/docs/utilities/heat-graph.mdx +0 -237
- package/.docs/raw/docs/utilities/react-o11y.mdx +0 -362
- package/.docs/raw/docs/utilities/tw-shimmer.mdx +0 -212
- package/dist/constants.d.ts +0 -14
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -19
- package/dist/constants.js.map +0 -1
- package/dist/prepare-docs/code-examples.d.ts +0 -5
- package/dist/prepare-docs/code-examples.d.ts.map +0 -1
- package/dist/prepare-docs/code-examples.js +0 -117
- package/dist/prepare-docs/code-examples.js.map +0 -1
- package/dist/prepare-docs/copy-raw.d.ts +0 -5
- package/dist/prepare-docs/copy-raw.d.ts.map +0 -1
- package/dist/prepare-docs/copy-raw.js +0 -49
- package/dist/prepare-docs/copy-raw.js.map +0 -1
- package/dist/prepare-docs/prepare.d.ts +0 -1
- package/dist/prepare-docs/prepare.js +0 -22
- package/dist/prepare-docs/prepare.js.map +0 -1
- package/dist/prompts/xulux-playground.d.ts +0 -12
- package/dist/prompts/xulux-playground.d.ts.map +0 -1
- package/dist/prompts/xulux-playground.js +0 -33
- package/dist/prompts/xulux-playground.js.map +0 -1
- package/dist/tools/docs.d.ts +0 -22
- package/dist/tools/docs.d.ts.map +0 -1
- package/dist/tools/docs.js +0 -177
- package/dist/tools/docs.js.map +0 -1
- package/dist/tools/examples.d.ts +0 -24
- package/dist/tools/examples.d.ts.map +0 -1
- package/dist/tools/examples.js +0 -87
- package/dist/tools/examples.js.map +0 -1
- package/dist/tools/resources.d.ts +0 -6
- package/dist/tools/resources.d.ts.map +0 -1
- package/dist/tools/resources.js +0 -75
- package/dist/tools/resources.js.map +0 -1
- package/dist/tools/search.d.ts +0 -24
- package/dist/tools/search.d.ts.map +0 -1
- package/dist/tools/search.js +0 -39
- package/dist/tools/search.js.map +0 -1
- package/dist/tools/tests/mcp-test-client.d.ts +0 -15
- package/dist/tools/tests/mcp-test-client.d.ts.map +0 -1
- package/dist/tools/tests/mcp-test-client.js +0 -68
- package/dist/tools/tests/mcp-test-client.js.map +0 -1
- package/dist/tools/tests/test-setup.d.ts +0 -7
- package/dist/tools/tests/test-setup.d.ts.map +0 -1
- package/dist/tools/tests/test-setup.js +0 -36
- package/dist/tools/tests/test-setup.js.map +0 -1
- package/dist/tools/xulux-templates.d.ts +0 -58
- package/dist/tools/xulux-templates.d.ts.map +0 -1
- package/dist/tools/xulux-templates.js +0 -84
- package/dist/tools/xulux-templates.js.map +0 -1
- package/dist/utils/cache.d.ts +0 -5
- package/dist/utils/cache.d.ts.map +0 -1
- package/dist/utils/cache.js +0 -18
- package/dist/utils/cache.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -10
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -20
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/mcp-format.d.ts +0 -11
- package/dist/utils/mcp-format.d.ts.map +0 -1
- package/dist/utils/mcp-format.js +0 -14
- package/dist/utils/mcp-format.js.map +0 -1
- package/dist/utils/mdx.d.ts +0 -12
- package/dist/utils/mdx.d.ts.map +0 -1
- package/dist/utils/mdx.js +0 -45
- package/dist/utils/mdx.js.map +0 -1
- package/dist/utils/paths.d.ts +0 -12
- package/dist/utils/paths.d.ts.map +0 -1
- package/dist/utils/paths.js +0 -93
- package/dist/utils/paths.js.map +0 -1
- package/dist/utils/search.d.ts +0 -10
- package/dist/utils/search.d.ts.map +0 -1
- package/dist/utils/search.js +0 -97
- package/dist/utils/search.js.map +0 -1
- package/dist/utils/security.d.ts +0 -5
- package/dist/utils/security.d.ts.map +0 -1
- package/dist/utils/security.js +0 -22
- package/dist/utils/security.js.map +0 -1
- package/dist/xulux/catalog-client.d.ts +0 -14
- package/dist/xulux/catalog-client.d.ts.map +0 -1
- package/dist/xulux/catalog-client.js +0 -112
- package/dist/xulux/catalog-client.js.map +0 -1
- package/dist/xulux/fallback-catalog.d.ts +0 -7
- package/dist/xulux/fallback-catalog.d.ts.map +0 -1
- package/dist/xulux/fallback-catalog.js +0 -47
- package/dist/xulux/fallback-catalog.js.map +0 -1
- package/dist/xulux/fetch-sandbox.d.ts +0 -5
- package/dist/xulux/fetch-sandbox.d.ts.map +0 -1
- package/dist/xulux/fetch-sandbox.js +0 -40
- package/dist/xulux/fetch-sandbox.js.map +0 -1
- package/dist/xulux/template-service.d.ts +0 -84
- package/dist/xulux/template-service.d.ts.map +0 -1
- package/dist/xulux/template-service.js +0 -223
- package/dist/xulux/template-service.js.map +0 -1
- package/dist/xulux/types.d.ts +0 -55
- package/dist/xulux/types.d.ts.map +0 -1
- package/dist/xulux/types.js +0 -6
- package/dist/xulux/types.js.map +0 -1
- package/src/constants.ts +0 -24
- package/src/prepare-docs/code-examples.ts +0 -158
- package/src/prepare-docs/copy-raw.ts +0 -50
- package/src/prepare-docs/prepare.ts +0 -24
- package/src/prompts/xulux-playground.ts +0 -36
- package/src/tools/docs.ts +0 -255
- package/src/tools/examples.ts +0 -114
- package/src/tools/resources.ts +0 -111
- package/src/tools/search.ts +0 -46
- package/src/tools/tests/completions.test.ts +0 -60
- package/src/tools/tests/directory-size-cap.test.ts +0 -50
- package/src/tools/tests/docs.test.ts +0 -147
- package/src/tools/tests/examples.test.ts +0 -94
- package/src/tools/tests/integration.test.ts +0 -45
- package/src/tools/tests/json-parsing.test.ts +0 -23
- package/src/tools/tests/listings-cache.test.ts +0 -19
- package/src/tools/tests/mcp-protocol.test.ts +0 -216
- package/src/tools/tests/mcp-test-client.ts +0 -111
- package/src/tools/tests/path-traversal.test.ts +0 -84
- package/src/tools/tests/resources.test.ts +0 -133
- package/src/tools/tests/search.test.ts +0 -37
- package/src/tools/tests/test-setup.ts +0 -50
- package/src/tools/tests/xulux-templates.test.ts +0 -325
- package/src/tools/xulux-templates.ts +0 -141
- package/src/utils/cache.ts +0 -20
- package/src/utils/logger.ts +0 -20
- package/src/utils/mcp-format.ts +0 -14
- package/src/utils/mdx.ts +0 -59
- package/src/utils/paths.ts +0 -139
- package/src/utils/search.ts +0 -131
- package/src/utils/security.ts +0 -52
- package/src/utils/tests/cache.test.ts +0 -51
- package/src/utils/tests/mcp-format.test.ts +0 -22
- package/src/utils/tests/security.test.ts +0 -119
- package/src/xulux/catalog-client.ts +0 -150
- package/src/xulux/fallback-catalog.ts +0 -63
- package/src/xulux/fetch-sandbox.ts +0 -56
- package/src/xulux/template-service.ts +0 -406
- package/src/xulux/types.ts +0 -64
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Message Timing & Token Stats
|
|
3
|
-
description: Display stream metadata in AI chat — generation duration, tokens per second, and time to first token, rendered via assistant-ui's React components.
|
|
4
|
-
platforms: ["react"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Display stream performance metrics — duration, tokens per second, TTFT — on assistant messages.
|
|
8
|
-
|
|
9
|
-
<Callout type="warn">
|
|
10
|
-
This feature is experimental. The `useMessageTiming()` API and the set of tracked fields may change in future versions.
|
|
11
|
-
</Callout>
|
|
12
|
-
|
|
13
|
-
<Callout type="info">
|
|
14
|
-
The [`MessageTiming`](/docs/ui/message-timing) registry component provides a ready-made badge + popover UI. This guide covers the underlying `useMessageTiming()` hook for custom implementations and runtime-specific setup.
|
|
15
|
-
</Callout>
|
|
16
|
-
|
|
17
|
-
## Reading Timing Data
|
|
18
|
-
|
|
19
|
-
Use `useMessageTiming()` inside a message component to access timing data:
|
|
20
|
-
|
|
21
|
-
```tsx
|
|
22
|
-
import type { FC } from "react";
|
|
23
|
-
import { useMessageTiming } from "@assistant-ui/react";
|
|
24
|
-
|
|
25
|
-
const MessageTimingDisplay: FC = () => {
|
|
26
|
-
const timing = useMessageTiming();
|
|
27
|
-
if (!timing?.totalStreamTime) return null;
|
|
28
|
-
|
|
29
|
-
const formatMs = (ms: number) =>
|
|
30
|
-
ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(2)}s`;
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<span className="text-xs text-muted-foreground">
|
|
34
|
-
{formatMs(timing.totalStreamTime)}
|
|
35
|
-
{timing.tokensPerSecond !== undefined &&
|
|
36
|
-
` · ${timing.tokensPerSecond.toFixed(1)} tok/s`}
|
|
37
|
-
</span>
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Place it inside `MessagePrimitive.Root`, typically near the action bar:
|
|
43
|
-
|
|
44
|
-
```tsx {8}
|
|
45
|
-
const AssistantMessage: FC = () => {
|
|
46
|
-
return (
|
|
47
|
-
<MessagePrimitive.Root>
|
|
48
|
-
<MessagePrimitive.Parts>{...}</MessagePrimitive.Parts>
|
|
49
|
-
<ActionBarPrimitive.Root>
|
|
50
|
-
<ActionBarPrimitive.Copy />
|
|
51
|
-
<ActionBarPrimitive.Reload />
|
|
52
|
-
<MessageTimingDisplay />
|
|
53
|
-
</ActionBarPrimitive.Root>
|
|
54
|
-
</MessagePrimitive.Root>
|
|
55
|
-
);
|
|
56
|
-
};
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### `useMessageTiming()` Return Fields
|
|
60
|
-
|
|
61
|
-
| Field | Type | Description |
|
|
62
|
-
|-------|------|-------------|
|
|
63
|
-
| `streamStartTime` | `number` | Unix timestamp when stream started |
|
|
64
|
-
| `firstTokenTime` | `number?` | Time to first text token (ms) |
|
|
65
|
-
| `totalStreamTime` | `number?` | Total stream duration (ms) |
|
|
66
|
-
| `tokenCount` | `number?` | Output token count from message metadata usage |
|
|
67
|
-
| `tokensPerSecond` | `number?` | Throughput (tokens/sec), when token usage is available |
|
|
68
|
-
| `totalChunks` | `number` | Total stream chunks received |
|
|
69
|
-
| `toolCallCount` | `number` | Number of tool calls |
|
|
70
|
-
|
|
71
|
-
## Runtime Support
|
|
72
|
-
|
|
73
|
-
| Runtime | Supported | Notes |
|
|
74
|
-
|---------|:-:|-------|
|
|
75
|
-
| [Data Stream](/docs/runtimes/custom/data-stream) | Yes | Automatic via `AssistantMessageAccumulator` |
|
|
76
|
-
| AI SDK (`useChatRuntime`) | Yes | Automatic via client-side tracking |
|
|
77
|
-
| Local (`useLocalRuntime`) | Yes | Pass timing in `ChatModelRunResult.metadata` |
|
|
78
|
-
| ExternalStore | Yes | Pass timing in `ThreadMessageLike.metadata` |
|
|
79
|
-
| LangGraph | Yes | Automatic via client-side tracking |
|
|
80
|
-
| AG-UI | Yes | Automatic via client-side tracking |
|
|
81
|
-
| OpenCode | Yes | Automatic via client-side tracking |
|
|
82
|
-
|
|
83
|
-
### Data Stream
|
|
84
|
-
|
|
85
|
-
Timing is tracked automatically inside `AssistantMessageAccumulator`. No setup required.
|
|
86
|
-
|
|
87
|
-
```tsx
|
|
88
|
-
import { useDataStreamRuntime } from "@assistant-ui/react-data-stream";
|
|
89
|
-
|
|
90
|
-
const runtime = useDataStreamRuntime({ api: "/api/chat" });
|
|
91
|
-
// useMessageTiming() works out of the box
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### AI SDK (`useChatRuntime`)
|
|
95
|
-
|
|
96
|
-
Timing is tracked automatically on the client side by observing streaming state transitions and content changes. Timing is finalized when each stream completes.
|
|
97
|
-
|
|
98
|
-
<Callout type="warn">
|
|
99
|
-
`tokenCount` and `tokensPerSecond` require usage metadata from `finish` or `finish-step` in your AI SDK route. If usage metadata is not emitted, duration and TTFT metrics still work, but token-based metrics are omitted.
|
|
100
|
-
</Callout>
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
import { useChatRuntime } from "@assistant-ui/ai-sdk";
|
|
104
|
-
|
|
105
|
-
const runtime = useChatRuntime();
|
|
106
|
-
// useMessageTiming() works out of the box
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Local (`useLocalRuntime`)
|
|
110
|
-
|
|
111
|
-
Pass timing in the `metadata` field of your `ChatModelRunResult`:
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
import type { ChatModelAdapter } from "@assistant-ui/react";
|
|
115
|
-
|
|
116
|
-
const myAdapter: ChatModelAdapter = {
|
|
117
|
-
async run({ messages, abortSignal }) {
|
|
118
|
-
const startTime = Date.now();
|
|
119
|
-
const result = await callMyAPI(messages, abortSignal);
|
|
120
|
-
const totalStreamTime = Date.now() - startTime;
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
content: [{ type: "text", text: result.text }],
|
|
124
|
-
metadata: {
|
|
125
|
-
timing: {
|
|
126
|
-
streamStartTime: startTime,
|
|
127
|
-
totalStreamTime,
|
|
128
|
-
tokenCount: result.usage?.completionTokens,
|
|
129
|
-
tokensPerSecond:
|
|
130
|
-
result.usage?.completionTokens
|
|
131
|
-
? result.usage.completionTokens / (totalStreamTime / 1000)
|
|
132
|
-
: undefined,
|
|
133
|
-
totalChunks: 1,
|
|
134
|
-
toolCallCount: 0,
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### ExternalStore (`useExternalStoreRuntime`)
|
|
143
|
-
|
|
144
|
-
Pass timing in the `metadata.timing` field of your `ThreadMessageLike` messages:
|
|
145
|
-
|
|
146
|
-
```tsx
|
|
147
|
-
import type { ThreadMessageLike } from "@assistant-ui/react";
|
|
148
|
-
|
|
149
|
-
const message: ThreadMessageLike = {
|
|
150
|
-
role: "assistant",
|
|
151
|
-
content: [{ type: "text", text: fullText }],
|
|
152
|
-
metadata: {
|
|
153
|
-
timing: {
|
|
154
|
-
streamStartTime: startTime,
|
|
155
|
-
firstTokenTime,
|
|
156
|
-
totalStreamTime,
|
|
157
|
-
tokenCount,
|
|
158
|
-
tokensPerSecond,
|
|
159
|
-
totalChunks: chunks,
|
|
160
|
-
toolCallCount: 0,
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### LangGraph (`useLangGraphRuntime`)
|
|
167
|
-
|
|
168
|
-
Timing is tracked automatically on the client side by observing streaming state transitions and `LangChainMessage` content changes. No setup required.
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
|
|
172
|
-
|
|
173
|
-
const runtime = useLangGraphRuntime({ stream: myStream });
|
|
174
|
-
// useMessageTiming() works out of the box
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### AG-UI (`useAgUiRuntime`)
|
|
178
|
-
|
|
179
|
-
Timing is tracked automatically on the client side by the AG-UI run aggregator. Each emitted message includes timing metadata computed from stream chunk observations.
|
|
180
|
-
|
|
181
|
-
```tsx
|
|
182
|
-
import { useMemo } from "react";
|
|
183
|
-
import { useAgUiRuntime } from "@assistant-ui/react-ag-ui";
|
|
184
|
-
import { HttpAgent } from "@ag-ui/client";
|
|
185
|
-
|
|
186
|
-
const agent = useMemo(
|
|
187
|
-
() => new HttpAgent({ url: "http://localhost:8000/agent" }),
|
|
188
|
-
[],
|
|
189
|
-
);
|
|
190
|
-
const runtime = useAgUiRuntime({ agent });
|
|
191
|
-
// useMessageTiming() works out of the box
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### OpenCode (`useOpenCodeRuntime`)
|
|
195
|
-
|
|
196
|
-
Timing is tracked automatically on the client side by observing `OpenCodeThreadState` transitions and assistant message content deltas. No setup required.
|
|
197
|
-
|
|
198
|
-
```tsx
|
|
199
|
-
import { useOpenCodeRuntime } from "@assistant-ui/react-opencode";
|
|
200
|
-
|
|
201
|
-
const runtime = useOpenCodeRuntime();
|
|
202
|
-
// useMessageTiming() works out of the box
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## API Reference
|
|
206
|
-
|
|
207
|
-
### `useMessageTiming()`
|
|
208
|
-
|
|
209
|
-
```tsx
|
|
210
|
-
const timing: MessageTiming | undefined = useMessageTiming();
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
Returns timing metadata for the current assistant message, or `undefined` for non-assistant messages or when no timing data is available.
|
|
214
|
-
|
|
215
|
-
Must be used inside a `MessagePrimitive.Root` context.
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Quote Selected Text
|
|
3
|
-
description: Let users select text from AI messages and quote it back into the composer. Full quoting flow with backend handling and programmatic API in assistant-ui.
|
|
4
|
-
platforms: ["react"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
import { QuoteComposerSample } from "@/components/pages/docs/samples/quote-composer";
|
|
8
|
-
|
|
9
|
-
<QuoteComposerSample />
|
|
10
|
-
|
|
11
|
-
## Get Started
|
|
12
|
-
|
|
13
|
-
Install and wire up the `quote` registry component by following the [Quote component page](/docs/ui/quote). It covers the install command, component placement, and the `injectQuoteContext` helper for forwarding quote data to the LLM.
|
|
14
|
-
|
|
15
|
-
<Callout type="warn">
|
|
16
|
-
**Limitations:** only one quote can be active at a time. `setQuote` replaces the previous quote instead of appending. The floating toolbar only appears when the selection is entirely within a single message part; cross-message and cross-part selections are ignored.
|
|
17
|
-
</Callout>
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## How It Works
|
|
22
|
-
|
|
23
|
-
When a user selects text in an assistant message, a floating toolbar appears with a Quote button. Clicking it calls `composer.setQuote()` to store the selection on the composer. The [Quote component](/docs/ui/quote) does this out of the box.
|
|
24
|
-
|
|
25
|
-
When the message is sent, the composer runtime automatically writes the quote to `message.metadata.custom.quote` and clears it from the composer.
|
|
26
|
-
|
|
27
|
-
On the backend, the route handler extracts the quote from metadata and surfaces it to the LLM. We export a helper called `injectQuoteContext` that handles this automatically for AI-SDK. Without this step, the quote appears in the UI but is not sent to the model as context. See [Backend Handling](#backend-handling) for more info and alternatives.
|
|
28
|
-
|
|
29
|
-
### Data Shape
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
type QuoteInfo = {
|
|
33
|
-
readonly text: string; // selected plain text
|
|
34
|
-
readonly messageId: string; // source message ID
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Stored at: message.metadata.custom.quote
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Backend Handling
|
|
41
|
-
|
|
42
|
-
Quote data travels in message metadata, not content, so the LLM will not see it unless your backend extracts and surfaces it. The simplest path is [`injectQuoteContext`](/docs/ui/quote#forward-quote-context-to-the-llm), which prepends quoted text as a markdown blockquote before the message parts.
|
|
43
|
-
|
|
44
|
-
For provider-specific handling, work with the quote metadata directly.
|
|
45
|
-
|
|
46
|
-
### Claude SDK Citations
|
|
47
|
-
|
|
48
|
-
Pass the quoted text as a citation source so Claude produces citations that reference it:
|
|
49
|
-
|
|
50
|
-
```typescript title="app/api/chat/route.ts"
|
|
51
|
-
import Anthropic from "@anthropic-ai/sdk";
|
|
52
|
-
|
|
53
|
-
const client = new Anthropic();
|
|
54
|
-
|
|
55
|
-
export async function POST(req: Request) {
|
|
56
|
-
const { messages } = await req.json();
|
|
57
|
-
|
|
58
|
-
const claudeMessages = messages.map((msg) => {
|
|
59
|
-
const quote = msg.metadata?.custom?.quote;
|
|
60
|
-
if (!quote?.text) {
|
|
61
|
-
return { role: msg.role, content: extractText(msg) };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
role: "user",
|
|
66
|
-
content: [
|
|
67
|
-
{
|
|
68
|
-
type: "text",
|
|
69
|
-
text: quote.text,
|
|
70
|
-
cache_control: { type: "ephemeral" },
|
|
71
|
-
citations: { enabled: true },
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
type: "text",
|
|
75
|
-
text: extractText(msg),
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const response = await client.messages.create({
|
|
82
|
-
model: "claude-sonnet-4-6",
|
|
83
|
-
max_tokens: 1024,
|
|
84
|
-
messages: claudeMessages,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// ... stream response back
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### OpenAI Message Context
|
|
92
|
-
|
|
93
|
-
Inject the quote as additional context in the user message:
|
|
94
|
-
|
|
95
|
-
```typescript title="app/api/chat/route.ts"
|
|
96
|
-
function injectQuoteForOpenAI(messages) {
|
|
97
|
-
return messages.map((msg) => {
|
|
98
|
-
const quote = msg.metadata?.custom?.quote;
|
|
99
|
-
if (!quote?.text || msg.role !== "user") return msg;
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
...msg,
|
|
103
|
-
content: `[Referring to: "${quote.text}"]\n\n${msg.content}`,
|
|
104
|
-
};
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Reading Quote Data
|
|
110
|
-
|
|
111
|
-
Use `useMessageQuote` to access quote data in custom components:
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
import { useMessageQuote } from "@assistant-ui/react";
|
|
115
|
-
|
|
116
|
-
function CustomQuoteDisplay() {
|
|
117
|
-
const quote = useMessageQuote();
|
|
118
|
-
if (!quote) return null;
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<blockquote className="border-l-2 pl-3 text-sm text-muted-foreground">
|
|
122
|
-
{quote.text}
|
|
123
|
-
</blockquote>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Programmatic API
|
|
129
|
-
|
|
130
|
-
Set or clear quotes via `useAui` from `@assistant-ui/react`. Call `aui.thread.composer().setQuote()` when your component is rendered outside of a specific thread context, or `aui.composer.setQuote()` when it is rendered inside a thread:
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
import { useAui } from "@assistant-ui/react";
|
|
134
|
-
|
|
135
|
-
function MyComponent() {
|
|
136
|
-
const aui = useAui();
|
|
137
|
-
|
|
138
|
-
const quoteText = () => {
|
|
139
|
-
aui.thread.composer().setQuote({
|
|
140
|
-
text: "The text to quote",
|
|
141
|
-
messageId: "msg-123",
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const clearQuote = () => {
|
|
146
|
-
aui.thread.composer().setQuote(undefined);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return (
|
|
150
|
-
<>
|
|
151
|
-
<button onClick={quoteText}>Set Quote</button>
|
|
152
|
-
<button onClick={clearQuote}>Clear Quote</button>
|
|
153
|
-
</>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## Design Notes
|
|
159
|
-
|
|
160
|
-
- **snapshot text:** the selected text is captured when the quote is created and is not linked to the source message afterward.
|
|
161
|
-
- **streaming messages:** the toolbar still works while a message is streaming because it relies on the captured selection rather than message status.
|
|
162
|
-
- **`isEmpty` unchanged:** a quote by itself does not make the composer non-empty; the user still needs to type a reply.
|
|
163
|
-
- **scroll hides toolbar:** the toolbar hides on scroll because its position would otherwise become stale.
|
|
164
|
-
|
|
165
|
-
## Related
|
|
166
|
-
|
|
167
|
-
- [Quote component](/docs/ui/quote): Installation, component setup, and API reference
|
|
168
|
-
- [Message Editing](/docs/guides/editing): Edit user messages
|
|
169
|
-
- [Thread](/docs/ui/thread): Main chat container
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Resumable Stream Deployment
|
|
3
|
-
description: Production hardening for resumable streams. Authorization, serverless lifetimes, TTLs, key isolation, observability, resource limits, and incident response.
|
|
4
|
-
platforms: ["react"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
This guide assumes you have the basic wiring from [Resumable Streams](/docs/guides/resumable-streams) in place and focuses on what to add before serving production traffic.
|
|
8
|
-
|
|
9
|
-
## Authentication and authorization
|
|
10
|
-
|
|
11
|
-
The default resume endpoint serves any caller that knows the `streamId`. Treat the id as opaque, not as a credential. Bind every newly created `streamId` to the requesting user at acquire time and verify the binding on every resume.
|
|
12
|
-
|
|
13
|
-
Store the binding next to the rest of your session state, or in Redis under a separate key. The example below uses a parallel `<keyPrefix>:owner:<streamId>` entry that mirrors the TTL of the underlying stream.
|
|
14
|
-
|
|
15
|
-
```ts title="/lib/resumable-context.ts"
|
|
16
|
-
import { createResumableStreamContext } from "assistant-stream/resumable";
|
|
17
|
-
import { redis } from "@/lib/redis";
|
|
18
|
-
import { store } from "@/lib/resumable-store";
|
|
19
|
-
|
|
20
|
-
const OWNER_PREFIX = "aui:resumable:owner";
|
|
21
|
-
const OWNER_TTL_SEC = 24 * 60 * 60;
|
|
22
|
-
|
|
23
|
-
export const resumableContext = createResumableStreamContext({ store });
|
|
24
|
-
|
|
25
|
-
export async function bindStreamToUser(streamId: string, userId: string) {
|
|
26
|
-
await redis.set(`${OWNER_PREFIX}:${streamId}`, userId, { EX: OWNER_TTL_SEC });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function assertStreamOwner(streamId: string, userId: string) {
|
|
30
|
-
const owner = await redis.get(`${OWNER_PREFIX}:${streamId}`);
|
|
31
|
-
if (owner !== userId) {
|
|
32
|
-
throw new Response("Not Found", { status: 404 });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Wrap `resume` with the ownership check. Returning 404 (not 403) avoids confirming the existence of a stream the caller does not own.
|
|
38
|
-
|
|
39
|
-
```ts title="/app/api/chat/resume/[streamId]/route.ts"
|
|
40
|
-
import { assertStreamOwner, resumableContext } from "@/lib/resumable-context";
|
|
41
|
-
import { getSessionUserId } from "@/lib/auth";
|
|
42
|
-
|
|
43
|
-
export async function GET(
|
|
44
|
-
req: Request,
|
|
45
|
-
ctx: { params: Promise<{ streamId: string }> },
|
|
46
|
-
) {
|
|
47
|
-
const userId = await getSessionUserId(req);
|
|
48
|
-
if (!userId) return new Response("Unauthorized", { status: 401 });
|
|
49
|
-
|
|
50
|
-
const { streamId } = await ctx.params;
|
|
51
|
-
await assertStreamOwner(streamId, userId);
|
|
52
|
-
|
|
53
|
-
const stream = await resumableContext.resume(streamId);
|
|
54
|
-
if (!stream) return new Response("Not Found", { status: 404 });
|
|
55
|
-
|
|
56
|
-
return new Response(stream, {
|
|
57
|
-
headers: { "Content-Type": "text/event-stream" },
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## `waitUntil` on serverless
|
|
63
|
-
|
|
64
|
-
On Vercel and Cloudflare the request handler is torn down once the response is returned, taking the producer task with it. Without a `waitUntil` hook the persisted stream stops growing the moment the originating request unwinds, so reconnects only see the bytes that happened to land before the response flushed.
|
|
65
|
-
|
|
66
|
-
On Vercel, pass `after` from `next/server`:
|
|
67
|
-
|
|
68
|
-
```ts title="/lib/resumable-context.ts"
|
|
69
|
-
import { after } from "next/server";
|
|
70
|
-
import { createResumableStreamContext } from "assistant-stream/resumable";
|
|
71
|
-
import { store } from "@/lib/resumable-store";
|
|
72
|
-
|
|
73
|
-
export const resumableContext = createResumableStreamContext({
|
|
74
|
-
store,
|
|
75
|
-
waitUntil: after,
|
|
76
|
-
});
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
On Cloudflare Workers, take the `ExecutionContext` from your handler and forward `ctx.waitUntil`:
|
|
80
|
-
|
|
81
|
-
```ts title="/src/worker.ts"
|
|
82
|
-
import { createResumableStreamContext } from "assistant-stream/resumable";
|
|
83
|
-
import { store } from "./resumable-store";
|
|
84
|
-
|
|
85
|
-
export default {
|
|
86
|
-
async fetch(req: Request, env: Env, ctx: ExecutionContext) {
|
|
87
|
-
const resumableContext = createResumableStreamContext({
|
|
88
|
-
store,
|
|
89
|
-
waitUntil: (promise) => ctx.waitUntil(promise),
|
|
90
|
-
});
|
|
91
|
-
return handle(req, resumableContext);
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
In long-lived Node servers (a custom Express app, a container) `waitUntil` can be omitted; the producer task runs on the same event loop as the handler and is not preempted.
|
|
97
|
-
|
|
98
|
-
## TTL strategy
|
|
99
|
-
|
|
100
|
-
Streams expire 24 hours after the last write. The default suits typical chat workloads where a user might reload after lunch, but every deployment should pick a number deliberately.
|
|
101
|
-
|
|
102
|
-
- Shorten when chunks contain sensitive payloads (PII, drafts, internal documents). A 5 to 30 minute window usually covers reload survival without leaving recoverable bytes around.
|
|
103
|
-
- Extend for long-running agent tasks that may legitimately stretch past a day. Set the TTL above the worst-case task duration so the producer can still finalize.
|
|
104
|
-
- Match TTLs across layers. The store TTL, the owner-binding TTL, and any signed cookie that references `streamId` should expire together; otherwise one outlives the other and either leaks or 404s unexpectedly.
|
|
105
|
-
|
|
106
|
-
Configure on the store for the global default and on the context for a per-deployment override:
|
|
107
|
-
|
|
108
|
-
```ts
|
|
109
|
-
import {
|
|
110
|
-
createInMemoryResumableStreamStore,
|
|
111
|
-
createResumableStreamContext,
|
|
112
|
-
} from "assistant-stream/resumable";
|
|
113
|
-
|
|
114
|
-
const store = createInMemoryResumableStreamStore({
|
|
115
|
-
defaultTtlMs: 30 * 60 * 1000,
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
export const resumableContext = createResumableStreamContext({
|
|
119
|
-
store,
|
|
120
|
-
ttlMs: 30 * 60 * 1000,
|
|
121
|
-
});
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The Redis adapters accept the same `defaultTtlMs` option.
|
|
125
|
-
|
|
126
|
-
## Multi-tenant key isolation
|
|
127
|
-
|
|
128
|
-
When multiple apps or tenants share a Redis instance, set `keyPrefix` per environment so a misconfigured stream in one tenant cannot collide with, or be deleted alongside, another's. The prefix becomes the leading segment of every meta and data key.
|
|
129
|
-
|
|
130
|
-
```ts title="/lib/resumable-store.ts"
|
|
131
|
-
import { createClient } from "redis";
|
|
132
|
-
import { createRedisResumableStreamStore } from "assistant-stream/resumable/redis";
|
|
133
|
-
|
|
134
|
-
const client = createClient({ url: process.env.REDIS_URL });
|
|
135
|
-
await client.connect();
|
|
136
|
-
|
|
137
|
-
export const store = createRedisResumableStreamStore(client, {
|
|
138
|
-
keyPrefix: `aui:${process.env.APP_NAME}:${process.env.TENANT_ID}`,
|
|
139
|
-
});
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Per-tenant prefixes also make incident response cheaper. A `SCAN MATCH aui:app:tenant-42:*` lets you audit or purge a single tenant without touching the rest.
|
|
143
|
-
|
|
144
|
-
## Observability hooks
|
|
145
|
-
|
|
146
|
-
`ResumableStreamContextOptions` exposes lifecycle hooks for structured logging, metrics, and tracing. Hook exceptions and rejected promises are reported through `console.error` without affecting stream output or stored lifecycle status.
|
|
147
|
-
|
|
148
|
-
```ts title="/lib/resumable-context.ts"
|
|
149
|
-
import { createResumableStreamContext } from "assistant-stream/resumable";
|
|
150
|
-
import { logger, metrics } from "@/lib/observability";
|
|
151
|
-
import { store } from "@/lib/resumable-store";
|
|
152
|
-
|
|
153
|
-
export const resumableContext = createResumableStreamContext({
|
|
154
|
-
store,
|
|
155
|
-
onAcquire: (streamId, role) => {
|
|
156
|
-
metrics.increment("resumable.acquire", { role });
|
|
157
|
-
logger.info("resumable.acquire", { streamId, role });
|
|
158
|
-
},
|
|
159
|
-
onAppend: (streamId, byteLength) => {
|
|
160
|
-
metrics.histogram("resumable.append.bytes", byteLength);
|
|
161
|
-
},
|
|
162
|
-
onFinalize: (streamId, status, error) => {
|
|
163
|
-
metrics.increment("resumable.finalize", { status });
|
|
164
|
-
logger.info("resumable.finalize", { streamId, status, error });
|
|
165
|
-
},
|
|
166
|
-
onError: (streamId, error) => {
|
|
167
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
168
|
-
logger.error("resumable.error", { streamId, error: message });
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
Keep synchronous hook work cheap. `onAcquire` runs on the `run()` request path for producers and consumers alike, while the remaining hooks run on the producer's streaming hot path. Returned promises are observed for failures but are not awaited.
|
|
174
|
-
|
|
175
|
-
## Resource limits
|
|
176
|
-
|
|
177
|
-
The in-memory store enforces three caps that the Redis adapters intentionally leave to the underlying database. Set them whenever your process can be reached by untrusted callers.
|
|
178
|
-
|
|
179
|
-
```ts
|
|
180
|
-
import { createInMemoryResumableStreamStore } from "assistant-stream/resumable";
|
|
181
|
-
|
|
182
|
-
const store = createInMemoryResumableStreamStore({
|
|
183
|
-
maxChunkBytes: 64 * 1024,
|
|
184
|
-
maxEntriesPerStream: 5000,
|
|
185
|
-
maxStreams: 10_000,
|
|
186
|
-
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
- `maxChunkBytes` rejects oversized writes from a misbehaving producer (a runaway tool result, a base64 blob accidentally piped through). The producer task fails fast instead of pinning memory.
|
|
190
|
-
- `maxEntriesPerStream` caps the per-stream entry count. This bounds how much any single stream can grow before it starts erroring; pair it with TTLs so finalized streams clear quickly.
|
|
191
|
-
- `maxStreams` caps total live streams. Useful as a backstop in shared development environments and in single-tenant containers; in serverless deployments the platform already constrains concurrency.
|
|
192
|
-
|
|
193
|
-
These limits exist on the in-memory store. For Redis, configure `maxmemory` and an eviction policy on the server, and rely on application-level rate limiting upstream.
|
|
194
|
-
|
|
195
|
-
## Incident response
|
|
196
|
-
|
|
197
|
-
The streamId leaks through response headers, browser session storage, server access logs, and (in some setups) error reports. If you suspect any of those channels were compromised, treat all in-flight stream ids as exposed.
|
|
198
|
-
|
|
199
|
-
What to log up front, so you have it when you need it:
|
|
200
|
-
|
|
201
|
-
- The acquiring user id, request id, and IP for every `acquire` call (via `onAcquire`).
|
|
202
|
-
- The finalize status (and any error) for every stream (via `onFinalize`).
|
|
203
|
-
- The owner-binding writes and reads, with the user id and the streamId.
|
|
204
|
-
|
|
205
|
-
What to rotate or invalidate during an incident:
|
|
206
|
-
|
|
207
|
-
- Bump `keyPrefix` on the store. Existing streams become unreachable and new ones land under the rotated namespace.
|
|
208
|
-
- Invalidate signed session cookies that reference any cached streamId.
|
|
209
|
-
- Drop the owner-binding keys for affected users (`DEL aui:resumable:owner:*` scoped by user) so resumes are forced through a fresh acquire.
|
|
210
|
-
- Shorten `defaultTtlMs` temporarily so any orphaned stream rolls off quickly.
|
|
211
|
-
|
|
212
|
-
After rotation, reissue stream ids server-side and redirect clients through a fresh acquire; do not trust any streamId the client already holds.
|