@applica-software-guru/persona-chat-sdk 0.1.102
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/.eslintrc.cjs +11 -0
- package/.github/copilot-instructions.md +3 -0
- package/.nvmrc +1 -0
- package/.prettierignore +5 -0
- package/.prettierrc +8 -0
- package/CLAUDE.md +3 -0
- package/GEMINI.md +3 -0
- package/README.md +33 -0
- package/bitbucket-pipelines.yml +19 -0
- package/components.json +24 -0
- package/dist/bundle.cjs.js +28 -0
- package/dist/bundle.cjs.js.map +1 -0
- package/dist/bundle.es.js +5173 -0
- package/dist/bundle.es.js.map +1 -0
- package/dist/bundle.iife.js +28 -0
- package/dist/bundle.iife.js.map +1 -0
- package/dist/bundle.umd.js +28 -0
- package/dist/bundle.umd.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/logging.d.ts +18 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/messages.d.ts +9 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/projects.d.ts +17 -0
- package/dist/projects.d.ts.map +1 -0
- package/dist/protocol/base.d.ts +25 -0
- package/dist/protocol/base.d.ts.map +1 -0
- package/dist/protocol/index.d.ts +6 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/rest.d.ts +25 -0
- package/dist/protocol/rest.d.ts.map +1 -0
- package/dist/protocol/transaction.d.ts +56 -0
- package/dist/protocol/transaction.d.ts.map +1 -0
- package/dist/protocol/webrtc.d.ts +60 -0
- package/dist/protocol/webrtc.d.ts.map +1 -0
- package/dist/protocol/websocket.d.ts +22 -0
- package/dist/protocol/websocket.d.ts.map +1 -0
- package/dist/runtime/context.d.ts +34 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/file-attachment-adapter.d.ts +15 -0
- package/dist/runtime/file-attachment-adapter.d.ts.map +1 -0
- package/dist/runtime/handlers.d.ts +21 -0
- package/dist/runtime/handlers.d.ts.map +1 -0
- package/dist/runtime/listeners.d.ts +6 -0
- package/dist/runtime/listeners.d.ts.map +1 -0
- package/dist/runtime/protocols.d.ts +17 -0
- package/dist/runtime/protocols.d.ts.map +1 -0
- package/dist/runtime/threads.d.ts +34 -0
- package/dist/runtime/threads.d.ts.map +1 -0
- package/dist/runtime/utils.d.ts +10 -0
- package/dist/runtime/utils.d.ts.map +1 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/storage/base.d.ts +9 -0
- package/dist/storage/base.d.ts.map +1 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/persona.d.ts +29 -0
- package/dist/storage/persona.d.ts.map +1 -0
- package/dist/tools.d.ts +72 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/types.d.ts +237 -0
- package/dist/types.d.ts.map +1 -0
- package/docs/README.md +13 -0
- package/docs/api-reference.md +16 -0
- package/docs/contributing.md +21 -0
- package/docs/customization.md +74 -0
- package/docs/features.md +7 -0
- package/docs/installation.md +9 -0
- package/docs/messages.md +214 -0
- package/docs/protocols.md +39 -0
- package/docs/transactions.md +121 -0
- package/docs/usage.md +40 -0
- package/jsconfig.node.json +10 -0
- package/package.json +82 -0
- package/playground/index.html +14 -0
- package/playground/src/app.tsx +10 -0
- package/playground/src/chat.tsx +117 -0
- package/playground/src/components/assistant-ui/assistant-modal.tsx +57 -0
- package/playground/src/components/assistant-ui/attachment.tsx +197 -0
- package/playground/src/components/assistant-ui/markdown-text.tsx +228 -0
- package/playground/src/components/assistant-ui/thread-list.tsx +91 -0
- package/playground/src/components/assistant-ui/thread.tsx +302 -0
- package/playground/src/components/assistant-ui/threadlist-sidebar.tsx +59 -0
- package/playground/src/components/assistant-ui/tool-fallback.tsx +93 -0
- package/playground/src/components/assistant-ui/tooltip-icon-button.tsx +42 -0
- package/playground/src/components/chat/logging.tsx +53 -0
- package/playground/src/components/ui/avatar.tsx +51 -0
- package/playground/src/components/ui/button.tsx +60 -0
- package/playground/src/components/ui/dialog.tsx +141 -0
- package/playground/src/components/ui/input.tsx +21 -0
- package/playground/src/components/ui/separator.tsx +26 -0
- package/playground/src/components/ui/sheet.tsx +139 -0
- package/playground/src/components/ui/sidebar.tsx +619 -0
- package/playground/src/components/ui/skeleton.tsx +13 -0
- package/playground/src/components/ui/tooltip.tsx +59 -0
- package/playground/src/hooks/theme.ts +70 -0
- package/playground/src/hooks/use-mobile.ts +19 -0
- package/playground/src/lib/utils.ts +6 -0
- package/playground/src/main.tsx +10 -0
- package/playground/src/styles.css +120 -0
- package/playground/src/tools.ts +149 -0
- package/playground/src/vite-env.d.ts +1 -0
- package/preview-build.sh +23 -0
- package/src/index.ts +7 -0
- package/src/logging.ts +34 -0
- package/src/messages.ts +202 -0
- package/src/projects.ts +57 -0
- package/src/protocol/base.ts +73 -0
- package/src/protocol/index.ts +5 -0
- package/src/protocol/rest.ts +107 -0
- package/src/protocol/transaction.ts +182 -0
- package/src/protocol/webrtc.ts +379 -0
- package/src/protocol/websocket.ts +111 -0
- package/src/runtime/context.ts +88 -0
- package/src/runtime/file-attachment-adapter.ts +48 -0
- package/src/runtime/handlers.ts +322 -0
- package/src/runtime/index.ts +6 -0
- package/src/runtime/listeners.ts +79 -0
- package/src/runtime/protocols.ts +169 -0
- package/src/runtime/threads.ts +105 -0
- package/src/runtime/utils.ts +46 -0
- package/src/runtime.tsx +334 -0
- package/src/storage/base.ts +13 -0
- package/src/storage/index.ts +2 -0
- package/src/storage/persona.ts +138 -0
- package/src/tools.ts +211 -0
- package/src/types.ts +284 -0
- package/tsconfig.json +36 -0
- package/tsconfig.node.json +15 -0
- package/vite.config.ts +74 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { ArrowDownIcon, ArrowUpIcon, CheckIcon, CopyIcon, RefreshCwIcon, Square } from 'lucide-react';
|
|
2
|
+
|
|
3
|
+
import { ActionBarPrimitive, ComposerPrimitive, ErrorPrimitive, MessagePrimitive, ThreadPrimitive } from '@assistant-ui/react';
|
|
4
|
+
|
|
5
|
+
import type { FC } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Button } from '@/components/ui/button';
|
|
8
|
+
import { MarkdownText } from '@/components/assistant-ui/markdown-text';
|
|
9
|
+
import { ToolFallback } from '@/components/assistant-ui/tool-fallback';
|
|
10
|
+
import { TooltipIconButton } from '@/components/assistant-ui/tooltip-icon-button';
|
|
11
|
+
import { ComposerAddAttachment, ComposerAttachments, UserMessageAttachments } from '@/components/assistant-ui/attachment';
|
|
12
|
+
|
|
13
|
+
export const Thread: FC = () => {
|
|
14
|
+
return (
|
|
15
|
+
<ThreadPrimitive.Root
|
|
16
|
+
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
|
|
17
|
+
style={{
|
|
18
|
+
['--thread-max-width' as string]: '44rem',
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
<ThreadPrimitive.Viewport
|
|
22
|
+
turnAnchor="top"
|
|
23
|
+
className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
|
|
24
|
+
>
|
|
25
|
+
<ThreadPrimitive.If empty>
|
|
26
|
+
<ThreadWelcome />
|
|
27
|
+
</ThreadPrimitive.If>
|
|
28
|
+
|
|
29
|
+
<ThreadPrimitive.Messages
|
|
30
|
+
components={{
|
|
31
|
+
UserMessage,
|
|
32
|
+
EditComposer,
|
|
33
|
+
AssistantMessage,
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
<ThreadPrimitive.ViewportFooter className="aui-thread-viewport-footer sticky bottom-0 mx-auto mt-4 flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6">
|
|
38
|
+
<ThreadScrollToBottom />
|
|
39
|
+
<Composer />
|
|
40
|
+
</ThreadPrimitive.ViewportFooter>
|
|
41
|
+
</ThreadPrimitive.Viewport>
|
|
42
|
+
</ThreadPrimitive.Root>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const ThreadScrollToBottom: FC = () => {
|
|
47
|
+
return (
|
|
48
|
+
<ThreadPrimitive.ScrollToBottom asChild>
|
|
49
|
+
<TooltipIconButton
|
|
50
|
+
tooltip="Scroll to bottom"
|
|
51
|
+
variant="outline"
|
|
52
|
+
className="aui-thread-scroll-to-bottom -top-12 absolute z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent"
|
|
53
|
+
>
|
|
54
|
+
<ArrowDownIcon />
|
|
55
|
+
</TooltipIconButton>
|
|
56
|
+
</ThreadPrimitive.ScrollToBottom>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const ThreadWelcome: FC = () => {
|
|
61
|
+
return (
|
|
62
|
+
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
|
|
63
|
+
<div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
|
|
64
|
+
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-8">
|
|
65
|
+
<div className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-2 animate-in font-semibold text-2xl duration-300 ease-out">
|
|
66
|
+
Hello there!
|
|
67
|
+
</div>
|
|
68
|
+
<div className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-2 animate-in text-2xl text-muted-foreground/65 delay-100 duration-300 ease-out">
|
|
69
|
+
How can I help you today?
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<ThreadSuggestions />
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const ThreadSuggestions: FC = () => {
|
|
79
|
+
return (
|
|
80
|
+
<div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
|
|
81
|
+
{[
|
|
82
|
+
{
|
|
83
|
+
title: "What's the weather",
|
|
84
|
+
label: 'in San Francisco?',
|
|
85
|
+
action: "What's the weather in San Francisco?",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: 'Explain React hooks',
|
|
89
|
+
label: 'like useState and useEffect',
|
|
90
|
+
action: 'Explain React hooks like useState and useEffect',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
title: 'Write a SQL query',
|
|
94
|
+
label: 'to find top customers',
|
|
95
|
+
action: 'Write a SQL query to find top customers',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
title: 'Create a meal plan',
|
|
99
|
+
label: 'for healthy weight loss',
|
|
100
|
+
action: 'Create a meal plan for healthy weight loss',
|
|
101
|
+
},
|
|
102
|
+
].map((suggestedAction, index) => (
|
|
103
|
+
<div
|
|
104
|
+
key={`suggested-action-${suggestedAction.title}-${index}`}
|
|
105
|
+
className="aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-4 @md:nth-[n+3]:block nth-[n+3]:hidden animate-in fill-mode-both duration-300 ease-out"
|
|
106
|
+
style={{ animationDelay: `${index * 50}ms` }}
|
|
107
|
+
>
|
|
108
|
+
<ThreadPrimitive.Suggestion prompt={suggestedAction.action} send asChild>
|
|
109
|
+
<Button
|
|
110
|
+
variant="ghost"
|
|
111
|
+
className="aui-thread-welcome-suggestion h-auto w-full flex-1 @md:flex-col flex-wrap items-start justify-start gap-1 rounded-3xl border px-5 py-4 text-left text-sm dark:hover:bg-accent/60"
|
|
112
|
+
aria-label={suggestedAction.action}
|
|
113
|
+
>
|
|
114
|
+
<span className="aui-thread-welcome-suggestion-text-1 font-medium">{suggestedAction.title}</span>
|
|
115
|
+
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">{suggestedAction.label}</span>
|
|
116
|
+
</Button>
|
|
117
|
+
</ThreadPrimitive.Suggestion>
|
|
118
|
+
</div>
|
|
119
|
+
))}
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const Composer: FC = () => {
|
|
125
|
+
return (
|
|
126
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
127
|
+
<ComposerPrimitive.AttachmentDropzone className="aui-composer-attachment-dropzone flex w-full flex-col rounded-3xl border border-input bg-background px-1 pt-2 shadow-xs outline-none transition-[color,box-shadow] has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-[3px] has-[textarea:focus-visible]:ring-ring/50 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50 dark:bg-background">
|
|
128
|
+
<ComposerAttachments />
|
|
129
|
+
<ComposerPrimitive.Input
|
|
130
|
+
placeholder="Send a message..."
|
|
131
|
+
className="aui-composer-input mb-1 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pt-1.5 pb-3 text-base outline-none placeholder:text-muted-foreground focus-visible:ring-0"
|
|
132
|
+
rows={1}
|
|
133
|
+
autoFocus
|
|
134
|
+
aria-label="Message input"
|
|
135
|
+
/>
|
|
136
|
+
<ComposerAction />
|
|
137
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
138
|
+
</ComposerPrimitive.Root>
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const ComposerAction: FC = () => {
|
|
143
|
+
return (
|
|
144
|
+
<div className="aui-composer-action-wrapper relative mx-1 mt-2 mb-2 flex items-center justify-between">
|
|
145
|
+
<ComposerAddAttachment />
|
|
146
|
+
|
|
147
|
+
<ThreadPrimitive.If running={false}>
|
|
148
|
+
<ComposerPrimitive.Send asChild>
|
|
149
|
+
<TooltipIconButton
|
|
150
|
+
tooltip="Send message"
|
|
151
|
+
side="bottom"
|
|
152
|
+
type="submit"
|
|
153
|
+
variant="default"
|
|
154
|
+
size="icon"
|
|
155
|
+
className="aui-composer-send size-[34px] rounded-full p-1"
|
|
156
|
+
aria-label="Send message"
|
|
157
|
+
>
|
|
158
|
+
<ArrowUpIcon className="aui-composer-send-icon size-5" />
|
|
159
|
+
</TooltipIconButton>
|
|
160
|
+
</ComposerPrimitive.Send>
|
|
161
|
+
</ThreadPrimitive.If>
|
|
162
|
+
|
|
163
|
+
<ThreadPrimitive.If running>
|
|
164
|
+
<ComposerPrimitive.Cancel asChild>
|
|
165
|
+
<Button
|
|
166
|
+
type="button"
|
|
167
|
+
variant="default"
|
|
168
|
+
size="icon"
|
|
169
|
+
className="aui-composer-cancel size-[34px] rounded-full border border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90"
|
|
170
|
+
aria-label="Stop generating"
|
|
171
|
+
>
|
|
172
|
+
<Square className="aui-composer-cancel-icon size-3.5 fill-white dark:fill-black" />
|
|
173
|
+
</Button>
|
|
174
|
+
</ComposerPrimitive.Cancel>
|
|
175
|
+
</ThreadPrimitive.If>
|
|
176
|
+
</div>
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const MessageError: FC = () => {
|
|
181
|
+
return (
|
|
182
|
+
<MessagePrimitive.Error>
|
|
183
|
+
<ErrorPrimitive.Root className="aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200">
|
|
184
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
185
|
+
</ErrorPrimitive.Root>
|
|
186
|
+
</MessagePrimitive.Error>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const ReasoningContent: FC<{ text: string }> = ({ text }) => {
|
|
191
|
+
return (
|
|
192
|
+
<div className="aui-reasoning-content my-2 rounded-lg border border-muted bg-muted/30 p-3 text-muted-foreground text-sm italic">
|
|
193
|
+
<div className="mb-1 font-semibold text-xs uppercase tracking-wide">Thinking...</div>
|
|
194
|
+
<div>{text}</div>
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const AssistantMessage: FC = () => {
|
|
200
|
+
return (
|
|
201
|
+
<MessagePrimitive.Root
|
|
202
|
+
className="aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-4 duration-150 ease-out"
|
|
203
|
+
data-role="assistant"
|
|
204
|
+
>
|
|
205
|
+
<div className="aui-assistant-message-content wrap-break-word mx-2 text-foreground leading-7">
|
|
206
|
+
<MessagePrimitive.Parts
|
|
207
|
+
components={{
|
|
208
|
+
Text: MarkdownText,
|
|
209
|
+
Reasoning: ReasoningContent,
|
|
210
|
+
tools: { Fallback: ToolFallback },
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
<MessageError />
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<div className="aui-assistant-message-footer mt-2 ml-2 flex">
|
|
217
|
+
<AssistantActionBar />
|
|
218
|
+
</div>
|
|
219
|
+
</MessagePrimitive.Root>
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const AssistantActionBar: FC = () => {
|
|
224
|
+
return (
|
|
225
|
+
<ActionBarPrimitive.Root
|
|
226
|
+
hideWhenRunning
|
|
227
|
+
autohide="not-last"
|
|
228
|
+
autohideFloat="single-branch"
|
|
229
|
+
className="aui-assistant-action-bar-root -ml-1 col-start-3 row-start-2 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm"
|
|
230
|
+
>
|
|
231
|
+
<ActionBarPrimitive.Copy asChild>
|
|
232
|
+
<TooltipIconButton tooltip="Copy">
|
|
233
|
+
<MessagePrimitive.If copied>
|
|
234
|
+
<CheckIcon />
|
|
235
|
+
</MessagePrimitive.If>
|
|
236
|
+
<MessagePrimitive.If copied={false}>
|
|
237
|
+
<CopyIcon />
|
|
238
|
+
</MessagePrimitive.If>
|
|
239
|
+
</TooltipIconButton>
|
|
240
|
+
</ActionBarPrimitive.Copy>
|
|
241
|
+
<ActionBarPrimitive.Reload asChild>
|
|
242
|
+
<TooltipIconButton tooltip="Refresh">
|
|
243
|
+
<RefreshCwIcon />
|
|
244
|
+
</TooltipIconButton>
|
|
245
|
+
</ActionBarPrimitive.Reload>
|
|
246
|
+
</ActionBarPrimitive.Root>
|
|
247
|
+
);
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const UserMessage: FC = () => {
|
|
251
|
+
return (
|
|
252
|
+
<MessagePrimitive.Root
|
|
253
|
+
className="aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-4 duration-150 ease-out [&:where(>*)]:col-start-2"
|
|
254
|
+
data-role="user"
|
|
255
|
+
>
|
|
256
|
+
<UserMessageAttachments />
|
|
257
|
+
|
|
258
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
259
|
+
<div className="aui-user-message-content wrap-break-word rounded-3xl bg-muted px-5 py-2.5 text-foreground">
|
|
260
|
+
<MessagePrimitive.Parts />
|
|
261
|
+
</div>
|
|
262
|
+
<div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
|
|
263
|
+
<UserActionBar />
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
</MessagePrimitive.Root>
|
|
267
|
+
);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const UserActionBar: FC = () => {
|
|
271
|
+
return (
|
|
272
|
+
<ActionBarPrimitive.Root hideWhenRunning autohide="not-last" className="aui-user-action-bar-root flex flex-col items-end">
|
|
273
|
+
{/* Edit button disabled */}
|
|
274
|
+
</ActionBarPrimitive.Root>
|
|
275
|
+
);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const EditComposer: FC = () => {
|
|
279
|
+
return (
|
|
280
|
+
<MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 px-2">
|
|
281
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-7/8 flex-col rounded-xl bg-muted">
|
|
282
|
+
<ComposerPrimitive.Input
|
|
283
|
+
className="aui-edit-composer-input flex min-h-[60px] w-full resize-none bg-transparent p-4 text-foreground outline-none"
|
|
284
|
+
autoFocus
|
|
285
|
+
/>
|
|
286
|
+
|
|
287
|
+
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end">
|
|
288
|
+
<ComposerPrimitive.Cancel asChild>
|
|
289
|
+
<Button variant="ghost" size="sm" aria-label="Cancel edit">
|
|
290
|
+
Cancel
|
|
291
|
+
</Button>
|
|
292
|
+
</ComposerPrimitive.Cancel>
|
|
293
|
+
<ComposerPrimitive.Send asChild>
|
|
294
|
+
<Button size="sm" aria-label="Update message">
|
|
295
|
+
Update
|
|
296
|
+
</Button>
|
|
297
|
+
</ComposerPrimitive.Send>
|
|
298
|
+
</div>
|
|
299
|
+
</ComposerPrimitive.Root>
|
|
300
|
+
</MessagePrimitive.Root>
|
|
301
|
+
);
|
|
302
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Github, MessagesSquare } from 'lucide-react';
|
|
3
|
+
import {
|
|
4
|
+
Sidebar,
|
|
5
|
+
SidebarContent,
|
|
6
|
+
SidebarFooter,
|
|
7
|
+
SidebarHeader,
|
|
8
|
+
SidebarMenu,
|
|
9
|
+
SidebarMenuButton,
|
|
10
|
+
SidebarMenuItem,
|
|
11
|
+
SidebarRail,
|
|
12
|
+
} from '@/components/ui/sidebar';
|
|
13
|
+
import { ThreadList } from '@/components/assistant-ui/thread-list';
|
|
14
|
+
|
|
15
|
+
export function ThreadListSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|
16
|
+
return (
|
|
17
|
+
<Sidebar {...props}>
|
|
18
|
+
<SidebarHeader className="aui-sidebar-header mb-2 border-b">
|
|
19
|
+
<div className="aui-sidebar-header-content flex items-center justify-between">
|
|
20
|
+
<SidebarMenu>
|
|
21
|
+
<SidebarMenuItem>
|
|
22
|
+
<SidebarMenuButton size="lg" asChild>
|
|
23
|
+
<a href="https://assistant-ui.com" target="_blank" rel="noopener noreferrer">
|
|
24
|
+
<div className="aui-sidebar-header-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
25
|
+
<MessagesSquare className="aui-sidebar-header-icon size-4" />
|
|
26
|
+
</div>
|
|
27
|
+
<div className="aui-sidebar-header-heading mr-6 flex flex-col gap-0.5 leading-none">
|
|
28
|
+
<span className="aui-sidebar-header-title font-semibold">assistant-ui</span>
|
|
29
|
+
</div>
|
|
30
|
+
</a>
|
|
31
|
+
</SidebarMenuButton>
|
|
32
|
+
</SidebarMenuItem>
|
|
33
|
+
</SidebarMenu>
|
|
34
|
+
</div>
|
|
35
|
+
</SidebarHeader>
|
|
36
|
+
<SidebarContent className="aui-sidebar-content px-2">
|
|
37
|
+
<ThreadList />
|
|
38
|
+
</SidebarContent>
|
|
39
|
+
<SidebarRail />
|
|
40
|
+
<SidebarFooter className="aui-sidebar-footer border-t">
|
|
41
|
+
<SidebarMenu>
|
|
42
|
+
<SidebarMenuItem>
|
|
43
|
+
<SidebarMenuButton size="lg" asChild>
|
|
44
|
+
<a href="https://github.com/assistant-ui/assistant-ui" target="_blank">
|
|
45
|
+
<div className="aui-sidebar-footer-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
46
|
+
<Github className="aui-sidebar-footer-icon size-4" />
|
|
47
|
+
</div>
|
|
48
|
+
<div className="aui-sidebar-footer-heading flex flex-col gap-0.5 leading-none">
|
|
49
|
+
<span className="aui-sidebar-footer-title font-semibold">GitHub</span>
|
|
50
|
+
<span>View Source</span>
|
|
51
|
+
</div>
|
|
52
|
+
</a>
|
|
53
|
+
</SidebarMenuButton>
|
|
54
|
+
</SidebarMenuItem>
|
|
55
|
+
</SidebarMenu>
|
|
56
|
+
</SidebarFooter>
|
|
57
|
+
</Sidebar>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
2
|
+
import {
|
|
3
|
+
CheckIcon,
|
|
4
|
+
ChevronDownIcon,
|
|
5
|
+
ChevronUpIcon,
|
|
6
|
+
XCircleIcon,
|
|
7
|
+
} from "lucide-react";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { Button } from "@/components/ui/button";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
|
|
12
|
+
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
13
|
+
toolName,
|
|
14
|
+
argsText,
|
|
15
|
+
result,
|
|
16
|
+
status,
|
|
17
|
+
}) => {
|
|
18
|
+
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
19
|
+
|
|
20
|
+
const isCancelled =
|
|
21
|
+
status?.type === "incomplete" && status.reason === "cancelled";
|
|
22
|
+
const cancelledReason =
|
|
23
|
+
isCancelled && status.error
|
|
24
|
+
? typeof status.error === "string"
|
|
25
|
+
? status.error
|
|
26
|
+
: JSON.stringify(status.error)
|
|
27
|
+
: null;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
className={cn(
|
|
32
|
+
"aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3",
|
|
33
|
+
isCancelled && "border-muted-foreground/30 bg-muted/30",
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
<div className="aui-tool-fallback-header flex items-center gap-2 px-4">
|
|
37
|
+
{isCancelled ? (
|
|
38
|
+
<XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
|
|
39
|
+
) : (
|
|
40
|
+
<CheckIcon className="aui-tool-fallback-icon size-4" />
|
|
41
|
+
)}
|
|
42
|
+
<p
|
|
43
|
+
className={cn(
|
|
44
|
+
"aui-tool-fallback-title grow",
|
|
45
|
+
isCancelled && "text-muted-foreground line-through",
|
|
46
|
+
)}
|
|
47
|
+
>
|
|
48
|
+
{isCancelled ? "Cancelled tool: " : "Used tool: "}
|
|
49
|
+
<b>{toolName}</b>
|
|
50
|
+
</p>
|
|
51
|
+
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
52
|
+
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
53
|
+
</Button>
|
|
54
|
+
</div>
|
|
55
|
+
{!isCollapsed && (
|
|
56
|
+
<div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
|
|
57
|
+
{cancelledReason && (
|
|
58
|
+
<div className="aui-tool-fallback-cancelled-root px-4">
|
|
59
|
+
<p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
|
|
60
|
+
Cancelled reason:
|
|
61
|
+
</p>
|
|
62
|
+
<p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
|
|
63
|
+
{cancelledReason}
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
<div
|
|
68
|
+
className={cn(
|
|
69
|
+
"aui-tool-fallback-args-root px-4",
|
|
70
|
+
isCancelled && "opacity-60",
|
|
71
|
+
)}
|
|
72
|
+
>
|
|
73
|
+
<pre className="aui-tool-fallback-args-value whitespace-pre-wrap">
|
|
74
|
+
{argsText}
|
|
75
|
+
</pre>
|
|
76
|
+
</div>
|
|
77
|
+
{!isCancelled && result !== undefined && (
|
|
78
|
+
<div className="aui-tool-fallback-result-root border-t border-dashed px-4 pt-2">
|
|
79
|
+
<p className="aui-tool-fallback-result-header font-semibold">
|
|
80
|
+
Result:
|
|
81
|
+
</p>
|
|
82
|
+
<pre className="aui-tool-fallback-result-content whitespace-pre-wrap">
|
|
83
|
+
{typeof result === "string"
|
|
84
|
+
? result
|
|
85
|
+
: JSON.stringify(result, null, 2)}
|
|
86
|
+
</pre>
|
|
87
|
+
</div>
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ComponentPropsWithRef, forwardRef } from "react";
|
|
4
|
+
import { Slottable } from "@radix-ui/react-slot";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Tooltip,
|
|
8
|
+
TooltipContent,
|
|
9
|
+
TooltipTrigger,
|
|
10
|
+
} from "@/components/ui/tooltip";
|
|
11
|
+
import { Button } from "@/components/ui/button";
|
|
12
|
+
import { cn } from "@/lib/utils";
|
|
13
|
+
|
|
14
|
+
export type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
|
15
|
+
tooltip: string;
|
|
16
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const TooltipIconButton = forwardRef<
|
|
20
|
+
HTMLButtonElement,
|
|
21
|
+
TooltipIconButtonProps
|
|
22
|
+
>(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
|
|
23
|
+
return (
|
|
24
|
+
<Tooltip>
|
|
25
|
+
<TooltipTrigger asChild>
|
|
26
|
+
<Button
|
|
27
|
+
variant="ghost"
|
|
28
|
+
size="icon"
|
|
29
|
+
{...rest}
|
|
30
|
+
className={cn("aui-button-icon size-6 p-1", className)}
|
|
31
|
+
ref={ref}
|
|
32
|
+
>
|
|
33
|
+
<Slottable>{children}</Slottable>
|
|
34
|
+
<span className="aui-sr-only sr-only">{tooltip}</span>
|
|
35
|
+
</Button>
|
|
36
|
+
</TooltipTrigger>
|
|
37
|
+
<TooltipContent side={side}>{tooltip}</TooltipContent>
|
|
38
|
+
</Tooltip>
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
TooltipIconButton.displayName = "TooltipIconButton";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { usePersonaRuntimeEndpoint, usePersonaRuntimeMessages } from '@applica-software-guru/persona-chat-sdk';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
|
|
5
|
+
function MessageLogger() {
|
|
6
|
+
const messages = usePersonaRuntimeMessages();
|
|
7
|
+
const { reasoning, user, assistant, sources } = useMemo(() => {
|
|
8
|
+
const reasoning = _.filter(messages, (message) => message.role === 'assistant' && message.type === 'reasoning').length;
|
|
9
|
+
const user = _.filter(messages, (message) => message.role === 'user').length;
|
|
10
|
+
const assistant = _.filter(messages, (message) => message.role === 'assistant').length;
|
|
11
|
+
const sources = _.filter(messages, (message) => message.role === 'assistant' && message.sources).length;
|
|
12
|
+
return { reasoning, user, assistant, sources };
|
|
13
|
+
}, [messages]);
|
|
14
|
+
return (
|
|
15
|
+
<div className="absolute top-0 left-0 w-30 h-40 overflow-y-auto m-2 box-border border-gray-300 rounded-lg shadow-lg p-2">
|
|
16
|
+
<h3 className="text-md font-bold mb-2">Messages</h3>
|
|
17
|
+
<p className="top-0 left-0 bg-white text-black text-sm">
|
|
18
|
+
<span className="text-gray-500">
|
|
19
|
+
User: <span className="font-bold">{user}</span>
|
|
20
|
+
</span>
|
|
21
|
+
<br />
|
|
22
|
+
<span className="text-gray-500">
|
|
23
|
+
Assistant: <span className="font-bold">{assistant}</span>
|
|
24
|
+
</span>
|
|
25
|
+
<br />
|
|
26
|
+
<span className="text-gray-500">
|
|
27
|
+
Reasoning: <span className="font-bold">{reasoning}</span>
|
|
28
|
+
</span>
|
|
29
|
+
<br />
|
|
30
|
+
<span className="text-gray-500">
|
|
31
|
+
Sources: <span className="font-bold">{sources}</span>
|
|
32
|
+
</span>
|
|
33
|
+
<br />
|
|
34
|
+
<span className="text-gray-500">
|
|
35
|
+
Total: <span className="font-bold">{messages.length}</span>
|
|
36
|
+
</span>
|
|
37
|
+
<br />
|
|
38
|
+
</p>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function EndpointLogger() {
|
|
44
|
+
const endpoint = usePersonaRuntimeEndpoint();
|
|
45
|
+
return (
|
|
46
|
+
<div className="absolute top-0 right-0 w-50 h-40 overflow-y-auto m-2 box-border border-gray-300 rounded-lg shadow-lg p-2">
|
|
47
|
+
<h3 className="text-md font-bold mb-2">Endpoint</h3>
|
|
48
|
+
<p className="top-0 left-0 bg-white text-black text-sm">{endpoint || 'No endpoint available'}</p>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { MessageLogger, EndpointLogger };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Avatar({
|
|
7
|
+
className,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
|
|
10
|
+
return (
|
|
11
|
+
<AvatarPrimitive.Root
|
|
12
|
+
data-slot="avatar"
|
|
13
|
+
className={cn(
|
|
14
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function AvatarImage({
|
|
23
|
+
className,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
26
|
+
return (
|
|
27
|
+
<AvatarPrimitive.Image
|
|
28
|
+
data-slot="avatar-image"
|
|
29
|
+
className={cn("aspect-square size-full", className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function AvatarFallback({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
39
|
+
return (
|
|
40
|
+
<AvatarPrimitive.Fallback
|
|
41
|
+
data-slot="avatar-fallback"
|
|
42
|
+
className={cn(
|
|
43
|
+
"bg-muted flex size-full items-center justify-center rounded-full",
|
|
44
|
+
className
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { Avatar, AvatarImage, AvatarFallback }
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
13
|
+
destructive:
|
|
14
|
+
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
15
|
+
outline:
|
|
16
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
17
|
+
secondary:
|
|
18
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
19
|
+
ghost:
|
|
20
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
25
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
26
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
27
|
+
icon: "size-9",
|
|
28
|
+
"icon-sm": "size-8",
|
|
29
|
+
"icon-lg": "size-10",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: {
|
|
33
|
+
variant: "default",
|
|
34
|
+
size: "default",
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
function Button({
|
|
40
|
+
className,
|
|
41
|
+
variant,
|
|
42
|
+
size,
|
|
43
|
+
asChild = false,
|
|
44
|
+
...props
|
|
45
|
+
}: React.ComponentProps<"button"> &
|
|
46
|
+
VariantProps<typeof buttonVariants> & {
|
|
47
|
+
asChild?: boolean
|
|
48
|
+
}) {
|
|
49
|
+
const Comp = asChild ? Slot : "button"
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Comp
|
|
53
|
+
data-slot="button"
|
|
54
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { Button, buttonVariants }
|