@applica-software-guru/persona-sdk 0.1.45 → 0.1.47

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.
@@ -3,12 +3,25 @@ import {
3
3
  ActionBarPrimitive,
4
4
  BranchPickerPrimitive,
5
5
  ComposerPrimitive,
6
+ FileContentPart,
7
+ ImageContentPart,
6
8
  MessagePrimitive,
7
9
  ReasoningContentPartProps,
8
10
  ThreadPrimitive,
9
11
  } from '@assistant-ui/react';
10
- import { useCallback, useMemo, type FC } from 'react';
11
- import { ArrowDownIcon, CheckIcon, ChevronLeftIcon, ChevronRightIcon, CopyIcon, SendHorizontalIcon, MicIcon } from 'lucide-react';
12
+ import { JSX, useCallback, useMemo, type FC } from 'react';
13
+ import {
14
+ ArrowDownIcon,
15
+ CheckIcon,
16
+ ChevronLeftIcon,
17
+ ChevronRightIcon,
18
+ CopyIcon,
19
+ SendHorizontalIcon,
20
+ MicIcon,
21
+ FileIcon,
22
+ ImageIcon,
23
+ ArchiveIcon,
24
+ } from 'lucide-react';
12
25
  import { cn } from '@/lib/utils';
13
26
 
14
27
  import { Button } from '@/components/ui/button';
@@ -16,7 +29,7 @@ import { MarkdownText } from '@/components/assistant-ui/markdown-text';
16
29
  import { TooltipIconButton } from '@/components/assistant-ui/tooltip-icon-button';
17
30
  import { ToolFallback } from '@/components/assistant-ui/tool-fallback';
18
31
 
19
- import { usePersonaRuntimeWebRTCProtocol } from '@applica-software-guru/persona-sdk';
32
+ import { usePersonaRuntimeEndpoint, usePersonaRuntimeWebRTCProtocol } from '@applica-software-guru/persona-sdk';
20
33
 
