@base44-preview/sdk 0.8.18-pr.91.cfad1b0 → 0.8.19-pr.126.c537ed8

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/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl } from
4
4
  export { createClient, createClientFromRequest, Base44Error, getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, };
5
5
  export type { Base44Client, CreateClientConfig, CreateClientOptions, Base44ErrorJSON, };
6
6
  export * from "./types.js";
7
- export type { EntitiesModule, EntityHandler, RealtimeEventType, RealtimeEvent, RealtimeCallback, } from "./modules/entities.types.js";
7
+ export type { EntitiesModule, EntityHandler, EntityRecord, EntityTypeRegistry, RealtimeEventType, RealtimeEvent, RealtimeCallback, } from "./modules/entities.types.js";
8
8
  export type { AuthModule, LoginResponse, RegisterParams, VerifyOtpParams, ChangePasswordParams, ResetPasswordParams, User, } from "./modules/auth.types.js";
9
9
  export type { IntegrationsModule, IntegrationPackage, IntegrationEndpointFunction, CoreIntegrations, InvokeLLMParams, GenerateImageParams, GenerateImageResult, UploadFileParams, UploadFileResult, SendEmailParams, SendEmailResult, ExtractDataFromUploadedFileParams, ExtractDataFromUploadedFileResult, UploadPrivateFileParams, UploadPrivateFileResult, CreateFileSignedUrlParams, CreateFileSignedUrlResult, } from "./modules/integrations.types.js";
10
- export type { FunctionsModule } from "./modules/functions.types.js";
11
- export type { AgentsModule, AgentConversation, AgentMessage, AgentMessageReasoning, AgentMessageToolCall, AgentMessageUsage, AgentMessageCustomContext, AgentMessageMetadata, CreateConversationParams, } from "./modules/agents.types.js";
10
+ export type { FunctionsModule, FunctionNameRegistry, } from "./modules/functions.types.js";
11
+ export type { AgentsModule, AgentNameRegistry, AgentConversation, AgentMessage, AgentMessageReasoning, AgentMessageToolCall, AgentMessageUsage, AgentMessageCustomContext, AgentMessageMetadata, CreateConversationParams, } from "./modules/agents.types.js";
12
12
  export type { AppLogsModule } from "./modules/app-logs.types.js";
13
13
  export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
14
14
  export type { ConnectorsModule } from "./modules/connectors.types.js";
