@base44-preview/sdk 0.7.0-pr.26.fe973bb → 0.7.0-pr.27.ff44f1a

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/README.md CHANGED
@@ -15,15 +15,15 @@ yarn add @base44/sdk
15
15
  ### Basic Setup
16
16
 
17
17
  ```javascript
18
- import { createClient } from "@base44/sdk";
18
+ import { createClient } from '@base44/sdk';
19
19
 
20
20
  // Create a client instance
21
21
  const base44 = createClient({
22
- serverUrl: "https://base44.app", // Optional, defaults to 'https://base44.app'
23
- appId: "your-app-id", // Required
24
- token: "your-user-token", // Optional, for user authentication
25
- serviceToken: "your-service-token", // Optional, for service role authentication
26
- autoInitAuth: true, // Optional, defaults to true - auto-detects tokens from URL or localStorage
22
+ serverUrl: 'https://base44.app', // Optional, defaults to 'https://base44.app'
23
+ appId: 'your-app-id', // Required
24
+ token: 'your-user-token', // Optional, for user authentication
25
+ serviceToken: 'your-service-token', // Optional, for service role authentication
26
+ autoInitAuth: true, // Optional, defaults to true - auto-detects tokens from URL or localStorage
27
27
  });
28
28
  ```
29
29
 
@@ -35,31 +35,31 @@ const products = await base44.entities.Product.list();
35
35
 
36
36
  // Filter products by category
37
37
  const filteredProducts = await base44.entities.Product.filter({
38
- category: ["electronics", "computers"],
38
+ category: ['electronics', 'computers']
39
39
  });
40
40
 
41
41
  // Get a specific product
42
- const product = await base44.entities.Product.get("product-id");
42
+ const product = await base44.entities.Product.get('product-id');
43
43
 
44
44
  // Create a new product
45
45
  const newProduct = await base44.entities.Product.create({
46
- name: "New Product",
46
+ name: 'New Product',
47
47
  price: 99.99,
48
- category: "electronics",
48
+ category: 'electronics'
49
49
  });
50
50
 
51
51
  // Update a product
