Skip to content

Commit 7a5fc96

Browse files
author
alban bertolini
committed
feat: ai proxy
1 parent b0c2b49 commit 7a5fc96

15 files changed

+856
-1
lines changed

packages/agent/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@forestadmin/datasource-customizer": "1.61.3",
1818
"@forestadmin/datasource-toolkit": "1.48.0",
1919
"@forestadmin/forestadmin-client": "1.36.8",
20+
"@forestadmin/ai-proxy": "0.0.1",
2021
"@koa/cors": "^5.0.0",
2122
"@koa/router": "^12.0.0",
2223
"@types/koa__router": "^12.0.0",

packages/agent/src/routes/ai-proxy.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { ForestAIProxy, createForestAIProxy } from '@forestadmin/ai-proxy';
2+
import { DataSource } from '@forestadmin/datasource-toolkit';
3+
import Router from '@koa/router';
4+
import { Context } from 'koa';
5+
6+
import BaseRoute from './base-route';
7+
import { ForestAdminHttpDriverServices } from '../services';
8+
import { AgentOptionsWithDefaults, HttpCode, RouteType } from '../types';
9+
10+
export default class AIProxy extends BaseRoute {
11+
readonly type = RouteType.PrivateRoute;
12+
private forestProxy: ForestAIProxy;
13+
14+
constructor(services: ForestAdminHttpDriverServices, options: AgentOptionsWithDefaults) {
15+
super(services, options);
16+
this.forestProxy = createForestAIProxy();
17+
}
18+
19+
setupRoutes(router: Router): void {
20+
router.post(`/ai-proxy`, this.proxy.bind(this));
21+
}
22+
23+
private async proxy(context: Context) {
24+
try {
25+
const { openAIApiKey } = this.options.experimental.ai.openAI;
26+
27+
if (context.query.provider === 'openai' && openAIApiKey) {
28+
context.response.body = await this.forestProxy.proxyOpenAI({ openAIApiKey }, context.body);
29+
context.response.status = HttpCode.Ok;
30+
} else {
31+
// TODO add a link to the documentation
32+
context.throw(HttpCode.BadRequest, 'Provider not supported or API key not set');
33+
}
34+
} catch (error) {
35+
console.error(error);
36+
context.throw(HttpCode.InternalServerError, 'Error while proxying AI request');
37+
}
38+
39+
context.response.status = HttpCode.Ok;
40+
}
41+
}

packages/agent/src/routes/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Get from './access/get';
1111
import List from './access/list';
1212
import ListRelated from './access/list-related';
1313
import NativeQueryDatasource from './access/native-query-datasource';
14+
import AIProxy from './ai-proxy';
1415
import BaseRoute from './base-route';
1516
import Capabilities from './capabilities';
1617
import ActionRoute from './modification/action/action';
@@ -56,6 +57,7 @@ export const RELATED_ROUTES_CTOR = [
5657
DissociateDeleteRelated,
5758
ListRelated,
5859
];
60+
export const AI_ROUTES_CTOR = [AIProxy];
5961
export const RELATED_RELATION_ROUTES_CTOR = [UpdateRelation];
6062
export const CAPABILITIES_ROUTES_CTOR = [Capabilities];
6163
export const NATIVE_QUERY_ROUTES_CTOR = [NativeQueryDatasource];
@@ -108,6 +110,14 @@ function getCapabilitiesRoutes(
108110
return routes;
109111
}
110112

113+
function getAIRoutes(options: Options, services: Services): BaseRoute[] {
114+
const routes: BaseRoute[] = [];
115+
116+
routes.push(...AI_ROUTES_CTOR.map(Route => new Route(services, options)));
117+
118+
return routes;
119+
}
120+
111121
function getNativeQueryRoutes(
112122
dataSource: DataSource,
113123
options: Options,
@@ -171,6 +181,7 @@ export default function makeRoutes(
171181
): BaseRoute[] {
172182
const routes = [
173183
...getRootRoutes(options, services),
184+
...getAIRoutes(options, services),
174185
...getCrudRoutes(dataSource, options, services),
175186
...getCapabilitiesRoutes(dataSource, options, services),
176187
...getNativeQueryRoutes(dataSource, options, services),

packages/agent/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type AgentOptions = {
2222
experimental?: {
2323
webhookCustomActions?: boolean;
2424
updateRecordCustomActions?: boolean;
25+
ai: { openAI?: { openAIApiKey?: string } };
2526
};
2627
maxBodySize?: string;
2728
/**

packages/ai-proxy/CHANGELOG.md

Whitespace-only changes.

0 commit comments

Comments
 (0)