21
34
  export const Thread: FC = () => {
22
35
  return (
@@ -172,6 +185,47 @@ const Reasoning: FC<ReasoningContentPartProps> = ({ text }: ReasoningContentPart
172
185
  return <div className="text-sm text-muted-foreground break-words whitespace-pre-wrap">{text}</div>;
173
186
  };
174
187
 
188
+ const Image: FC<ImageContentPart> = ({ image }: ImageContentPart) => {
189
+ const baseEndpoint = usePersonaRuntimeEndpoint();
190
+ return (
191
+ <div className="flex items-center gap-2 border rounded-lg border-muted bg-muted p-4 my-2">
192
+ <img src={`${baseEndpoint}/files/${image}`} alt="Image" className="max-h-96 max-w-full rounded-lg object-cover" />
193
+ </div>
194
+ );
195
+ };
196
+
197
+ const File: FC<FileContentPart> = ({ data, mimeType }) => {
198
+ const isImage = useMemo(() => mimeType.startsWith('image/'), [mimeType]);
199
+ if (isImage) {
200
+ return <Image image={data} type="image" />;
201
+ }
202
+ const fileName = useMemo(() => {
203
+ const parts = data.split('/');
204
+ return parts[parts.length - 1];
205
+ }, [data]);
206
+ const baseEndpoint = usePersonaRuntimeEndpoint();
207
+ const getIconByMimeType = (mimeType: string) => {
208
+ const iconMap: Record<string, JSX.Element> = {
209
+ 'application/pdf': <FileIcon />,
210
+ 'image/png': <ImageIcon />,
211
+ 'image/jpeg': <ImageIcon />,
212
+ 'application/zip': <ArchiveIcon />,
213
+ };
214
+
215
+ return iconMap[mimeType] || <FileIcon />;
216
+ };
217
+ const icon = getIconByMimeType(mimeType);
218
+
219
+ return (
220
+ <div className="flex items-center gap-2 border rounded-lg border-muted bg-muted p-4 my-2">
221
+ <div className="text-muted-foreground">{icon}</div>
222
+ <a target="_blank" href={`${baseEndpoint}/files/${data}`} download={fileName} className="text-md text-muted-foreground">
223
+ {fileName}
224
+ </a>
225
+ </div>
226
+ );
227
+ };
228
+
175
229
  const AssistantMessage: FC = () => {
176
230
  return (
177
231
  <MessagePrimitive.Root className="grid grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] relative w-full max-w-[var(--thread-max-width)] py-4">
@@ -179,6 +233,7 @@ const AssistantMessage: FC = () => {
179
233
  <MessagePrimitive.Content
180
234
  components={{
181
235
  Text: MarkdownText,
236
+ File,
182
237
  Reasoning,
183
238
  tools: {
184
239
  Fallback: ToolFallback,
package/src/messages.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PersonaMessage } from './types';
2
- import { ThreadMessageLike } from '@assistant-ui/react';
2
+ import { FileContentPart, ThreadMessageLike } from '@assistant-ui/react';
3
3
 
4
4
  function removeEmptyMessages(messages: PersonaMessage[]): PersonaMessage[] {
5
5
  return messages.filter((message) => {
@@ -14,6 +14,9 @@ function parseMessages(messages: PersonaMessage[]): PersonaMessage[] {
14
14
  let currentMessage: PersonaMessage | null = null;
15
15
 
16
16
  for (const message of messages) {
17
+ if (message.type === 'transaction') {
18
+ continue;
19
+ }
17
20
  if (message.type === 'reasoning') {
18
21
  if (currentMessage != null) {
19
22
  outputMessages.push(currentMessage);
@@ -37,6 +40,7 @@ function parseMessages(messages: PersonaMessage[]): PersonaMessage[] {
37
40
  (currentMessage.role === message.role || message.finishReason === 'stop')
38
41
  ) {
39
42
  currentMessage.text += message.text;
43
+ currentMessage.files = [...(currentMessage.files ?? []), ...(message.files ?? [])];
40
44
  } else {
41
45
  if (currentMessage) {
42
46
  outputMessages.push(currentMessage);
@@ -50,10 +54,20 @@ function parseMessages(messages: PersonaMessage[]): PersonaMessage[] {
50
54
  if (currentMessage) {
51
55
  outputMessages.push(currentMessage);
52
56
  }
53
- return removeEmptyMessages(outputMessages);
57
+ const cleanMessages = removeEmptyMessages(outputMessages);
58
+ return cleanMessages;
54
59
  }
55
60
 
56
61
  function convertMessage(message: PersonaMessage): ThreadMessageLike {
62
+ const files =
63
+ message.files?.map(
64
+ (file) =>
65
+ ({
66
+ type: 'file',
67
+ data: file.url,
68
+ mimeType: file.contentType,
69
+ } as FileContentPart),
70
+ ) ?? [];
57
71
  if (message.role === 'function') {
58
72
  return {
59
73
  id: message.id!,
@@ -72,7 +86,10 @@ function convertMessage(message: PersonaMessage): ThreadMessageLike {
72
86
  return {
73
87
  id: message.id!,
74
88
  role: message.role,
75
- content: message.type === 'reasoning' ? [{ type: 'reasoning', text: message.text }] : [{ type: 'text', text: message.text }],
89
+ content:
90
+ message.type === 'reasoning'
91
+ ? [{ type: 'reasoning', text: message.text }, ...files]
92
+ : [{ type: 'text', text: message.text }, ...files],
76
93
  };
77
94
  }
78
95
 
@@ -1,4 +1,13 @@
1
- import { Message, MessageListenerCallback, PersonaMessage, PersonaProtocol, ProtocolStatus, Session, StatusChangeCallback } from '../types';
1
+ import {
2
+ Message,
3
+ MessageListenerCallback,
4
+ PersonaPayload,
5
+ PersonaProtocol,
6
+ PersonaTransaction,
7
+ ProtocolStatus,
8
+ Session,
9
+ StatusChangeCallback,
10
+ } from '../types';
2
11
 
3
12
  abstract class PersonaProtocolBase implements PersonaProtocol {
4
13
  abstract status: ProtocolStatus;
@@ -19,10 +28,10 @@ abstract class PersonaProtocolBase implements PersonaProtocol {
19
28
  this.session = session;
20
29
  }
21
30
 
22
- public async notifyMessage(message: PersonaMessage): Promise<void> {
31
+ public async notifyMessage(message: PersonaPayload): Promise<void> {
23
32
  this.messageCallbacks.forEach((callback) => callback(message));
24
33
  }
25
- public async notifyMessages(messages: PersonaMessage[]): Promise<void> {
34
+ public async notifyMessages(messages: PersonaPayload[]): Promise<void> {
26
35
  messages.forEach((message) => {
27
36
  this.messageCallbacks.forEach((callback) => callback(message));
28
37
  });
@@ -50,6 +59,8 @@ abstract class PersonaProtocolBase implements PersonaProtocol {
50
59
  abstract connect(session?: Session): Promise<Session>;
51
60
  abstract disconnect(): Promise<void>;
52
61
  abstract send(message: Message): Promise<void>;
62
+
63
+ public onTransaction(_: PersonaTransaction) {}
53
64
  }
54
65
 
55
66
  export { PersonaProtocolBase };
@@ -2,3 +2,4 @@ export * from './rest';
2
2
  export * from './base';
3
3
  export * from './websocket';
4
4
  export * from './webrtc';
5
+ export * from './transaction';
@@ -56,7 +56,12 @@ class PersonaRESTProtocol extends PersonaProtocolBase {
56
56
  },
57
57
  });
58
58
  const personaResponse = (await response.json()) as PersonaResponse;
59
- this.notifyMessages(personaResponse.response.messages);
59
+ this.notifyMessages(
60
+ personaResponse.response.messages.map((payload) => ({
61
+ type: 'message',
62
+ payload,
63
+ })),
64
+ );
60
65
  }
61
66
  }
62
67
 
@@ -0,0 +1,154 @@
1
+ import { PersonaProtocolBase } from './base';
2
+ import {
3
+ Message,
4
+ Session,
5
+ ProtocolStatus,
6
+ PersonaProtocolBaseConfig,
7
+ PersonaTransaction,
8
+ FunctionCall,
9
+ ReadonlyJSONObject,
10
+ } from '../types';
11
+
12
+ type FinishTransactionRequest = {
13
+ success: boolean;
14
+ output: any;
15
+ error: string | null;
16
+ };
17
+
18
+ class PersonaTransactionsManager {
19
+ private config: PersonaTransactionProtocolConfig;
20
+
21
+ constructor(config: PersonaTransactionProtocolConfig) {
22
+ this.config = config;
23
+ }
24
+
25
+ async complete(transaction: PersonaTransaction, request: FinishTransactionRequest): Promise<void> {
26
+ await this.persist(transaction, { ...request, success: true });
27
+ this.config.logger?.debug('Transaction completed:', transaction);
28
+ }
29
+
30
+ async fail(transaction: PersonaTransaction, request: FinishTransactionRequest): Promise<void> {
31
+ await this.persist(transaction, { ...request, success: false });
32
+ this.config.logger?.debug('Transaction failed:', { ...transaction, ...request });
33
+ }
34
+
35
+ async persist(transaction: PersonaTransaction, request: FinishTransactionRequest): Promise<void> {
36
+ await fetch(`${this.config.apiUrl}/transactions/${transaction.id}`, {
37
+ body: JSON.stringify(request),
38
+ method: 'POST',
39
+ headers: {
40
+ 'Content-Type': 'application/json',
41
+ Accept: 'application/json',
42
+ 'x-persona-apikey': this.config.apiKey,
43
+ },
44
+ });
45
+ }
46
+ }
47
+
48
+ export type PersonaToolCallback = (args: ReadonlyJSONObject | undefined) => void;
49
+ export type PersonaTools = {
50
+ [key: string]: PersonaToolCallback;
51
+ };
52
+
53
+ class PersonaPersistableTransaction {
54
+ private transaction: PersonaTransaction;
55
+ private manager: PersonaTransactionsManager;
56
+
57
+ constructor(transaction: PersonaTransaction, manager: PersonaTransactionsManager) {
58
+ this.transaction = transaction;
59
+ this.manager = manager;
60
+ }
61
+
62
+ public getFunctionCall(): FunctionCall | null {
63
+ return this.transaction.functionCall;
64
+ }
65
+
66
+ async invoke(tools: PersonaTools): Promise<void> {
67
+ const functionCall = this.transaction.functionCall;
68
+ if (!functionCall) {
69
+ await this.fail('No function call found');
70
+ return;
71
+ }
72
+ const functionName = functionCall.name;
73
+ const functionArgs = functionCall.args;
74
+ const tool = tools[functionName];
75
+ if (!tool) {
76
+ await this.fail(`Tool ${functionName} not found`);
77
+ return;
78
+ }
79
+ try {
80
+ const result = await tool(functionArgs);
81
+ await this.complete({ date: new Date().toISOString(), result });
82
+ } catch (error) {
83
+ await this.fail(`Error executing tool ${functionName}: ${error}`);
84
+ }
85
+ }
86
+ async complete(output: any): Promise<void> {
87
+ await this.manager.complete(this.transaction, { success: true, output, error: null });
88
+ }
89
+ async fail(error: string): Promise<void> {
90
+ await this.manager.fail(this.transaction, { success: false, output: null, error });
91
+ }
92
+ }
93
+
94
+ type PersonaTransactionCallback = (transaction: PersonaPersistableTransaction) => void;
95
+
96
+ type PersonaTransactionProtocolConfig = PersonaProtocolBaseConfig & {
97
+ apiUrl: string;
98
+ onTransaction: PersonaTransactionCallback;
99
+ };
100
+
101
+ class PersonaTransactionProtocol extends PersonaProtocolBase {
102
+ status: ProtocolStatus;
103
+ autostart: boolean;
104
+ session: Session;
105
+ config: PersonaTransactionProtocolConfig;
106
+ notify: boolean = true;
107
+
108
+ constructor(config: PersonaTransactionProtocolConfig) {
109
+ super();
110
+ this.config = config;
111
+ this.status = 'disconnected';
112
+ this.autostart = true;
113
+ }
114
+
115
+ public getName(): string {
116
+ return 'transaction';
117
+ }
118
+
119
+ public getPriority(): number {
120
+ return 0;
121
+ }
122
+
123
+ public async connect(session: Session): Promise<Session> {
124
+ this.setStatus('connected');
125
+ return session;
126
+ }
127
+
128
+ public async disconnect(): Promise<void> {
129
+ this.setStatus('disconnected');
130
+ this.session = null;
131
+ }
132
+
133
+ public async syncSession(session: Session): Promise<void> {
134
+ this.session = session;
135
+ }
136
+
137
+ public async send(message: Message): Promise<void> {
138
+ this.config.logger?.debug('Sending message:', message);
139
+ throw new Error('Not implemented');
140
+ }
141
+
142
+ public onTransaction(transaction: PersonaTransaction): void {
143
+ if (!this.config.onTransaction) {
144
+ this.config.logger?.error('Transaction protocol config is not set');
145
+ return;
146
+ }
147
+ const manager = new PersonaTransactionsManager(this.config);
148
+ const persistable = new PersonaPersistableTransaction(transaction, manager);
149
+ this.config.onTransaction(persistable);
150
+ }
151
+ }
152
+
153
+ export { PersonaTransactionProtocol };
154
+ export type { PersonaTransactionProtocolConfig, FinishTransactionRequest, PersonaPersistableTransaction, PersonaTransactionCallback };
@@ -1,5 +1,5 @@
1
1
  import { PersonaProtocolBase } from './base';
2
- import { Message, PersonaMessage, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
2
+ import { Message, PersonaPayload, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
3
3
 
4
4
  type AudioAnalysisData = {
5
5
  localAmplitude: number;
@@ -274,11 +274,8 @@ class PersonaWebRTCProtocol extends PersonaProtocolBase {
274
274
  this.autostart = config?.autostart ?? false;
275
275
  this.webRTCClient = new PersonaWebRTCClient(config);
276
276
  this.webRTCClient.addMessageCallback((msg: MessageEvent) => {
277
- config.logger?.debug('Received data message:', msg.data);
278
- const data = JSON.parse(msg.data) as { type: 'message' | unknown; payload: PersonaMessage | unknown };
279
- if (data.type === 'message') {
280
- this.notifyMessage(data.payload as PersonaMessage);
281
- }
277
+ const data = JSON.parse(msg.data) as PersonaPayload;
278
+ this.notifyMessage(data);
282
279
  });
283
280
  }
284
281
 
@@ -1,4 +1,4 @@
1
- import { Message, PersonaMessage, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
1
+ import { Message, PersonaPayload, PersonaProtocolBaseConfig, ProtocolStatus, Session } from '../types';
2
2
  import { PersonaProtocolBase } from './base';
3
3
 
4
4
  type PersonaWebSocketProtocolConfig = PersonaProtocolBaseConfig & {
@@ -56,14 +56,8 @@ class PersonaWebSocketProtocol extends PersonaProtocolBase {
56
56
  this.setStatus('connected');
57
57
  });
58
58
  this.webSocket.addEventListener('message', (event) => {
59
- const data = JSON.parse(event.data) as { type: 'message' | unknown; payload: PersonaMessage | unknown };
60
-
61
- if (data.type !== 'message') {
62
- return;
63
- }
64
- const message = data.payload as PersonaMessage & { thought?: string };
65
-
66
- this.notifyMessage(message?.thought ? { role: 'assistant', type: 'reasoning', text: message.thought } : message);
59
+ const data = JSON.parse(event.data) as PersonaPayload;
60
+ this.notifyMessage(data);
67
61
  });
68
62
  this.webSocket.addEventListener('close', () => {
69
63
  this.setStatus('disconnected');
package/src/runtime.tsx CHANGED
@@ -3,16 +3,20 @@ import { useExternalStoreRuntime, AppendMessage, AssistantRuntimeProvider } from
3
3
  import {
4
4
  PersonaConfig,
5
5
  PersonaMessage,
6
+ PersonaPayload,
6
7
  PersonaProtocol,
7
8
  PersonaProtocolBaseConfig,
8
9
  PersonaResponse,
10
+ PersonaTransaction,
9
11
  ProtocolStatus,
10
12
  Session,
11
13
  } from './types';
12
14
  import { parseMessages, convertMessage } from './messages';
13
15
  import {
16
+ PersonaPersistableTransaction,
14
17
  PersonaRESTProtocol,
15
18
  PersonaRESTProtocolConfig,
19
+ PersonaTransactionProtocol,
16
20
  PersonaWebRTCProtocol,
17
21
  PersonaWebRTCProtocolConfig,
18
22
  PersonaWebSocketProtocol,
@@ -49,7 +53,7 @@ function PersonaRuntimeProviderInner({
49
53
  const baseEndpoint = dev ? 'localhost:8000' : 'persona.applica.guru/api';
50
54
  const baseEndpointProtocol = dev ? 'http' : 'https';
51
55
  const baseWebSocketProtocol = dev ? 'ws' : 'wss';
52
- const availableProtocols = Object.keys(_protocols).map((key) => {
56
+ let availableProtocols = Object.keys(_protocols).map((key) => {
53
57
  switch (key) {
54
58
  case 'rest':
55
59
  const restConfig: PersonaProtocolBaseConfig | true | undefined = _protocols[key];
@@ -88,6 +92,20 @@ function PersonaRuntimeProviderInner({
88
92
  throw new Error(`Unknown protocol: ${key}`);
89
93
  }
90
94
  });
95
+
96
+ if (config.tools) {
97
+ availableProtocols.push(
98
+ new PersonaTransactionProtocol({
99
+ apiUrl: `${baseEndpointProtocol}://${baseEndpoint}`,
100
+ apiKey: config.apiKey,
101
+ agentId: config.agentId,
102
+ onTransaction: async (transaction: PersonaPersistableTransaction) => {
103
+ await transaction.invoke(config.tools!);
104
+ },
105
+ logger,
106
+ }),
107
+ );
108
+ }
91
109
  return availableProtocols;
92
110
  }
93
111
  throw new Error('Invalid protocols configuration');
@@ -109,8 +127,15 @@ function PersonaRuntimeProviderInner({
109
127
  protocolsStatus.set(protocol.getName(), status);
110
128
  setProtocolsStatus(new Map(protocolsStatus));
111
129
  });
112
- protocol.addMessageListener((message: PersonaMessage) => {
113
- setMessages((currentConversation) => parseMessages([...currentConversation, ...[{ ...message, protocol: protocol.getName() }]]));
130
+ protocol.addMessageListener((message: PersonaPayload) => {
131
+ if (message.type === 'message') {
132
+ const personaMessage = message.payload as PersonaMessage;
133
+ setMessages((currentConversation) =>
134
+ parseMessages([...currentConversation, ...[{ ...personaMessage, protocol: protocol.getName() }]]),
135
+ );
136
+ } else if (message.type === 'transaction') {
137
+ protocols.filter((p) => p !== protocol).forEach((p) => p.onTransaction(message.payload as PersonaTransaction));
138
+ }
114
139
  });
115
140
  if (protocol.autostart && protocol.status === 'disconnected') {
116
141
  logger?.debug(`Connecting to protocol: ${protocol.getName()}`);
@@ -206,9 +231,22 @@ function usePersonaRuntimeProtocol(protocol: string): PersonaProtocol | null {
206
231
  };
207
232
  }
208
233
 
234
+ function usePersonaRuntimeEndpoint(): string {
235
+ const context = useContext(PersonaRuntimeContext);
236
+ if (!context) {
237
+ throw new Error('usePersonaRuntimeEndpoint must be used within a PersonaRuntimeProvider');
238
+ }
239
+ for (const protocol of context.protocols) {
240
+ if (protocol.getName() === 'rest') {
241
+ return (protocol as PersonaRESTProtocol).config.apiUrl;
242
+ }
243
+ }
244
+ throw new Error('REST protocol not found');
245
+ }
246
+
209
247
  function usePersonaRuntimeWebRTCProtocol(): PersonaWebRTCProtocol | null {
210
248
  return usePersonaRuntimeProtocol('webrtc') as PersonaWebRTCProtocol;
211
249
  }
212
250
 
213
- export { PersonaRuntimeProvider, usePersonaRuntime, usePersonaRuntimeProtocol, usePersonaRuntimeWebRTCProtocol };
251
+ export { PersonaRuntimeProvider, usePersonaRuntimeEndpoint, usePersonaRuntime, usePersonaRuntimeProtocol, usePersonaRuntimeWebRTCProtocol };
214
252
  export type { PersonaMessage, PersonaResponse };
package/src/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { PersonaTools } from 'src/protocol';
1
2
  import { PersonaLogger } from './logging';
2
3
  import { ReactNode } from 'react';
3
4
 
@@ -17,18 +18,60 @@ export type FunctionResponse = {
17
18
  function_call_id: string;
18
19
  };
19
20
 
21
+ export type PersonaFile = {
22
+ name: string;
23
+ url: string;
24
+ contentType: string;
25
+ };
26
+
27
+ export type PersonaSession = {
28
+ id: string;
29
+ code: string;
30
+ projectId: string;
31
+ agentId: string;
32
+ currentAgentId: string;
33
+ userId: string;
34
+ status: 'active' | 'finished';
35
+ type: 'realtime' | 'async';
36
+ createdAt: string;
37
+ finishedAt: string | null;
38
+ };
39
+
40
+ export type PersonaAgentContext = {
41
+ data: unknown;
42
+ files: PersonaFile[];
43
+ session: PersonaSession;
44
+ };
45
+
46
+ export type PersonaTransaction = {
47
+ id: string;
48
+ projectId: string;
49
+ sessionId: string;
50
+ status: 'pending' | 'completed' | 'failed';
51
+ error: string | null;
52
+ functionCall: FunctionCall | null;
53
+ context: PersonaAgentContext;
54
+ };
55
+
20
56
  export type PersonaMessage = {
21
57
  id?: string | null;
22
58
  protocol?: string;
59
+ thought?: string;
23
60
  text: string;
24
- type: 'reasoning' | 'text';
61
+ type: 'reasoning' | 'text' | 'transaction';
25
62
  role: 'user' | 'assistant' | 'function';
63
+ files?: PersonaFile[];
26
64
  sessionId?: string;
27
65
  finishReason?: 'stop' | 'function_call';
28
66
  functionCalls?: FunctionCall[];
29
67
  functionResponse?: FunctionResponse;
30
68
  };
31
69
 
70
+ export type PersonaPayload = {
71
+ type: 'message' | 'transaction';
72
+ payload: PersonaMessage | PersonaTransaction;
73
+ };
74
+
32
75
  export type ModelResponse = {
33
76
  messages: PersonaMessage[];
34
77
  };
@@ -51,7 +94,7 @@ export type PersonaWebRTCConfig = PersonaBaseConfig & {
51
94
  export type Session = string | null | undefined;
52
95
  export type Message = string;
53
96
 
54
- export type MessageListenerCallback = (message: PersonaMessage) => void;
97
+ export type MessageListenerCallback = (message: PersonaPayload) => void;
55
98
  export type StatusChangeCallback = (status: ProtocolStatus) => void;
56
99
 
57
100
  export type ProtocolStatus = 'disconnected' | 'connecting' | 'connected';
@@ -71,6 +114,8 @@ export interface PersonaProtocol {
71
114
  connect: (session?: Session) => Promise<Session>;
72
115
  disconnect: () => Promise<void>;
73
116
 
117
+ onTransaction: (transaction: PersonaTransaction) => void;
118
+
74
119
  setSession: (session: Session) => Promise<void>;
75
120
 
76
121
  send: (message: Message) => Promise<void>;
@@ -95,4 +140,6 @@ export type PersonaConfig = PersonaBaseConfig &
95
140
  webrtc?: PersonaProtocolBaseConfig | true;
96
141
  websocket?: PersonaProtocolBaseConfig | true;
97
142
  };
143
+
144
+ tools?: PersonaTools;
98
145
  };