-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtool-call-renderer-demo.tsx
More file actions
129 lines (119 loc) · 4.13 KB
/
Copy pathtool-call-renderer-demo.tsx
File metadata and controls
129 lines (119 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"use client";
import {
AssistantRuntimeProvider,
MessagePrimitive,
ThreadPrimitive,
useLocalRuntime,
} from "@assistant-ui/react";
import { ToolCallRenderer } from "@assistant-ui/chords";
import { DemoWrapper } from "./demo-wrapper";
import type { ChatModelAdapter } from "@assistant-ui/react";
import { FC } from "react";
let callCount = 0;
const demoAdapter: ChatModelAdapter = {
async *run({ abortSignal }) {
callCount++;
const toolCallId = `call_${callCount}`;
// Phase 1: tool call running
yield {
content: [
{
type: "tool-call" as const,
toolCallId,
toolName: "get_weather",
args: { location: "Paris, France", units: "celsius" },
argsText: JSON.stringify({
location: "Paris, France",
units: "celsius",
}),
},
],
};
await new Promise((r) => setTimeout(r, 1000));
if (abortSignal.aborted) return;
// Phase 2: tool call complete + text
yield {
content: [
{
type: "tool-call" as const,
toolCallId,
toolName: "get_weather",
args: { location: "Paris, France", units: "celsius" },
argsText: JSON.stringify({
location: "Paris, France",
units: "celsius",
}),
result: { temperature: 22, condition: "Sunny", humidity: "45%" },
},
{
type: "text" as const,
text: "The weather in Paris is 22°C and sunny.",
},
],
};
},
};
export function ToolCallRendererDemo() {
const runtime = useLocalRuntime(demoAdapter);
return (
<DemoWrapper>
<AssistantRuntimeProvider runtime={runtime}>
{/* <ThreadPrimitive.Root className="flex h-87.5 flex-col rounded-xl border border-zinc-800 bg-zinc-950 text-white">
*/}
<ThreadPrimitive.Root className="flex h-87.5 flex-col rounded-xl border border-zinc-400 dark:border-zinc-800 bg-white text-zinc-900 dark:bg-zinc-950 dark:text-white px-8">
<div className="relative min-h-0 flex-1">
<ThreadPrimitive.Viewport className="flex h-full flex-col gap-2 overflow-y-auto px-4 pt-4 pb-4">
<ThreadPrimitive.Messages
components={{
UserMessage: DemoUserMessage,
AssistantMessage: DemoAssistantMessage,
}}
/>
</ThreadPrimitive.Viewport>
</div>
<div className="border-t border-zinc-300 dark:border-zinc-800 px-4 py-2">
<ThreadPrimitive.If running={false}>
<ThreadPrimitive.Suggestion
prompt="What's the weather in Paris?"
send
className="w-full rounded-lg dark:bg-white/5 bg-black/10 px-3 py-2 text-left text-sm dark:text-white/60 text-black dark:hover:bg-white/10 hover:bg-black/15 transition-colors"
>
Send a message to trigger the tool call demo
</ThreadPrimitive.Suggestion>
</ThreadPrimitive.If>
</div>
</ThreadPrimitive.Root>
</AssistantRuntimeProvider>
</DemoWrapper>
);
}
const DemoUserMessage: FC = () => {
return (
<MessagePrimitive.Root className="group/message mx-auto flex w-full max-w-3xl flex-col items-end gap-1">
<div className="max-w-[80%] rounded-3xl bg-zinc-100 px-5 text-zinc-900 dark:bg-white/10 dark:text-white/90">
<MessagePrimitive.Content />
</div>
</MessagePrimitive.Root>
);
};
function DemoAssistantMessage() {
return (
<MessagePrimitive.Root className="group/message mx-auto flex w-full max-w-3xl gap-3 ">
<div className="flex mt-2.5 size-8 shrink-0 items-center justify-center rounded-full border border-zinc-300 text-xs shadow dark:border-white/15">
A
</div>
<div className="flex-1 pt-0.5 pr-64">
<MessagePrimitive.Parts
components={{
Text: ({ text }) => (
<span className="text-sm dark:text-white/90 text-black">
{text}
</span>
),
tools: { Fallback: ToolCallRenderer },
}}
/>
</div>
</MessagePrimitive.Root>
);
}