@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.
Files changed (132) hide show
  1. package/.eslintrc.cjs +11 -0
  2. package/.github/copilot-instructions.md +3 -0
  3. package/.nvmrc +1 -0
  4. package/.prettierignore +5 -0
  5. package/.prettierrc +8 -0
  6. package/CLAUDE.md +3 -0
  7. package/GEMINI.md +3 -0
  8. package/README.md +33 -0
  9. package/bitbucket-pipelines.yml +19 -0
  10. package/components.json +24 -0
  11. package/dist/bundle.cjs.js +28 -0
  12. package/dist/bundle.cjs.js.map +1 -0
  13. package/dist/bundle.es.js +5173 -0
  14. package/dist/bundle.es.js.map +1 -0
  15. package/dist/bundle.iife.js +28 -0
  16. package/dist/bundle.iife.js.map +1 -0
  17. package/dist/bundle.umd.js +28 -0
  18. package/dist/bundle.umd.js.map +1 -0
  19. package/dist/index.d.ts +8 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/logging.d.ts +18 -0
  22. package/dist/logging.d.ts.map +1 -0
  23. package/dist/messages.d.ts +9 -0
  24. package/dist/messages.d.ts.map +1 -0
  25. package/dist/projects.d.ts +17 -0
  26. package/dist/projects.d.ts.map +1 -0
  27. package/dist/protocol/base.d.ts +25 -0
  28. package/dist/protocol/base.d.ts.map +1 -0
  29. package/dist/protocol/index.d.ts +6 -0
  30. package/dist/protocol/index.d.ts.map +1 -0
  31. package/dist/protocol/rest.d.ts +25 -0
  32. package/dist/protocol/rest.d.ts.map +1 -0
  33. package/dist/protocol/transaction.d.ts +56 -0
  34. package/dist/protocol/transaction.d.ts.map +1 -0
  35. package/dist/protocol/webrtc.d.ts +60 -0
  36. package/dist/protocol/webrtc.d.ts.map +1 -0
  37. package/dist/protocol/websocket.d.ts +22 -0
  38. package/dist/protocol/websocket.d.ts.map +1 -0
  39. package/dist/runtime/context.d.ts +34 -0
  40. package/dist/runtime/context.d.ts.map +1 -0
  41. package/dist/runtime/file-attachment-adapter.d.ts +15 -0
  42. package/dist/runtime/file-attachment-adapter.d.ts.map +1 -0
  43. package/dist/runtime/handlers.d.ts +21 -0
  44. package/dist/runtime/handlers.d.ts.map +1 -0
  45. package/dist/runtime/listeners.d.ts +6 -0
  46. package/dist/runtime/listeners.d.ts.map +1 -0
  47. package/dist/runtime/protocols.d.ts +17 -0
  48. package/dist/runtime/protocols.d.ts.map +1 -0
  49. package/dist/runtime/threads.d.ts +34 -0
  50. package/dist/runtime/threads.d.ts.map +1 -0
  51. package/dist/runtime/utils.d.ts +10 -0
  52. package/dist/runtime/utils.d.ts.map +1 -0
  53. package/dist/runtime.d.ts +6 -0
  54. package/dist/runtime.d.ts.map +1 -0
  55. package/dist/storage/base.d.ts +9 -0
  56. package/dist/storage/base.d.ts.map +1 -0
  57. package/dist/storage/index.d.ts +3 -0
  58. package/dist/storage/index.d.ts.map +1 -0
  59. package/dist/storage/persona.d.ts +29 -0
  60. package/dist/storage/persona.d.ts.map +1 -0
  61. package/dist/tools.d.ts +72 -0
  62. package/dist/tools.d.ts.map +1 -0
  63. package/dist/types.d.ts +237 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/docs/README.md +13 -0
  66. package/docs/api-reference.md +16 -0
  67. package/docs/contributing.md +21 -0
  68. package/docs/customization.md +74 -0
  69. package/docs/features.md +7 -0
  70. package/docs/installation.md +9 -0
  71. package/docs/messages.md +214 -0
  72. package/docs/protocols.md +39 -0
  73. package/docs/transactions.md +121 -0
  74. package/docs/usage.md +40 -0
  75. package/jsconfig.node.json +10 -0
  76. package/package.json +82 -0
  77. package/playground/index.html +14 -0
  78. package/playground/src/app.tsx +10 -0
  79. package/playground/src/chat.tsx +117 -0
  80. package/playground/src/components/assistant-ui/assistant-modal.tsx +57 -0
  81. package/playground/src/components/assistant-ui/attachment.tsx +197 -0
  82. package/playground/src/components/assistant-ui/markdown-text.tsx +228 -0
  83. package/playground/src/components/assistant-ui/thread-list.tsx +91 -0
  84. package/playground/src/components/assistant-ui/thread.tsx +302 -0
  85. package/playground/src/components/assistant-ui/threadlist-sidebar.tsx +59 -0
  86. package/playground/src/components/assistant-ui/tool-fallback.tsx +93 -0
  87. package/playground/src/components/assistant-ui/tooltip-icon-button.tsx +42 -0
  88. package/playground/src/components/chat/logging.tsx +53 -0
  89. package/playground/src/components/ui/avatar.tsx +51 -0
  90. package/playground/src/components/ui/button.tsx +60 -0
  91. package/playground/src/components/ui/dialog.tsx +141 -0
  92. package/playground/src/components/ui/input.tsx +21 -0
  93. package/playground/src/components/ui/separator.tsx +26 -0
  94. package/playground/src/components/ui/sheet.tsx +139 -0
  95. package/playground/src/components/ui/sidebar.tsx +619 -0
  96. package/playground/src/components/ui/skeleton.tsx +13 -0
  97. package/playground/src/components/ui/tooltip.tsx +59 -0
  98. package/playground/src/hooks/theme.ts +70 -0
  99. package/playground/src/hooks/use-mobile.ts +19 -0
  100. package/playground/src/lib/utils.ts +6 -0
  101. package/playground/src/main.tsx +10 -0
  102. package/playground/src/styles.css +120 -0
  103. package/playground/src/tools.ts +149 -0
  104. package/playground/src/vite-env.d.ts +1 -0
  105. package/preview-build.sh +23 -0
  106. package/src/index.ts +7 -0
  107. package/src/logging.ts +34 -0
  108. package/src/messages.ts +202 -0
  109. package/src/projects.ts +57 -0
  110. package/src/protocol/base.ts +73 -0
  111. package/src/protocol/index.ts +5 -0
  112. package/src/protocol/rest.ts +107 -0
  113. package/src/protocol/transaction.ts +182 -0
  114. package/src/protocol/webrtc.ts +379 -0
  115. package/src/protocol/websocket.ts +111 -0
  116. package/src/runtime/context.ts +88 -0
  117. package/src/runtime/file-attachment-adapter.ts +48 -0
  118. package/src/runtime/handlers.ts +322 -0
  119. package/src/runtime/index.ts +6 -0
  120. package/src/runtime/listeners.ts +79 -0
  121. package/src/runtime/protocols.ts +169 -0
  122. package/src/runtime/threads.ts +105 -0
  123. package/src/runtime/utils.ts +46 -0
  124. package/src/runtime.tsx +334 -0
  125. package/src/storage/base.ts +13 -0
  126. package/src/storage/index.ts +2 -0
  127. package/src/storage/persona.ts +138 -0
  128. package/src/tools.ts +211 -0
  129. package/src/types.ts +284 -0
  130. package/tsconfig.json +36 -0
  131. package/tsconfig.node.json +15 -0
  132. package/vite.config.ts +74 -0
