@applica-software-guru/persona-sdk 0.1.48 → 0.1.52
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/.nvmrc +1 -1
- package/bitbucket-pipelines.yml +1 -1
- package/components.json +21 -0
- package/dist/bundle.cjs.js +2 -2
- package/dist/bundle.cjs.js.map +1 -1
- package/dist/bundle.es.js +280 -251
- package/dist/bundle.es.js.map +1 -1
- package/dist/bundle.iife.js +2 -2
- package/dist/bundle.iife.js.map +1 -1
- package/dist/bundle.umd.js +2 -2
- package/dist/bundle.umd.js.map +1 -1
- package/dist/protocol/base.d.ts +2 -2
- package/dist/protocol/base.d.ts.map +1 -1
- package/dist/protocol/rest.d.ts +2 -2
- package/dist/protocol/rest.d.ts.map +1 -1
- package/dist/protocol/transaction.d.ts +2 -2
- package/dist/protocol/transaction.d.ts.map +1 -1
- package/dist/protocol/webrtc.d.ts +3 -3
- package/dist/protocol/webrtc.d.ts.map +1 -1
- package/dist/protocol/websocket.d.ts +2 -2
- package/dist/protocol/websocket.d.ts.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -6
- package/playground/src/chat.tsx +4 -1
- package/playground/src/components/assistant-ui/attachment.tsx +214 -0
- package/playground/src/components/assistant-ui/thread.tsx +5 -1
- package/playground/src/components/ui/dialog.tsx +133 -0
- package/playground/src/lib/utils.ts +3 -3
- package/playground/src/styles.css +119 -0
- package/src/protocol/base.ts +2 -2
- package/src/protocol/rest.ts +2 -2
- package/src/protocol/transaction.ts +2 -2
- package/src/protocol/webrtc.ts +5 -5
- package/src/protocol/websocket.ts +2 -2
- package/src/runtime.tsx +53 -2
- package/src/types.ts +8 -3
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { PropsWithChildren, useEffect, useState, type FC } from "react";
|
|
4
|
+
import { CircleXIcon, FileIcon, PaperclipIcon } from "lucide-react";
|
|
5
|
+
import {
|
|
6
|
+
AttachmentPrimitive,
|
|
7
|
+
ComposerPrimitive,
|
|
8
|
+
MessagePrimitive,
|
|
9
|
+
useAttachment,
|
|
10
|
+
} from "@assistant-ui/react";
|
|
11
|
+
import { useShallow } from "zustand/shallow";
|
|
12
|
+
import {
|
|
13
|
+
Tooltip,
|
|
14
|
+
TooltipContent,
|
|
15
|
+
TooltipTrigger,
|
|
16
|
+
} from "@/components/ui/tooltip";
|
|
17
|
+
import {
|
|
18
|
+
Dialog,
|
|
19
|
+
DialogTitle,
|
|
20
|
+
DialogTrigger,
|
|
21
|
+
DialogOverlay,
|
|
22
|
+
DialogPortal,
|
|
23
|
+
} from "@/components/ui/dialog";
|
|
24
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
|
25
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
26
|
+
import { DialogContent as DialogPrimitiveContent } from "@radix-ui/react-dialog";
|
|
27
|
+
|
|
28
|
+
const useFileSrc = (file: File | undefined) => {
|
|
29
|
+
const [src, setSrc] = useState<string | undefined>(undefined);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!file) {
|
|
33
|
+
setSrc(undefined);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const objectUrl = URL.createObjectURL(file);
|
|
38
|
+
setSrc(objectUrl);
|
|
39
|
+
|
|
40
|
+
return () => {
|
|
41
|
+
URL.revokeObjectURL(objectUrl);
|
|
42
|
+
};
|
|
43
|
+
}, [file]);
|
|
44
|
+
|
|
45
|
+
return src;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const useAttachmentSrc = () => {
|
|
49
|
+
const { file, src } = useAttachment(
|
|
50
|
+
useShallow((a): { file?: File; src?: string } => {
|
|
51
|
+
if (a.type !== "image") return {};
|
|
52
|
+
if (a.file) return { file: a.file };
|
|
53
|
+
const src = a.content?.filter((c) => c.type === "image")[0]?.image;
|
|
54
|
+
if (!src) return {};
|
|
55
|
+
return { src };
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return useFileSrc(file) ?? src;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
type AttachmentPreviewProps = {
|
|
63
|
+
src: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const AttachmentPreview: FC<AttachmentPreviewProps> = ({ src }) => {
|
|
67
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
71
|
+
<img
|
|
72
|
+
src={src}
|
|
73
|
+
style={{
|
|
74
|
+
width: "auto",
|
|
75
|
+
height: "auto",
|
|
76
|
+
maxWidth: "75dvh",
|
|
77
|
+
maxHeight: "75dvh",
|
|
78
|
+
display: isLoaded ? "block" : "none",
|
|
79
|
+
overflow: "clip",
|
|
80
|
+
}}
|
|
81
|
+
onLoad={() => setIsLoaded(true)}
|
|
82
|
+
alt="Preview"
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
|
|
88
|
+
const src = useAttachmentSrc();
|
|
89
|
+
|
|
90
|
+
if (!src) return children;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<Dialog>
|
|
94
|
+
<DialogTrigger className="hover:bg-accent/50 cursor-pointer transition-colors" asChild>
|
|
95
|
+
{children}
|
|
96
|
+
</DialogTrigger>
|
|
97
|
+
<AttachmentDialogContent>
|
|
98
|
+
<DialogTitle className="aui-sr-only">
|
|
99
|
+
Image Attachment Preview
|
|
100
|
+
</DialogTitle>
|
|
101
|
+
<AttachmentPreview src={src} />
|
|
102
|
+
</AttachmentDialogContent>
|
|
103
|
+
</Dialog>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const AttachmentThumb: FC = () => {
|
|
108
|
+
const isImage = useAttachment((a) => a.type === "image");
|
|
109
|
+
const src = useAttachmentSrc();
|
|
110
|
+
return (
|
|
111
|
+
<Avatar className="bg-muted flex size-10 items-center justify-center rounded border text-sm">
|
|
112
|
+
<AvatarFallback delayMs={isImage ? 200 : 0}>
|
|
113
|
+
<FileIcon />
|
|
114
|
+
</AvatarFallback>
|
|
115
|
+
<AvatarImage src={src} />
|
|
116
|
+
</Avatar>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const AttachmentUI: FC = () => {
|
|
121
|
+
const canRemove = useAttachment((a) => a.source !== "message");
|
|
122
|
+
const typeLabel = useAttachment((a) => {
|
|
123
|
+
const type = a.type;
|
|
124
|
+
switch (type) {
|
|
125
|
+
case "image":
|
|
126
|
+
return "Image";
|
|
127
|
+
case "document":
|
|
128
|
+
return "Document";
|
|
129
|
+
case "file":
|
|
130
|
+
return "File";
|
|
131
|
+
default:
|
|
132
|
+
const _exhaustiveCheck: never = type;
|
|
133
|
+
throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return (
|
|
137
|
+
<Tooltip>
|
|
138
|
+
<AttachmentPrimitive.Root className="relative mt-3">
|
|
139
|
+
<AttachmentPreviewDialog>
|
|
140
|
+
<TooltipTrigger asChild>
|
|
141
|
+
<div className="flex h-12 w-40 items-center justify-center gap-2 rounded-lg border p-1">
|
|
142
|
+
<AttachmentThumb />
|
|
143
|
+
<div className="flex-grow basis-0">
|
|
144
|
+
<p className="text-muted-foreground line-clamp-1 text-ellipsis break-all text-xs font-bold">
|
|
145
|
+
<AttachmentPrimitive.Name />
|
|
146
|
+
</p>
|
|
147
|
+
<p className="text-muted-foreground text-xs">{typeLabel}</p>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
</TooltipTrigger>
|
|
151
|
+
</AttachmentPreviewDialog>
|
|
152
|
+
{canRemove && <AttachmentRemove />}
|
|
153
|
+
</AttachmentPrimitive.Root>
|
|
154
|
+
<TooltipContent side="top">
|
|
155
|
+
<AttachmentPrimitive.Name />
|
|
156
|
+
</TooltipContent>
|
|
157
|
+
</Tooltip>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const AttachmentRemove: FC = () => {
|
|
162
|
+
return (
|
|
163
|
+
<AttachmentPrimitive.Remove asChild>
|
|
164
|
+
<TooltipIconButton
|
|
165
|
+
tooltip="Remove file"
|
|
166
|
+
className="text-muted-foreground [&>svg]:bg-background absolute -right-3 -top-3 size-6 [&>svg]:size-4 [&>svg]:rounded-full"
|
|
167
|
+
side="top"
|
|
168
|
+
>
|
|
169
|
+
<CircleXIcon />
|
|
170
|
+
</TooltipIconButton>
|
|
171
|
+
</AttachmentPrimitive.Remove>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const UserMessageAttachments: FC = () => {
|
|
176
|
+
return (
|
|
177
|
+
<div className="flex w-full flex-row gap-3 col-span-full col-start-1 row-start-1 justify-end">
|
|
178
|
+
<MessagePrimitive.Attachments components={{ Attachment: AttachmentUI }} />
|
|
179
|
+
</div>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const ComposerAttachments: FC = () => {
|
|
184
|
+
return (
|
|
185
|
+
<div className="flex w-full flex-row gap-3 px-10">
|
|
186
|
+
<ComposerPrimitive.Attachments
|
|
187
|
+
components={{ Attachment: AttachmentUI }}
|
|
188
|
+
/>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const ComposerAddAttachment: FC = () => {
|
|
194
|
+
return (
|
|
195
|
+
<ComposerPrimitive.AddAttachment asChild>
|
|
196
|
+
<TooltipIconButton
|
|
197
|
+
className="my-2.5 size-8 p-2 transition-opacity ease-in"
|
|
198
|
+
tooltip="Add Attachment"
|
|
199
|
+
variant="ghost"
|
|
200
|
+
>
|
|
201
|
+
<PaperclipIcon />
|
|
202
|
+
</TooltipIconButton>
|
|
203
|
+
</ComposerPrimitive.AddAttachment>
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const AttachmentDialogContent: FC<PropsWithChildren> = ({ children }) => (
|
|
208
|
+
<DialogPortal>
|
|
209
|
+
<DialogOverlay />
|
|
210
|
+
<DialogPrimitiveContent className="aui-dialog-content">
|
|
211
|
+
{children}
|
|
212
|
+
</DialogPrimitiveContent>
|
|
213
|
+
</DialogPortal>
|
|
214
|
+
);
|
|
@@ -30,6 +30,7 @@ import { TooltipIconButton } from '@/components/assistant-ui/tooltip-icon-button
|
|
|
30
30
|
import { ToolFallback } from '@/components/assistant-ui/tool-fallback';
|
|
31
31
|
|
|
32
32
|
import { usePersonaRuntimeEndpoint, usePersonaRuntimeWebRTCProtocol } from '@applica-software-guru/persona-sdk';
|
|
33
|
+
import { ComposerAddAttachment, ComposerAttachments, UserMessageAttachments } from './attachment';
|
|
33
34
|
|
|
34
35
|
export const Thread: FC = () => {
|
|
35
36
|
return (
|
|
@@ -89,6 +90,8 @@ const ThreadWelcome: FC = () => {
|
|
|
89
90
|
const Composer: FC = () => {
|
|
90
91
|
return (
|
|
91
92
|
<ComposerPrimitive.Root className="focus-within:border-ring/20 flex w-full flex-wrap items-end rounded-lg border bg-inherit px-2.5 shadow-sm transition-colors ease-in">
|
|
93
|
+
<ComposerAttachments />
|
|
94
|
+
<ComposerAddAttachment />
|
|
92
95
|
<ComposerPrimitive.Input
|
|
93
96
|
rows={1}
|
|
94
97
|
autoFocus
|
|
@@ -118,7 +121,7 @@ const SpeakButton: FC = () => {
|
|
|
118
121
|
return (
|
|
119
122
|
<TooltipIconButton
|
|
120
123
|
className={cn(
|
|
121
|
-
'hover:text-primary my-2.5 size-8 p-2 ml-2 transition-opacity ease-in
|
|
124
|
+
'hover:text-primary my-2.5 size-8 p-2 ml-2 transition-opacity ease-in cursor-pointer',
|
|
122
125
|
isConnected && 'animate-pulse text-blue-500',
|
|
123
126
|
)}
|
|
124
127
|
variant="default"
|
|
@@ -156,6 +159,7 @@ const UserMessage: FC = () => {
|
|
|
156
159
|
return (
|
|
157
160
|
<MessagePrimitive.Root className="grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 [&:where(>*)]:col-start-2 w-full max-w-[var(--thread-max-width)] py-4">
|
|
158
161
|
<div className="bg-muted text-foreground max-w-[calc(var(--thread-max-width)*0.8)] break-words rounded-3xl px-5 py-2.5 col-start-2 row-start-2">
|
|
162
|
+
<UserMessageAttachments />
|
|
159
163
|
<MessagePrimitive.Content />
|
|
160
164
|
</div>
|
|
161
165
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
|
3
|
+
import { XIcon } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
function Dialog({
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
10
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function DialogTrigger({
|
|
14
|
+
...props
|
|
15
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
16
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DialogPortal({
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
22
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function DialogClose({
|
|
26
|
+
...props
|
|
27
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
28
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function DialogOverlay({
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
35
|
+
return (
|
|
36
|
+
<DialogPrimitive.Overlay
|
|
37
|
+
data-slot="dialog-overlay"
|
|
38
|
+
className={cn(
|
|
39
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function DialogContent({
|
|
48
|
+
className,
|
|
49
|
+
children,
|
|
50
|
+
...props
|
|
51
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
|
52
|
+
return (
|
|
53
|
+
<DialogPortal data-slot="dialog-portal">
|
|
54
|
+
<DialogOverlay />
|
|
55
|
+
<DialogPrimitive.Content
|
|
56
|
+
data-slot="dialog-content"
|
|
57
|
+
className={cn(
|
|
58
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
|
65
|
+
<XIcon />
|
|
66
|
+
<span className="sr-only">Close</span>
|
|
67
|
+
</DialogPrimitive.Close>
|
|
68
|
+
</DialogPrimitive.Content>
|
|
69
|
+
</DialogPortal>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
data-slot="dialog-header"
|
|
77
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
84
|
+
return (
|
|
85
|
+
<div
|
|
86
|
+
data-slot="dialog-footer"
|
|
87
|
+
className={cn(
|
|
88
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
89
|
+
className
|
|
90
|
+
)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function DialogTitle({
|
|
97
|
+
className,
|
|
98
|
+
...props
|
|
99
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
100
|
+
return (
|
|
101
|
+
<DialogPrimitive.Title
|
|
102
|
+
data-slot="dialog-title"
|
|
103
|
+
className={cn("text-lg leading-none font-semibold", className)}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function DialogDescription({
|
|
110
|
+
className,
|
|
111
|
+
...props
|
|
112
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
113
|
+
return (
|
|
114
|
+
<DialogPrimitive.Description
|
|
115
|
+
data-slot="dialog-description"
|
|
116
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
117
|
+
{...props}
|
|
118
|
+
/>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
Dialog,
|
|
124
|
+
DialogClose,
|
|
125
|
+
DialogContent,
|
|
126
|
+
DialogDescription,
|
|
127
|
+
DialogFooter,
|
|
128
|
+
DialogHeader,
|
|
129
|
+
DialogOverlay,
|
|
130
|
+
DialogPortal,
|
|
131
|
+
DialogTitle,
|
|
132
|
+
DialogTrigger,
|
|
133
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ClassValue
|
|
2
|
-
import { twMerge } from
|
|
1
|
+
import { clsx, type ClassValue } from "clsx"
|
|
2
|
+
import { twMerge } from "tailwind-merge"
|
|
3
3
|
|
|
4
4
|
export function cn(...inputs: ClassValue[]) {
|
|
5
|
-
return twMerge(clsx(inputs))
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
6
6
|
}
|
|
@@ -1 +1,120 @@
|
|
|
1
1
|
@import 'tailwindcss';
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
|
|
4
|
+
@custom-variant dark (&:is(.dark *));
|
|
5
|
+
|
|
6
|
+
@theme inline {
|
|
7
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
8
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
9
|
+
--radius-lg: var(--radius);
|
|
10
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
11
|
+
--color-background: var(--background);
|
|
12
|
+
--color-foreground: var(--foreground);
|
|
13
|
+
--color-card: var(--card);
|
|
14
|
+
--color-card-foreground: var(--card-foreground);
|
|
15
|
+
--color-popover: var(--popover);
|
|
16
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
17
|
+
--color-primary: var(--primary);
|
|
18
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
19
|
+
--color-secondary: var(--secondary);
|
|
20
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
21
|
+
--color-muted: var(--muted);
|
|
22
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
23
|
+
--color-accent: var(--accent);
|
|
24
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
25
|
+
--color-destructive: var(--destructive);
|
|
26
|
+
--color-border: var(--border);
|
|
27
|
+
--color-input: var(--input);
|
|
28
|
+
--color-ring: var(--ring);
|
|
29
|
+
--color-chart-1: var(--chart-1);
|
|
30
|
+
--color-chart-2: var(--chart-2);
|
|
31
|
+
--color-chart-3: var(--chart-3);
|
|
32
|
+
--color-chart-4: var(--chart-4);
|
|
33
|
+
--color-chart-5: var(--chart-5);
|
|
34
|
+
--color-sidebar: var(--sidebar);
|
|
35
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
36
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
37
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
38
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
39
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
40
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
41
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:root {
|
|
45
|
+
--radius: 0.625rem;
|
|
46
|
+
--background: oklch(1 0 0);
|
|
47
|
+
--foreground: oklch(0.145 0 0);
|
|
48
|
+
--card: oklch(1 0 0);
|
|
49
|
+
--card-foreground: oklch(0.145 0 0);
|
|
50
|
+
--popover: oklch(1 0 0);
|
|
51
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
52
|
+
--primary: oklch(0.205 0 0);
|
|
53
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
54
|
+
--secondary: oklch(0.97 0 0);
|
|
55
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
56
|
+
--muted: oklch(0.97 0 0);
|
|
57
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
58
|
+
--accent: oklch(0.97 0 0);
|
|
59
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
60
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
61
|
+
--border: oklch(0.922 0 0);
|
|
62
|
+
--input: oklch(0.922 0 0);
|
|
63
|
+
--ring: oklch(0.708 0 0);
|
|
64
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
65
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
66
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
67
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
68
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
69
|
+
--sidebar: oklch(0.985 0 0);
|
|
70
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
71
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
72
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
73
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
74
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
75
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
76
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.dark {
|
|
80
|
+
--background: oklch(0.145 0 0);
|
|
81
|
+
--foreground: oklch(0.985 0 0);
|
|
82
|
+
--card: oklch(0.205 0 0);
|
|
83
|
+
--card-foreground: oklch(0.985 0 0);
|
|
84
|
+
--popover: oklch(0.205 0 0);
|
|
85
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
86
|
+
--primary: oklch(0.922 0 0);
|
|
87
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
88
|
+
--secondary: oklch(0.269 0 0);
|
|
89
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
90
|
+
--muted: oklch(0.269 0 0);
|
|
91
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
92
|
+
--accent: oklch(0.269 0 0);
|
|
93
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
94
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
95
|
+
--border: oklch(1 0 0 / 10%);
|
|
96
|
+
--input: oklch(1 0 0 / 15%);
|
|
97
|
+
--ring: oklch(0.556 0 0);
|
|
98
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
99
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
100
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
101
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
102
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
103
|
+
--sidebar: oklch(0.205 0 0);
|
|
104
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
105
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
106
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
107
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
108
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
109
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
110
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@layer base {
|
|
114
|
+
* {
|
|
115
|
+
@apply border-border outline-ring/50;
|
|
116
|
+
}
|
|
117
|
+
body {
|
|
118
|
+
@apply bg-background text-foreground;
|
|
119
|
+
}
|
|
120
|
+
}
|
package/src/protocol/base.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Message,
|
|
3
2
|
MessageListenerCallback,
|
|
3
|
+
PersonaMessage,
|
|
4
4
|
PersonaPayload,
|
|
5
5
|
PersonaProtocol,
|
|
6
6
|
PersonaTransaction,
|
|
@@ -58,7 +58,7 @@ abstract class PersonaProtocolBase implements PersonaProtocol {
|
|
|
58
58
|
abstract getPriority(): number;
|
|
59
59
|
abstract connect(session?: Session): Promise<Session>;
|
|
60
60
|
abstract disconnect(): Promise<void>;
|
|
61
|
-
abstract send(message:
|
|
61
|
+
abstract send(message: Array<PersonaMessage> | PersonaMessage): Promise<void>;
|
|
62
62
|
|
|
63
63
|
public onTransaction(_: PersonaTransaction) {}
|
|
64
64
|
}
|
package/src/protocol/rest.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PersonaProtocolBase } from './base';
|
|
2
|
-
import {
|
|
2
|
+
import { PersonaResponse, Session, ProtocolStatus, PersonaProtocolBaseConfig, PersonaMessage } from '../types';
|
|
3
3
|
|
|
4
4
|
type PersonaRESTProtocolConfig = PersonaProtocolBaseConfig & {
|
|
5
5
|
apiUrl: string;
|
|
@@ -41,7 +41,7 @@ class PersonaRESTProtocol extends PersonaProtocolBase {
|
|
|
41
41
|
this.session = session;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
public async send(message:
|
|
44
|
+
public async send(message: Array<PersonaMessage> | PersonaMessage): Promise<void> {
|
|
45
45
|
const { apiUrl, apiKey, agentId } = this.config;
|
|
46
46
|
const sessionId = this.session ?? 'new';
|
|
47
47
|
const input = message;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { PersonaProtocolBase } from './base';
|
|
2
2
|
import {
|
|
3
|
-
Message,
|
|
4
3
|
Session,
|
|
5
4
|
ProtocolStatus,
|
|
6
5
|
PersonaProtocolBaseConfig,
|
|
7
6
|
PersonaTransaction,
|
|
8
7
|
FunctionCall,
|
|
9
8
|
ReadonlyJSONObject,
|
|
9
|
+
PersonaMessage,
|
|
10
10
|
} from '../types';
|
|
11
11
|
|
|
12
12
|
type FinishTransactionRequest = {
|
|
@@ -134,7 +134,7 @@ class PersonaTransactionProtocol extends PersonaProtocolBase {
|
|
|
134
134
|
this.session = session;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
public async send(message:
|
|
137
|
+
public async send(message: Array<PersonaMessage> | PersonaMessage): Promise<void> {
|
|
138
138
|
this.config.logger?.debug('Sending message:', message);
|
|
139
139
|
throw new Error('Not implemented');
|
|
140
140
|
}
|
package/src/protocol/webrtc.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PersonaProtocolBase } from './base';
|
|
2
|
-
import {
|
|
2
|
+
import { PersonaMessage, PersonaPayload, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
|
|
3
3
|
|
|
4
4
|
type AudioAnalysisData = {
|
|
5
5
|
localAmplitude: number;
|
|
@@ -187,13 +187,13 @@ class PersonaWebRTCClient {
|
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
public sendMessage(message:
|
|
190
|
+
public sendMessage(message: Array<PersonaMessage> | PersonaMessage): void {
|
|
191
191
|
if (!this.dataChannel) {
|
|
192
192
|
this.config.logger?.warn('Data channel is not open, cannot send message');
|
|
193
193
|
return;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
this.dataChannel.send(message);
|
|
196
|
+
this.dataChannel.send(JSON.stringify({ type: 'request', payload: message }));
|
|
197
197
|
this.config.logger?.info('Sent message:', message);
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -322,12 +322,12 @@ class PersonaWebRTCProtocol extends PersonaProtocolBase {
|
|
|
322
322
|
this.config?.logger?.debug('Disconnected from WebRTC');
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
public send(message:
|
|
325
|
+
public send(message: Array<PersonaMessage> | PersonaMessage): Promise<void> {
|
|
326
326
|
if (this.status !== 'connected') {
|
|
327
327
|
return Promise.reject(new Error('Not connected'));
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
this.webRTCClient.sendMessage(message
|
|
330
|
+
this.webRTCClient.sendMessage(message);
|
|
331
331
|
return Promise.resolve();
|
|
332
332
|
}
|
|
333
333
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PersonaMessage, PersonaPayload, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
|
|
2
2
|
import { PersonaProtocolBase } from './base';
|
|
3
3
|
|
|
4
4
|
type PersonaWebSocketProtocolConfig = PersonaProtocolBaseConfig & {
|
|
@@ -86,7 +86,7 @@ class PersonaWebSocketProtocol extends PersonaProtocolBase {
|
|
|
86
86
|
return Promise.resolve();
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
public send(message:
|
|
89
|
+
public send(message: Array<PersonaMessage> | PersonaMessage): Promise<void> {
|
|
90
90
|
if (this.webSocket && this.status === 'connected') {
|
|
91
91
|
this.webSocket.send(JSON.stringify({ type: 'request', payload: message }));
|
|
92
92
|
return Promise.resolve();
|