@assistant-ui/mcp-docs-server 0.2.1 → 0.2.3
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/.docs/organized/code-examples/waterfall.md +3 -3
- package/.docs/organized/code-examples/with-a2a.md +5 -4
- package/.docs/organized/code-examples/with-ag-ui.md +7 -6
- package/.docs/organized/code-examples/with-ai-sdk-v7.md +14 -13
- package/.docs/organized/code-examples/with-artifacts.md +12 -11
- package/.docs/organized/code-examples/with-assistant-transport.md +6 -5
- package/.docs/organized/code-examples/with-browser-extension.md +6 -6
- package/.docs/organized/code-examples/with-chain-of-thought.md +16 -14
- package/.docs/organized/code-examples/with-cloud-standalone.md +7 -7
- package/.docs/organized/code-examples/with-cloud.md +11 -10
- package/.docs/organized/code-examples/with-custom-thread-list.md +11 -10
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +14 -13
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +15 -14
- package/.docs/organized/code-examples/with-eve.md +6 -5
- package/.docs/organized/code-examples/with-expo.md +213 -36
- package/.docs/organized/code-examples/with-external-store.md +6 -5
- package/.docs/organized/code-examples/with-ffmpeg.md +11 -10
- package/.docs/organized/code-examples/with-generative-ui.md +263 -29
- package/.docs/organized/code-examples/with-google-adk.md +5 -4
- package/.docs/organized/code-examples/with-heat-graph.md +3 -3
- package/.docs/organized/code-examples/with-image-generation.md +8 -7
- package/.docs/organized/code-examples/with-interactables.md +11 -10
- package/.docs/organized/code-examples/with-langchain.md +10 -9
- package/.docs/organized/code-examples/with-langgraph.md +7 -6
- package/.docs/organized/code-examples/with-livekit.md +15 -14
- package/.docs/organized/code-examples/with-mcp.md +14 -12
- package/.docs/organized/code-examples/with-nuxt.md +511 -575
- package/.docs/organized/code-examples/with-opencode.md +4 -4
- package/.docs/organized/code-examples/with-openui.md +450 -0
- package/.docs/organized/code-examples/with-pi.md +6 -5
- package/.docs/organized/code-examples/with-react-hook-form.md +16 -13
- package/.docs/organized/code-examples/with-react-ink-web.md +65 -15
- package/.docs/organized/code-examples/with-react-ink.md +5 -4
- package/.docs/organized/code-examples/with-react-router.md +8 -7
- package/.docs/organized/code-examples/with-resumable-stream.md +13 -12
- package/.docs/organized/code-examples/with-store.md +3 -3
- package/.docs/organized/code-examples/with-svelte.md +415 -0
- package/.docs/organized/code-examples/with-sveltekit.md +1061 -0
- package/.docs/organized/code-examples/with-tanstack.md +10 -9
- package/.docs/organized/code-examples/with-tap-runtime.md +5 -4
- package/.docs/organized/code-examples/with-virtualized-thread.md +6 -5
- package/.docs/organized/code-examples/with-vue.md +2 -2
- package/.docs/raw/docs/{(docs) → (getting-started)}/cli.mdx +6 -1
- package/.docs/raw/docs/{(docs) → (getting-started)}/devtools.mdx +1 -1
- package/.docs/raw/docs/{(docs) → (getting-started)}/index.mdx +4 -2
- package/.docs/raw/docs/{(docs) → (getting-started)}/installation.mdx +26 -26
- package/.docs/raw/docs/(reference)/api-reference/adapters/suggestions.mdx +6 -0
- package/.docs/raw/docs/(reference)/api-reference/context-providers/assistant-runtime-provider.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +6 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +5 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +9 -2
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +2 -2
- package/.docs/raw/docs/(reference)/api-reference/integrations/{react-ai-sdk.mdx → ai-sdk.mdx} +43 -18
- package/.docs/raw/docs/(reference)/api-reference/integrations/eve.mdx +61 -2
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +3 -3
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +2 -2
- package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +20 -2
- package/.docs/raw/docs/(reference)/api-reference/tools/interactables.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/transport/frame.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +32 -1
- package/.docs/raw/docs/(reference)/api-reference/voice/session.mdx +1 -1
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +10 -10
- package/.docs/raw/docs/cloud/ai-sdk.mdx +4 -2
- package/.docs/raw/docs/cloud/index.mdx +1 -1
- package/.docs/raw/docs/copilots/assistant-frame.mdx +19 -8
- package/.docs/raw/docs/guides/attachments.mdx +4 -4
- package/.docs/raw/docs/guides/branching.mdx +1 -1
- package/.docs/raw/docs/guides/chatgpt-subscription.mdx +1 -1
- package/.docs/raw/docs/guides/context-api.mdx +15 -17
- package/.docs/raw/docs/guides/dictation.mdx +2 -2
- package/.docs/raw/docs/guides/electron.mdx +1 -1
- package/.docs/raw/docs/guides/latex.mdx +1 -1
- package/.docs/raw/docs/guides/mentions.mdx +2 -0
- package/.docs/raw/docs/guides/message-timing.mdx +11 -5
- package/.docs/raw/docs/guides/quoting.mdx +1 -1
- package/.docs/raw/docs/guides/resumable-streams.mdx +3 -3
- package/.docs/raw/docs/guides/speech.mdx +1 -1
- package/.docs/raw/docs/guides/suggestions.mdx +8 -5
- package/.docs/raw/docs/guides/voice.mdx +1 -1
- package/.docs/raw/docs/ink/hooks.mdx +1 -1
- package/.docs/raw/docs/ink/index.mdx +3 -2
- package/.docs/raw/docs/ink/migration.mdx +1 -1
- package/.docs/raw/docs/ink/primitives.mdx +1 -1
- package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/{cloudflare-agents/overview.mdx → cloudflare-agents.mdx} +4 -3
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +1 -1
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
- package/.docs/raw/docs/integrations/index.mdx +2 -2
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +149 -131
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +2 -2
- package/.docs/raw/docs/migrations/v0-15.mdx +34 -0
- package/.docs/raw/docs/primitives/action-bar.mdx +1 -1
- package/.docs/raw/docs/primitives/assistant-modal.mdx +1 -1
- package/.docs/raw/docs/primitives/attachment.mdx +1 -1
- package/.docs/raw/docs/primitives/branch-picker.mdx +1 -1
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +3 -3
- package/.docs/raw/docs/primitives/composer.mdx +1 -1
- package/.docs/raw/docs/primitives/error.mdx +1 -1
- package/.docs/raw/docs/primitives/message.mdx +1 -1
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +1 -1
- package/.docs/raw/docs/primitives/suggestion.mdx +4 -2
- package/.docs/raw/docs/primitives/thread-list.mdx +1 -1
- package/.docs/raw/docs/primitives/thread.mdx +2 -2
- package/.docs/raw/docs/react-native/adapters.mdx +1 -1
- package/.docs/raw/docs/react-native/index.mdx +2 -2
- package/.docs/raw/docs/react-native/migration.mdx +2 -2
- package/.docs/raw/docs/react-native/primitives.mdx +142 -5
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +48 -6
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +3 -3
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +4 -4
- package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +31 -16
- package/.docs/raw/docs/runtimes/claude-managed-agents.mdx +118 -0
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +3 -3
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +3 -3
- package/.docs/raw/docs/runtimes/concepts/stability.mdx +2 -1
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +73 -33
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +1 -1
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +6 -2
- package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +4 -0
- package/.docs/raw/docs/runtimes/opencode/quickstart.mdx +1 -1
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +9 -2
- package/.docs/raw/docs/tools/backend.mdx +4 -4
- package/.docs/raw/docs/tools/defining-tools.mdx +21 -2
- package/.docs/raw/docs/tools/generative-ui-primitive.mdx +180 -0
- package/.docs/raw/docs/tools/generative-ui-slack.mdx +167 -0
- package/.docs/raw/docs/tools/generative-ui-teams.mdx +160 -0
- package/.docs/raw/docs/tools/generative-ui.mdx +224 -211
- package/.docs/raw/docs/tools/index.mdx +2 -1
- package/.docs/raw/docs/tools/interactables.mdx +8 -7
- package/.docs/raw/docs/tools/mcp-apps.mdx +18 -1
- package/.docs/raw/docs/tools/mcp.mdx +2 -2
- package/.docs/raw/docs/tools/openui.mdx +175 -0
- package/.docs/raw/docs/tools/tool-ui.mdx +18 -7
- package/.docs/raw/docs/tools/user-managed-mcp.mdx +7 -3
- package/.docs/raw/docs/ui/assistant-modal.mdx +3 -3
- package/.docs/raw/docs/ui/assistant-sidebar.mdx +1 -1
- package/.docs/raw/docs/ui/attachment.mdx +50 -3
- package/.docs/raw/docs/ui/composer-trigger-popover.mdx +36 -1
- package/.docs/raw/docs/ui/context-display.mdx +1 -1
- package/.docs/raw/docs/ui/directive-text.mdx +1 -1
- package/.docs/raw/docs/ui/file.mdx +2 -2
- package/.docs/raw/docs/ui/follow-up-suggestions.mdx +1 -1
- package/.docs/raw/docs/ui/image.mdx +2 -2
- package/.docs/raw/docs/ui/markdown.mdx +40 -1
- package/.docs/raw/docs/ui/mermaid.mdx +1 -1
- package/.docs/raw/docs/ui/message-timing.mdx +1 -1
- package/.docs/raw/docs/ui/model-selector.mdx +4 -4
- package/.docs/raw/docs/ui/part-grouping.mdx +1 -1
- package/.docs/raw/docs/ui/quote.mdx +3 -3
- package/.docs/raw/docs/ui/reasoning.mdx +31 -3
- package/.docs/raw/docs/ui/scrollbar.mdx +1 -1
- package/.docs/raw/docs/ui/sources.mdx +10 -1
- package/.docs/raw/docs/ui/streamdown.mdx +2 -2
- package/.docs/raw/docs/ui/syntax-highlighting.mdx +1 -1
- package/.docs/raw/docs/ui/thread-list.mdx +40 -1
- package/.docs/raw/docs/ui/thread.mdx +49 -2
- package/.docs/raw/docs/ui/tool-fallback.mdx +23 -9
- package/.docs/raw/docs/ui/tool-group.mdx +1 -1
- package/.docs/raw/docs/ui/voice.mdx +1 -1
- package/.docs/raw/docs/utilities/react-o11y.mdx +2 -2
- package/dist/xulux/catalog-client.d.ts.map +1 -1
- package/dist/xulux/catalog-client.js +51 -6
- package/dist/xulux/catalog-client.js.map +1 -1
- package/dist/xulux/types.d.ts +7 -7
- package/dist/xulux/types.d.ts.map +1 -1
- package/dist/xulux/types.js.map +1 -1
- package/package.json +5 -5
- package/src/tools/tests/docs.test.ts +10 -7
- package/src/tools/tests/path-traversal.test.ts +5 -2
- package/src/tools/tests/xulux-templates.test.ts +63 -0
- package/src/xulux/catalog-client.ts +68 -23
- package/src/xulux/types.ts +17 -13
- package/.docs/raw/docs/tools/interactables-legacy.mdx +0 -423
- package/.docs/raw/docs/ui/accordion.mdx +0 -266
- package/.docs/raw/docs/ui/badge.mdx +0 -150
- package/.docs/raw/docs/ui/diff-viewer.mdx +0 -280
- package/.docs/raw/docs/ui/dot-matrix.mdx +0 -133
- package/.docs/raw/docs/ui/number-roll.mdx +0 -154
- package/.docs/raw/docs/ui/select.mdx +0 -254
- package/.docs/raw/docs/ui/tabs.mdx +0 -271
- /package/.docs/raw/docs/{(docs) → (getting-started)}/architecture.mdx +0 -0
- /package/.docs/raw/docs/{(docs) → (getting-started)}/base-ui.mdx +0 -0
- /package/.docs/raw/docs/{(docs) → (getting-started)}/llm.mdx +0 -0
- /package/.docs/raw/docs/{(docs) → (getting-started)}/rtl.mdx +0 -0
|
@@ -17,7 +17,7 @@ export async function POST(req: Request) {
|
|
|
17
17
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
18
18
|
|
|
19
19
|
const result = streamText({
|
|
20
|
-
model: openai("gpt-5.
|
|
20
|
+
model: openai("gpt-5.6-luna"),
|
|
21
21
|
messages: await convertToModelMessages(messages),
|
|
22
22
|
stopWhen: stepCountIs(10),
|
|
23
23
|
});
|
|
@@ -127,7 +127,7 @@ export default function RootLayout({
|
|
|
127
127
|
"use client";
|
|
128
128
|
|
|
129
129
|
import { AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
130
|
-
import { useChatRuntime } from "@assistant-ui/
|
|
130
|
+
import { useChatRuntime } from "@assistant-ui/ai-sdk";
|
|
131
131
|
import { ElevenLabsVoiceAdapter } from "@/lib/elevenlabs-voice-adapter";
|
|
132
132
|
import { VoiceThread } from "./voice-thread";
|
|
133
133
|
|
|
@@ -423,7 +423,7 @@ export class ElevenLabsVoiceAdapter implements RealtimeVoiceAdapter {
|
|
|
423
423
|
import { withAui } from "@assistant-ui/next";
|
|
424
424
|
/** @type {import('next').NextConfig} */
|
|
425
425
|
const nextConfig = {
|
|
426
|
-
transpilePackages: ["@assistant-ui/react", "@assistant-ui/
|
|
426
|
+
transpilePackages: ["@assistant-ui/react", "@assistant-ui/ai-sdk"],
|
|
427
427
|
};
|
|
428
428
|
|
|
429
429
|
export default withAui(nextConfig);
|
|
@@ -439,20 +439,20 @@ export default withAui(nextConfig);
|
|
|
439
439
|
"version": "0.0.0",
|
|
440
440
|
"type": "module",
|
|
441
441
|
"dependencies": {
|
|
442
|
-
"@ai-sdk/openai": "^4.0.
|
|
443
|
-
"@ai-sdk/react": "^4.0.
|
|
442
|
+
"@ai-sdk/openai": "^4.0.46",
|
|
443
|
+
"@ai-sdk/react": "^4.0.80",
|
|
444
|
+
"@assistant-ui/ai-sdk": "workspace:*",
|
|
444
445
|
"@assistant-ui/react": "workspace:^",
|
|
445
|
-
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
446
446
|
"@assistant-ui/react-markdown": "workspace:^",
|
|
447
447
|
"@assistant-ui/ui": "workspace:*",
|
|
448
|
-
"@elevenlabs/client": "^1.
|
|
448
|
+
"@elevenlabs/client": "^1.21.0",
|
|
449
449
|
"@tailwindcss/postcss": "^4.3.3",
|
|
450
|
-
"ai": "^7.0.
|
|
450
|
+
"ai": "^7.0.77",
|
|
451
451
|
"class-variance-authority": "^0.7.1",
|
|
452
452
|
"clsx": "^2.1.1",
|
|
453
|
-
"lucide-react": "^1.
|
|
454
|
-
"motion": "^13.
|
|
455
|
-
"next": "^16.3.
|
|
453
|
+
"lucide-react": "^1.33.0",
|
|
454
|
+
"motion": "^13.1.1",
|
|
455
|
+
"next": "^16.3.2",
|
|
456
456
|
"postcss": "^8.5.26",
|
|
457
457
|
"react": "^19.2.8",
|
|
458
458
|
"react-dom": "^19.2.8",
|
|
@@ -463,9 +463,9 @@ export default withAui(nextConfig);
|
|
|
463
463
|
"devDependencies": {
|
|
464
464
|
"@assistant-ui/next": "workspace:*",
|
|
465
465
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
466
|
-
"@types/node": "^26.
|
|
466
|
+
"@types/node": "^26.2.0",
|
|
467
467
|
"@types/react": "^19.2.18",
|
|
468
|
-
"@types/react-dom": "^19.2.
|
|
468
|
+
"@types/react-dom": "^19.2.5",
|
|
469
469
|
"tw-animate-css": "^1.4.0",
|
|
470
470
|
"typescript": "^7.0.2"
|
|
471
471
|
},
|
|
@@ -500,6 +500,7 @@ export default withAui(nextConfig);
|
|
|
500
500
|
"@/components/assistant-ui/*": [
|
|
501
501
|
"../../packages/ui/src/components/assistant-ui/*"
|
|
502
502
|
],
|
|
503
|
+
"@/hooks/*": ["../../packages/ui/src/hooks/*"],
|
|
503
504
|
"@/components/ui/*": [
|
|
504
505
|
"../../packages/ui/src/components/ui/base/*",
|
|
505
506
|
"../../packages/ui/src/components/ui/radix/*"
|
|
@@ -21,7 +21,7 @@ export async function POST(req: Request) {
|
|
|
21
21
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
22
22
|
|
|
23
23
|
const result = streamText({
|
|
24
|
-
model: openai("gpt-5.
|
|
24
|
+
model: openai("gpt-5.6-luna"),
|
|
25
25
|
messages: await convertToModelMessages(messages),
|
|
26
26
|
stopWhen: stepCountIs(10),
|
|
27
27
|
tools: {
|
|
@@ -240,7 +240,7 @@ import {
|
|
|
240
240
|
AuiConfig,
|
|
241
241
|
Suggestions,
|
|
242
242
|
} from "@assistant-ui/react";
|
|
243
|
-
import { useChatRuntime } from "@assistant-ui/
|
|
243
|
+
import { useChatRuntime } from "@assistant-ui/ai-sdk";
|
|
244
244
|
import { ElevenLabsScribeAdapter } from "@/lib/elevenlabs-scribe-adapter";
|
|
245
245
|
|
|
246
246
|
function ThreadWithSuggestions() {
|
|
@@ -548,7 +548,7 @@ export class ElevenLabsScribeAdapter implements DictationAdapter {
|
|
|
548
548
|
import { withAui } from "@assistant-ui/next";
|
|
549
549
|
/** @type {import('next').NextConfig} */
|
|
550
550
|
const nextConfig = {
|
|
551
|
-
transpilePackages: ["@assistant-ui/react", "@assistant-ui/
|
|
551
|
+
transpilePackages: ["@assistant-ui/react", "@assistant-ui/ai-sdk"],
|
|
552
552
|
};
|
|
553
553
|
|
|
554
554
|
export default withAui(nextConfig);
|
|
@@ -564,20 +564,20 @@ export default withAui(nextConfig);
|
|
|
564
564
|
"version": "0.0.0",
|
|
565
565
|
"type": "module",
|
|
566
566
|
"dependencies": {
|
|
567
|
-
"@ai-sdk/openai": "^4.0.
|
|
568
|
-
"@ai-sdk/react": "^4.0.
|
|
567
|
+
"@ai-sdk/openai": "^4.0.46",
|
|
568
|
+
"@ai-sdk/react": "^4.0.80",
|
|
569
|
+
"@assistant-ui/ai-sdk": "workspace:*",
|
|
569
570
|
"@assistant-ui/react": "workspace:^",
|
|
570
|
-
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
571
571
|
"@assistant-ui/react-markdown": "workspace:^",
|
|
572
572
|
"@assistant-ui/ui": "workspace:*",
|
|
573
|
-
"@elevenlabs/client": "^1.
|
|
573
|
+
"@elevenlabs/client": "^1.21.0",
|
|
574
574
|
"@tailwindcss/postcss": "^4.3.3",
|
|
575
|
-
"ai": "^7.0.
|
|
575
|
+
"ai": "^7.0.77",
|
|
576
576
|
"class-variance-authority": "^0.7.1",
|
|
577
577
|
"clsx": "^2.1.1",
|
|
578
|
-
"lucide-react": "^1.
|
|
579
|
-
"motion": "^13.
|
|
580
|
-
"next": "^16.3.
|
|
578
|
+
"lucide-react": "^1.33.0",
|
|
579
|
+
"motion": "^13.1.1",
|
|
580
|
+
"next": "^16.3.2",
|
|
581
581
|
"postcss": "^8.5.26",
|
|
582
582
|
"react": "^19.2.8",
|
|
583
583
|
"react-dom": "^19.2.8",
|
|
@@ -588,9 +588,9 @@ export default withAui(nextConfig);
|
|
|
588
588
|
"devDependencies": {
|
|
589
589
|
"@assistant-ui/next": "workspace:*",
|
|
590
590
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
591
|
-
"@types/node": "^26.
|
|
591
|
+
"@types/node": "^26.2.0",
|
|
592
592
|
"@types/react": "^19.2.18",
|
|
593
|
-
"@types/react-dom": "^19.2.
|
|
593
|
+
"@types/react-dom": "^19.2.5",
|
|
594
594
|
"tw-animate-css": "^1.4.0",
|
|
595
595
|
"typescript": "^7.0.2"
|
|
596
596
|
},
|
|
@@ -644,7 +644,7 @@ npm run dev
|
|
|
644
644
|
## Related Documentation
|
|
645
645
|
|
|
646
646
|
- [assistant-ui Documentation](https://www.assistant-ui.com/docs)
|
|
647
|
-
- [ElevenLabs Scribe](https://elevenlabs.io/docs/
|
|
647
|
+
- [ElevenLabs Scribe](https://elevenlabs.io/docs/overview/capabilities/speech-to-text)
|
|
648
648
|
|
|
649
649
|
```
|
|
650
650
|
|
|
@@ -670,6 +670,7 @@ npm run dev
|
|
|
670
670
|
"@/components/assistant-ui/*": [
|
|
671
671
|
"../../packages/ui/src/components/assistant-ui/*"
|
|
672
672
|
],
|
|
673
|
+
"@/hooks/*": ["../../packages/ui/src/hooks/*"],
|
|
673
674
|
"@/components/ui/*": [
|
|
674
675
|
"../../packages/ui/src/components/ui/base/*",
|
|
675
676
|
"../../packages/ui/src/components/ui/radix/*"
|
|
@@ -336,9 +336,9 @@ export default withEve(withAui(nextConfig));
|
|
|
336
336
|
"@assistant-ui/ui": "workspace:*",
|
|
337
337
|
"class-variance-authority": "^0.7.1",
|
|
338
338
|
"clsx": "^2.1.1",
|
|
339
|
-
"eve": "^0.
|
|
340
|
-
"lucide-react": "^1.
|
|
341
|
-
"next": "^16.3.
|
|
339
|
+
"eve": "^0.44.4",
|
|
340
|
+
"lucide-react": "^1.33.0",
|
|
341
|
+
"next": "^16.3.2",
|
|
342
342
|
"react": "^19.2.8",
|
|
343
343
|
"react-dom": "^19.2.8",
|
|
344
344
|
"tailwind-merge": "^3.6.0"
|
|
@@ -347,9 +347,9 @@ export default withEve(withAui(nextConfig));
|
|
|
347
347
|
"@assistant-ui/next": "workspace:*",
|
|
348
348
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
349
349
|
"@tailwindcss/postcss": "^4.3.3",
|
|
350
|
-
"@types/node": "^26.
|
|
350
|
+
"@types/node": "^26.2.0",
|
|
351
351
|
"@types/react": "^19.2.18",
|
|
352
|
-
"@types/react-dom": "^19.2.
|
|
352
|
+
"@types/react-dom": "^19.2.5",
|
|
353
353
|
"postcss": "^8.5.26",
|
|
354
354
|
"tailwindcss": "^4.3.3",
|
|
355
355
|
"tw-animate-css": "^1.4.0",
|
|
@@ -385,6 +385,7 @@ The Eve channel is served on the same origin as the Next app, so the browser UI
|
|
|
385
385
|
"@/components/assistant-ui/*": [
|
|
386
386
|
"../../packages/ui/src/components/assistant-ui/*"
|
|
387
387
|
],
|
|
388
|
+
"@/hooks/*": ["../../packages/ui/src/hooks/*"],
|
|
388
389
|
"@/components/ui/*": [
|
|
389
390
|
"../../packages/ui/src/components/ui/base/*",
|
|
390
391
|
"../../packages/ui/src/components/ui/radix/*"
|
|
@@ -115,6 +115,7 @@ function NewChatButton() {
|
|
|
115
115
|
return (
|
|
116
116
|
<Pressable
|
|
117
117
|
accessibilityLabel="New chat"
|
|
118
|
+
accessibilityRole="button"
|
|
118
119
|
hitSlop={8}
|
|
119
120
|
onPress={() => {
|
|
120
121
|
haptics.selection();
|
|
@@ -191,7 +192,7 @@ export default function RootLayout() {
|
|
|
191
192
|
## app/api/chat+api.ts
|
|
192
193
|
|
|
193
194
|
```typescript
|
|
194
|
-
import { frontendTools } from "@assistant-ui/
|
|
195
|
+
import { frontendTools } from "@assistant-ui/ai-sdk";
|
|
195
196
|
import { openai } from "@ai-sdk/openai";
|
|
196
197
|
import {
|
|
197
198
|
convertToModelMessages,
|
|
@@ -204,7 +205,7 @@ export async function POST(req: Request) {
|
|
|
204
205
|
const body = await req.json();
|
|
205
206
|
const { messages, tools } = body;
|
|
206
207
|
|
|
207
|
-
const model = openai("gpt-5.
|
|
208
|
+
const model = openai("gpt-5.6-luna");
|
|
208
209
|
|
|
209
210
|
const prunedMessages = pruneMessages({
|
|
210
211
|
messages: await convertToModelMessages(messages),
|
|
@@ -375,6 +376,7 @@ function AttachButton() {
|
|
|
375
376
|
return (
|
|
376
377
|
<Pressable
|
|
377
378
|
accessibilityLabel="Add image"
|
|
379
|
+
accessibilityRole="button"
|
|
378
380
|
onPress={pickImage}
|
|
379
381
|
hitSlop={6}
|
|
380
382
|
style={({ pressed }) => [
|
|
@@ -636,6 +638,7 @@ import { useEffect, useRef } from "react";
|
|
|
636
638
|
import { View, Text, Animated, Platform, StyleSheet } from "react-native";
|
|
637
639
|
import { Image } from "expo-image";
|
|
638
640
|
import {
|
|
641
|
+
AuiIf,
|
|
639
642
|
useAuiState,
|
|
640
643
|
MessagePrimitive,
|
|
641
644
|
ErrorPrimitive,
|
|
@@ -764,12 +767,19 @@ function AssistantMessage() {
|
|
|
764
767
|
/>
|
|
765
768
|
</ErrorPrimitive.Root>
|
|
766
769
|
</View>
|
|
767
|
-
<
|
|
770
|
+
<AuiIf
|
|
771
|
+
condition={(s) =>
|
|
772
|
+
!(
|
|
773
|
+
s.message.role === "assistant" &&
|
|
774
|
+
s.message.status.type === "running"
|
|
775
|
+
)
|
|
776
|
+
}
|
|
777
|
+
>
|
|
768
778
|
<View style={styles.actionsRow}>
|
|
769
779
|
<MessageBranchPicker align="flex-start" />
|
|
770
780
|
<MessageActionBar />
|
|
771
781
|
</View>
|
|
772
|
-
</
|
|
782
|
+
</AuiIf>
|
|
773
783
|
</MessagePrimitive.Root>
|
|
774
784
|
);
|
|
775
785
|
}
|
|
@@ -864,7 +874,7 @@ import {
|
|
|
864
874
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
865
875
|
import { MessageBubble } from "./message";
|
|
866
876
|
import { Composer } from "./composer";
|
|
867
|
-
import { ThreadPrimitive } from "@assistant-ui/react-native";
|
|
877
|
+
import { AuiIf, ThreadPrimitive } from "@assistant-ui/react-native";
|
|
868
878
|
import { useTheme } from "@/hooks/use-theme";
|
|
869
879
|
import { Radius, Spacing } from "@/constants/theme";
|
|
870
880
|
import { haptics } from "@/lib/haptics";
|
|
@@ -916,10 +926,10 @@ function EmptyState() {
|
|
|
916
926
|
function ChatMessages() {
|
|
917
927
|
return (
|
|
918
928
|
<>
|
|
919
|
-
<
|
|
929
|
+
<AuiIf condition={(s) => s.thread.isEmpty}>
|
|
920
930
|
<EmptyState />
|
|
921
|
-
</
|
|
922
|
-
<
|
|
931
|
+
</AuiIf>
|
|
932
|
+
<AuiIf condition={(s) => !s.thread.isEmpty}>
|
|
923
933
|
<ThreadPrimitive.MessagesFlatList
|
|
924
934
|
style={styles.flex}
|
|
925
935
|
contentContainerStyle={styles.messageList}
|
|
@@ -927,7 +937,7 @@ function ChatMessages() {
|
|
|
927
937
|
>
|
|
928
938
|
{() => <MessageBubble />}
|
|
929
939
|
</ThreadPrimitive.MessagesFlatList>
|
|
930
|
-
</
|
|
940
|
+
</AuiIf>
|
|
931
941
|
</>
|
|
932
942
|
);
|
|
933
943
|
}
|
|
@@ -1425,8 +1435,8 @@ import { View, Text, Pressable, StyleSheet } from "react-native";
|
|
|
1425
1435
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
1426
1436
|
import {
|
|
1427
1437
|
ThreadListPrimitive,
|
|
1428
|
-
ThreadListItemByIndexProvider,
|
|
1429
1438
|
useAui,
|
|
1439
|
+
useAuiState,
|
|
1430
1440
|
} from "@assistant-ui/react-native";
|
|
1431
1441
|
import type { DrawerContentComponentProps } from "expo-router/build/react-navigation/drawer/types";
|
|
1432
1442
|
import { ThreadListItem } from "./ThreadListItem";
|
|
@@ -1438,6 +1448,9 @@ import { haptics } from "@/lib/haptics";
|
|
|
1438
1448
|
export function ThreadListDrawer({ navigation }: DrawerContentComponentProps) {
|
|
1439
1449
|
const { colors } = useTheme();
|
|
1440
1450
|
const aui = useAui();
|
|
1451
|
+
const isNewThreadActive = useAuiState(
|
|
1452
|
+
(s) => s.threads.newThreadId === s.threads.mainThreadId,
|
|
1453
|
+
);
|
|
1441
1454
|
const insets = useSafeAreaInsets();
|
|
1442
1455
|
|
|
1443
1456
|
return (
|
|
@@ -1449,6 +1462,8 @@ export function ThreadListDrawer({ navigation }: DrawerContentComponentProps) {
|
|
|
1449
1462
|
>
|
|
1450
1463
|
<ThreadListPrimitive.Root style={styles.root}>
|
|
1451
1464
|
<Pressable
|
|
1465
|
+
accessibilityRole="button"
|
|
1466
|
+
accessibilityState={{ selected: isNewThreadActive }}
|
|
1452
1467
|
onPressIn={haptics.selection}
|
|
1453
1468
|
onPress={() => {
|
|
1454
1469
|
aui.threads.switchToNewThread();
|
|
@@ -1470,10 +1485,8 @@ export function ThreadListDrawer({ navigation }: DrawerContentComponentProps) {
|
|
|
1470
1485
|
</Text>
|
|
1471
1486
|
|
|
1472
1487
|
<ThreadListPrimitive.Items
|
|
1473
|
-
renderItem={(
|
|
1474
|
-
<
|
|
1475
|
-
<ThreadListItem onSelect={() => navigation.closeDrawer()} />
|
|
1476
|
-
</ThreadListItemByIndexProvider>
|
|
1488
|
+
renderItem={() => (
|
|
1489
|
+
<ThreadListItem onSelect={() => navigation.closeDrawer()} />
|
|
1477
1490
|
)}
|
|
1478
1491
|
style={styles.list}
|
|
1479
1492
|
contentContainerStyle={styles.listContent}
|
|
@@ -1546,6 +1559,8 @@ export function ThreadListItem({ onSelect }: { onSelect: () => void }) {
|
|
|
1546
1559
|
return (
|
|
1547
1560
|
<ThreadListItemPrimitive.Root>
|
|
1548
1561
|
<Pressable
|
|
1562
|
+
accessibilityRole="button"
|
|
1563
|
+
accessibilityState={{ selected: isActive }}
|
|
1549
1564
|
onPressIn={haptics.selection}
|
|
1550
1565
|
onPress={() => {
|
|
1551
1566
|
aui.threadListItem.switchTo();
|
|
@@ -1777,21 +1792,181 @@ export const Spacing = {
|
|
|
1777
1792
|
|
|
1778
1793
|
```
|
|
1779
1794
|
|
|
1795
|
+
## hooks/anonymous-session-fetch.test.ts
|
|
1796
|
+
|
|
1797
|
+
```typescript
|
|
1798
|
+
import { describe, expect, it, vi } from "vitest";
|
|
1799
|
+
import {
|
|
1800
|
+
createAnonymousSessionFetch,
|
|
1801
|
+
shouldUseAnonymousSessionFetch,
|
|
1802
|
+
} from "./anonymous-session-fetch";
|
|
1803
|
+
|
|
1804
|
+
describe("Expo anonymous session fetch", () => {
|
|
1805
|
+
it("only bootstraps the protected browser flow on web", () => {
|
|
1806
|
+
expect(
|
|
1807
|
+
shouldUseAnonymousSessionFetch(
|
|
1808
|
+
"https://www.assistant-ui.com/api/chat",
|
|
1809
|
+
"web",
|
|
1810
|
+
),
|
|
1811
|
+
).toBe(true);
|
|
1812
|
+
expect(
|
|
1813
|
+
shouldUseAnonymousSessionFetch(
|
|
1814
|
+
"https://www.assistant-ui.com/api/chat",
|
|
1815
|
+
"ios",
|
|
1816
|
+
),
|
|
1817
|
+
).toBe(false);
|
|
1818
|
+
expect(shouldUseAnonymousSessionFetch("/api/chat", "web")).toBe(false);
|
|
1819
|
+
});
|
|
1820
|
+
|
|
1821
|
+
it("retries bootstrap on the next request after issuance fails", async () => {
|
|
1822
|
+
const fetchMock = vi
|
|
1823
|
+
.fn<typeof fetch>()
|
|
1824
|
+
.mockRejectedValueOnce(new Error("temporary network failure"))
|
|
1825
|
+
.mockResolvedValueOnce(new Response(null, { status: 403 }))
|
|
1826
|
+
.mockResolvedValueOnce(Response.json({ token: "signed-session" }))
|
|
1827
|
+
.mockResolvedValueOnce(new Response("ok"));
|
|
1828
|
+
const sessionFetch = createAnonymousSessionFetch(
|
|
1829
|
+
"https://www.assistant-ui.com/api/chat",
|
|
1830
|
+
fetchMock,
|
|
1831
|
+
);
|
|
1832
|
+
|
|
1833
|
+
const failedResponse = await sessionFetch(
|
|
1834
|
+
"https://www.assistant-ui.com/api/chat",
|
|
1835
|
+
{ method: "POST" },
|
|
1836
|
+
);
|
|
1837
|
+
const recoveredResponse = await sessionFetch(
|
|
1838
|
+
"https://www.assistant-ui.com/api/chat",
|
|
1839
|
+
{ method: "POST" },
|
|
1840
|
+
);
|
|
1841
|
+
|
|
1842
|
+
expect(failedResponse.status).toBe(403);
|
|
1843
|
+
expect(recoveredResponse.status).toBe(200);
|
|
1844
|
+
expect(fetchMock).toHaveBeenCalledTimes(4);
|
|
1845
|
+
expect(
|
|
1846
|
+
new Headers(fetchMock.mock.calls[1]?.[1]?.headers).get(
|
|
1847
|
+
"x-assistant-ui-anonymous-session",
|
|
1848
|
+
),
|
|
1849
|
+
).toBeNull();
|
|
1850
|
+
expect(
|
|
1851
|
+
new Headers(fetchMock.mock.calls[3]?.[1]?.headers).get(
|
|
1852
|
+
"x-assistant-ui-anonymous-session",
|
|
1853
|
+
),
|
|
1854
|
+
).toBe("signed-session");
|
|
1855
|
+
});
|
|
1856
|
+
|
|
1857
|
+
it("accepts a same-origin 204 cookie bootstrap", async () => {
|
|
1858
|
+
const fetchMock = vi
|
|
1859
|
+
.fn<typeof fetch>()
|
|
1860
|
+
.mockResolvedValueOnce(new Response(null, { status: 204 }))
|
|
1861
|
+
.mockResolvedValueOnce(new Response("ok"));
|
|
1862
|
+
const sessionFetch = createAnonymousSessionFetch(
|
|
1863
|
+
"https://example.com/api/chat",
|
|
1864
|
+
fetchMock,
|
|
1865
|
+
);
|
|
1866
|
+
|
|
1867
|
+
const response = await sessionFetch("https://example.com/api/chat", {
|
|
1868
|
+
method: "POST",
|
|
1869
|
+
});
|
|
1870
|
+
|
|
1871
|
+
expect(response.status).toBe(200);
|
|
1872
|
+
expect(fetchMock.mock.calls[0]?.[1]?.credentials).toBe("same-origin");
|
|
1873
|
+
expect(
|
|
1874
|
+
new Headers(fetchMock.mock.calls[1]?.[1]?.headers).get(
|
|
1875
|
+
"x-assistant-ui-anonymous-session",
|
|
1876
|
+
),
|
|
1877
|
+
).toBeNull();
|
|
1878
|
+
});
|
|
1879
|
+
});
|
|
1880
|
+
|
|
1881
|
+
```
|
|
1882
|
+
|
|
1883
|
+
## hooks/anonymous-session-fetch.ts
|
|
1884
|
+
|
|
1885
|
+
```typescript
|
|
1886
|
+
// Mirrored inline in examples/with-react-ink-web/app/ink-app.tsx; keep in sync.
|
|
1887
|
+
const ANONYMOUS_SESSION_HEADER = "x-assistant-ui-anonymous-session";
|
|
1888
|
+
|
|
1889
|
+
export function shouldUseAnonymousSessionFetch(
|
|
1890
|
+
chatApi: string,
|
|
1891
|
+
platform: string,
|
|
1892
|
+
): boolean {
|
|
1893
|
+
return platform === "web" && chatApi.startsWith("http");
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
export function createAnonymousSessionFetch(
|
|
1897
|
+
chatApi: string,
|
|
1898
|
+
fetchImplementation: typeof fetch = fetch,
|
|
1899
|
+
): typeof fetch {
|
|
1900
|
+
let tokenPromise: Promise<string | null> | null = null;
|
|
1901
|
+
|
|
1902
|
+
const getToken = () => {
|
|
1903
|
+
tokenPromise ??= (async () => {
|
|
1904
|
+
const endpoint = new URL("/api/anonymous-session", chatApi);
|
|
1905
|
+
const response = await fetchImplementation(endpoint, {
|
|
1906
|
+
credentials: "same-origin",
|
|
1907
|
+
});
|
|
1908
|
+
if (!response.ok) {
|
|
1909
|
+
throw new Error("Unable to start an anonymous session");
|
|
1910
|
+
}
|
|
1911
|
+
if (response.status === 204) return null;
|
|
1912
|
+
const payload = (await response.json()) as { token?: unknown };
|
|
1913
|
+
if (typeof payload.token !== "string" || !payload.token) {
|
|
1914
|
+
throw new Error("Anonymous session token is missing");
|
|
1915
|
+
}
|
|
1916
|
+
return payload.token;
|
|
1917
|
+
})().catch(() => {
|
|
1918
|
+
tokenPromise = null;
|
|
1919
|
+
return null;
|
|
1920
|
+
});
|
|
1921
|
+
return tokenPromise;
|
|
1922
|
+
};
|
|
1923
|
+
|
|
1924
|
+
return async (input, init) => {
|
|
1925
|
+
const requestTemplate =
|
|
1926
|
+
input instanceof Request ? new Request(input, init) : null;
|
|
1927
|
+
|
|
1928
|
+
const send = async () => {
|
|
1929
|
+
const headers = new Headers(requestTemplate?.headers ?? init?.headers);
|
|
1930
|
+
const token = await getToken();
|
|
1931
|
+
if (token) headers.set(ANONYMOUS_SESSION_HEADER, token);
|
|
1932
|
+
if (requestTemplate) {
|
|
1933
|
+
return fetchImplementation(requestTemplate.clone(), { headers });
|
|
1934
|
+
}
|
|
1935
|
+
return fetchImplementation(input, { ...init, headers });
|
|
1936
|
+
};
|
|
1937
|
+
|
|
1938
|
+
const response = await send();
|
|
1939
|
+
if (response.status !== 401) return response;
|
|
1940
|
+
tokenPromise = null;
|
|
1941
|
+
return send();
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
```
|
|
1946
|
+
|
|
1780
1947
|
## hooks/use-app-runtime.ts
|
|
1781
1948
|
|
|
1782
1949
|
```typescript
|
|
1783
1950
|
import { useMemo } from "react";
|
|
1784
|
-
import {
|
|
1785
|
-
useChatRuntime,
|
|
1786
|
-
AssistantChatTransport,
|
|
1787
|
-
} from "@assistant-ui/react-ai-sdk";
|
|
1951
|
+
import { useChatRuntime, AssistantChatTransport } from "@assistant-ui/ai-sdk";
|
|
1788
1952
|
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
|
|
1953
|
+
import { Platform } from "react-native";
|
|
1954
|
+
import {
|
|
1955
|
+
createAnonymousSessionFetch,
|
|
1956
|
+
shouldUseAnonymousSessionFetch,
|
|
1957
|
+
} from "./anonymous-session-fetch";
|
|
1789
1958
|
|
|
1790
1959
|
const CHAT_API = process.env.EXPO_PUBLIC_CHAT_ENDPOINT_URL ?? "/api/chat";
|
|
1791
1960
|
|
|
1792
1961
|
export function useAppRuntime() {
|
|
1793
1962
|
const transport = useMemo(
|
|
1794
|
-
() =>
|
|
1963
|
+
() =>
|
|
1964
|
+
new AssistantChatTransport({
|
|
1965
|
+
api: CHAT_API,
|
|
1966
|
+
...(shouldUseAnonymousSessionFetch(CHAT_API, Platform.OS)
|
|
1967
|
+
? { fetch: createAnonymousSessionFetch(CHAT_API) }
|
|
1968
|
+
: {}),
|
|
1969
|
+
}),
|
|
1795
1970
|
[],
|
|
1796
1971
|
);
|
|
1797
1972
|
return useChatRuntime({
|
|
@@ -1933,28 +2108,29 @@ module.exports = withAui(config);
|
|
|
1933
2108
|
"android": "expo run:android",
|
|
1934
2109
|
"ios": "expo run:ios",
|
|
1935
2110
|
"web": "expo start --web",
|
|
1936
|
-
"export:web": "expo export --platform web && node scripts/flatten-assets.mjs"
|
|
2111
|
+
"export:web": "expo export --platform web && node scripts/flatten-assets.mjs",
|
|
2112
|
+
"test": "vitest run"
|
|
1937
2113
|
},
|
|
1938
2114
|
"dependencies": {
|
|
1939
|
-
"@ai-sdk/openai": "^4.0.
|
|
1940
|
-
"@ai-sdk/react": "^4.0.
|
|
1941
|
-
"@assistant-ui/
|
|
2115
|
+
"@ai-sdk/openai": "^4.0.42",
|
|
2116
|
+
"@ai-sdk/react": "^4.0.69",
|
|
2117
|
+
"@assistant-ui/ai-sdk": "workspace:*",
|
|
1942
2118
|
"@assistant-ui/react-native": "workspace:*",
|
|
1943
2119
|
"@expo/vector-icons": "^15.1.1",
|
|
1944
2120
|
"@react-navigation/drawer": "7.9.4",
|
|
1945
2121
|
"@react-navigation/native": "7.1.33",
|
|
1946
|
-
"ai": "^7.0.
|
|
1947
|
-
"expo": "~57.0.
|
|
2122
|
+
"ai": "^7.0.66",
|
|
2123
|
+
"expo": "~57.0.16",
|
|
1948
2124
|
"expo-clipboard": "~57.0.1",
|
|
1949
|
-
"expo-constants": "~57.0.
|
|
2125
|
+
"expo-constants": "~57.0.14",
|
|
1950
2126
|
"expo-font": "~57.0.1",
|
|
1951
2127
|
"expo-haptics": "~57.0.1",
|
|
1952
|
-
"expo-image": "~57.0.
|
|
1953
|
-
"expo-image-picker": "~57.0.
|
|
1954
|
-
"expo-linking": "~57.0.
|
|
1955
|
-
"expo-router": "~57.0.
|
|
1956
|
-
"expo-server": "~57.0.
|
|
1957
|
-
"expo-splash-screen": "~57.0.
|
|
2128
|
+
"expo-image": "~57.0.3",
|
|
2129
|
+
"expo-image-picker": "~57.0.13",
|
|
2130
|
+
"expo-linking": "~57.0.6",
|
|
2131
|
+
"expo-router": "~57.0.16",
|
|
2132
|
+
"expo-server": "~57.0.3",
|
|
2133
|
+
"expo-splash-screen": "~57.0.8",
|
|
1958
2134
|
"expo-status-bar": "~57.0.1",
|
|
1959
2135
|
"expo-symbols": "^57.0.2",
|
|
1960
2136
|
"expo-system-ui": "~57.0.2",
|
|
@@ -1974,7 +2150,8 @@ module.exports = withAui(config);
|
|
|
1974
2150
|
"@babel/core": "^7.29.7",
|
|
1975
2151
|
"@types/react": "~19.2.18",
|
|
1976
2152
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
1977
|
-
"typescript-7": "npm:typescript@~7.0.2"
|
|
2153
|
+
"typescript-7": "npm:typescript@~7.0.2",
|
|
2154
|
+
"vitest": "^4.1.10"
|
|
1978
2155
|
},
|
|
1979
2156
|
"private": true
|
|
1980
2157
|
}
|
|
@@ -1988,7 +2165,7 @@ module.exports = withAui(config);
|
|
|
1988
2165
|
|
|
1989
2166
|
A native chat app built with [assistant-ui](https://www.assistant-ui.com) and [Expo](https://expo.dev). It runs on iOS, Android, and the web from a single codebase, and is styled to match the assistant-ui web kit: a clean, neutral, ChatGPT-grade look with subtle hairline borders.
|
|
1990
2167
|
|
|
1991
|
-
The chat is powered by `@assistant-ui/react-native` with the AI SDK runtime (`@assistant-ui/
|
|
2168
|
+
The chat is powered by `@assistant-ui/react-native` with the AI SDK runtime (`@assistant-ui/ai-sdk`). The example leans on native Expo APIs throughout:
|
|
1992
2169
|
|
|
1993
2170
|
- **SF Symbols** (`expo-symbols`) for native iconography on iOS, with a Material Icons fallback on Android and the web.
|
|
1994
2171
|
- **Haptics** (`expo-haptics`) for tactile feedback on send, stop, and selection.
|
|
@@ -2012,7 +2189,7 @@ It follows the assistant-ui component conventions: `MessagePrimitive.Parts` for
|
|
|
2012
2189
|
cp .env.example .env
|
|
2013
2190
|
```
|
|
2014
2191
|
|
|
2015
|
-
The bundled API route (`app/api/chat+api.ts`) needs `OPENAI_API_KEY`. To point the app at a separately hosted backend instead, set `EXPO_PUBLIC_CHAT_ENDPOINT_URL`.
|
|
2192
|
+
The bundled API route (`app/api/chat+api.ts`) needs `OPENAI_API_KEY`. To point the app at a separately hosted backend instead, set `EXPO_PUBLIC_CHAT_ENDPOINT_URL`. Browser deployments use `/api/anonymous-session` when the hosted backend supports it and otherwise send the request normally. Native deployments should use a backend intended for their app.
|
|
2016
2193
|
|
|
2017
2194
|
3. Start the app:
|
|
2018
2195
|
|
|
@@ -2060,7 +2237,7 @@ It follows the assistant-ui component conventions: `MessagePrimitive.Parts` for
|
|
|
2060
2237
|
{
|
|
2061
2238
|
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
2062
2239
|
"ignoreCommand": "bash ../../scripts/vercel-ignore-changeset-release.sh",
|
|
2063
|
-
"buildCommand": "cd ../.. && pnpm turbo build --filter=@assistant-ui/react-native --filter=@assistant-ui/
|
|
2240
|
+
"buildCommand": "cd ../.. && pnpm turbo build --filter=@assistant-ui/react-native --filter=@assistant-ui/ai-sdk --filter=@assistant-ui/metro && cd examples/with-expo && pnpm run export:web",
|
|
2064
2241
|
"outputDirectory": "dist",
|
|
2065
2242
|
"framework": null
|
|
2066
2243
|
}
|
|
@@ -324,8 +324,8 @@ export default withAui(nextConfig);
|
|
|
324
324
|
"@assistant-ui/ui": "workspace:*",
|
|
325
325
|
"class-variance-authority": "^0.7.1",
|
|
326
326
|
"clsx": "^2.1.1",
|
|
327
|
-
"lucide-react": "^1.
|
|
328
|
-
"next": "^16.3.
|
|
327
|
+
"lucide-react": "^1.33.0",
|
|
328
|
+
"next": "^16.3.2",
|
|
329
329
|
"react": "^19.2.8",
|
|
330
330
|
"react-dom": "^19.2.8",
|
|
331
331
|
"tailwind-merge": "^3.6.0"
|
|
@@ -334,9 +334,9 @@ export default withAui(nextConfig);
|
|
|
334
334
|
"@assistant-ui/next": "workspace:*",
|
|
335
335
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
336
336
|
"@tailwindcss/postcss": "^4.3.3",
|
|
337
|
-
"@types/node": "^26.
|
|
337
|
+
"@types/node": "^26.2.0",
|
|
338
338
|
"@types/react": "^19.2.18",
|
|
339
|
-
"@types/react-dom": "^19.2.
|
|
339
|
+
"@types/react-dom": "^19.2.5",
|
|
340
340
|
"postcss": "^8.5.26",
|
|
341
341
|
"tailwindcss": "^4.3.3",
|
|
342
342
|
"tw-animate-css": "^1.4.0",
|
|
@@ -386,7 +386,7 @@ npm run dev
|
|
|
386
386
|
## Related Documentation
|
|
387
387
|
|
|
388
388
|
- [assistant-ui Documentation](https://www.assistant-ui.com/docs)
|
|
389
|
-
- [External Store Runtime Guide](https://www.assistant-ui.com/docs/runtimes/external-store)
|
|
389
|
+
- [External Store Runtime Guide](https://www.assistant-ui.com/docs/runtimes/custom/external-store)
|
|
390
390
|
|
|
391
391
|
```
|
|
392
392
|
|
|
@@ -401,6 +401,7 @@ npm run dev
|
|
|
401
401
|
"@/components/assistant-ui/*": [
|
|
402
402
|
"../../packages/ui/src/components/assistant-ui/*"
|
|
403
403
|
],
|
|
404
|
+
"@/hooks/*": ["../../packages/ui/src/hooks/*"],
|
|
404
405
|
"@/components/ui/*": [
|
|
405
406
|
"../../packages/ui/src/components/ui/base/*",
|
|
406
407
|
"../../packages/ui/src/components/ui/radix/*"
|