@@ -0,0 +1,214 @@
1
+ # Messages and Storage
2
+
3
+ ## Accessing Messages
4
+
5
+ ### usePersonaRuntimeMessages
6
+
7
+ The `usePersonaRuntimeMessages` hook provides a simple way to access the current list of messages managed by the Persona Chat SDK runtime. This hook returns an array of `PersonaMessage` objects, which represent the conversation history, including user, assistant, and reasoning messages.
8
+
9
+ **Usage Example:**
10
+
11
+ ```tsx
12
+ import { usePersonaRuntimeMessages } from '@applica-software-guru/persona-chat-sdk';
13
+
14
+ function MessageLogger() {
15
+ const messages = usePersonaRuntimeMessages();
16
+ return (
17
+ <div>
18
+ <h3>Messages</h3>
19
+ <pre>{JSON.stringify(messages, null, 2)}</pre>
20
+ </div>
21
+ );
22
+ }
23
+ ```
24
+
25
+ This hook must be used within a `PersonaRuntimeProvider`.
26
+
27
+ ### usePersonaRuntime and getMessages
28
+
29
+ The `usePersonaRuntime` hook gives you access to the Persona runtime context, which now includes a `getMessages` method. This method returns the current array of `PersonaMessage` objects, allowing you to programmatically retrieve the latest messages at any time.
30
+
31
+ **Usage Example:**
32
+
33
+ ```tsx
34
+ import { usePersonaRuntime } from '@applica-software-guru/persona-chat-sdk';
35
+
36
+ function MyComponent() {
37
+ const { getMessages } = usePersonaRuntime();
38
+ const messages = getMessages();
39
+ // Use messages as needed
40
+ }
41
+ ```
42
+
43
+ Both approaches are useful for building custom UI components, analytics, or debugging tools that need access to the chat history.
44
+
45
+ ---
46
+
47
+ ## Message Filtering
48
+
49
+ The `messageFilter` prop allows you to process and filter messages before they are displayed in the chat interface. This provides powerful customization capabilities for controlling what messages users see and how they are presented.
50
+
51
+ ### Basic Usage
52
+
53
+ Add a `messageFilter` function to your `PersonaRuntimeProvider`:
54
+
55
+ ```tsx
56
+ import { PersonaRuntimeProvider, MessageFilter, PersonaMessage } from '@applica-software-guru/persona-chat-sdk';
57
+
58
+ const myMessageFilter: MessageFilter = (messages: PersonaMessage[]) => {
59
+ // Process and return the filtered messages
60
+ return messages.filter((message) => message.type !== 'reasoning');
61
+ };
62
+
63
+ function App() {
64
+ return (
65
+ <PersonaRuntimeProvider apiKey="your-api-key" agentId="your-agent-id" protocols={{ rest: true }} messageFilter={myMessageFilter}>
66
+ {/* Your app content */}
67
+ </PersonaRuntimeProvider>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ### MessageFilter Type
73
+
74
+ ```typescript
75
+ type MessageFilter = (messages: PersonaMessage[]) => PersonaMessage[];
76
+ ```
77
+
78
+ The function receives an array of `PersonaMessage` objects and must return an array of `PersonaMessage` objects.
79
+
80
+ ### Common Use Cases
81
+
82
+ #### 1. Hide Reasoning Messages
83
+
84
+ ```tsx
85
+ const hideReasoningFilter: MessageFilter = (messages) => {
86
+ return messages.filter((message) => message.type !== 'reasoning');
87
+ };
88
+ ```
89
+
90
+ #### 2. Content Filtering
91
+
92
+ ```tsx
93
+ const profanityFilter: MessageFilter = (messages) => {
94
+ const bannedWords = ['spam', 'inappropriate'];
95
+ return messages.filter((message) => {
96
+ const text = message.text.toLowerCase();
97
+ return !bannedWords.some((word) => text.includes(word));
98
+ });
99
+ };
100
+ ```
101
+
102
+ #### 3. Message Limit
103
+
104
+ ```tsx
105
+ const messageLimitFilter: MessageFilter = (messages) => {
106
+ const maxMessages = 50;
107
+ return messages.length > maxMessages ? messages.slice(-maxMessages) : messages;
108
+ };
109
+ ```
110
+
111
+ #### 4. Text Transformation
112
+
113
+ ```tsx
114
+ const transformTextFilter: MessageFilter = (messages) => {
115
+ return messages.map((message) => ({
116
+ ...message,
117
+ text: message.text.replace(/\b(TODO|FIXME)\b/g, '⚠️ $1'),
118
+ }));
119
+ };
120
+ ```
121
+
122
+ #### 5. Combining Multiple Filters
123
+
124
+ ```tsx
125
+ const combinedFilter: MessageFilter = (messages) => {
126
+ let filtered = hideReasoningFilter(messages);
127
+ filtered = profanityFilter(filtered);
128
+ filtered = messageLimitFilter(filtered);
129
+ return filtered;
130
+ };
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Message Storage
136
+
137
+ The Persona Chat SDK provides a flexible message storage system that allows you to persist conversation history across sessions. By default, messages are stored in memory, but you can easily switch to localStorage or implement your own custom storage solution.
138
+
139
+ ### Storage Implementations
140
+
141
+ #### InMemoryMessageStorage (Default)
142
+
143
+ Messages are stored in memory and lost on page reload. This is the default if no storage is specified.
144
+
145
+ ```tsx
146
+ import { PersonaRuntimeProvider, InMemoryMessageStorage } from '@applica-software-guru/persona-chat-sdk';
147
+
148
+ const storage = new InMemoryMessageStorage();
149
+
150
+ <PersonaRuntimeProvider apiKey="your-api-key" agentId="your-agent-id" protocols={{ rest: true }} threads={true} messageStorage={storage}>
151
+ {/* Your app */}
152
+ </PersonaRuntimeProvider>;
153
+ ```
154
+
155
+ #### LocalStorageMessageStorage
156
+
157
+ Messages persist across page reloads using browser localStorage.
158
+
159
+ ```tsx
160
+ import { PersonaRuntimeProvider, LocalStorageMessageStorage } from '@applica-software-guru/persona-chat-sdk';
161
+
162
+ const storage = new LocalStorageMessageStorage('my_app_messages_');
163
+
164
+ <PersonaRuntimeProvider apiKey="your-api-key" agentId="your-agent-id" protocols={{ rest: true }} threads={true} messageStorage={storage}>
165
+ {/* Your app */}
166
+ </PersonaRuntimeProvider>;
167
+ ```
168
+
169
+ ### Custom Storage Implementation
170
+
171
+ You can implement your own storage solution by implementing the `MessageStorage` interface:
172
+
173
+ ```tsx
174
+ import { MessageStorage, PersonaMessage, Session } from '@applica-software-guru/persona-chat-sdk';
175
+
176
+ class CustomMessageStorage implements MessageStorage {
177
+ async saveMessages(sessionId: Session, messages: PersonaMessage[]): Promise<void> {
178
+ // Your custom save logic (e.g., IndexedDB, remote API)
179
+ await fetch('/api/save-messages', {
180
+ method: 'POST',
181
+ body: JSON.stringify({ sessionId, messages }),
182
+ });
183
+ }
184
+
185
+ async loadMessages(sessionId: Session): Promise<PersonaMessage[]> {
186
+ // Your custom load logic
187
+ const response = await fetch(`/api/load-messages/${sessionId}`);
188
+ return await response.json();
189
+ }
190
+
191
+ async deleteMessages(sessionId: Session): Promise<void> {
192
+ // Your custom delete logic
193
+ await fetch(`/api/delete-messages/${sessionId}`, { method: 'DELETE' });
194
+ }
195
+
196
+ async clearAll(): Promise<void> {
197
+ // Clear all messages
198
+ await fetch('/api/clear-all-messages', { method: 'DELETE' });
199
+ }
200
+
201
+ async getAllSessionIds(): Promise<Session[]> {
202
+ // Get all session IDs
203
+ const response = await fetch('/api/session-ids');
204
+ return await response.json();
205
+ }
206
+ }
207
+
208
+ const customStorage = new CustomMessageStorage();
209
+
210
+ <PersonaRuntimeProvider
211
+ messageStorage={customStorage}
212
+ // ... other props
213
+ />;
214
+ ```
@@ -0,0 +1,39 @@
1
+ # Protocols
2
+
3
+ The Persona Chat SDK supports multiple communication protocols to provide flexibility and performance. These protocols can work together, sharing the same session and data, to ensure the best possible experience.
4
+
5
+ ## Protocols Overview
6
+
7
+ ### REST
8
+
9
+ - **Description**: A simple and reliable protocol for sending and receiving data.
10
+ - **Use Case**: Ideal for applications where real-time communication is not critical.
11
+
12
+ ### WebSocket
13
+
14
+ - **Description**: A full-duplex communication protocol that enables real-time interaction between the client and server.
15
+ - **Use Case**: Suitable for scenarios requiring low-latency communication, such as live chat applications.
16
+
17
+ ### WebRTC
18
+
19
+ - **Description**: A peer-to-peer communication protocol designed primarily for ultra-fast audio sessions, while also supporting high-speed messaging with minimal latency.
20
+ - **Use Case**: Perfect for real-time, interactive applications where rapid audio communication and responsiveness are critical.
21
+ - **Why WebRTC?**: By creating direct peer-to-peer connections, WebRTC eliminates unnecessary server delays, ensuring the fastest possible audio sessions and seamless message exchanges.
22
+
23
+ **Pro Tip**: For optimal audio performance, make sure WebRTC is enabled in the `protocols` configuration of your application.
24
+
25
+ ---
26
+
27
+ ## How Protocols Work Together
28
+
29
+ The Persona Chat SDK runtime is designed to use multiple protocols simultaneously, ensuring flexibility and reliability. Here’s how it works:
30
+
31
+ 1. **Shared Session**: All protocols share the same session and operate on the same data, ensuring consistency across communication channels.
32
+ 2. **Protocol Selection**: The runtime automatically selects the fastest and most reliable protocol from the list of enabled protocols. For example:
33
+ - If WebRTC is available and started, it will be prioritized for its ultra-low latency.
34
+ - If WebRTC is not available, WebSocket will be used for real-time communication.
35
+ - REST will act as a fallback for non-real-time communication.
36
+ 3. **WebRTC Startup**: WebRTC requires manual startup by the user (e.g., clicking a microphone icon to enable audio/video). Once started, WebRTC participates in the list of reliable protocols and is used for the fastest communication.
37
+ 4. **Seamless Integration**: Even if WebRTC is not started, other protocols like WebSocket and REST will continue to function, ensuring uninterrupted communication.
38
+
39
+ This design allows the Persona Chat SDK to adapt dynamically to the available protocols, providing the best possible performance and reliability.
@@ -0,0 +1,121 @@
1
+ # Transactions and Tools
2
+
3
+ The Transaction Protocol in the Persona Chat SDK is designed to handle structured interactions between the client and the Persona API. It allows you to define and execute specific operations (tools) in response to function calls.
4
+
5
+ ## How It Works
6
+
7
+ 1. **Transaction Handling**: The protocol listens for incoming transactions and invokes the appropriate tool based on the function call.
8
+ 2. **Session Management**: It shares the same session as other protocols, ensuring consistency.
9
+ 3. **Custom Logic**: You can define custom tools to handle specific function calls.
10
+
11
+ ## Usage Example
12
+
13
+ To enable the Transaction Protocol, include it in the `protocols` configuration of the `PersonaRuntimeProvider`:
14
+
15
+ ```tsx
16
+ <PersonaRuntimeProvider
17
+ dev
18
+ logger={logger}
19
+ protocols={{
20
+ transaction: async (transaction) => {
21
+ await transaction.invoke({
22
+ get_user_agent: () => navigator.userAgent || 'unknown',
23
+ get_client_date: () => ({ date: new Date().toISOString() }),
24
+ });
25
+ },
26
+ }}
27
+ session="your-session-id"
28
+ apiKey="your-api-key"
29
+ agentId="your-agent-id"
30
+ >
31
+ <YourComponent />
32
+ </PersonaRuntimeProvider>
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Managing Tools
38
+
39
+ ### Using the `tools` Prop in PersonaRuntimeProvider
40
+
41
+ The `tools` prop allows you to define custom tools that the Transaction Protocol can invoke in response to function calls.
42
+
43
+ #### 1. As an Object (Legacy, Backward Compatible)
44
+
45
+ > **Important:** When using the legacy object format, your agent configuration must also include the tool schema for each tool. If the schema is missing, the configured tools will not work as expected. This is not required when using the array format with `createTool`.
46
+
47
+ ```tsx
48
+ <PersonaRuntimeProvider
49
+ tools={{
50
+ get_user_agent: () => navigator.userAgent || 'unknown',
51
+ get_client_date: () => ({ date: new Date().toISOString() }),
52
+ }}
53
+ ...otherProps
54
+ />
55
+ ```
56
+
57
+ #### 2. As an Array of Tool Instances (Recommended)
58
+
59
+ For better type safety, schema support, and documentation, you can define tools using the `createTool` utility:
60
+
61
+ ```tsx
62
+ import { createTool } from '@applica-software-guru/persona-chat-sdk';
63
+
64
+ const tools = [
65
+ createTool({
66
+ name: 'sum',
67
+ title: 'Sum two numbers',
68
+ description: 'Sums two numbers and returns the result.',
69
+ parameters: {
70
+ a: { type: 'number', description: 'First number to sum', required: true },
71
+ b: { type: 'number', description: 'Second number to sum', required: true },
72
+ },
73
+ output: {
74
+ result: { type: 'number', description: 'Sum of the two numbers' },
75
+ },
76
+ implementation: async (a: number, b: number) => {
77
+ return { result: a + b };
78
+ },
79
+ }),
80
+ ];
81
+
82
+ <PersonaRuntimeProvider
83
+ tools={tools}
84
+ ...otherProps
85
+ />
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Advanced Transaction Handling
91
+
92
+ You can manage transactions manually by inspecting the function call and executing the `complete` or `fail` methods.
93
+
94
+ ```tsx
95
+ <PersonaRuntimeProvider
96
+ protocols={{
97
+ transaction: async (transaction) => {
98
+ const { functionCall, persistable } = transaction;
99
+
100
+ try {
101
+ if (functionCall.name === 'get_user_agent') {
102
+ const result = navigator.userAgent || 'unknown';
103
+ await persistable.complete(result);
104
+ } else {
105
+ throw new Error(`Unknown function call: ${functionCall.name}`);
106
+ }
107
+ } catch (error) {
108
+ await persistable.fail({ error: error.message });
109
+ }
110
+ },
111
+ }}
112
+ ...
113
+ />
114
+ ```
115
+
116
+ ## Best Practices
117
+
118
+ 1. **Tool Naming**: Use descriptive names.
119
+ 2. **Error Handling**: Handle errors gracefully.
120
+ 3. **Testing**: Test tools thoroughly.
121
+ 4. **Security**: Avoid exposing sensitive data.
package/docs/usage.md ADDED
@@ -0,0 +1,40 @@
1
+ # Usage
2
+
3
+ Here’s an example of how to use the Persona SDK in your chat application:
4
+
5
+ ```typescript
6
+ import dynamic from 'next/dynamic';
7
+
8
+ const PersonaRuntimeProvider = dynamic(() => import('@applica-software-guru/persona-chat-sdk').then((mod) => mod.PersonaRuntimeProvider), {
9
+ ssr: false,
10
+ });
11
+
12
+ const logger = new PersonaConsoleLogger();
13
+
14
+ function Chat() {
15
+ return (
16
+ <PersonaRuntimeProvider
17
+ dev
18
+ logger={logger}
19
+ protocols={{
20
+ rest: true,
21
+ webrtc: true,
22
+ websocket: true,
23
+ }}
24
+ session={'<session-id>'}
25
+ apiKey="<api-key>"
26
+ agentId={'<agent-name>'}
27
+ >
28
+ <div className="h-dvh w-full">
29
+ <Thread />
30
+ </div>
31
+ </PersonaRuntimeProvider>
32
+ );
33
+ }
34
+ ```
35
+
36
+ **Note**: When using WebRTC, it is recommended to import `PersonaRuntimeProvider` dynamically with `ssr: false` (as shown above) to ensure compatibility with server-side rendering frameworks like Next.js.
37
+
38
+ ### Development Mode
39
+
40
+ Use the `dev` prop to enable development mode. This redirects all traffic to a local installation of Persona (e.g., `localhost:8000`).
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowSyntheticDefaultImports": true,
4
+ "composite": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "Node",
7
+ "resolveJsonModule": true
8
+ },
9
+ "include": ["vite.config.js", "package.json"]
10
+ }
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@applica-software-guru/persona-chat-sdk",
3
+ "private": false,
4
+ "version": "0.1.102",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc --outDir dist && vite build",
9
+ "preview": "vite preview",
10
+ "lint": "eslint . --ext .ts,.tsx",
11
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
12
+ "format": "prettier --write ."
13
+ },
14
+ "devDependencies": {
15
+ "@assistant-ui/react-markdown": "^0.11.6",
16
+ "@radix-ui/react-avatar": "^1.1.11",
17
+ "@radix-ui/react-tooltip": "^1.2.8",
18
+ "@radix-ui/react-separator": "^1.1.8",
19
+ "@tailwindcss/vite": "^4.0.17",
20
+ "@types/inflection": "^1.13.2",
21
+ "@types/lodash": "^4.17.15",
22
+ "@types/node": "^20.12.13",
23
+ "@types/react-dom": "^19.1.1",
24
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
25
+ "@typescript-eslint/parser": "^7.18.0",
26
+ "@vitejs/plugin-react": "^4.3.0",
27
+ "class-variance-authority": "^0.7.1",
28
+ "clsx": "^2.1.1",
29
+ "eslint": "^8.25.0",
30
+ "eslint-config-prettier": "^8.10.0",
31
+ "eslint-config-react-app": "7.0.1",
32
+ "eslint-plugin-export": "^0.1.2",
33
+ "eslint-plugin-filenames": "^1.3.2",
34
+ "eslint-plugin-import": "^2.26.0",
35
+ "eslint-plugin-jsx-a11y": "^6.6.1",
36
+ "eslint-plugin-prettier": "^4.2.1",
37
+ "eslint-plugin-react": "^7.31.10",
38
+ "eslint-plugin-react-hooks": "^4.6.0",
39
+ "eslint-plugin-react-refresh": "^0.4.19",
40
+ "eslint-plugin-sort-exports": "^0.9.1",
41
+ "husky": "^9.0.11",
42
+ "jsdom": "^22.1.0",
43
+ "lodash": "^4.17.21",
44
+ "lucide-react": "^0.485.0",
45
+ "prettier": "^2.8.8",
46
+ "react": "^19.0.0",
47
+ "react-dom": "^19.0.0",
48
+ "react-markdown": "^10.0.1",
49
+ "remark-gfm": "^4.0.1",
50
+ "tailwind-merge": "^3.2.0",
51
+ "tailwindcss": "^4.0.17",
52
+ "tw-animate-css": "^1.2.8",
53
+ "typescript": "^5.4.5",
54
+ "vite": "^5.2.12",
55
+ "vite-plugin-compression": "^0.5.1",
56
+ "vite-plugin-dts": "^2.3.0",
57
+ "vite-plugin-linter": "^2.0.2",
58
+ "vitest": "^1.6.0"
59
+ },
60
+ "peerDependencies": {
61
+ "@assistant-ui/react": "^0.11.47",
62
+ "@radix-ui/react-dialog": "^1.1.15",
63
+ "@radix-ui/react-slot": "^1.2.4",
64
+ "react": "^18 || ^19 || ^19.0.0-rc",
65
+ "react-dom": "^18 || ^19 || ^19.0.0-rc",
66
+ "rehype-raw": "^7.0.0",
67
+ "zustand": "^5.0.9"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "react-dom": {
71
+ "optional": false
72
+ }
73
+ },
74
+ "dependencies": {},
75
+ "keywords": [
76
+ "persona-chat-sdk"
77
+ ],
78
+ "main": "dist/bundle.cjs.js",
79
+ "module": "dist/bundle.es.js",
80
+ "types": "dist/index.d.ts",
81
+ "typings": "dist/index.d.ts"
82
+ }
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <link href="/src/styles.css" rel="stylesheet">
8
+ <title>Persona SDK</title>
9
+ </head>
10
+ <body>
11
+ <div id="app"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,10 @@
1
+ function App() {
2
+ return (
3
+ <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
4
+ <h1 className="text-4xl font-bold text-gray-800">Hello, world!</h1>
5
+ <p className="mt-4 text-lg text-gray-600">This is a simple React app.</p>
6
+ </div>
7
+ );
8
+ }
9
+
10
+ export default App;
@@ -0,0 +1,117 @@
1
+ import { Thread } from '@/components/assistant-ui/thread';
2
+ import { PersonaRuntimeProvider, PersonaConsoleLogger, Session } from '@applica-software-guru/persona-chat-sdk';
3
+ import { useMemo } from 'react';
4
+ import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
5
+ import { ThreadListSidebar } from '@/components/assistant-ui/threadlist-sidebar';
6
+ import { SunIcon, MoonIcon, RefreshCcwDot } from 'lucide-react';
7
+ import { useColorScheme } from './hooks/theme';
8
+
9
+ const logger = new PersonaConsoleLogger();
10
+
11
+ function generateSID() {
12
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
13
+ let sid = '';
14
+ for (let i = 0; i < 16; i++) {
15
+ sid += chars.charAt(Math.floor(Math.random() * chars.length));
16
+ }
17
+ return sid;
18
+ }
19
+
20
+ function getQueryParam(param: string): string | null {
21
+ const urlParams = new URLSearchParams(window.location.search);
22
+ return urlParams.get(param);
23
+ }
24
+
25
+ function Chat() {
26
+ const sidebar = getQueryParam('sidebar') === 'true';
27
+ const enableAttachments = getQueryParam('enableAttachments') !== 'false';
28
+ const agentId = getQueryParam('agentId');
29
+ const userId = getQueryParam('userId') || 'anonymous';
30
+ const apiKey = getQueryParam('apiKey');
31
+ const sid = getQueryParam('sid');
32
+
33
+ const session = useMemo((): Session => {
34
+ if (sid) {
35
+ return sid;
36
+ }
37
+ return generateSID();
38
+ }, [sid]);
39
+
40
+ return (
41
+ <PersonaRuntimeProvider
42
+ // dev
43
+ // baseUrl="http://localhost:8000"
44
+ logger={logger}
45
+ context={{
46
+ data: {
47
+ username: 'Roberto',
48
+ userAgent: 'Playground Client v1.0',
49
+ },
50
+ }}
51
+ tools={[]}
52
+ protocols={{
53
+ rest: true,
54
+ webrtc: false,
55
+ websocket: true,
56
+ }}
57
+ session={session}
58
+ apiKey={apiKey!}
59
+ userId={userId}
60
+ agentId={agentId!}
61
+ enableAttachments={enableAttachments}
62
+ threads={sidebar}
63
+ onThreadCreate={(threadId) => {
64
+ logger.info('Thread created:', threadId);
65
+ }}
66
+ onThreadSwitch={(threadId) => {
67
+ logger.info('Switched to thread:', threadId);
68
+ }}
69
+ onThreadRename={(threadId, newTitle) => {
70
+ logger.info('Thread renamed:', threadId, newTitle);
71
+ }}
72
+ onThreadArchive={(threadId) => {
73
+ logger.info('Thread archived:', threadId);
74
+ }}
75
+ onThreadDelete={(threadId) => {
76
+ logger.info('Thread deleted:', threadId);
77
+ }}
78
+ >
79
+ {sidebar ? (
80
+ <SidebarProvider>
81
+ <div className="flex h-dvh w-full">
82
+ <ThreadListSidebar />
83
+ <SidebarInset>
84
+ <SidebarTrigger className="absolute top-4 left-4" />
85
+ <ThemeToggle />
86
+ <Thread />
87
+ </SidebarInset>
88
+ </div>
89
+ </SidebarProvider>
90
+ ) : (
91
+ <div className="relative h-dvh w-full">
92
+ <ThemeToggle />
93
+ <Thread />
94
+ </div>
95
+ )}
96
+ </PersonaRuntimeProvider>
97
+ );
98
+ }
99
+
100
+ function ThemeToggle() {
101
+ const { theme, toggle } = useColorScheme();
102
+ const title = theme === 'auto' ? 'System theme (auto)' : theme === 'dark' ? 'Dark mode' : 'Light mode';
103
+
104
+ return (
105
+ <button
106
+ onClick={toggle}
107
+ aria-label={`Toggle theme, current: ${title}`}
108
+ title={`Toggle theme, current: ${title}`}
109
+ type="button"
110
+ className="absolute top-4 right-4 z-50 pointer-events-auto inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-card p-2 text-foreground shadow-sm hover:cursor-pointer"
111
+ >
112
+ {theme === 'dark' ? <MoonIcon /> : theme === 'light' ? <SunIcon /> : <RefreshCcwDot />}
113
+ </button>
114
+ );
115
+ }
116
+
117
+ export { Chat };