52
- const updatedProduct = await base44.entities.Product.update("product-id", {
53
- price: 89.99,
52
+ const updatedProduct = await base44.entities.Product.update('product-id', {
53
+ price: 89.99
54
54
  });
55
55
 
56
56
  // Delete a product
57
- await base44.entities.Product.delete("product-id");
57
+ await base44.entities.Product.delete('product-id');
58
58
 
59
59
  // Bulk create products
60
60
  const newProducts = await base44.entities.Product.bulkCreate([
61
- { name: "Product 1", price: 19.99 },
62
- { name: "Product 2", price: 29.99 },
61
+ { name: 'Product 1', price: 19.99 },
62
+ { name: 'Product 2', price: 29.99 }
63
63
  ]);
64
64
  ```
65
65
 
@@ -68,13 +68,13 @@ const newProducts = await base44.entities.Product.bulkCreate([
68
68
  Service role authentication allows server-side applications to perform operations with elevated privileges. This is useful for administrative tasks, background jobs, and server-to-server communication.
69
69
 
70
70
  ```javascript
71
- import { createClient } from "@base44/sdk";
71
+ import { createClient } from '@base44/sdk';
72
72
 
73
73
  // Create a client with service role token
74
74
  const base44 = createClient({
75
- appId: "your-app-id",
76
- token: "user-token", // For user operations
77
- serviceToken: "service-token", // For service role operations
75
+ appId: 'your-app-id',
76
+ token: 'user-token', // For user operations
77
+ serviceToken: 'service-token' // For service role operations
78
78
  });
79
79
 
80
80
  // User operations (uses user token)
@@ -90,7 +90,7 @@ const allEntities = await base44.asServiceRole.entities.User.list();
90
90
  // Note: Service role does NOT have access to auth module for security
91
91
 
92
92
  // If no service token is provided, accessing asServiceRole throws an error
93
- const clientWithoutService = createClient({ appId: "your-app-id" });
93
+ const clientWithoutService = createClient({ appId: 'your-app-id' });
94
94
  try {
95
95
  await clientWithoutService.asServiceRole.entities.User.list();
96
96
  } catch (error) {
@@ -103,20 +103,20 @@ try {
103
103
  For server-side applications, you can create a client from incoming HTTP requests:
104
104
 
105
105
  ```javascript
106
- import { createClientFromRequest } from "@base44/sdk";
106
+ import { createClientFromRequest } from '@base44/sdk';
107
107
 
108
108
  // In your server handler (Express, Next.js, etc.)
109
- app.get("/api/data", async (req, res) => {
109
+ app.get('/api/data', async (req, res) => {
110
110
  try {
111
111
  // Extract client configuration from request headers
112
112
  const base44 = createClientFromRequest(req);
113
-
113
+
114
114
  // Headers used:
115
115
  // - Authorization: Bearer <user-token>
116
116
  // - Base44-Service-Authorization: Bearer <service-token>
117
117
  // - Base44-App-Id: <app-id>
118
118
  // - Base44-Api-Url: <custom-api-url> (optional)
119
-
119
+
120
120
  // Use appropriate authentication based on available tokens
121
121
  let data;
122
122
  if (base44.asServiceRole) {
@@ -126,7 +126,7 @@ app.get("/api/data", async (req, res) => {
126
126
  // Only user token available - use user permissions
127
127
  data = await base44.entities.PublicData.list();
128
128
  }
129
-
129
+
130
130
  res.json(data);
131
131
  } catch (error) {
132
132
  res.status(500).json({ error: error.message });
@@ -139,15 +139,15 @@ app.get("/api/data", async (req, res) => {
139
139
  ```javascript
140
140
  // Send an email using the Core integration
141
141
  const emailResult = await base44.integrations.Core.SendEmail({
142
- to: "user@example.com",
143
- subject: "Hello from Base44",
144
- body: "This is a test email sent via the Base44 SDK",
142
+ to: 'user@example.com',
143
+ subject: 'Hello from Base44',
144
+ body: 'This is a test email sent via the Base44 SDK'
145
145
  });
146
146
 
147
147
  // Use a custom integration
148
148
  const result = await base44.integrations.CustomPackage.CustomEndpoint({
149
- param1: "value1",
150
- param2: "value2",
149
+ param1: 'value1',
150
+ param2: 'value2'
151
151
  });
152
152
 
153
153
  // Upload a file
@@ -155,7 +155,7 @@ const fileInput = document.querySelector('input[type="file"]');
155
155
  const file = fileInput.files[0];
156
156
  const uploadResult = await base44.integrations.Core.UploadFile({
157
157
  file,
158
- metadata: { type: "profile-picture" },
158
+ metadata: { type: 'profile-picture' }
159
159
  });
160
160
  ```
161
161
 
@@ -168,49 +168,45 @@ The SDK provides comprehensive authentication capabilities to help you build sec
168
168
  To create a client with authentication:
169
169
 
170
170
  ```javascript
171
- import { createClient } from "@base44/sdk";
172
- import { getAccessToken } from "@base44/sdk/utils/auth-utils";
171
+ import { createClient } from '@base44/sdk';
172
+ import { getAccessToken } from '@base44/sdk/utils/auth-utils';
173
173
 
174
174
  // Create a client with authentication
175
175
  const base44 = createClient({
176
- appId: "your-app-id",
177
- token: getAccessToken(), // Automatically retrieves token from localStorage or URL
176
+ appId: 'your-app-id',
177
+ token: getAccessToken() // Automatically retrieves token from localStorage or URL
178
178
  });
179
179
 
180
180
  // Check authentication status
181
181
  const isAuthenticated = await base44.auth.isAuthenticated();
182
- console.log("Authenticated:", isAuthenticated);
182
+ console.log('Authenticated:', isAuthenticated);
183
183
 
184
184
  // Get current user information (requires authentication)
185
185
  if (isAuthenticated) {
186
186
  const user = await base44.auth.me();
187
- console.log("Current user:", user);
187
+ console.log('Current user:', user);
188
188
  }
189
189
  ```
190
190
 
191
191
  ### Login and Logout
192
192
 
193
193
  ```javascript
194
- import { createClient } from "@base44/sdk";
195
- import {
196
- getAccessToken,
197
- saveAccessToken,
198
- removeAccessToken,
199
- } from "@base44/sdk/utils/auth-utils";
194
+ import { createClient } from '@base44/sdk';
195
+ import { getAccessToken, saveAccessToken, removeAccessToken } from '@base44/sdk/utils/auth-utils';
200
196
 
201
- const base44 = createClient({ appId: "your-app-id" });
197
+ const base44 = createClient({ appId: 'your-app-id' });
202
198
 
203
199
  // Redirect to the login page
204
200
  // This will redirect to: base44.app/login?from_url=http://your-app.com/dashboard&app_id=your-app-id
205
201
  function handleLogin() {
206
- base44.auth.login("/dashboard");
202
+ base44.auth.login('/dashboard');
207
203
  }
208
204
 
209
205
  // Handle successful login (on return from Base44 login)
210
206
  function handleLoginReturn() {
211
207
  const token = getAccessToken();
212
208
  if (token) {
213
- console.log("Successfully logged in with token:", token);
209
+ console.log('Successfully logged in with token:', token);
214
210
  // The token is automatically saved to localStorage and removed from URL
215
211
  }
216
212
  }
@@ -218,7 +214,7 @@ function handleLoginReturn() {
218
214
  // Logout
219
215
  function handleLogout() {
220
216
  removeAccessToken();
221
- window.location.href = "/login";
217
+ window.location.href = '/login';
222
218
  }
223
219
  ```
224
220
 
@@ -227,13 +223,10 @@ function handleLogout() {
227
223
  Here's a complete example of implementing Base44 authentication in a React application:
228
224
 
229
225
  ```jsx
230
- import React, { createContext, useContext, useEffect, useState } from "react";
231
- import { Navigate, Outlet, Route, Routes, useLocation } from "react-router-dom";
232
- import { createClient } from "@base44/sdk";
233
- import {
234
- getAccessToken,
235
- removeAccessToken,
236
- } from "@base44/sdk/utils/auth-utils";
226
+ import React, { createContext, useContext, useEffect, useState } from 'react';
227
+ import { Navigate, Outlet, Route, Routes, useLocation } from 'react-router-dom';
228
+ import { createClient } from '@base44/sdk';
229
+ import { getAccessToken, removeAccessToken } from '@base44/sdk/utils/auth-utils';
237
230
 
238
231
  // Create AuthContext
239
232
  const AuthContext = createContext(null);
@@ -242,10 +235,10 @@ const AuthContext = createContext(null);
242
235
  function AuthProvider({ children }) {
243
236
  const [user, setUser] = useState(null);
244
237
  const [loading, setLoading] = useState(true);
245
- const [client] = useState(() =>
246
- createClient({
247
- appId: "your-app-id",
248
- token: getAccessToken(),
238
+ const [client] = useState(() =>
239
+ createClient({
240
+ appId: 'your-app-id',
241
+ token: getAccessToken()
249
242
  })
250
243
  );
251
244
 
@@ -258,12 +251,12 @@ function AuthProvider({ children }) {
258
251
  setUser(userData);
259
252
  }
260
253
  } catch (error) {
261
- console.error("Authentication error:", error);
254
+ console.error('Authentication error:', error);
262
255
  } finally {
263
256
  setLoading(false);
264
257
  }
265
258
  }
266
-
259
+
267
260
  loadUser();
268
261
  }, [client]);
269
262
 
@@ -274,7 +267,7 @@ function AuthProvider({ children }) {
274
267
  const logout = () => {
275
268
  removeAccessToken();
276
269
  setUser(null);
277
- window.location.href = "/login";
270
+ window.location.href = '/login';
278
271
  };
279
272
 
280
273
  return (
@@ -288,7 +281,7 @@ function AuthProvider({ children }) {
288
281
  function useAuth() {
289
282
  const context = useContext(AuthContext);
290
283
  if (!context) {
291
- throw new Error("useAuth must be used within an AuthProvider");
284
+ throw new Error('useAuth must be used within an AuthProvider');
292
285
  }
293
286
  return context;
294
287
  }
@@ -330,12 +323,12 @@ function Dashboard() {
330
323
  async function loadTodos() {
331
324
  try {
332
325
  // Load user-specific data using the SDK
333
- const items = await client.entities.Todo.filter({
334
- assignee: user.id,
326
+ const items = await client.entities.Todo.filter({
327
+ assignee: user.id
335
328
  });
336
329
  setTodos(items);
337
330
  } catch (error) {
338
- console.error("Failed to load todos:", error);
331
+ console.error('Failed to load todos:', error);
339
332
  } finally {
340
333
  setLoading(false);
341
334
  }
@@ -348,13 +341,13 @@ function Dashboard() {
348
341
  <div>
349
342
  <h1>Welcome, {user.name}!</h1>
350
343
  <button onClick={logout}>Logout</button>
351
-
344
+
352
345
  <h2>Your Todos</h2>
353
346
  {loading ? (
354
347
  <div>Loading todos...</div>
355
348
  ) : (
356
349
  <ul>
357
- {todos.map((todo) => (
350
+ {todos.map(todo => (
358
351
  <li key={todo.id}>{todo.title}</li>
359
352
  ))}
360
353
  </ul>
@@ -366,11 +359,11 @@ function Dashboard() {
366
359
  // Login Page
367
360
  function LoginPage() {
368
361
  const { login, user } = useAuth();
369
-
362
+
370
363
  if (user) {
371
364
  return <Navigate to="/dashboard" />;
372
365
  }
373
-
366
+
374
367
  return (
375
368
  <div>
376
369
  <h1>Login Required</h1>
@@ -402,21 +395,21 @@ function App() {
402
395
  This SDK includes TypeScript definitions out of the box:
403
396
 
404
397
  ```typescript
405
- import { createClient, Base44Error } from "@base44/sdk";
406
- import type { Entity, Base44Client, AuthModule } from "@base44/sdk";
398
+ import { createClient, Base44Error } from '@base44/sdk';
399
+ import type { Entity, Base44Client, AuthModule } from '@base44/sdk';
407
400
 
408
401
  // Create a typed client
409
402
  const base44: Base44Client = createClient({
410
- appId: "your-app-id",
403
+ appId: 'your-app-id'
411
404
  });
412
405
 
413
406
  // Using the entities module with type safety
414
407
  async function fetchProducts() {
415
408
  try {
416
409
  const products: Entity[] = await base44.entities.Product.list();
417
- console.log(products.map((p) => p.name));
418
-
419
- const product: Entity = await base44.entities.Product.get("product-id");
410
+ console.log(products.map(p => p.name));
411
+
412
+ const product: Entity = await base44.entities.Product.get('product-id');
420
413
  console.log(product.name);
421
414
  } catch (error) {
422
415
  if (error instanceof Base44Error) {
@@ -428,8 +421,8 @@ async function fetchProducts() {
428
421
  // Service role operations with TypeScript
429
422
  async function adminOperations() {
430
423
  const base44 = createClient({
431
- appId: "your-app-id",
432
- serviceToken: "service-token",
424
+ appId: 'your-app-id',
425
+ serviceToken: 'service-token'
433
426
  });
434
427
 
435
428
  // TypeScript knows asServiceRole requires a service token
@@ -447,19 +440,19 @@ async function adminOperations() {
447
440
  async function handleAuth(auth: AuthModule) {
448
441
  // Check authentication
449
442
  const isAuthenticated: boolean = await auth.isAuthenticated();
450
-
443
+
451
444
  if (isAuthenticated) {
452
445
  // Get user info
453
446
  const user: Entity = await auth.me();
454
447
  console.log(`Logged in as: ${user.name}, Role: ${user.role}`);
455
-
448
+
456
449
  // Update user
457
450
  const updatedUser: Entity = await auth.updateMe({
458
- preferences: { theme: "dark" },
451
+ preferences: { theme: 'dark' }
459
452
  });
460
453
  } else {
461
454
  // Redirect to login
462
- auth.login("/dashboard");
455
+ auth.login('/dashboard');
463
456
  }
464
457
  }
465
458
 
@@ -476,9 +469,9 @@ You can define your own entity interfaces for better type safety:
476
469
  interface User extends Entity {
477
470
  name: string;
478
471
  email: string;
479
- role: "admin" | "editor" | "viewer";
472
+ role: 'admin' | 'editor' | 'viewer';
480
473
  preferences?: {
481
- theme: "light" | "dark";
474
+ theme: 'light' | 'dark';
482
475
  notifications: boolean;
483
476
  };
484
477
  }
@@ -492,13 +485,13 @@ interface Product extends Entity {
492
485
 
493
486
  // Use your custom interfaces with the SDK
494
487
  async function getLoggedInUser(): Promise<User | null> {
495
- const base44 = createClient({ appId: "your-app-id" });
496
-
488
+ const base44 = createClient({ appId: 'your-app-id' });
489
+
497
490
  try {
498
- const user = (await base44.auth.me()) as User;
491
+ const user = await base44.auth.me() as User;
499
492
  return user;
500
493
  } catch (error) {
501
- console.error("Failed to get user:", error);
494
+ console.error('Failed to get user:', error);
502
495
  return null;
503
496
  }
504
497
  }
@@ -507,24 +500,24 @@ async function getLoggedInUser(): Promise<User | null> {
507
500
  function useBase44User() {
508
501
  const [user, setUser] = useState<User | null>(null);
509
502
  const [loading, setLoading] = useState<boolean>(true);
510
-
503
+
511
504
  useEffect(() => {
512
- const base44 = createClient({ appId: "your-app-id" });
513
-
505
+ const base44 = createClient({ appId: 'your-app-id' });
506
+
514
507
  async function fetchUser() {
515
508
  try {
516
- const userData = (await base44.auth.me()) as User;
509
+ const userData = await base44.auth.me() as User;
517
510
  setUser(userData);
518
511
  } catch (error) {
519
- console.error("Auth error:", error);
512
+ console.error('Auth error:', error);
520
513
  } finally {
521
514
  setLoading(false);
522
515
  }
523
516
  }
524
-
517
+
525
518
  fetchUser();
526
519
  }, []);
527
-
520
+
528
521
  return { user, loading };
529
522
  }
530
523
  ```
@@ -534,9 +527,9 @@ function useBase44User() {
534
527
  The SDK provides a custom `Base44Error` class for error handling:
535
528
 
536
529
  ```javascript
537
- import { createClient, Base44Error } from "@base44/sdk";
530
+ import { createClient, Base44Error } from '@base44/sdk';
538
531
 
539
- const base44 = createClient({ appId: "your-app-id" });
532
+ const base44 = createClient({ appId: 'your-app-id' });
540
533
 
541
534
  try {
542
535
  const result = await base44.entities.NonExistentEntity.list();
@@ -547,7 +540,7 @@ try {
547
540
  console.error(`Code: ${error.code}`);
548
541
  console.error(`Data: ${JSON.stringify(error.data)}`);
549
542
  } else {
550
- console.error("Unexpected error:", error);
543
+ console.error('Unexpected error:', error);
551
544
  }
552
545
  }
553
546
  ```
@@ -562,8 +555,8 @@ const result = await base44.functions.myFunction();
562
555
 
563
556
  // Invoke a function with parameters
564
557
  const result = await base44.functions.calculateTotal({
565
- items: ["item1", "item2"],
566
- discount: 0.1,
558
+ items: ['item1', 'item2'],
559
+ discount: 0.1
567
560
  });
568
561
 
569
562
  // Functions are automatically authenticated with the user token
@@ -571,447 +564,6 @@ const result = await base44.functions.calculateTotal({
571
564
  const serviceResult = await base44.asServiceRole.functions.adminFunction();
572
565
  ```
573
566
 
574
- ## AI Agents
575
-
576
- The SDK provides comprehensive support for AI agent conversations with real-time messaging capabilities.
577
-
578
- ### Basic Agent Setup
579
-
580
- ```javascript
581
- import { createClient } from "@base44/sdk";
582
-
583
- // Create a client with agents support
584
- const base44 = createClient({
585
- appId: "your-app-id",
586
- token: "your-auth-token",
587
- agents: {
588
- enableWebSocket: true, // Enable real-time updates
589
- socketUrl: "wss://base44.app/ws", // Optional: custom WebSocket URL
590
- },
591
- });
592
- ```
593
-
594
- ### Working with Agent Conversations
595
-
596
- ```javascript
597
- // Create a new conversation with an agent
598
- const conversation = await base44.agents.createConversation({
599
- agent_name: "customer-support-agent",
600
- metadata: {
601
- source: "web-app",
602
- priority: "normal",
603
- customer_id: "cust_12345",
604
- },
605
- });
606
-
607
- // Send a message to the agent
608
- const response = await base44.agents.sendMessage(conversation.id, {
609
- role: "user",
610
- content: "Hello! I need help with my account.",
611
- metadata: {
612
- timestamp: new Date().toISOString(),
613
- },
614
- });
615
-
616
- // Get conversation history
617
- const fullConversation = await base44.agents.getConversation(conversation.id);
618
- console.log("Messages:", fullConversation.messages);
619
-
620
- // List all conversations
621
- const conversations = await base44.agents.listConversations({
622
- limit: 10,
623
- sort: { created_at: -1 },
624
- });
625
- ```
626
-
627
- ### Real-Time Agent Conversations
628
-
629
- ```javascript
630
- // Subscribe to real-time updates for a conversation
631
- const unsubscribe = base44.agents.subscribeToConversation(
632
- conversation.id,
633
- (updatedConversation) => {
634
- console.log("New messages:", updatedConversation.messages);
635
-
636
- // Handle new agent responses
637
- const lastMessage =
638
- updatedConversation.messages[updatedConversation.messages.length - 1];
639
- if (lastMessage?.role === "assistant") {
640
- displayAgentMessage(lastMessage.content);
641
- }
642
- }
643
- );
644
-
645
- // Send a message and receive real-time responses
646
- await base44.agents.sendMessage(conversation.id, {
647
- role: "user",
648
- content: "Can you help me with billing questions?",
649
- });
650
-
651
- // Clean up subscription when done
652
- unsubscribe();
653
- ```
654
-
655
- ### Advanced Agent Usage
656
-
657
- ```javascript
658
- // Filter conversations by agent type
659
- const supportConversations = await base44.agents.listConversations({
660
- query: { agent_name: "support-agent" },
661
- limit: 20,
662
- });
663
-
664
- // Update conversation metadata
665
- await base44.agents.updateConversation(conversation.id, {
666
- metadata: {
667
- status: "resolved",
668
- satisfaction_rating: 5,
669
- resolution_time: "5 minutes",
670
- },
671
- });
672
-
673
- // Delete a specific message from conversation
674
- await base44.agents.deleteMessage(conversation.id, "message-id");
675
-
676
- // Check WebSocket connection status
677
- const status = base44.agents.getWebSocketStatus();
678
- console.log("WebSocket enabled:", status.enabled);
679
- console.log("WebSocket connected:", status.connected);
680
-
681
- // Manually control WebSocket connection
682
- if (status.enabled && !status.connected) {
683
- await base44.agents.connectWebSocket();
684
- }
685
-
686
- // Disconnect WebSocket when done
687
- base44.agents.disconnectWebSocket();
688
- ```
689
-
690
- ### TypeScript Support for Agents
691
-
692
- ```typescript
693
- import {
694
- createClient,
695
- AgentConversation,
696
- Message,
697
- CreateConversationPayload,
698
- } from "@base44/sdk";
699
-
700
- // Define custom conversation metadata interface
701
- interface CustomerSupportMetadata {
702
- customer_id: string;
703
- priority: "low" | "normal" | "high" | "urgent";
704
- department: "sales" | "support" | "technical";
705
- source: "web" | "mobile" | "email";
706
- }
707
-
708
- // Create typed conversation
709
- const conversation: AgentConversation = await base44.agents.createConversation({
710
- agent_name: "support-agent",
711
- metadata: {
712
- customer_id: "cust_123",
713
- priority: "high",
714
- department: "support",
715
- source: "web",
716
- } as CustomerSupportMetadata,
717
- });
718
-
719
- // Send typed message
720
- const message: Omit<Message, "id"> = {
721
- role: "user",
722
- content: "I need help with my order",
723
- timestamp: new Date().toISOString(),
724
- metadata: {
725
- intent: "order_inquiry",
726
- order_id: "ord_456",
727
- },
728
- };
729
-
730
- const response: Message = await base44.agents.sendMessage(
731
- conversation.id,
732
- message
733
- );
734
- ```
735
-
736
- ### Customer Service Chatbot Example
737
-
738
- ```javascript
739
- class CustomerServiceBot {
740
- constructor(base44Client) {
741
- this.client = base44Client;
742
- this.activeConversations = new Map();
743
- }
744
-
745
- async startConversation(customerId, initialMessage) {
746
- // Create conversation with customer context
747
- const conversation = await this.client.agents.createConversation({
748
- agent_name: "customer-service-bot",
749
- metadata: {
750
- customer_id: customerId,
751
- session_start: new Date().toISOString(),
752
- channel: "web-chat",
753
- },
754
- });
755
-
756
- // Set up real-time message handling
757
- const unsubscribe = this.client.agents.subscribeToConversation(
758
- conversation.id,
759
- (updatedConversation) => {
760
- this.handleConversationUpdate(updatedConversation);
761
- }
762
- );
763
-
764
- // Store conversation reference
765
- this.activeConversations.set(conversation.id, {
766
- conversation,
767
- unsubscribe,
768
- customerId,
769
- });
770
-
771
- // Send initial message
772
- await this.client.agents.sendMessage(conversation.id, {
773
- role: "user",
774
- content: initialMessage,
775
- metadata: { message_type: "initial_inquiry" },
776
- });
777
-
778
- return conversation.id;
779
- }
780
-
781
- handleConversationUpdate(conversation) {
782
- const lastMessage = conversation.messages[conversation.messages.length - 1];
783
-
784
- if (lastMessage?.role === "assistant") {
785
- // Display agent response to user
786
- this.displayMessage(conversation.id, lastMessage);
787
-
788
- // Check for escalation keywords
789
- if (this.shouldEscalate(lastMessage.content)) {
790
- this.escalateToHuman(conversation.id);
791
- }
792
- }
793
- }
794
-
795
- shouldEscalate(messageContent) {
796
- const escalationKeywords = [
797
- "human agent",
798
- "supervisor",
799
- "manager",
800
- "escalate",
801
- ];
802
- return escalationKeywords.some((keyword) =>
803
- messageContent.toLowerCase().includes(keyword)
804
- );
805
- }
806
-
807
- async escalateToHuman(conversationId) {
808
- await this.client.agents.updateConversation(conversationId, {
809
- metadata: {
810
- escalated: true,
811
- escalation_time: new Date().toISOString(),
812
- status: "pending_human_agent",
813
- },
814
- });
815
-
816
- console.log(`Conversation ${conversationId} escalated to human agent`);
817
- }
818
-
819
- async endConversation(conversationId) {
820
- const conversationData = this.activeConversations.get(conversationId);
821
- if (conversationData) {
822
- // Clean up subscription
823
- conversationData.unsubscribe();
824
-
825
- // Update conversation status
826
- await this.client.agents.updateConversation(conversationId, {
827
- metadata: {
828
- status: "completed",
829
- session_end: new Date().toISOString(),
830
- },
831
- });
832
-
833
- this.activeConversations.delete(conversationId);
834
- }
835
- }
836
-
837
- displayMessage(conversationId, message) {
838
- // Implement your UI message display logic here
839
- console.log(`[${conversationId}] Agent: ${message.content}`);
840
- }
841
- }
842
-
843
- // Usage
844
- const customerBot = new CustomerServiceBot(base44);
845
- const conversationId = await customerBot.startConversation(
846
- "customer_123",
847
- "Hi, I have a problem with my recent order"
848
- );
849
- ```
850
-
851
- ### Multi-Agent System Example
852
-
853
- ```javascript
854
- class MultiAgentRouter {
855
- constructor(base44Client) {
856
- this.client = base44Client;
857
- this.agents = {
858
- sales: "sales-agent",
859
- support: "support-agent",
860
- technical: "technical-agent",
861
- };
862
- }
863
-
864
- async routeQuery(userQuery, customerContext) {
865
- // Determine the best agent based on query content
866
- const department = this.classifyQuery(userQuery);
867
- const agentName = this.agents[department];
868
-
869
- // Create conversation with appropriate agent
870
- const conversation = await this.client.agents.createConversation({
871
- agent_name: agentName,
872
- metadata: {
873
- ...customerContext,
874
- department,
875
- routing_reason: `Auto-routed based on query classification`,
876
- original_query: userQuery,
877
- },
878
- });
879
-
880
- // Send initial message
881
- await this.client.agents.sendMessage(conversation.id, {
882
- role: "user",
883
- content: userQuery,
884
- metadata: {
885
- routing_department: department,
886
- confidence: this.getClassificationConfidence(userQuery, department),
887
- },
888
- });
889
-
890
- return { conversationId: conversation.id, department, agent: agentName };
891
- }
892
-
893
- classifyQuery(query) {
894
- const lowerQuery = query.toLowerCase();
895
-
896
- if (
897
- lowerQuery.includes("buy") ||
898
- lowerQuery.includes("price") ||
899
- lowerQuery.includes("plan")
900
- ) {
901
- return "sales";
902
- }
903
- if (
904
- lowerQuery.includes("api") ||
905
- lowerQuery.includes("integration") ||
906
- lowerQuery.includes("code")
907
- ) {
908
- return "technical";
909
- }
910
- return "support"; // Default to support
911
- }
912
-
913
- getClassificationConfidence(query, department) {
914
- // Simple confidence scoring (you could use ML models here)
915
- const keywords = {
916
- sales: ["buy", "purchase", "price", "plan", "upgrade", "billing"],
917
- technical: ["api", "integration", "code", "sdk", "development", "bug"],
918
- support: ["help", "problem", "issue", "account", "login", "password"],
919
- };
920
-
921
- const queryWords = query.toLowerCase().split(" ");
922
- const matches = keywords[department].filter((keyword) =>
923
- queryWords.some((word) => word.includes(keyword))
924
- );
925
-
926
- return Math.min(matches.length * 0.3, 1.0);
927
- }
928
- }
929
-
930
- // Usage
931
- const router = new MultiAgentRouter(base44);
932
- const result = await router.routeQuery(
933
- "I want to upgrade to your enterprise plan",
934
- { customer_id: "cust_789", tier: "premium" }
935
- );
936
-
937
- console.log(
938
- `Routed to ${result.department} (${result.agent}): ${result.conversationId}`
939
- );
940
- ```
941
-
942
- ### Error Handling with Agents
943
-
944
- ```javascript
945
- import { Base44Error } from "@base44/sdk";
946
-
947
- async function robustAgentInteraction() {
948
- const maxRetries = 3;
949
- let retryCount = 0;
950
-
951
- while (retryCount < maxRetries) {
952
- try {
953
- // Attempt to create conversation
954
- const conversation = await base44.agents.createConversation({
955
- agent_name: "support-agent",
956
- });
957
-
958
- // Send message with retry logic
959
- const response = await base44.agents.sendMessage(conversation.id, {
960
- role: "user",
961
- content: "Hello, I need assistance",
962
- });
963
-
964
- console.log("Successfully sent message:", response);
965
- return conversation;
966
- } catch (error) {
967
- retryCount++;
968
-
969
- if (error instanceof Base44Error) {
970
- console.error(`Agent API Error (${error.status}): ${error.message}`);
971
-
972
- // Don't retry on client errors (4xx)
973
- if (error.status >= 400 && error.status < 500) {
974
- throw error;
975
- }
976
- } else {
977
- console.error("Network or other error:", error);
978
- }
979
-
980
- if (retryCount >= maxRetries) {
981
- throw new Error(
982
- `Failed to create agent conversation after ${maxRetries} attempts`
983
- );
984
- }
985
-
986
- // Exponential backoff
987
- const delay = Math.pow(2, retryCount) * 1000;
988
- console.log(
989
- `Retrying in ${delay}ms... (attempt ${retryCount + 1}/${maxRetries})`
990
- );
991
- await new Promise((resolve) => setTimeout(resolve, delay));
992
- }
993
- }
994
- }
995
-
996
- // WebSocket error handling
997
- base44.agents.subscribeToConversation(
998
- conversationId,
999
- (conversation) => {
1000
- // Handle successful updates
1001
- console.log("Conversation updated:", conversation.id);
1002
- },
1003
- (error) => {
1004
- // Handle WebSocket errors
1005
- console.error("WebSocket error:", error);
1006
-
1007
- // Attempt to reconnect
1008
- setTimeout(() => {
1009
- base44.agents.connectWebSocket().catch(console.error);
1010
- }, 5000);
1011
- }
1012
- );
1013
- ```
1014
-
1015
567
  ## Testing
1016
568
 
1017
569
  The SDK includes comprehensive tests to ensure reliability.
@@ -1038,7 +590,6 @@ E2E tests require access to a Base44 API. To run these tests:
1038
590
 
1039
591
  1. Copy `tests/.env.example` to `tests/.env`
1040
592
  2. Fill in your Base44 API credentials in the `.env` file:
1041
-
1042
593
  ```
1043
594
  BASE44_SERVER_URL=https://base44.app
1044
595
  BASE44_APP_ID=your_app_id_here
@@ -1052,25 +603,25 @@ E2E tests require access to a Base44 API. To run these tests:
1052
603
  You can use the provided test utilities for writing your own tests:
1053
604
 
1054
605
  ```javascript
1055
- const { createClient } = require("@base44/sdk");
1056
- const { getTestConfig } = require("@base44/sdk/tests/utils/test-config");
606
+ const { createClient } = require('@base44/sdk');
607
+ const { getTestConfig } = require('@base44/sdk/tests/utils/test-config');
1057
608
 
1058
- describe("My Tests", () => {
609
+ describe('My Tests', () => {
1059
610
  let base44;
1060
-
611
+
1061
612
  beforeAll(() => {
1062
613
  const config = getTestConfig();
1063
614
  base44 = createClient({
1064
615
  serverUrl: config.serverUrl,
1065
616
  appId: config.appId,
1066
617
  });
1067
-
618
+
1068
619
  if (config.token) {
1069
620
  base44.setToken(config.token);
1070
621
  }
1071
622
  });
1072
-
1073
- test("My test", async () => {
623
+
624
+ test('My test', async () => {
1074
625
  const todos = await base44.entities.Todo.filter({}, 10);
1075
626
  expect(Array.isArray(todos)).toBe(true);
1076
627
  expect(todos.length).toBeGreaterThan(0);
@@ -1080,4 +631,4 @@ describe("My Tests", () => {
1080
631
 
1081
632
  ## License
1082
633
 
1083
- MIT
634
+ MIT