@base44-preview/sdk 0.8.32-pr.202.0f8275d → 0.8.32-pr.205.168e407
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/client.js +9 -0
- package/dist/client.types.d.ts +5 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/modules/ai-gateway.d.ts +20 -0
- package/dist/modules/ai-gateway.js +42 -0
- package/dist/modules/dynamic-agents.d.ts +32 -0
- package/dist/modules/dynamic-agents.js +176 -0
- package/dist/modules/dynamic-agents.types.d.ts +127 -0
- package/dist/modules/dynamic-agents.types.js +2 -0
- package/dist/modules/functions.js +45 -31
- package/dist/modules/functions.types.d.ts +13 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -7,6 +7,7 @@ import { createConnectorsModule, createUserConnectorsModule, } from "./modules/c
|
|
|
7
7
|
import { getAccessToken } from "./utils/auth-utils.js";
|
|
8
8
|
import { createFunctionsModule } from "./modules/functions.js";
|
|
9
9
|
import { createAgentsModule } from "./modules/agents.js";
|
|
10
|
+
import { createDynamicAgentsModule } from "./modules/dynamic-agents.js";
|
|
10
11
|
import { createAppLogsModule } from "./modules/app-logs.js";
|
|
11
12
|
import { createUsersModule } from "./modules/users.js";
|
|
12
13
|
import { RoomsSocket } from "./utils/socket-utils.js";
|
|
@@ -150,6 +151,10 @@ export function createClient(config) {
|
|
|
150
151
|
serverUrl,
|
|
151
152
|
token,
|
|
152
153
|
}),
|
|
154
|
+
dynamicAgents: createDynamicAgentsModule({
|
|
155
|
+
serverUrl,
|
|
156
|
+
getToken: () => token || getAccessToken() || undefined,
|
|
157
|
+
}),
|
|
153
158
|
appLogs: createAppLogsModule(axiosClient, appId),
|
|
154
159
|
users: createUsersModule(axiosClient, appId),
|
|
155
160
|
analytics: createAnalyticsModule({
|
|
@@ -192,6 +197,10 @@ export function createClient(config) {
|
|
|
192
197
|
serverUrl,
|
|
193
198
|
token,
|
|
194
199
|
}),
|
|
200
|
+
dynamicAgents: createDynamicAgentsModule({
|
|
201
|
+
serverUrl,
|
|
202
|
+
getToken: () => serviceToken,
|
|
203
|
+
}),
|
|
195
204
|
appLogs: createAppLogsModule(serviceRoleAxiosClient, appId),
|
|
196
205
|
cleanup: () => {
|
|
197
206
|
if (socket) {
|
package/dist/client.types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { FunctionsModule } from "./modules/functions.types.js";
|
|
|
7
7
|
import type { AgentsModule } from "./modules/agents.types.js";
|
|
8
8
|
import type { AppLogsModule } from "./modules/app-logs.types.js";
|
|
9
9
|
import type { AnalyticsModule } from "./modules/analytics.types.js";
|
|
10
|
+
import type { DynamicAgentsModule } from "./modules/dynamic-agents.types.js";
|
|
10
11
|
/**
|
|
11
12
|
* Options for creating a Base44 client.
|
|
12
13
|
*/
|
|
@@ -85,6 +86,8 @@ export interface Base44Client {
|
|
|
85
86
|
analytics: AnalyticsModule;
|
|
86
87
|
/** {@link AppLogsModule | App logs module} for tracking app usage. */
|
|
87
88
|
appLogs: AppLogsModule;
|
|
89
|
+
/** {@link DynamicAgentsModule | Dynamic agents module} for code-defined AI agents and tool loops. */
|
|
90
|
+
dynamicAgents: DynamicAgentsModule;
|
|
88
91
|
/** {@link AuthModule | Auth module} for user authentication and management. */
|
|
89
92
|
auth: AuthModule;
|
|
90
93
|
/** {@link UserConnectorsModule | Connectors module} for app-user OAuth flows. */
|
|
@@ -126,6 +129,8 @@ export interface Base44Client {
|
|
|
126
129
|
agents: AgentsModule;
|
|
127
130
|
/** {@link AppLogsModule | App logs module} with elevated permissions. */
|
|
128
131
|
appLogs: AppLogsModule;
|
|
132
|
+
/** {@link DynamicAgentsModule | Dynamic agents module} with elevated permissions. */
|
|
133
|
+
dynamicAgents: DynamicAgentsModule;
|
|
129
134
|
/** {@link ConnectorsModule | Connectors module} for OAuth token retrieval. */
|
|
130
135
|
connectors: ConnectorsModule;
|
|
131
136
|
/** {@link EntitiesModule | Entities module} with elevated permissions. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createClient, createClientFromRequest, type Base44Client, type CreateClientConfig, type CreateClientOptions } from "./client.js";
|
|
2
2
|
import { Base44Error, type Base44ErrorJSON } from "./utils/axios-client.js";
|
|
3
3
|
import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl } from "./utils/auth-utils.js";
|
|
4
|
-
|
|
4
|
+
import { tool } from "./modules/dynamic-agents.js";
|
|
5
|
+
export { createClient, createClientFromRequest, Base44Error, getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, tool, };
|
|
5
6
|
export type { Base44Client, CreateClientConfig, CreateClientOptions, Base44ErrorJSON, };
|
|
6
7
|
export * from "./types.js";
|
|
7
8
|
export type { DeleteManyResult, DeleteResult, EntitiesModule, EntityFilterOperators, EntityFilterQuery, EntityFilterValue, EntityHandler, EntityRecord, EntityTypeRegistry, ImportResult, RealtimeEventType, RealtimeEvent, RealtimeCallback, SortField, UpdateManyResult, } from "./modules/entities.types.js";
|
|
@@ -13,4 +14,5 @@ export type { AppLogsModule } from "./modules/app-logs.types.js";
|
|
|
13
14
|
export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
|
|
14
15
|
export type { ConnectorsModule, UserConnectorsModule, } from "./modules/connectors.types.js";
|
|
15
16
|
export type { CustomIntegrationsModule, CustomIntegrationCallParams, CustomIntegrationCallResponse, } from "./modules/custom-integrations.types.js";
|
|
17
|
+
export type { Tool, JSONSchema, ChatMessage, Step, RunUsage, RunResult, RunInput, RunOptions, ToolChoice, AgentConfig, Agent, DynamicAgentsModule, } from "./modules/dynamic-agents.types.js";
|
|
16
18
|
export type { GetAccessTokenOptions, SaveAccessTokenOptions, RemoveAccessTokenOptions, GetLoginUrlOptions, } from "./utils/auth-utils.types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createClient, createClientFromRequest, } from "./client.js";
|
|
2
2
|
import { Base44Error } from "./utils/axios-client.js";
|
|
3
3
|
import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, } from "./utils/auth-utils.js";
|
|
4
|
-
|
|
4
|
+
import { tool } from "./modules/dynamic-agents.js";
|
|
5
|
+
export { createClient, createClientFromRequest, Base44Error, getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, tool, };
|
|
5
6
|
export * from "./types.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DynamicAgentsModuleConfig } from "./dynamic-agents.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the AI Gateway connection from a client config.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveConnection(config: DynamicAgentsModuleConfig): {
|
|
7
|
+
baseURL: string;
|
|
8
|
+
apiKey: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Creates the gateway transport. Owns the single HTTP call to the OpenAI-compatible
|
|
12
|
+
* `/chat/completions` endpoint. Shaped so a streaming `.stream()` method can be added
|
|
13
|
+
* later without changing callers of `.complete()`.
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function createGatewayTransport(config: DynamicAgentsModuleConfig): {
|
|
17
|
+
complete(body: Record<string, unknown>, opts?: {
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}): Promise<any>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Base44Error } from "../utils/axios-client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the AI Gateway connection from a client config.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export function resolveConnection(config) {
|
|
7
|
+
var _a;
|
|
8
|
+
const { serverUrl, getToken } = config;
|
|
9
|
+
// No appId in the path: the gateway resolves the app by request Host.
|
|
10
|
+
return {
|
|
11
|
+
baseURL: `${serverUrl}/api/ai/unified/v1`,
|
|
12
|
+
apiKey: (_a = getToken()) !== null && _a !== void 0 ? _a : "",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates the gateway transport. Owns the single HTTP call to the OpenAI-compatible
|
|
17
|
+
* `/chat/completions` endpoint. Shaped so a streaming `.stream()` method can be added
|
|
18
|
+
* later without changing callers of `.complete()`.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export function createGatewayTransport(config) {
|
|
22
|
+
return {
|
|
23
|
+
async complete(body, opts = {}) {
|
|
24
|
+
const { baseURL, apiKey } = resolveConnection(config);
|
|
25
|
+
const res = await fetch(`${baseURL}/chat/completions`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
Authorization: `Bearer ${apiKey}`,
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify(body),
|
|
32
|
+
signal: opts.signal,
|
|
33
|
+
});
|
|
34
|
+
const json = await res.json().catch(() => null);
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const err = (json && json.error) || {};
|
|
37
|
+
throw new Base44Error(err.message || `AI Gateway request failed with status ${res.status}`, res.status, err.code || err.type || "ai_gateway_error", json, null);
|
|
38
|
+
}
|
|
39
|
+
return json;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AgentConfig, ChatMessage, DynamicAgentsModule, DynamicAgentsModuleConfig, Tool } from "./dynamic-agents.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Defines a tool an agent can call.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* const getWeather = tool({
|
|
8
|
+
* description: "Get the current weather for a city.",
|
|
9
|
+
* parameters: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
|
|
10
|
+
* execute: async ({ city }) => ({ city, tempC: 28 }),
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function tool(t: Tool): Tool;
|
|
15
|
+
/**
|
|
16
|
+
* Maps a `{ name: Tool }` map to the OpenAI `tools[]` array. Returns `undefined`
|
|
17
|
+
* when empty so the param is omitted from the request body.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare function serializeTools(tools?: Record<string, Tool>): any[] | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Builds the gateway request body from config + messages using an explicit whitelist.
|
|
23
|
+
* Rejected params (max_tokens, stop, top_p, penalties, logit_bias, seed, n) can never
|
|
24
|
+
* appear because only the supported keys are ever written.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildRequestBody(config: AgentConfig, messages: ChatMessage[]): Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates the `base44.dynamicAgents` module.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function createDynamicAgentsModule(config: DynamicAgentsModuleConfig): DynamicAgentsModule;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { createGatewayTransport } from "./ai-gateway.js";
|
|
2
|
+
/**
|
|
3
|
+
* Defines a tool an agent can call.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* const getWeather = tool({
|
|
8
|
+
* description: "Get the current weather for a city.",
|
|
9
|
+
* parameters: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
|
|
10
|
+
* execute: async ({ city }) => ({ city, tempC: 28 }),
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function tool(t) {
|
|
15
|
+
return t;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Maps a `{ name: Tool }` map to the OpenAI `tools[]` array. Returns `undefined`
|
|
19
|
+
* when empty so the param is omitted from the request body.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export function serializeTools(tools) {
|
|
23
|
+
if (!tools)
|
|
24
|
+
return undefined;
|
|
25
|
+
const entries = Object.entries(tools);
|
|
26
|
+
if (entries.length === 0)
|
|
27
|
+
return undefined;
|
|
28
|
+
return entries.map(([name, t]) => ({
|
|
29
|
+
type: "function",
|
|
30
|
+
function: { name, description: t.description, parameters: t.parameters },
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Builds the gateway request body from config + messages using an explicit whitelist.
|
|
35
|
+
* Rejected params (max_tokens, stop, top_p, penalties, logit_bias, seed, n) can never
|
|
36
|
+
* appear because only the supported keys are ever written.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export function buildRequestBody(config, messages) {
|
|
40
|
+
const body = {
|
|
41
|
+
model: config.model,
|
|
42
|
+
messages,
|
|
43
|
+
};
|
|
44
|
+
if (config.temperature !== undefined)
|
|
45
|
+
body.temperature = config.temperature;
|
|
46
|
+
if (config.toolChoice !== undefined)
|
|
47
|
+
body.tool_choice = config.toolChoice;
|
|
48
|
+
if (config.responseFormat !== undefined) {
|
|
49
|
+
body.response_format = {
|
|
50
|
+
type: "json_schema",
|
|
51
|
+
json_schema: { name: "response", schema: config.responseFormat, strict: true },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const tools = serializeTools(config.tools);
|
|
55
|
+
if (tools)
|
|
56
|
+
body.tools = tools;
|
|
57
|
+
return body;
|
|
58
|
+
}
|
|
59
|
+
const DEFAULT_MAX_STEPS = 8;
|
|
60
|
+
function inputToMessages(input) {
|
|
61
|
+
if ("messages" in input)
|
|
62
|
+
return input.messages;
|
|
63
|
+
return [{ role: "user", content: input.prompt }];
|
|
64
|
+
}
|
|
65
|
+
function stringifyResult(out) {
|
|
66
|
+
return typeof out === "string" ? out : JSON.stringify(out);
|
|
67
|
+
}
|
|
68
|
+
function mapUsage(raw) {
|
|
69
|
+
const u = (raw && raw.usage) || {};
|
|
70
|
+
return {
|
|
71
|
+
promptTokens: u.prompt_tokens,
|
|
72
|
+
completionTokens: u.completion_tokens,
|
|
73
|
+
totalTokens: u.total_tokens,
|
|
74
|
+
credits: u.base44_credits,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates the `base44.dynamicAgents` module.
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
export function createDynamicAgentsModule(config) {
|
|
82
|
+
const transport = createGatewayTransport(config);
|
|
83
|
+
function create(agentConfig) {
|
|
84
|
+
var _a;
|
|
85
|
+
const maxSteps = (_a = agentConfig.maxSteps) !== null && _a !== void 0 ? _a : DEFAULT_MAX_STEPS;
|
|
86
|
+
const tools = agentConfig.tools;
|
|
87
|
+
const agent = {
|
|
88
|
+
async run(input, options = {}) {
|
|
89
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
90
|
+
const messages = [];
|
|
91
|
+
if (agentConfig.system)
|
|
92
|
+
messages.push({ role: "system", content: agentConfig.system });
|
|
93
|
+
messages.push(...inputToMessages(input));
|
|
94
|
+
const steps = [];
|
|
95
|
+
let raw = null;
|
|
96
|
+
for (let i = 0; i < maxSteps; i++) {
|
|
97
|
+
const body = buildRequestBody(agentConfig, messages);
|
|
98
|
+
raw = await transport.complete(body, { signal: options.abortSignal });
|
|
99
|
+
const choice = (_a = raw === null || raw === void 0 ? void 0 : raw.choices) === null || _a === void 0 ? void 0 : _a[0];
|
|
100
|
+
const message = (_b = choice === null || choice === void 0 ? void 0 : choice.message) !== null && _b !== void 0 ? _b : { role: "assistant", content: "" };
|
|
101
|
+
messages.push(message);
|
|
102
|
+
const toolCalls = message.tool_calls;
|
|
103
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
104
|
+
return {
|
|
105
|
+
text: (_c = message.content) !== null && _c !== void 0 ? _c : "",
|
|
106
|
+
steps,
|
|
107
|
+
finishReason: (_d = choice === null || choice === void 0 ? void 0 : choice.finish_reason) !== null && _d !== void 0 ? _d : "stop",
|
|
108
|
+
usage: mapUsage(raw),
|
|
109
|
+
raw,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const toolResults = [];
|
|
113
|
+
for (const call of toolCalls) {
|
|
114
|
+
const name = (_e = call.function) === null || _e === void 0 ? void 0 : _e.name;
|
|
115
|
+
const t = tools === null || tools === void 0 ? void 0 : tools[name];
|
|
116
|
+
let args = {};
|
|
117
|
+
try {
|
|
118
|
+
args = JSON.parse(((_f = call.function) === null || _f === void 0 ? void 0 : _f.arguments) || "{}");
|
|
119
|
+
}
|
|
120
|
+
catch (_l) {
|
|
121
|
+
args = {};
|
|
122
|
+
}
|
|
123
|
+
let resultContent;
|
|
124
|
+
if (!t) {
|
|
125
|
+
resultContent = `Error: tool "${name}" is not available.`;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
try {
|
|
129
|
+
resultContent = stringifyResult(await t.execute(args));
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
resultContent = `Error: ${(_g = e === null || e === void 0 ? void 0 : e.message) !== null && _g !== void 0 ? _g : String(e)}`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
messages.push({ role: "tool", tool_call_id: call.id, content: resultContent });
|
|
136
|
+
toolResults.push({ toolCallId: call.id, toolName: name, args, result: resultContent });
|
|
137
|
+
}
|
|
138
|
+
steps.push({ toolResults });
|
|
139
|
+
}
|
|
140
|
+
// maxSteps exhausted
|
|
141
|
+
const lastMessage = (_j = (_h = raw === null || raw === void 0 ? void 0 : raw.choices) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.message;
|
|
142
|
+
return {
|
|
143
|
+
text: (_k = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.content) !== null && _k !== void 0 ? _k : "",
|
|
144
|
+
steps,
|
|
145
|
+
finishReason: "max_steps",
|
|
146
|
+
usage: mapUsage(raw),
|
|
147
|
+
raw,
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
asTool(toolOpts) {
|
|
151
|
+
return {
|
|
152
|
+
description: toolOpts.description,
|
|
153
|
+
parameters: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: { prompt: { type: "string", description: "What to ask the sub-agent." } },
|
|
156
|
+
required: ["prompt"],
|
|
157
|
+
},
|
|
158
|
+
execute: async (args) => {
|
|
159
|
+
const result = await agent.run({ prompt: args.prompt });
|
|
160
|
+
return result.text;
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
return agent;
|
|
166
|
+
}
|
|
167
|
+
function run(runConfig, options) {
|
|
168
|
+
if ("messages" in runConfig) {
|
|
169
|
+
const { messages, ...agentConfig } = runConfig;
|
|
170
|
+
return create(agentConfig).run({ messages }, options);
|
|
171
|
+
}
|
|
172
|
+
const { prompt, ...agentConfig } = runConfig;
|
|
173
|
+
return create(agentConfig).run({ prompt }, options);
|
|
174
|
+
}
|
|
175
|
+
return { create, run };
|
|
176
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JSON Schema object describing a tool's input parameters.
|
|
3
|
+
* Use the standard JSON Schema `object` shape: `{ type: "object", properties: {...}, required: [...] }`.
|
|
4
|
+
*/
|
|
5
|
+
export type JSONSchema = Record<string, unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* A tool an agent can call. Create one with {@linkcode tool | tool()}, or derive it from a
|
|
8
|
+
* resource with `.asTool()`.
|
|
9
|
+
*/
|
|
10
|
+
export interface Tool {
|
|
11
|
+
/** Natural-language description the model uses to decide when to call the tool. */
|
|
12
|
+
description: string;
|
|
13
|
+
/** JSON Schema for the tool's arguments. */
|
|
14
|
+
parameters: JSONSchema;
|
|
15
|
+
/** Runs the tool. Receives parsed arguments; returns any JSON-serializable value (or a string). */
|
|
16
|
+
execute: (args: any) => Promise<unknown> | unknown;
|
|
17
|
+
}
|
|
18
|
+
/** An OpenAI-shaped chat message used internally and accepted by {@linkcode Agent.run}. */
|
|
19
|
+
export interface ChatMessage {
|
|
20
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
21
|
+
content?: string | null;
|
|
22
|
+
tool_calls?: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
type: "function";
|
|
25
|
+
function: {
|
|
26
|
+
name: string;
|
|
27
|
+
arguments: string;
|
|
28
|
+
};
|
|
29
|
+
}>;
|
|
30
|
+
tool_call_id?: string;
|
|
31
|
+
}
|
|
32
|
+
/** One iteration of the agent loop: the tool calls the model made and their results. */
|
|
33
|
+
export interface Step {
|
|
34
|
+
toolResults: Array<{
|
|
35
|
+
toolCallId: string;
|
|
36
|
+
toolName: string;
|
|
37
|
+
args: unknown;
|
|
38
|
+
result: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/** Token/credit usage for a run. `credits` is the Base44 gateway's `base44_credits`. */
|
|
42
|
+
export interface RunUsage {
|
|
43
|
+
promptTokens?: number;
|
|
44
|
+
completionTokens?: number;
|
|
45
|
+
totalTokens?: number;
|
|
46
|
+
credits?: number;
|
|
47
|
+
}
|
|
48
|
+
/** Result of {@linkcode Agent.run} / {@linkcode DynamicAgentsModule.run}. */
|
|
49
|
+
export interface RunResult {
|
|
50
|
+
/** The model's final text output. */
|
|
51
|
+
text: string;
|
|
52
|
+
/** The loop history (one entry per step that made tool calls). */
|
|
53
|
+
steps: Step[];
|
|
54
|
+
/** Why the run ended: `"stop"` (model finished), `"tool_calls"`, or `"max_steps"`. */
|
|
55
|
+
finishReason: string;
|
|
56
|
+
/** Token and credit usage from the final completion. */
|
|
57
|
+
usage: RunUsage;
|
|
58
|
+
/** The raw final completion body, for advanced use. */
|
|
59
|
+
raw: unknown;
|
|
60
|
+
}
|
|
61
|
+
/** Input to {@linkcode Agent.run}: either a single prompt or a full message list. */
|
|
62
|
+
export type RunInput = {
|
|
63
|
+
prompt: string;
|
|
64
|
+
} | {
|
|
65
|
+
messages: ChatMessage[];
|
|
66
|
+
};
|
|
67
|
+
/** Per-run options. */
|
|
68
|
+
export interface RunOptions {
|
|
69
|
+
/** Abort the run (and the in-flight gateway request). */
|
|
70
|
+
abortSignal?: AbortSignal;
|
|
71
|
+
}
|
|
72
|
+
/** OpenAI-compatible tool choice. */
|
|
73
|
+
export type ToolChoice = "auto" | "none" | "required" | {
|
|
74
|
+
type: "function";
|
|
75
|
+
function: {
|
|
76
|
+
name: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/** Configuration for a dynamic agent. */
|
|
80
|
+
export interface AgentConfig {
|
|
81
|
+
/** Model alias (e.g. `"claude_sonnet_4_6"`, `"gpt_5_mini"`) or vendor id. */
|
|
82
|
+
model: string;
|
|
83
|
+
/** System prompt. */
|
|
84
|
+
system?: string;
|
|
85
|
+
/** Tools the agent may call, keyed by name. */
|
|
86
|
+
tools?: Record<string, Tool>;
|
|
87
|
+
/** Max loop iterations before stopping. Default `8`. */
|
|
88
|
+
maxSteps?: number;
|
|
89
|
+
/** Sampling temperature. Omitted unless set. Note: GPT-5 models only accept `1`. */
|
|
90
|
+
temperature?: number;
|
|
91
|
+
/** A JSON Schema to constrain output to structured JSON (`response_format: json_schema`). */
|
|
92
|
+
responseFormat?: JSONSchema;
|
|
93
|
+
/** Controls whether/which tool the model must call. */
|
|
94
|
+
toolChoice?: ToolChoice;
|
|
95
|
+
}
|
|
96
|
+
/** A reusable dynamic agent. */
|
|
97
|
+
export interface Agent {
|
|
98
|
+
/** Run the agent's tool-calling loop to completion. */
|
|
99
|
+
run(input: RunInput, options?: RunOptions): Promise<RunResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Turn this agent into a {@linkcode Tool} so another agent can call it as a sub-agent.
|
|
102
|
+
* (Implemented in Effort 2.)
|
|
103
|
+
*/
|
|
104
|
+
asTool(opts: {
|
|
105
|
+
name?: string;
|
|
106
|
+
description: string;
|
|
107
|
+
}): Tool;
|
|
108
|
+
}
|
|
109
|
+
/** The `base44.dynamicAgents` module. */
|
|
110
|
+
export interface DynamicAgentsModule {
|
|
111
|
+
/** Define a reusable agent. */
|
|
112
|
+
create(config: AgentConfig): Agent;
|
|
113
|
+
/** One-shot: `create(config).run({ prompt })`. */
|
|
114
|
+
run(config: AgentConfig & RunInput, options?: RunOptions): Promise<RunResult>;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Configuration for the dynamic-agents module.
|
|
118
|
+
*
|
|
119
|
+
* Note: the gateway resolves the app by request Host, so no `appId` is needed here —
|
|
120
|
+
* `serverUrl` must be an app-resolving domain.
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
export interface DynamicAgentsModuleConfig {
|
|
124
|
+
serverUrl: string;
|
|
125
|
+
/** Returns the current bearer token at call time (thunk — never a captured string). */
|
|
126
|
+
getToken: () => string | undefined;
|
|
127
|
+
}
|
|
@@ -31,38 +31,40 @@ export function createFunctionsModule(axios, appId, config) {
|
|
|
31
31
|
}
|
|
32
32
|
return headers;
|
|
33
33
|
};
|
|
34
|
+
// Hoisted so both the returned `invoke` property and `asTool.execute` can reference it
|
|
35
|
+
// without relying on `this` (which breaks when the object is spread into the client).
|
|
36
|
+
const invoke = async (functionName, data) => {
|
|
37
|
+
// Validate input
|
|
38
|
+
if (typeof data === "string") {
|
|
39
|
+
throw new Error(`Function ${functionName} must receive an object with named parameters, received: ${data}`);
|
|
40
|
+
}
|
|
41
|
+
let formData;
|
|
42
|
+
let contentType;
|
|
43
|
+
// Handle file uploads with FormData
|
|
44
|
+
if (data instanceof FormData ||
|
|
45
|
+
(data && Object.values(data).some((value) => value instanceof File))) {
|
|
46
|
+
formData = new FormData();
|
|
47
|
+
Object.keys(data).forEach((key) => {
|
|
48
|
+
if (data[key] instanceof File) {
|
|
49
|
+
formData.append(key, data[key], data[key].name);
|
|
50
|
+
}
|
|
51
|
+
else if (typeof data[key] === "object" && data[key] !== null) {
|
|
52
|
+
formData.append(key, JSON.stringify(data[key]));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
formData.append(key, data[key]);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
contentType = "multipart/form-data";
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
formData = data;
|
|
62
|
+
contentType = "application/json";
|
|
63
|
+
}
|
|
64
|
+
return axios.post(`/apps/${appId}/functions/${functionName}`, formData || data, { headers: { "Content-Type": contentType } });
|
|
65
|
+
};
|
|
34
66
|
return {
|
|
35
|
-
|
|
36
|
-
async invoke(functionName, data) {
|
|
37
|
-
// Validate input
|
|
38
|
-
if (typeof data === "string") {
|
|
39
|
-
throw new Error(`Function ${functionName} must receive an object with named parameters, received: ${data}`);
|
|
40
|
-
}
|
|
41
|
-
let formData;
|
|
42
|
-
let contentType;
|
|
43
|
-
// Handle file uploads with FormData
|
|
44
|
-
if (data instanceof FormData ||
|
|
45
|
-
(data && Object.values(data).some((value) => value instanceof File))) {
|
|
46
|
-
formData = new FormData();
|
|
47
|
-
Object.keys(data).forEach((key) => {
|
|
48
|
-
if (data[key] instanceof File) {
|
|
49
|
-
formData.append(key, data[key], data[key].name);
|
|
50
|
-
}
|
|
51
|
-
else if (typeof data[key] === "object" && data[key] !== null) {
|
|
52
|
-
formData.append(key, JSON.stringify(data[key]));
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
formData.append(key, data[key]);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
contentType = "multipart/form-data";
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
formData = data;
|
|
62
|
-
contentType = "application/json";
|
|
63
|
-
}
|
|
64
|
-
return axios.post(`/apps/${appId}/functions/${functionName}`, formData || data, { headers: { "Content-Type": contentType } });
|
|
65
|
-
},
|
|
67
|
+
invoke,
|
|
66
68
|
// Fetch a backend function endpoint directly.
|
|
67
69
|
async fetch(path, init = {}) {
|
|
68
70
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -75,5 +77,17 @@ export function createFunctionsModule(axios, appId, config) {
|
|
|
75
77
|
const response = await fetch(joinBaseUrl(config === null || config === void 0 ? void 0 : config.baseURL, primaryPath), requestInit);
|
|
76
78
|
return response;
|
|
77
79
|
},
|
|
80
|
+
// Turn a backend function into an agent tool.
|
|
81
|
+
asTool(name, opts) {
|
|
82
|
+
var _a;
|
|
83
|
+
return {
|
|
84
|
+
description: opts.description,
|
|
85
|
+
parameters: (_a = opts.parameters) !== null && _a !== void 0 ? _a : { type: "object", properties: {}, additionalProperties: true },
|
|
86
|
+
execute: async (args) => {
|
|
87
|
+
const res = await invoke(name, args !== null && args !== void 0 ? args : {});
|
|
88
|
+
return res === null || res === void 0 ? void 0 : res.data;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
},
|
|
78
92
|
};
|
|
79
93
|
}
|
|
@@ -86,6 +86,19 @@ export interface FunctionsModule {
|
|
|
86
86
|
* ```
|
|
87
87
|
*/
|
|
88
88
|
invoke(functionName: FunctionName, data?: Record<string, any>): Promise<any>;
|
|
89
|
+
/**
|
|
90
|
+
* Turns a backend function into a {@linkcode Tool} an agent can call.
|
|
91
|
+
*
|
|
92
|
+
* Functions are invoked by name with no server-known input schema, so you supply a
|
|
93
|
+
* `description` and (optionally) JSON Schema `parameters` for the model.
|
|
94
|
+
*
|
|
95
|
+
* @param name - The backend function name.
|
|
96
|
+
* @param opts - `description` (required) and optional JSON Schema `parameters`.
|
|
97
|
+
*/
|
|
98
|
+
asTool(name: FunctionName, opts: {
|
|
99
|
+
description: string;
|
|
100
|
+
parameters?: Record<string, unknown>;
|
|
101
|
+
}): import("./dynamic-agents.types.js").Tool;
|
|
89
102
|
/**
|
|
90
103
|
* Performs a direct HTTP request to a backend function path and returns the native `Response`.
|
|
91
104
|
*
|