Skip to content

Commit b96fed7

Browse files
yardend-wixclaude
andcommitted
feat(ai-gateway): add base44.aiGateway.connection()
Exposes the Base44 AI Gateway connection ({ baseURL, apiKey }) so apps can call the gateway from their own code with any OpenAI-compatible SDK, without hardcoding the URL or handling the token. Available on the user client and, with the service-role token, via asServiceRole. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2e1a764 commit b96fed7

7 files changed

Lines changed: 140 additions & 0 deletions

File tree

src/client.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { getAccessToken } from "./utils/auth-utils.js";
1111
import { createFunctionsModule } from "./modules/functions.js";
1212
import { createAgentsModule } from "./modules/agents.js";
13+
import { createAiGatewayModule } from "./modules/ai-gateway.js";
1314
import { createAppLogsModule } from "./modules/app-logs.js";
1415
import { createUsersModule } from "./modules/users.js";
1516
import { RoomsSocket, RoomsSocketConfig } from "./utils/socket-utils.js";
@@ -190,6 +191,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
190191
serverUrl,
191192
token,
192193
}),
194+
aiGateway: createAiGatewayModule({ serverUrl, token }),
193195
appLogs: createAppLogsModule(axiosClient, appId),
194196
users: createUsersModule(axiosClient, appId),
195197
analytics: createAnalyticsModule({
@@ -233,6 +235,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
233235
serverUrl,
234236
token,
235237
}),
238+
aiGateway: createAiGatewayModule({ serverUrl, token: serviceToken }),
236239
appLogs: createAppLogsModule(serviceRoleAxiosClient, appId),
237240
cleanup: () => {
238241
if (socket) {

src/client.types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
} from "./modules/connectors.types.js";
99
import type { FunctionsModule } from "./modules/functions.types.js";
1010
import type { AgentsModule } from "./modules/agents.types.js";
11+
import type { AiGatewayModule } from "./modules/ai-gateway.types.js";
1112
import type { AppLogsModule } from "./modules/app-logs.types.js";
1213
import type { AnalyticsModule } from "./modules/analytics.types.js";
1314

@@ -87,6 +88,8 @@ export interface CreateClientConfig {
8788
export interface Base44Client {
8889
/** {@link AgentsModule | Agents module} for managing AI agent conversations. */
8990
agents: AgentsModule;
91+
/** {@link AiGatewayModule | AI Gateway module} for connecting to the Base44 AI Gateway with your own SDK. */
92+
aiGateway: AiGatewayModule;
9093
/** {@link AnalyticsModule | Analytics module} for tracking custom events in your app. */
9194
analytics: AnalyticsModule;
9295
/** {@link AppLogsModule | App logs module} for tracking app usage. */
@@ -129,6 +132,8 @@ export interface Base44Client {
129132
readonly asServiceRole: {
130133
/** {@link AgentsModule | Agents module} with elevated permissions. */
131134
agents: AgentsModule;
135+
/** {@link AiGatewayModule | AI Gateway module} with the service-role token. */
136+
aiGateway: AiGatewayModule;
132137
/** {@link AppLogsModule | App logs module} with elevated permissions. */
133138
appLogs: AppLogsModule;
134139
/** {@link ConnectorsModule | Connectors module} for OAuth token retrieval. */

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ export type {
100100
CreateConversationParams,
101101
} from "./modules/agents.types.js";
102102

103+
export type {
104+
AiGatewayModule,
105+
GatewayConnection,
106+
} from "./modules/ai-gateway.types.js";
107+
103108
export type { AppLogsModule } from "./modules/app-logs.types.js";
104109

105110
export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";

src/modules/ai-gateway.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { getAccessToken } from "../utils/auth-utils.js";
2+
import {
3+
AiGatewayModule,
4+
AiGatewayModuleConfig,
5+
GatewayConnection,
6+
} from "./ai-gateway.types.js";
7+
8+
export function createAiGatewayModule({
9+
serverUrl,
10+
token,
11+
}: AiGatewayModuleConfig): AiGatewayModule {
12+
const connection = (): GatewayConnection => ({
13+
baseURL: `${serverUrl}/api/ai/unified/v1`,
14+
token: token ?? getAccessToken() ?? "",
15+
});
16+
17+
return {
18+
connection,
19+
};
20+
}

src/modules/ai-gateway.types.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* A connection to the Base44 AI Gateway.
3+
*
4+
* Contains the base URL and bearer token to use with any OpenAI-compatible client
5+
* (the OpenAI SDK, Mastra, and others) pointed at the Base44 AI Gateway.
6+
*/
7+
export interface GatewayConnection {
8+
/** Base URL of the gateway's OpenAI-compatible endpoint. */
9+
baseURL: string;
10+
/** Bearer token used to authenticate requests to the gateway. */
11+
token: string;
12+
}
13+
14+
/**
15+
* Configuration for the AI Gateway module.
16+
* @internal
17+
*/
18+
export interface AiGatewayModuleConfig {
19+
/** Server URL */
20+
serverUrl?: string;
21+
/** Authentication token */
22+
token?: string;
23+
}
24+
25+
/**
26+
* The AI Gateway module.
27+
*
28+
* Exposes the connection details for the Base44 AI Gateway so you can call it from
29+
* your own code using any OpenAI-compatible SDK — for example, to build a custom
30+
* agent on top of the gateway.
31+
*/
32+
export interface AiGatewayModule {
33+
/**
34+
* Gets the connection details for the Base44 AI Gateway.
35+
*
36+
* Returns the `baseURL` and `token` to pass to any OpenAI-compatible client (the
37+
* OpenAI SDK, Mastra, and others), so you can call the gateway from your own code
38+
* without constructing the URL or handling the token yourself.
39+
*
40+
* The `token` is the current caller's bearer token: the app user's token for
41+
* `base44.aiGateway`, or the service-role token for `base44.asServiceRole.aiGateway`.
42+
*
43+
* @returns The gateway {@linkcode GatewayConnection | connection} (`baseURL` and `token`).
44+
*
45+
* @example
46+
* ```typescript
47+
* // Inside a backend function, call the gateway with any OpenAI-compatible SDK
48+
* import { createClientFromRequest } from 'npm:@base44/sdk';
49+
* import OpenAI from 'npm:openai';
50+
*
51+
* Deno.serve(async (req) => {
52+
* const base44 = createClientFromRequest(req);
53+
* const { baseURL, token } = base44.aiGateway.connection();
54+
*
55+
* const openai = new OpenAI({ baseURL, apiKey: token });
56+
* const res = await openai.chat.completions.create({
57+
* model: 'claude_sonnet_4_6',
58+
* messages: [{ role: 'user', content: 'Hello!' }],
59+
* });
60+
* return Response.json({ text: res.choices[0].message.content });
61+
* });
62+
* ```
63+
*/
64+
connection(): GatewayConnection;
65+
}

src/modules/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./app.types.js";
22
export * from "./agents.types.js";
3+
export * from "./ai-gateway.types.js";
34
export * from "./connectors.types.js";
45
export * from "./analytics.types.js";

tests/unit/ai-gateway.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { describe, test, expect } from "vitest";
2+
import { createClient } from "../../src/index.ts";
3+
4+
describe("AI Gateway Module", () => {
5+
const appId = "test-app-id";
6+
const serverUrl = "https://api.base44.com";
7+
const baseURL = `${serverUrl}/api/ai/unified/v1`;
8+
9+
describe("connection", () => {
10+
test("should return the unified gateway baseURL", () => {
11+
const base44 = createClient({ serverUrl, appId });
12+
expect(base44.aiGateway.connection().baseURL).toBe(baseURL);
13+
});
14+
15+
test("should return an empty token when unauthenticated", () => {
16+
const base44 = createClient({ serverUrl, appId });
17+
expect(base44.aiGateway.connection().token).toBe("");
18+
});
19+
20+
test("should use the user token when authenticated", () => {
21+
const base44 = createClient({ serverUrl, appId, token: "user-token" });
22+
expect(base44.aiGateway.connection()).toEqual({
23+
baseURL,
24+
token: "user-token",
25+
});
26+
});
27+
28+
test("should use the service-role token via asServiceRole", () => {
29+
const base44 = createClient({
30+
serverUrl,
31+
appId,
32+
token: "user-token",
33+
serviceToken: "service-token",
34+
});
35+
expect(base44.asServiceRole.aiGateway.connection()).toEqual({
36+
baseURL,
37+
token: "service-token",
38+
});
39+
});
40+
});
41+
});

0 commit comments

Comments
 (0)