@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 +100 -549
- package/dist/client.d.ts +28 -55
- package/dist/client.js +14 -4
- package/dist/index.d.ts +0 -1
- package/dist/modules/agents.d.ts +14 -84
- package/dist/modules/agents.js +88 -243
- package/dist/modules/agents.types.d.ts +44 -0
- package/dist/modules/agents.types.js +1 -0
- package/dist/utils/socket-utils.d.ts +48 -0
- package/dist/utils/socket-utils.js +73 -0
- package/package.json +3 -2
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
|
|
18
|
+
import { createClient } from '@base44/sdk';
|
|
19
19
|
|
|
20
20
|
// Create a client instance
|
|
21
21
|
const base44 = createClient({
|
|
22
|
-
serverUrl:
|
|
23
|
-
appId:
|
|
24
|
-
token:
|
|
25
|
-
serviceToken:
|
|
26
|
-
autoInitAuth: true,
|
|
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: [
|
|
38
|
+
category: ['electronics', 'computers']
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
// Get a specific product
|
|
42
|
-
const product = await base44.entities.Product.get(
|
|
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:
|
|
46
|
+
name: 'New Product',
|
|
47
47
|
price: 99.99,
|
|
48
|
-
category:
|
|
48
|
+
category: 'electronics'
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
// Update a product
|
|
52
|
-
const updatedProduct = await base44.entities.Product.update(
|
|
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(
|
|
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:
|
|
62
|
-
{ name:
|
|
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
|
|
71
|
+
import { createClient } from '@base44/sdk';
|
|
72
72
|
|
|
73
73
|
// Create a client with service role token
|
|
74
74
|
const base44 = createClient({
|
|
75
|
-
appId:
|
|
76
|
-
token:
|
|
77
|
-
serviceToken:
|
|
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:
|
|
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
|
|
106
|
+
import { createClientFromRequest } from '@base44/sdk';
|
|
107
107
|
|
|
108
108
|
// In your server handler (Express, Next.js, etc.)
|
|
109
|
-
app.get(
|
|
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:
|
|
143
|
-
subject:
|
|
144
|
-
body:
|
|
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:
|
|
150
|
-
param2:
|
|
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:
|
|
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
|
|
172
|
-
import { getAccessToken } from
|
|
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:
|
|
177
|
-
token: getAccessToken()
|
|
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(
|
|
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(
|
|
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
|
|
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:
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
231
|
-
import { Navigate, Outlet, Route, Routes, useLocation } from
|
|
232
|
-
import { createClient } from
|
|
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:
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
406
|
-
import type { Entity, Base44Client, AuthModule } from
|
|
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:
|
|
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(
|
|
418
|
-
|
|
419
|
-
const product: Entity = await base44.entities.Product.get(
|
|
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:
|
|
432
|
-
serviceToken:
|
|
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:
|
|
451
|
+
preferences: { theme: 'dark' }
|
|
459
452
|
});
|
|
460
453
|
} else {
|
|
461
454
|
// Redirect to login
|
|
462
|
-
auth.login(
|
|
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:
|
|
472
|
+
role: 'admin' | 'editor' | 'viewer';
|
|
480
473
|
preferences?: {
|
|
481
|
-
theme:
|
|
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:
|
|
496
|
-
|
|
488
|
+
const base44 = createClient({ appId: 'your-app-id' });
|
|
489
|
+
|
|
497
490
|
try {
|
|
498
|
-
const user =
|
|
491
|
+
const user = await base44.auth.me() as User;
|
|
499
492
|
return user;
|
|
500
493
|
} catch (error) {
|
|
501
|
-
console.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:
|
|
513
|
-
|
|
505
|
+
const base44 = createClient({ appId: 'your-app-id' });
|
|
506
|
+
|
|
514
507
|
async function fetchUser() {
|
|
515
508
|
try {
|
|
516
|
-
const userData =
|
|
509
|
+
const userData = await base44.auth.me() as User;
|
|
517
510
|
setUser(userData);
|
|
518
511
|
} catch (error) {
|
|
519
|
-
console.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
|
|
530
|
+
import { createClient, Base44Error } from '@base44/sdk';
|
|
538
531
|
|
|
539
|
-
const base44 = createClient({ appId:
|
|
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(
|
|
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: [
|
|
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(
|
|
1056
|
-
const { getTestConfig } = require(
|
|
606
|
+
const { createClient } = require('@base44/sdk');
|
|
607
|
+
const { getTestConfig } = require('@base44/sdk/tests/utils/test-config');
|
|
1057
608
|
|
|
1058
|
-
describe(
|
|
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(
|
|
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
|