@assistant-ui/mcp-docs-server 0.1.28 → 0.1.29
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 +6 -6
- package/.docs/organized/code-examples/with-a2a.md +7 -7
- package/.docs/organized/code-examples/with-ag-ui.md +8 -8
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +9 -9
- package/.docs/organized/code-examples/with-artifacts.md +9 -9
- package/.docs/organized/code-examples/with-assistant-transport.md +7 -7
- package/.docs/organized/code-examples/with-chain-of-thought.md +9 -9
- package/.docs/organized/code-examples/with-cloud-standalone.md +9 -9
- package/.docs/organized/code-examples/with-cloud.md +9 -9
- package/.docs/organized/code-examples/with-custom-thread-list.md +9 -9
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +11 -11
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +11 -11
- package/.docs/organized/code-examples/with-expo.md +17 -17
- package/.docs/organized/code-examples/with-external-store.md +7 -7
- package/.docs/organized/code-examples/with-ffmpeg.md +9 -9
- package/.docs/organized/code-examples/with-generative-ui.md +9 -9
- package/.docs/organized/code-examples/with-google-adk.md +7 -7
- package/.docs/organized/code-examples/with-heat-graph.md +6 -6
- package/.docs/organized/code-examples/with-interactables.md +9 -9
- package/.docs/organized/code-examples/with-langgraph.md +8 -8
- package/.docs/organized/code-examples/with-livekit.md +50 -14
- package/.docs/organized/code-examples/with-opencode.md +2394 -0
- package/.docs/organized/code-examples/with-parent-id-grouping.md +8 -8
- package/.docs/organized/code-examples/with-react-hook-form.md +9 -9
- package/.docs/organized/code-examples/with-react-ink.md +3 -3
- package/.docs/organized/code-examples/with-react-router.md +8 -8
- package/.docs/organized/code-examples/with-store.md +6 -6
- package/.docs/organized/code-examples/with-tanstack.md +10 -10
- package/.docs/organized/code-examples/with-tap-runtime.md +7 -7
- package/.docs/raw/docs/(docs)/guides/voice.mdx +10 -3
- package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +2 -2
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +38 -0
- package/.docs/raw/docs/runtimes/custom/local.mdx +65 -18
- package/.docs/raw/docs/runtimes/google-adk/index.mdx +62 -0
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +137 -1
- package/package.json +4 -4
|
@@ -474,28 +474,28 @@ export default nextConfig;
|
|
|
474
474
|
"start": "next start"
|
|
475
475
|
},
|
|
476
476
|
"dependencies": {
|
|
477
|
-
"@ai-sdk/openai": "^3.0.
|
|
477
|
+
"@ai-sdk/openai": "^3.0.52",
|
|
478
478
|
"@assistant-ui/react": "workspace:*",
|
|
479
479
|
"@assistant-ui/react-markdown": "workspace:*",
|
|
480
480
|
"@assistant-ui/ui": "workspace:*",
|
|
481
481
|
"class-variance-authority": "^0.7.1",
|
|
482
482
|
"clsx": "^2.1.1",
|
|
483
|
-
"lucide-react": "^1.
|
|
484
|
-
"next": "^16.2.
|
|
485
|
-
"react": "^19.2.
|
|
486
|
-
"react-dom": "^19.2.
|
|
483
|
+
"lucide-react": "^1.8.0",
|
|
484
|
+
"next": "^16.2.3",
|
|
485
|
+
"react": "^19.2.5",
|
|
486
|
+
"react-dom": "^19.2.5",
|
|
487
487
|
"tailwind-merge": "^3.5.0"
|
|
488
488
|
},
|
|
489
489
|
"devDependencies": {
|
|
490
490
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
491
491
|
"@tailwindcss/postcss": "^4.2.2",
|
|
492
|
-
"@types/node": "^25.
|
|
492
|
+
"@types/node": "^25.6.0",
|
|
493
493
|
"@types/react": "^19.2.14",
|
|
494
494
|
"@types/react-dom": "^19.2.3",
|
|
495
|
-
"postcss": "^8.5.
|
|
495
|
+
"postcss": "^8.5.9",
|
|
496
496
|
"tailwindcss": "^4.2.2",
|
|
497
497
|
"tw-animate-css": "^1.4.0",
|
|
498
|
-
"typescript": "
|
|
498
|
+
"typescript": "^6.0.2"
|
|
499
499
|
}
|
|
500
500
|
}
|
|
501
501
|
|
|
@@ -537,32 +537,32 @@ export default nextConfig;
|
|
|
537
537
|
"start": "next start"
|
|
538
538
|
},
|
|
539
539
|
"dependencies": {
|
|
540
|
-
"@ai-sdk/openai": "^3.0.
|
|
540
|
+
"@ai-sdk/openai": "^3.0.52",
|
|
541
541
|
"@assistant-ui/react": "workspace:*",
|
|
542
542
|
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
543
543
|
"@assistant-ui/react-hook-form": "workspace:*",
|
|
544
544
|
"@assistant-ui/react-markdown": "workspace:*",
|
|
545
545
|
"@assistant-ui/ui": "workspace:*",
|
|
546
|
-
"ai": "^6.0.
|
|
546
|
+
"ai": "^6.0.159",
|
|
547
547
|
"class-variance-authority": "^0.7.1",
|
|
548
548
|
"clsx": "^2.1.1",
|
|
549
|
-
"lucide-react": "^1.
|
|
550
|
-
"next": "^16.2.
|
|
551
|
-
"react": "^19.2.
|
|
552
|
-
"react-dom": "^19.2.
|
|
549
|
+
"lucide-react": "^1.8.0",
|
|
550
|
+
"next": "^16.2.3",
|
|
551
|
+
"react": "^19.2.5",
|
|
552
|
+
"react-dom": "^19.2.5",
|
|
553
553
|
"react-hook-form": "^7.72.1",
|
|
554
554
|
"tailwind-merge": "^3.5.0"
|
|
555
555
|
},
|
|
556
556
|
"devDependencies": {
|
|
557
557
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
558
558
|
"@tailwindcss/postcss": "^4.2.2",
|
|
559
|
-
"@types/node": "^25.
|
|
559
|
+
"@types/node": "^25.6.0",
|
|
560
560
|
"@types/react": "^19.2.14",
|
|
561
561
|
"@types/react-dom": "^19.2.3",
|
|
562
|
-
"postcss": "^8.5.
|
|
562
|
+
"postcss": "^8.5.9",
|
|
563
563
|
"tailwindcss": "^4.2.2",
|
|
564
564
|
"tw-animate-css": "^1.4.0",
|
|
565
|
-
"typescript": "
|
|
565
|
+
"typescript": "^6.0.2"
|
|
566
566
|
}
|
|
567
567
|
}
|
|
568
568
|
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@assistant-ui/react-ink": "workspace:*",
|
|
18
18
|
"@assistant-ui/react-ink-markdown": "workspace:*",
|
|
19
|
-
"ink": "^
|
|
20
|
-
"react": "^19.2.
|
|
19
|
+
"ink": "^7.0.0",
|
|
20
|
+
"react": "^19.2.5"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/react": "^19.2.14",
|
|
24
24
|
"esbuild": "^0.28.0",
|
|
25
25
|
"tsx": "^4.21.0",
|
|
26
|
-
"typescript": "
|
|
26
|
+
"typescript": "^6.0.2"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -777,11 +777,11 @@ export default function Home() {
|
|
|
777
777
|
"class-variance-authority": "^0.7.1",
|
|
778
778
|
"clsx": "^2.1.1",
|
|
779
779
|
"eventsource-parser": "^3.0.6",
|
|
780
|
-
"isbot": "^5.1.
|
|
781
|
-
"lucide-react": "^1.
|
|
782
|
-
"openai": "^6.
|
|
783
|
-
"react": "^19.2.
|
|
784
|
-
"react-dom": "^19.2.
|
|
780
|
+
"isbot": "^5.1.38",
|
|
781
|
+
"lucide-react": "^1.8.0",
|
|
782
|
+
"openai": "^6.34.0",
|
|
783
|
+
"react": "^19.2.5",
|
|
784
|
+
"react-dom": "^19.2.5",
|
|
785
785
|
"react-router": "^7.14.0",
|
|
786
786
|
"remark-gfm": "^4.0.1",
|
|
787
787
|
"tailwind-merge": "^3.5.0"
|
|
@@ -789,13 +789,13 @@ export default function Home() {
|
|
|
789
789
|
"devDependencies": {
|
|
790
790
|
"@react-router/dev": "^7.14.0",
|
|
791
791
|
"@tailwindcss/vite": "^4.2.2",
|
|
792
|
-
"@types/node": "^25.
|
|
792
|
+
"@types/node": "^25.6.0",
|
|
793
793
|
"@types/react": "^19.2.14",
|
|
794
794
|
"@types/react-dom": "^19.2.3",
|
|
795
795
|
"tailwindcss": "^4.2.2",
|
|
796
796
|
"tw-animate-css": "^1.4.0",
|
|
797
|
-
"typescript": "
|
|
798
|
-
"vite": "^8.0.
|
|
797
|
+
"typescript": "^6.0.2",
|
|
798
|
+
"vite": "^8.0.8",
|
|
799
799
|
"vite-tsconfig-paths": "^6.1.1"
|
|
800
800
|
}
|
|
801
801
|
}
|
|
@@ -488,20 +488,20 @@ export default nextConfig;
|
|
|
488
488
|
"dependencies": {
|
|
489
489
|
"@assistant-ui/store": "workspace:*",
|
|
490
490
|
"@assistant-ui/tap": "workspace:*",
|
|
491
|
-
"next": "^16.2.
|
|
492
|
-
"react": "^19.2.
|
|
493
|
-
"react-dom": "^19.2.
|
|
491
|
+
"next": "^16.2.3",
|
|
492
|
+
"react": "^19.2.5",
|
|
493
|
+
"react-dom": "^19.2.5"
|
|
494
494
|
},
|
|
495
495
|
"devDependencies": {
|
|
496
496
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
497
497
|
"@tailwindcss/postcss": "^4.2.2",
|
|
498
|
-
"@types/node": "^25.
|
|
498
|
+
"@types/node": "^25.6.0",
|
|
499
499
|
"@types/react": "^19.2.14",
|
|
500
500
|
"@types/react-dom": "^19.2.3",
|
|
501
|
-
"postcss": "^8.5.
|
|
501
|
+
"postcss": "^8.5.9",
|
|
502
502
|
"tailwindcss": "^4.2.2",
|
|
503
503
|
"tw-animate-css": "^1.4.0",
|
|
504
|
-
"typescript": "
|
|
504
|
+
"typescript": "^6.0.2"
|
|
505
505
|
}
|
|
506
506
|
}
|
|
507
507
|
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"@assistant-ui/react": "workspace:*",
|
|
66
66
|
"@assistant-ui/react-markdown": "workspace:*",
|
|
67
67
|
"@tailwindcss/vite": "^4.2.2",
|
|
68
|
-
"@tanstack/react-router": "^1.168.
|
|
69
|
-
"@tanstack/react-start": "^1.167.
|
|
68
|
+
"@tanstack/react-router": "^1.168.19",
|
|
69
|
+
"@tanstack/react-start": "^1.167.35",
|
|
70
70
|
"class-variance-authority": "^0.7.1",
|
|
71
71
|
"clsx": "^2.1.1",
|
|
72
|
-
"lucide-react": "^1.
|
|
73
|
-
"nitro": "^3.0.
|
|
74
|
-
"openai": "^6.
|
|
75
|
-
"react": "^19.2.
|
|
76
|
-
"react-dom": "^19.2.
|
|
72
|
+
"lucide-react": "^1.8.0",
|
|
73
|
+
"nitro": "^3.0.260311-beta",
|
|
74
|
+
"openai": "^6.34.0",
|
|
75
|
+
"react": "^19.2.5",
|
|
76
|
+
"react-dom": "^19.2.5",
|
|
77
77
|
"remark-gfm": "^4.0.1",
|
|
78
78
|
"tailwind-merge": "^3.5.0",
|
|
79
79
|
"tailwindcss": "^4.2.2",
|
|
@@ -81,12 +81,12 @@
|
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
84
|
-
"@types/node": "^25.
|
|
84
|
+
"@types/node": "^25.6.0",
|
|
85
85
|
"@types/react": "^19.2.14",
|
|
86
86
|
"@types/react-dom": "^19.2.3",
|
|
87
87
|
"@vitejs/plugin-react": "^6.0.1",
|
|
88
|
-
"typescript": "
|
|
89
|
-
"vite": "^8.0.
|
|
88
|
+
"typescript": "^6.0.2",
|
|
89
|
+
"vite": "^8.0.8"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -597,22 +597,22 @@ export default nextConfig;
|
|
|
597
597
|
"@assistant-ui/ui": "workspace:*",
|
|
598
598
|
"class-variance-authority": "^0.7.1",
|
|
599
599
|
"clsx": "^2.1.1",
|
|
600
|
-
"lucide-react": "^1.
|
|
601
|
-
"next": "^16.2.
|
|
602
|
-
"react": "^19.2.
|
|
603
|
-
"react-dom": "^19.2.
|
|
600
|
+
"lucide-react": "^1.8.0",
|
|
601
|
+
"next": "^16.2.3",
|
|
602
|
+
"react": "^19.2.5",
|
|
603
|
+
"react-dom": "^19.2.5",
|
|
604
604
|
"tailwind-merge": "^3.5.0"
|
|
605
605
|
},
|
|
606
606
|
"devDependencies": {
|
|
607
607
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
608
608
|
"@tailwindcss/postcss": "^4.2.2",
|
|
609
|
-
"@types/node": "^25.
|
|
609
|
+
"@types/node": "^25.6.0",
|
|
610
610
|
"@types/react": "^19.2.14",
|
|
611
611
|
"@types/react-dom": "^19.2.3",
|
|
612
|
-
"postcss": "^8.5.
|
|
612
|
+
"postcss": "^8.5.9",
|
|
613
613
|
"tailwindcss": "^4.2.2",
|
|
614
614
|
"tw-animate-css": "^1.4.0",
|
|
615
|
-
"typescript": "
|
|
615
|
+
"typescript": "^6.0.2"
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
|
|
@@ -303,14 +303,21 @@ const runtime = useChatRuntime({
|
|
|
303
303
|
|
|
304
304
|
## Example: LiveKit
|
|
305
305
|
|
|
306
|
-
[LiveKit](https://livekit.io/) provides realtime voice via WebRTC rooms with transcription support.
|
|
306
|
+
[LiveKit](https://livekit.io/) provides realtime voice via WebRTC rooms with transcription support. Unlike fully-hosted agent services, LiveKit follows a "bring-your-own-agent" model: the browser adapter only joins a room, and you run a separate **agent worker** that joins the same room and handles STT, LLM, and TTS. Without an agent in the room, the client will connect successfully but have nothing to talk to.
|
|
307
|
+
|
|
308
|
+
### Prerequisites
|
|
309
|
+
|
|
310
|
+
1. **A LiveKit server** — create a [LiveKit Cloud](https://cloud.livekit.io/) project (grab the URL, API Key, and API Secret from the project settings) or self-host `livekit-server`.
|
|
311
|
+
2. **An agent worker** — built with the [LiveKit Agents SDK](https://docs.livekit.io/agents/) (Python or Node). The worker connects to your LiveKit server and is automatically dispatched into new rooms.
|
|
307
312
|
|
|
308
313
|
### Install Dependencies
|
|
309
314
|
|
|
310
315
|
```bash
|
|
311
|
-
npm install livekit-client
|
|
316
|
+
npm install livekit-client livekit-server-sdk
|
|
312
317
|
```
|
|
313
318
|
|
|
319
|
+
`livekit-client` powers the browser adapter; `livekit-server-sdk` is used server-side to mint access tokens.
|
|
320
|
+
|
|
314
321
|
### Usage
|
|
315
322
|
|
|
316
323
|
```tsx
|
|
@@ -330,4 +337,4 @@ const runtime = useChatRuntime({
|
|
|
330
337
|
});
|
|
331
338
|
```
|
|
332
339
|
|
|
333
|
-
See the `examples/with-livekit
|
|
340
|
+
See the [`with-livekit` example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-livekit) for a complete implementation: the browser adapter, the token endpoint, and a minimal Python agent worker using the OpenAI Realtime API.
|
|
@@ -238,12 +238,12 @@ const aui = useAui();
|
|
|
238
238
|
|
|
239
239
|
const history = useMemo<ThreadHistoryAdapter>(
|
|
240
240
|
() => ({
|
|
241
|
-
async append(message) {
|
|
241
|
+
async append({ message, parentId }) {
|
|
242
242
|
// Wait for initialization to complete and get the remoteId
|
|
243
243
|
const { remoteId } = await aui.threadListItem().initialize();
|
|
244
244
|
|
|
245
245
|
// Now safe to save the message using the remoteId
|
|
246
|
-
await saveMessageToDatabase(remoteId, message);
|
|
246
|
+
await saveMessageToDatabase(remoteId, parentId, message);
|
|
247
247
|
},
|
|
248
248
|
// ...
|
|
249
249
|
}),
|
|
@@ -424,6 +424,44 @@ const onEdit = async (message: AppendMessage) => {
|
|
|
424
424
|
};
|
|
425
425
|
```
|
|
426
426
|
|
|
427
|
+
### Branching Support
|
|
428
|
+
|
|
429
|
+
The `messages` array path assumes a linear conversation — each message's parent is the previous message. To support branching (e.g. regenerating responses creates alternative branches), use `ExportedMessageRepository.fromBranchableArray()` combined with `thread.import()`.
|
|
430
|
+
|
|
431
|
+
Each message must have an explicit `id` and `parentId`. Messages with the same `parentId` create branches:
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
import {
|
|
435
|
+
ExportedMessageRepository,
|
|
436
|
+
useExternalStoreRuntime,
|
|
437
|
+
} from "@assistant-ui/react";
|
|
438
|
+
|
|
439
|
+
// Your messages from the backend, each with an id and parentId
|
|
440
|
+
const backendMessages = [
|
|
441
|
+
{ id: "user-1", role: "user", content: "Hello", parentId: null },
|
|
442
|
+
{ id: "asst-1", role: "assistant", content: "Hi!", parentId: "user-1" },
|
|
443
|
+
// A second response to the same user message = a branch
|
|
444
|
+
{ id: "asst-2", role: "assistant", content: "Hey!", parentId: "user-1" },
|
|
445
|
+
];
|
|
446
|
+
|
|
447
|
+
// Convert to ExportedMessageRepository
|
|
448
|
+
const repo = ExportedMessageRepository.fromBranchableArray(
|
|
449
|
+
backendMessages.map((m) => ({
|
|
450
|
+
message: { id: m.id, role: m.role, content: m.content },
|
|
451
|
+
parentId: m.parentId,
|
|
452
|
+
})),
|
|
453
|
+
{ headId: "asst-1" }, // which branch to display initially
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
// Import into the runtime
|
|
457
|
+
runtime.thread.import(repo);
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
<Callout type="warn">
|
|
461
|
+
Messages in the array must be ordered so that parents appear before their
|
|
462
|
+
children. Each message **must** have an `id` field set.
|
|
463
|
+
</Callout>
|
|
464
|
+
|
|
427
465
|
### Tool Calling
|
|
428
466
|
|
|
429
467
|
Support tool calls with proper result handling:
|
|
@@ -501,26 +501,69 @@ export function MyRuntimeProvider({ children }) {
|
|
|
501
501
|
const { remoteId } = aui.threadListItem().getState();
|
|
502
502
|
if (!remoteId) return { messages: [] };
|
|
503
503
|
|
|
504
|
-
const
|
|
504
|
+
const rows = await db.messages.findByThreadId(remoteId);
|
|
505
505
|
return {
|
|
506
|
-
messages:
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
506
|
+
messages: rows.map((row) => {
|
|
507
|
+
const common = {
|
|
508
|
+
id: row.id,
|
|
509
|
+
createdAt: new Date(row.createdAt),
|
|
510
|
+
};
|
|
511
|
+
// `content` is stored as JSON — parse back into message parts
|
|
512
|
+
const content = JSON.parse(row.content);
|
|
513
|
+
|
|
514
|
+
if (row.role === "user") {
|
|
515
|
+
return {
|
|
516
|
+
parentId: row.parentId,
|
|
517
|
+
message: {
|
|
518
|
+
...common,
|
|
519
|
+
role: "user" as const,
|
|
520
|
+
content,
|
|
521
|
+
attachments: [],
|
|
522
|
+
metadata: { custom: {} },
|
|
523
|
+
},
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
if (row.role === "assistant") {
|
|
527
|
+
return {
|
|
528
|
+
parentId: row.parentId,
|
|
529
|
+
message: {
|
|
530
|
+
...common,
|
|
531
|
+
role: "assistant" as const,
|
|
532
|
+
content,
|
|
533
|
+
status: { type: "complete", reason: "stop" } as const,
|
|
534
|
+
metadata: {
|
|
535
|
+
custom: {},
|
|
536
|
+
unstable_state: null,
|
|
537
|
+
unstable_annotations: [],
|
|
538
|
+
unstable_data: [],
|
|
539
|
+
steps: [],
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
return {
|
|
545
|
+
parentId: row.parentId,
|
|
546
|
+
message: {
|
|
547
|
+
...common,
|
|
548
|
+
role: "system" as const,
|
|
549
|
+
content,
|
|
550
|
+
metadata: { custom: {} },
|
|
551
|
+
},
|
|
552
|
+
};
|
|
553
|
+
}),
|
|
512
554
|
};
|
|
513
555
|
},
|
|
514
556
|
|
|
515
|
-
async append(message) {
|
|
557
|
+
async append({ message, parentId }) {
|
|
516
558
|
// Wait for initialization to get remoteId (safe to call multiple times)
|
|
517
559
|
const { remoteId } = await aui.threadListItem().initialize();
|
|
518
560
|
|
|
519
561
|
await db.messages.create({
|
|
520
562
|
threadId: remoteId,
|
|
521
|
-
|
|
522
|
-
content: message.content,
|
|
563
|
+
parentId,
|
|
523
564
|
id: message.id,
|
|
565
|
+
role: message.role,
|
|
566
|
+
content: JSON.stringify(message.content),
|
|
524
567
|
createdAt: message.createdAt,
|
|
525
568
|
});
|
|
526
569
|
},
|
|
@@ -584,10 +627,10 @@ const aui = useAui();
|
|
|
584
627
|
|
|
585
628
|
const history = useMemo<ThreadHistoryAdapter>(
|
|
586
629
|
() => ({
|
|
587
|
-
async append(message) {
|
|
630
|
+
async append({ message, parentId }) {
|
|
588
631
|
// Wait for initialization - safe to call multiple times
|
|
589
632
|
const { remoteId } = await aui.threadListItem().initialize();
|
|
590
|
-
await db.messages.create({ threadId: remoteId, ...message });
|
|
633
|
+
await db.messages.create({ threadId: remoteId, parentId, ...message });
|
|
591
634
|
},
|
|
592
635
|
// ...
|
|
593
636
|
}),
|
|
@@ -613,8 +656,9 @@ interface ThreadRecord {
|
|
|
613
656
|
interface MessageRecord {
|
|
614
657
|
id: string;
|
|
615
658
|
threadId: string;
|
|
659
|
+
parentId: string | null;
|
|
616
660
|
role: "user" | "assistant" | "system";
|
|
617
|
-
content:
|
|
661
|
+
content: string; // JSON-encoded message content parts
|
|
618
662
|
createdAt: Date;
|
|
619
663
|
}
|
|
620
664
|
```
|
|
@@ -693,18 +737,21 @@ Persist and resume conversations:
|
|
|
693
737
|
```tsx
|
|
694
738
|
const historyAdapter: ThreadHistoryAdapter = {
|
|
695
739
|
async load() {
|
|
696
|
-
// Load messages from your storage
|
|
740
|
+
// Load messages from your storage.
|
|
741
|
+
// The API must return `{ messages: { parentId, message }[] }`
|
|
742
|
+
// where each `message` is a full ThreadMessage
|
|
743
|
+
// (including `metadata.custom`, plus `attachments` on user messages
|
|
744
|
+
// and `status` + the rest of `metadata` on assistant messages).
|
|
697
745
|
const response = await fetch(`/api/thread/current`);
|
|
698
|
-
|
|
699
|
-
return { messages };
|
|
746
|
+
return await response.json();
|
|
700
747
|
},
|
|
701
748
|
|
|
702
|
-
async append(message) {
|
|
749
|
+
async append({ message, parentId }) {
|
|
703
750
|
// Save new message to storage
|
|
704
751
|
await fetch(`/api/thread/messages`, {
|
|
705
752
|
method: "POST",
|
|
706
753
|
headers: { "Content-Type": "application/json" },
|
|
707
|
-
body: JSON.stringify({ message }),
|
|
754
|
+
body: JSON.stringify({ message, parentId }),
|
|
708
755
|
});
|
|
709
756
|
},
|
|
710
757
|
|
|
@@ -317,6 +317,64 @@ function AuthUI() {
|
|
|
317
317
|
|
|
318
318
|
`AdkAuthCredential` supports all ADK auth types: `apiKey`, `http`, `oauth2`, `openIdConnect`, `serviceAccount`.
|
|
319
319
|
|
|
320
|
+
### Input Requests
|
|
321
|
+
|
|
322
|
+
When an ADK Python 2.0+ Workflow's `RequestInput` node pauses execution to ask the user a question, ADK emits an `adk_request_input` function call marked as long-running. Respond with `useAdkSubmitInput` inside a tool UI — the helper wraps the answer as `{ result }` to match ADK's `unwrap_response` contract, so the Workflow node resumes with the unwrapped value:
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
import { makeAssistantToolUI } from "@assistant-ui/react";
|
|
326
|
+
import { useAdkSubmitInput } from "@assistant-ui/react-google-adk";
|
|
327
|
+
|
|
328
|
+
type RequestInputArgs = {
|
|
329
|
+
interrupt_id?: string;
|
|
330
|
+
message?: string;
|
|
331
|
+
payload?: unknown;
|
|
332
|
+
response_schema?: unknown;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
export const RequestInputToolUI = makeAssistantToolUI<RequestInputArgs, unknown>({
|
|
336
|
+
toolName: "adk_request_input",
|
|
337
|
+
render: function RequestInputUI({ toolCallId, args, result }) {
|
|
338
|
+
const submitInput = useAdkSubmitInput();
|
|
339
|
+
|
|
340
|
+
if (result !== undefined) {
|
|
341
|
+
return <p>Answered: {String(result)}</p>;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return (
|
|
345
|
+
<form
|
|
346
|
+
onSubmit={(e) => {
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
const value = (
|
|
349
|
+
e.currentTarget.elements.namedItem("answer") as HTMLInputElement
|
|
350
|
+
).value;
|
|
351
|
+
submitInput(toolCallId, value);
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
<p>{args.message ?? "Please provide input:"}</p>
|
|
355
|
+
<input name="answer" autoFocus />
|
|
356
|
+
<button type="submit">Submit</button>
|
|
357
|
+
</form>
|
|
358
|
+
);
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Register the tool UI inside `AssistantRuntimeProvider`:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
367
|
+
<RequestInputToolUI />
|
|
368
|
+
<Thread />
|
|
369
|
+
</AssistantRuntimeProvider>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
<Callout type="info">
|
|
373
|
+
`adk_request_input` is emitted only by ADK Python 2.0+ Workflow `RequestInput` nodes — ADK JS has no equivalent. Always respond via a tool UI with `useAdkSubmitInput`; HITL interrupts are automatically exempt from `autoCancelPendingToolCalls`, so typing a normal message in the composer will not overwrite the pending interrupt.
|
|
374
|
+
</Callout>
|
|
375
|
+
|
|
376
|
+
`useAdkSubmitInput` is sugar over the generic `addResult` — if you prefer, you can call `addResult({ result: value })` from inside the render function directly. The `{ result }` wrapper is required either way: the adapter JSON-stringifies the value before sending, and ADK's `unwrap_response` unwraps it on the backend before the Workflow node resumes.
|
|
377
|
+
|
|
320
378
|
### Artifacts
|
|
321
379
|
|
|
322
380
|
Track file artifacts created or modified by the agent:
|
|
@@ -384,6 +442,8 @@ function PendingToolsIndicator() {
|
|
|
384
442
|
}
|
|
385
443
|
```
|
|
386
444
|
|
|
445
|
+
This hook reports every tool call ADK marked via `long_running_tool_ids`, including HITL interrupts. To respond to a specific HITL type, see [Tool Confirmations](#tool-confirmations), [Auth Requests](#auth-requests), or [Input Requests](#input-requests).
|
|
446
|
+
|
|
387
447
|
### Per-Message Metadata
|
|
388
448
|
|
|
389
449
|
Access grounding, citation, and token usage metadata per message:
|
|
@@ -581,6 +641,7 @@ The resolved `checkpointId` is passed to your `stream` callback via `config.chec
|
|
|
581
641
|
| `useAdkSend()` | Send raw ADK messages |
|
|
582
642
|
| `useAdkConfirmTool()` | Confirm or deny a pending tool confirmation |
|
|
583
643
|
| `useAdkSubmitAuth()` | Submit auth credentials for a pending auth request |
|
|
644
|
+
| `useAdkSubmitInput()` | Submit the user's answer for a pending `adk_request_input` HITL interrupt |
|
|
584
645
|
| `useAdkToolConfirmations()` | Pending tool confirmation requests |
|
|
585
646
|
| `useAdkAuthRequests()` | Pending auth credential requests |
|
|
586
647
|
| `useAdkLongRunningToolIds()` | IDs of long-running tools awaiting input |
|
|
@@ -596,6 +657,7 @@ The resolved `checkpointId` is passed to your `stream` callback via `config.chec
|
|
|
596
657
|
| Tool calls & results | Supported |
|
|
597
658
|
| Tool confirmations (`useAdkConfirmTool`) | Supported |
|
|
598
659
|
| Auth credential flow (`useAdkSubmitAuth`) | Supported |
|
|
660
|
+
| Workflow input requests (`useAdkSubmitInput`, ADK Python 2.0+) | Supported |
|
|
599
661
|
| Multi-agent (author/branch tracking) | Supported |
|
|
600
662
|
| Agent transfer events | Supported |
|
|
601
663
|
| Escalation detection | Supported |
|