@@ -3,6 +3,8 @@ export function createAgentsModule({ axios, getSocket, appId, serverUrl, token,
3
3
  const baseURL = `/apps/${appId}/agents`;
4
4
  // Track active conversations
5
5
  const currentConversations = {};
6
+ // Stores client tool handlers keyed by conversation ID
7
+ const clientToolHandlers = {};
6
8
  const getConversations = () => {
7
9
  return axios.get(`${baseURL}/conversations`);
8
10
  };
@@ -20,6 +22,60 @@ export function createAgentsModule({ axios, getSocket, appId, serverUrl, token,
20
22
  const addMessage = async (conversation, message) => {
21
23
  return axios.post(`${baseURL}/conversations/v2/${conversation.id}/messages`, message);
22
24
  };
25
+ const registerClientToolHandlers = (conversationId, handlers) => {
26
+ clientToolHandlers[conversationId] = {
27
+ ...(clientToolHandlers[conversationId] || {}),
28
+ ...handlers,
29
+ };
30
+ };
31
+ const submitToolResults = (conversationId, results) => {
32
+ return axios.post(`${baseURL}/conversations/${conversationId}/client-tool-results`, { results });
33
+ };
34
+ const handlePendingClientTools = async (conversationId, message) => {
35
+ var _a;
36
+ if (!(message === null || message === void 0 ? void 0 : message.tool_calls))
37
+ return false;
38
+ const pendingCalls = message.tool_calls.filter((tc) => tc.status === "pending_client_execution");
39
+ if (pendingCalls.length === 0)
40
+ return false;
41
+ const handlers = clientToolHandlers[conversationId];
42
+ if (!handlers)
43
+ return false;
44
+ const results = [];
45
+ for (const tc of pendingCalls) {
46
+ const handler = handlers[tc.name];
47
+ if (!handler) {
48
+ results.push({
49
+ tool_call_id: tc.id,
50
+ result: `Error: No handler registered for client tool '${tc.name}'`,
51
+ });
52
+ continue;
53
+ }
54
+ try {
55
+ const args = JSON.parse(tc.arguments_string);
56
+ const context = {
57
+ appId,
58
+ conversationId,
59
+ toolCallId: tc.id,
60
+ toolName: tc.name,
61
+ messages: ((_a = currentConversations[conversationId]) === null || _a === void 0 ? void 0 : _a.messages) || [],
62
+ };
63
+ const result = await handler(args, context);
64
+ results.push({
65
+ tool_call_id: tc.id,
66
+ result: typeof result === "string" ? result : JSON.stringify(result),
67
+ });
68
+ }
69
+ catch (error) {
70
+ results.push({
71
+ tool_call_id: tc.id,
72
+ result: `Error executing client tool '${tc.name}': ${error.message}`,
73
+ });
74
+ }
75
+ }
76
+ await submitToolResults(conversationId, results);
77
+ return true;
78
+ };
23
79
  const subscribeToConversation = (conversationId, onUpdate) => {
24
80
  const room = `/agent-conversations/${conversationId}`;
25
81
  const socket = getSocket();
@@ -49,6 +105,8 @@ export function createAgentsModule({ axios, getSocket, appId, serverUrl, token,
49
105
  messages: updatedMessages,
50
106
  };
51
107
  onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(currentConversations[conversationId]);
108
+ // Automatically handle pending client tool calls
109
+ await handlePendingClientTools(conversationId, message);
52
110
  }
53
111
  }
54
112
  },
@@ -71,6 +129,9 @@ export function createAgentsModule({ axios, getSocket, appId, serverUrl, token,
71
129
  listConversations,
72
130
  createConversation,
73
131
  addMessage,
132
+ registerClientToolHandlers,
133
+ submitToolResults,
134
+ handlePendingClientTools,
74
135
  subscribeToConversation,
75
136
  getWhatsAppConnectURL,
76
137
  };
@@ -1,6 +1,16 @@
1
1
  import { AxiosInstance } from "axios";
2
2
  import { RoomsSocket } from "../utils/socket-utils.js";
3
3
  import { ModelFilterParams } from "../types.js";
4
+ /**
5
+ * Registry of agent names.
6
+ * Augment this interface to enable autocomplete for agent names.
7
+ */
8
+ export interface AgentNameRegistry {
9
+ }
10
+ /**
11
+ * Agent name type - uses registry keys if augmented, otherwise string.
12
+ */
13
+ export type AgentName = keyof AgentNameRegistry extends never ? string : keyof AgentNameRegistry;
4
14
  /**
5
15
  * Reasoning information for an agent message.
6
16
  *
@@ -27,7 +37,7 @@ export interface AgentMessageToolCall {
27
37
  /** Arguments passed to the tool as JSON string. */
28
38
  arguments_string: string;
29
39
  /** Status of the tool call. */
30
- status: "running" | "success" | "error" | "stopped";
40
+ status: "running" | "success" | "error" | "stopped" | "pending_client_execution";
31
41
  /** Results from the tool call. */
32
42
  results?: string;
33
43
  }
@@ -127,10 +137,41 @@ export interface AgentMessage {
127
137
  */
128
138
  export interface CreateConversationParams {
129
139
  /** The name of the agent to create a conversation with. */
130
- agent_name: string;
140
+ agent_name: AgentName;
131
141
  /** Optional metadata to attach to the conversation. */
132
142
  metadata?: Record<string, any>;
133
143
  }
144
+ /**
145
+ * Context passed to client tool handlers during execution.
146
+ */
147
+ export interface ClientToolContext {
148
+ /** The app ID. */
149
+ appId: string;
150
+ /** The conversation ID. */
151
+ conversationId: string;
152
+ /** The unique tool call ID. */
153
+ toolCallId: string;
154
+ /** The tool name. */
155
+ toolName: string;
156
+ /** The conversation messages so far. */
157
+ messages: AgentMessage[];
158
+ }
159
+ /**
160
+ * A client tool handler function.
161
+ *
162
+ * Receives parsed arguments and execution context, returns a string result
163
+ * (or an object that will be JSON.stringified).
164
+ */
165
+ export type ClientToolHandler = (args: Record<string, any>, context: ClientToolContext) => Promise<string | Record<string, any>> | string | Record<string, any>;
166
+ /**
167
+ * Result of a client tool execution, to be submitted back to the server.
168
+ */
169
+ export interface ClientToolResult {
170
+ /** The tool call ID this result corresponds to. */
171
+ tool_call_id: string;
172
+ /** The result string. */
173
+ result: string;
174
+ }
134
175
  /**
135
176
  * Configuration for creating the agents module.
136
177
  * @internal
@@ -171,7 +212,7 @@ export interface AgentsModuleConfig {
171
212
  *
172
213
  * This module is available to use with a client in all authentication modes:
173
214
  *
174
- * - **Anonymous or User authentication** (`base44.agents`): Access is scoped to the current user's permissions. Anonymous users can create conversations but can't retrieve them later, while authenticated users can access conversations they created.
215
+ * - **Anonymous or User authentication** (`base44.agents`): Access is scoped to the current user's permissions. Users must be authenticated to create and access conversations.
175
216
  * - **Service role authentication** (`base44.asServiceRole.agents`): Operations have elevated admin-level permissions. Can access all conversations that the app's admin role has access to.
176
217
  *
177
218
  */
@@ -200,6 +241,8 @@ export interface AgentsModule {
200
241
  * Retrieves a single conversation using its unique identifier. To retrieve
201
242
  * all conversations, use {@linkcode getConversations | getConversations()} To filter, sort, or paginate conversations, use {@linkcode listConversations | listConversations()}.
202
243
  *
244
+ * This function returns the complete stored conversation including full tool call results, even for large responses.
245
+ *
203
246
  * @param conversationId - The unique identifier of the conversation.
204
247
  * @returns Promise resolving to the conversation, or undefined if not found.
205
248
  *
@@ -292,12 +335,84 @@ export interface AgentsModule {
292
335
  * ```
293
336
  */
294
337
  addMessage(conversation: AgentConversation, message: Partial<AgentMessage>): Promise<AgentMessage>;
338
+ /**
339
+ * Registers handler functions for client-side tools defined in the agent configuration.
340
+ *
341
+ * Client tools are tools that execute in the browser rather than on the server.
342
+ * They are defined by the app builder in the agent configuration (name, description,
343
+ * parameters). The SDK caller provides the handler functions that run locally when
344
+ * the agent invokes these tools.
345
+ *
346
+ * When subscribed to the conversation via {@linkcode subscribeToConversation | subscribeToConversation()},
347
+ * client tool calls are handled automatically — the SDK detects pending client tool calls,
348
+ * executes the registered handlers, and submits results back to the server.
349
+ *
350
+ * For user info inside a handler, call `base44.auth.me()` from the handler body.
351
+ *
352
+ * @param conversationId - The conversation ID to register handlers for.
353
+ * @param handlers - Map of tool name to handler function. Each handler receives
354
+ * `(args, context)` where `args` are the parsed tool arguments and `context`
355
+ * includes `appId`, `conversationId`, `toolCallId`, `toolName`, and `messages`.
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * base44.agents.registerClientToolHandlers(conversation.id, {
360
+ * get_current_location: async ({ accuracy }, { conversationId, messages }) => {
361
+ * const pos = await new Promise((resolve, reject) =>
362
+ * navigator.geolocation.getCurrentPosition(resolve, reject, {
363
+ * enableHighAccuracy: accuracy === 'high'
364
+ * })
365
+ * );
366
+ * return JSON.stringify({
367
+ * lat: pos.coords.latitude,
368
+ * lng: pos.coords.longitude
369
+ * });
370
+ * },
371
+ * get_clipboard_text: async () => {
372
+ * return await navigator.clipboard.readText();
373
+ * }
374
+ * });
375
+ * ```
376
+ */
377
+ registerClientToolHandlers(conversationId: string, handlers: Record<string, ClientToolHandler>): void;
378
+ /**
379
+ * Submits results for client-side tool calls.
380
+ *
381
+ * This is called automatically when using {@linkcode subscribeToConversation | subscribeToConversation()}
382
+ * with registered handlers. You only need to call this directly if you are
383
+ * implementing custom tool call handling logic outside of the subscription flow.
384
+ *
385
+ * @param conversationId - The conversation ID.
386
+ * @param results - Array of tool call results.
387
+ */
388
+ submitToolResults(conversationId: string, results: ClientToolResult[]): Promise<any>;
389
+ /**
390
+ * Processes pending client-side tool calls from a message.
391
+ *
392
+ * Finds tool calls with `pending_client_execution` status, executes their
393
+ * registered handlers, and submits the results back to the server.
394
+ *
395
+ * This is called automatically by {@linkcode subscribeToConversation | subscribeToConversation()}.
396
+ * You only need to call this directly for custom handling flows.
397
+ *
398
+ * @param conversationId - The conversation ID.
399
+ * @param message - The message containing tool calls.
400
+ * @returns `true` if client tool calls were processed, `false` otherwise.
401
+ */
402
+ handlePendingClientTools(conversationId: string, message: AgentMessage): Promise<boolean>;
295
403
  /**
296
404
  * Subscribes to realtime updates for a conversation.
297
405
  *
298
406
  * Establishes a WebSocket connection to receive instant updates when new
299
407
  * messages are added to the conversation. Returns an unsubscribe function
300
408
  * to clean up the connection.
409
+ *
410
+ * Client tool handlers registered via {@linkcode registerClientToolHandlers | registerClientToolHandlers()}
411
+ * are automatically executed when tool calls with `pending_client_execution` status arrive.
412
+ *
413
+ * <Note>
414
+ When receiving messages through this function, tool call data is truncated for efficiency. The `arguments_string` is limited to 500 characters and `results` to 50 characters. The complete tool call data is always saved in storage and can be retrieved by calling {@linkcode getConversation | getConversation()} after the message completes.
415
+ </Note>
301
416
  *
302
417
  * @param conversationId - The conversation ID to subscribe to.
303
418
  * @param onUpdate - Callback function called when the conversation is updated. The callback receives a conversation object with the following properties:
@@ -342,5 +457,5 @@ export interface AgentsModule {
342
457
  * // User can open this URL to start a WhatsApp conversation
343
458
  * ```
344
459
  */
345
- getWhatsAppConnectURL(agentName: string): string;
460
+ getWhatsAppConnectURL(agentName: AgentName): string;
346
461
  }
@@ -1,7 +1,14 @@
1
+ /**
2
+ * Registry of connector integration types.
3
+ * Augment this interface to enable autocomplete for connector integration types.
4
+ */
5
+ export interface ConnectorIntegrationTypeRegistry {
6
+ }
1
7
  /**
2
8
  * The type of external integration/connector, such as `'googlecalendar'`, `'slack'`, or `'github'`.
9
+ * Uses registry keys if augmented, otherwise falls back to string.
3
10
  */
4
- export type ConnectorIntegrationType = string;
11
+ export type ConnectorIntegrationType = keyof ConnectorIntegrationTypeRegistry extends never ? string : keyof ConnectorIntegrationTypeRegistry;
5
12
  /**
6
13
  * Response from the connectors access token endpoint.
7
14
  */
@@ -70,6 +70,35 @@ export interface ImportResult<T = any> {
70
70
  * ```
71
71
  */
72
72
  export type SortField<T> = (keyof T & string) | `+${keyof T & string}` | `-${keyof T & string}`;
73
+ /**
74
+ * Fields added by the server to every entity record (id, dates, created_by, etc.).
75
+ */
76
+ interface ServerEntityFields {
77
+ /** Unique identifier of the record */
78
+ id: string;
79
+ /** ISO 8601 timestamp when the record was created */
80
+ created_date: string;
81
+ /** ISO 8601 timestamp when the record was last updated */
82
+ updated_date: string;
83
+ /** Email of the user who created the record (may be hidden in some responses) */
84
+ created_by?: string | null;
85
+ /** ID of the user who created the record */
86
+ created_by_id?: string | null;
87
+ /** Whether the record is sample/seed data */
88
+ is_sample?: boolean;
89
+ }
90
+ /**
91
+ * Registry mapping entity names to their TypeScript types.
92
+ * Augment this interface with your entity schema (user-defined fields only).
93
+ */
94
+ export interface EntityTypeRegistry {
95
+ }
96
+ /**
97
+ * Full record type for each entity: schema fields + server-injected fields (id, created_date, etc.).
98
+ */
99
+ export type EntityRecord = {
100
+ [K in keyof EntityTypeRegistry]: EntityTypeRegistry[K] & ServerEntityFields;
101
+ };
73
102
  /**
74
103
  * Entity handler providing CRUD operations for a specific entity type.
75
104
  *
@@ -276,7 +305,7 @@ export interface EntityHandler<T = any> {
276
305
  * status: 'completed',
277
306
  * priority: 'low'
278
307
  * });
279
- * console.log('Deleted:', result);
308
+ * console.log('Deleted:', result.deleted);
280
309
  * ```
281
310
  */
282
311
  deleteMany(query: Partial<T>): Promise<DeleteManyResult>;
@@ -351,6 +380,18 @@ export interface EntityHandler<T = any> {
351
380
  */
352
381
  subscribe(callback: RealtimeCallback<T>): () => void;
353
382
  }
383
+ /**
384
+ * Typed entities module - maps registry keys to typed handlers (full record type).
385
+ */
386
+ type TypedEntitiesModule = {
387
+ [K in keyof EntityTypeRegistry]: EntityHandler<EntityRecord[K]>;
388
+ };
389
+ /**
390
+ * Dynamic entities module - allows any entity name with untyped handler.
391
+ */
392
+ type DynamicEntitiesModule = {
393
+ [entityName: string]: EntityHandler<any>;
394
+ };
354
395
  /**
355
396
  * Entities module for managing app data.
356
397
  *
@@ -384,18 +425,5 @@ export interface EntityHandler<T = any> {
384
425
  * const allUsers = await base44.asServiceRole.entities.User.list();
385
426
  * ```
386
427
  */
387
- export interface EntitiesModule {
388
- /**
389
- * Access any entity by name.
390
- *
391
- * Use this to access entities defined in the app.
392
- *
393
- * @example
394
- * ```typescript
395
- * // Access entities dynamically
396
- * base44.entities.MyEntity
397
- * base44.entities.AnotherEntity
398
- * ```
399
- */
400
- [entityName: string]: EntityHandler<any>;
401
- }
428
+ export type EntitiesModule = TypedEntitiesModule & DynamicEntitiesModule;
429
+ export {};
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Registry of function names.
3
+ * Augment this interface to enable autocomplete for function names.
4
+ */
5
+ export interface FunctionNameRegistry {
6
+ }
7
+ /**
8
+ * Function name type - uses registry keys if augmented, otherwise string.
9
+ */
10
+ export type FunctionName = keyof FunctionNameRegistry extends never ? string : keyof FunctionNameRegistry;
1
11
  /**
2
12
  * Functions module for invoking custom backend functions.
3
13
  *
@@ -46,5 +56,5 @@ export interface FunctionsModule {
46
56
  * };
47
57
  * ```
48
58
  */
49
- invoke(functionName: string, data: Record<string, any>): Promise<any>;
59
+ invoke(functionName: FunctionName, data?: Record<string, any>): Promise<any>;
50
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/sdk",
3
- "version": "0.8.18-pr.91.cfad1b0",
3
+ "version": "0.8.19-pr.126.c537ed8",
4
4
  "description": "JavaScript SDK for Base44 API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",