@forestadmin/agent 1.108.2 → 1.110.0
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/agent.d.ts +14 -9
- package/dist/agent.js +129 -6
- package/dist/audit-trail/sql-store.js +39 -27
- package/dist/audit-trail/types.d.ts +12 -2
- package/dist/bff-routes.d.ts +6 -0
- package/dist/bff-routes.js +51 -2
- package/dist/embedded-bff.d.ts +23 -6
- package/dist/embedded-bff.js +70 -32
- package/dist/framework-mounter.d.ts +2 -1
- package/dist/framework-mounter.js +4 -1
- package/dist/gateway.d.ts +19 -0
- package/dist/gateway.js +96 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/routes/access/audit-trail-timeline.js +27 -15
- package/dist/routes/capabilities.js +4 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.js +1 -1
- package/dist/utils/express-to-koa.js +3 -1
- package/package.json +7 -7
package/dist/gateway.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AGENT_VERSION = exports.AGENT_BFF_PEER_VERSION = void 0;
|
|
4
|
+
exports.mcpUnavailable = mcpUnavailable;
|
|
5
|
+
exports.resolveGatewayServices = resolveGatewayServices;
|
|
6
|
+
exports.assertNoGatewayOverlap = assertNoGatewayOverlap;
|
|
7
|
+
exports.servesOAuth = servesOAuth;
|
|
8
|
+
exports.describeGatewayRoutes = describeGatewayRoutes;
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require, global-require
|
|
10
|
+
const { peerDependencies, version } = require('../package.json');
|
|
11
|
+
exports.AGENT_BFF_PEER_VERSION = peerDependencies['@forestadmin/agent-bff'];
|
|
12
|
+
exports.AGENT_VERSION = version;
|
|
13
|
+
const isWithin = (path, root) => path === root || path.startsWith(`${root}/`);
|
|
14
|
+
const HTTP_SERVICE_UNAVAILABLE = 503;
|
|
15
|
+
const MCP_UNAVAILABLE = {
|
|
16
|
+
starting: 'The MCP server is not started yet.',
|
|
17
|
+
stopped: 'The MCP server was stopped with the agent.',
|
|
18
|
+
};
|
|
19
|
+
function mcpUnavailable(isMcpRoute, state) {
|
|
20
|
+
return {
|
|
21
|
+
matches: isMcpRoute,
|
|
22
|
+
callback: (_req, res) => {
|
|
23
|
+
res.statusCode = HTTP_SERVICE_UNAVAILABLE;
|
|
24
|
+
res.setHeader('Content-Type', 'application/json');
|
|
25
|
+
res.end(JSON.stringify({
|
|
26
|
+
error: 'temporarily_unavailable',
|
|
27
|
+
error_description: MCP_UNAVAILABLE[state],
|
|
28
|
+
}));
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const TOP_LEVEL_OPTIONS = ['basePath', 'allowedOAuthClients'];
|
|
33
|
+
function resolveService(service) {
|
|
34
|
+
if (service === true)
|
|
35
|
+
return {};
|
|
36
|
+
return service || null;
|
|
37
|
+
}
|
|
38
|
+
function resolveGatewayServices({ mcp, api }) {
|
|
39
|
+
const mcpOptions = resolveService(mcp);
|
|
40
|
+
const nested = TOP_LEVEL_OPTIONS.find(option => mcpOptions && option in mcpOptions);
|
|
41
|
+
if (nested) {
|
|
42
|
+
throw new Error(`addGateway({ mcp: { ${nested} } }) is not supported: ${nested} covers every Gateway ` +
|
|
43
|
+
`service, set it as addGateway({ ${nested} }).`);
|
|
44
|
+
}
|
|
45
|
+
return { mcp: mcpOptions, api: resolveService(api) };
|
|
46
|
+
}
|
|
47
|
+
function assertNoGatewayOverlap(basePath, forestPath, { mcp, api }) {
|
|
48
|
+
if (basePath && isWithin(basePath, forestPath)) {
|
|
49
|
+
throw new Error(`basePath "${basePath}" overlaps the agent routes on ${forestPath}: ` +
|
|
50
|
+
'change the Gateway basePath or the agent prefix.');
|
|
51
|
+
}
|
|
52
|
+
const claimed = [
|
|
53
|
+
...(mcp ? [{ path: `${basePath}/mcp`, service: 'MCP' }] : []),
|
|
54
|
+
...(mcp || api ? [{ path: `${basePath}/oauth`, service: mcp ? 'MCP' : 'API' }] : []),
|
|
55
|
+
...(api ? [{ path: `${basePath}/api/agent`, service: 'API' }] : []),
|
|
56
|
+
];
|
|
57
|
+
const overlap = claimed.find(({ path }) => isWithin(forestPath, path));
|
|
58
|
+
if (overlap) {
|
|
59
|
+
throw new Error(`The agent routes on ${forestPath} overlap ${overlap.path}, claimed by the Gateway ` +
|
|
60
|
+
`${overlap.service}: change the agent prefix or the Gateway basePath.`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function servesInMemoryUploads({ fileUploads, enabledTools }) {
|
|
64
|
+
if (fileUploads === false || fileUploads?.storage)
|
|
65
|
+
return false;
|
|
66
|
+
return !enabledTools || enabledTools.includes('requestActionFileUpload');
|
|
67
|
+
}
|
|
68
|
+
function servesOAuth({ mcp, api }) {
|
|
69
|
+
return Boolean(mcp || api?.tokenEncryptionKey);
|
|
70
|
+
}
|
|
71
|
+
function describeGatewayRoutes(basePath, { mcp, api }) {
|
|
72
|
+
const lines = [];
|
|
73
|
+
if (mcp) {
|
|
74
|
+
const routes = [
|
|
75
|
+
`${basePath}/mcp`,
|
|
76
|
+
...(servesInMemoryUploads(mcp) ? [`${basePath}/mcp/uploads`] : []),
|
|
77
|
+
`${basePath}/oauth/*`,
|
|
78
|
+
`/.well-known/oauth-authorization-server${basePath}`,
|
|
79
|
+
`/.well-known/oauth-protected-resource${basePath}/mcp`,
|
|
80
|
+
];
|
|
81
|
+
lines.push(`[Gateway] MCP: ${routes.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
if (api) {
|
|
84
|
+
const routes = [
|
|
85
|
+
`${basePath}/api/agent/*`,
|
|
86
|
+
`${basePath}/api/health`,
|
|
87
|
+
...(api.openapiEnabled ? [`${basePath}/api/docs`] : []),
|
|
88
|
+
];
|
|
89
|
+
const oauth = api.tokenEncryptionKey
|
|
90
|
+
? `, ${basePath}/oauth/*?service=api`
|
|
91
|
+
: ' (API OAuth off: no tokenEncryptionKey)';
|
|
92
|
+
lines.push(`[Gateway] API: ${routes.join(', ')}${oauth}`);
|
|
93
|
+
}
|
|
94
|
+
return lines;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZXdheS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9nYXRld2F5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQXFCQSx3Q0FpQkM7QUFjRCx3REFZQztBQUVELHdEQXlCQztBQVFELGtDQUVDO0FBRUQsc0RBNkJDO0FBbElELHlHQUF5RztBQUN6RyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUc5RCxDQUFDO0FBRVcsUUFBQSxzQkFBc0IsR0FBRyxnQkFBZ0IsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBRXBFLFFBQUEsYUFBYSxHQUFHLE9BQU8sQ0FBQztBQUVyQyxNQUFNLFFBQVEsR0FBRyxDQUFDLElBQVksRUFBRSxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFFOUYsTUFBTSx3QkFBd0IsR0FBRyxHQUFHLENBQUM7QUFFckMsTUFBTSxlQUFlLEdBQUc7SUFDdEIsUUFBUSxFQUFFLG9DQUFvQztJQUM5QyxPQUFPLEVBQUUsNENBQTRDO0NBQ3RELENBQUM7QUFFRixTQUFnQixjQUFjLENBQzVCLFVBQW9DLEVBQ3BDLEtBQW1DO0lBRW5DLE9BQU87UUFDTCxPQUFPLEVBQUUsVUFBVTtRQUNuQixRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDdEIsR0FBRyxDQUFDLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQztZQUMxQyxHQUFHLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1lBQ2xELEdBQUcsQ0FBQyxHQUFHLENBQ0wsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDYixLQUFLLEVBQUUseUJBQXlCO2dCQUNoQyxpQkFBaUIsRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDO2FBQzFDLENBQUMsQ0FDSCxDQUFD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
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { TSchema } from '@forestadmin/datasource-customizer';
|
|
|
3
3
|
import Agent from './agent';
|
|
4
4
|
export declare function createAgent<S extends TSchema = TSchema>(options: AgentOptions): Agent<S>;
|
|
5
5
|
export { Agent };
|
|
6
|
-
export { AgentOptions, BffEmbedOptions, WorkflowExecutorEmbedOptions } from './types';
|
|
6
|
+
export { AgentOptions, BffEmbedOptions, GatewayOptions, McpEmbedOptions, WorkflowExecutorEmbedOptions, } from './types';
|
|
7
7
|
export * from '@forestadmin/datasource-customizer';
|
|
8
8
|
export { default as SchemaGenerator } from './utils/forest-schema/generator';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -28,4 +28,4 @@ __exportStar(require("@forestadmin/datasource-customizer"), exports);
|
|
|
28
28
|
// export is necessary for the agent-generator package
|
|
29
29
|
var generator_1 = require("./utils/forest-schema/generator");
|
|
30
30
|
Object.defineProperty(exports, "SchemaGenerator", { enumerable: true, get: function () { return __importDefault(generator_1).default; } });
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFLQSxrQ0FFQztBQUpELG9EQUE0QjtBQU1uQixnQkFORixlQUFLLENBTUU7QUFKZCxTQUFnQixXQUFXLENBQThCLE9BQXFCO0lBQzVFLE9BQU8sSUFBSSxlQUFLLENBQUksT0FBTyxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQVVELHFFQUFtRDtBQUVuRCxzREFBc0Q7QUFDdEQsNkRBQTZFO0FBQXBFLDZIQUFBLE9BQU8sT0FBbUIifQ==
|
|
@@ -19,7 +19,8 @@ class AuditTrailTimelineRoute extends base_route_1.default {
|
|
|
19
19
|
const query = context.request.query;
|
|
20
20
|
const timezone = query.timezone?.toString() || 'UTC';
|
|
21
21
|
const limit = (0, query_params_1.parsePageSize)(query['page[size]']?.toString());
|
|
22
|
-
const
|
|
22
|
+
const order = query.sort?.toString() === 'timestamp' ? 'asc' : 'desc';
|
|
23
|
+
const cursor = AuditTrailTimelineRoute.parseCursor(context, order);
|
|
23
24
|
// Parsed before the permission sweep so a malformed filter reads as a 400 whatever the caller
|
|
24
25
|
// is allowed to see.
|
|
25
26
|
const filters = {
|
|
@@ -31,15 +32,23 @@ class AuditTrailTimelineRoute extends base_route_1.default {
|
|
|
31
32
|
};
|
|
32
33
|
const collections = await this.readableCollections(context);
|
|
33
34
|
const { store } = this.options.auditTrail;
|
|
35
|
+
// Authors on the first page only, like the per-record route and Forest's activity-logs route:
|
|
36
|
+
// they do not change along the walk, and later pages omit the key rather than send `[]`.
|
|
34
37
|
// One row over the page: the only way to know whether a further page exists without a count.
|
|
35
|
-
const fetched =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
const [fetched, availableUsers] = await Promise.all([
|
|
39
|
+
collections.length
|
|
40
|
+
? store.listTimeline({ ...filters, ...cursor, order, collections, limit: limit + 1 })
|
|
41
|
+
: [],
|
|
42
|
+
!cursor.before && !cursor.after && store.listTimelineUsers
|
|
43
|
+
? store.listTimelineUsers({ ...filters, collections })
|
|
44
|
+
: undefined,
|
|
45
|
+
]);
|
|
38
46
|
const page = fetched.slice(0, limit);
|
|
39
47
|
context.response.body = {
|
|
40
48
|
data: page,
|
|
41
49
|
meta: {
|
|
42
|
-
cursor: fetched.length > limit ? AuditTrailTimelineRoute.nextCursor(page, cursor) : null,
|
|
50
|
+
cursor: fetched.length > limit ? AuditTrailTimelineRoute.nextCursor(page, cursor, order) : null,
|
|
51
|
+
...(availableUsers && { availableUsers }),
|
|
43
52
|
},
|
|
44
53
|
};
|
|
45
54
|
}
|
|
@@ -58,9 +67,9 @@ class AuditTrailTimelineRoute extends base_route_1.default {
|
|
|
58
67
|
}));
|
|
59
68
|
return names.filter(Boolean);
|
|
60
69
|
}
|
|
61
|
-
// `before` is an inclusive
|
|
62
|
-
// over as `excludeIds` rather than being skipped — that is what keeps
|
|
63
|
-
// two pages. When the previous page ended on the same timestamp its exclusions still apply, so a
|
|
70
|
+
// `before` (`after` on an oldest-first walk) is an inclusive bound, so the rows sharing the last
|
|
71
|
+
// row's timestamp are carried over as `excludeIds` rather than being skipped — that is what keeps
|
|
72
|
+
// a tie from falling between two pages. When the previous page ended on the same timestamp its exclusions still apply, so a
|
|
64
73
|
// timestamp holding more rows than fit on one page walks forward instead of looping.
|
|
65
74
|
//
|
|
66
75
|
// Null when that walk makes no progress. Staying on the same timestamp must add at least the last
|
|
@@ -70,26 +79,29 @@ class AuditTrailTimelineRoute extends base_route_1.default {
|
|
|
70
79
|
// ~9e15 rows to reach it. Ending the walk is the safe answer at that point; the upgrade, if such
|
|
71
80
|
// a table ever exists, is to carry the id as a string through `AuditRecord`, the cursor and the
|
|
72
81
|
// SQL binding.
|
|
73
|
-
static nextCursor(page, previous) {
|
|
82
|
+
static nextCursor(page, previous, order) {
|
|
83
|
+
const bound = order === 'asc' ? 'after' : 'before';
|
|
74
84
|
const last = page[page.length - 1];
|
|
75
|
-
const sameBoundary = previous
|
|
85
|
+
const sameBoundary = previous[bound] === last.timestamp;
|
|
76
86
|
const carried = sameBoundary ? previous.excludeIds : [];
|
|
77
87
|
const tied = page.filter(row => row.timestamp === last.timestamp).map(row => row.id);
|
|
78
88
|
const excludeIds = [...new Set([...carried, ...tied])];
|
|
79
89
|
if (sameBoundary && excludeIds.length === carried.length)
|
|
80
90
|
return null;
|
|
81
|
-
return {
|
|
91
|
+
return { [bound]: last.timestamp, excludeIds };
|
|
82
92
|
}
|
|
83
|
-
static parseCursor(context) {
|
|
93
|
+
static parseCursor(context, order) {
|
|
84
94
|
const query = context.request.query;
|
|
85
|
-
const
|
|
95
|
+
const bound = order === 'asc'
|
|
96
|
+
? { after: (0, query_params_1.parseDateBoundary)(query.after?.toString(), 'UTC', 'start') }
|
|
97
|
+
: { before: (0, query_params_1.parseDateBoundary)(query.before?.toString(), 'UTC', 'end') };
|
|
86
98
|
const excludeIds = (query.excludeIds?.toString() ?? '')
|
|
87
99
|
.split(',')
|
|
88
100
|
.map(token => token.trim())
|
|
89
101
|
.filter(token => /^\d+$/.test(token))
|
|
90
102
|
.map(token => Number.parseInt(token, 10));
|
|
91
|
-
return {
|
|
103
|
+
return { ...bound, excludeIds };
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
106
|
exports.default = AuditTrailTimelineRoute;
|
|
95
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXQtdHJhaWwtdGltZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcm91dGVzL2FjY2Vzcy9hdWRpdC10cmFpbC10aW1lbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQU9BLGlFQU13QztBQUN4Qyx1Q0FBd0M7QUFDeEMsK0RBQXNDO0FBS3RDLE1BQXFCLHVCQUF3QixTQUFRLG9CQUFTO0lBSzVELFlBQ0UsUUFBdUMsRUFDdkMsT0FBaUMsRUFDakMsVUFBc0I7UUFFdEIsS0FBSyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztRQVRsQixTQUFJLEdBQUcsaUJBQVMsQ0FBQyxZQUFZLENBQUM7UUFVckMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDL0IsQ0FBQztJQUVELFdBQVcsQ0FBQyxNQUFjO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVNLEtBQUssQ0FBQyxjQUFjLENBQUMsT0FBZ0I7UUFDMUMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFnQyxDQUFDO1FBQy9ELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksS0FBSyxDQUFDO1FBQ3JELE1BQU0sS0FBSyxHQUFHLElBQUEsNEJBQWEsRUFBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM3RCxNQUFNLEtBQUssR0FBVSxLQUFLLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDN0UsTUFBTSxNQUFNLEdBQUcsdUJBQXVCLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxLQUFL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
|
|
@@ -32,6 +32,9 @@ class Capabilities extends base_route_1.default {
|
|
|
32
32
|
// or a custom store without `listTimeline`, omits it or answers false, and the front keeps
|
|
33
33
|
// the project page on the activity logs instead of 404ing on every batch.
|
|
34
34
|
canUseAuditTrailTimeline: Boolean(this.options.auditTrail?.store?.listTimeline),
|
|
35
|
+
// An agent before this flag serves the timeline newest first whatever `sort` asks, so the
|
|
36
|
+
// front offers oldest first on the project page only when it is set.
|
|
37
|
+
canSortAuditTrailTimeline: Boolean(this.options.auditTrail?.store?.listTimeline),
|
|
35
38
|
checksRelationReadPermissions: !this.options.skipRelationReadPermissions,
|
|
36
39
|
},
|
|
37
40
|
collections: collections?.map(collection => {
|
|
@@ -83,4 +86,4 @@ class Capabilities extends base_route_1.default {
|
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
exports.default = Capabilities;
|
|
86
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwYWJpbGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JvdXRlcy9jYXBhYmlsaXRpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFNQSx3RUFBNkQ7QUFFN0QsOERBQXFDO0FBQ3JDLG9DQUErQztBQUUvQyxNQUFxQixZQUFhLFNBQVEsb0JBQVM7SUFJakQsWUFDRSxRQUF1QyxFQUN2QyxPQUFpQyxFQUNqQyxVQUFzQjtRQUV0QixLQUFLLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBUmxCLFNBQUksR0FBRyxpQkFBUyxDQUFDLFlBQVksQ0FBQztRQVNyQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUMvQixDQUFDO0lBRUQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxPQUFnQjtRQUM5QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FDakUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFzQyxDQUFDLGVBQWUsRUFBRSxRQUFRLENBQy9FLFVBQVUsQ0FBQyxJQUFJLENBQ2hCLENBQ0YsQ0FBQztRQUVGLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHO1lBQ3RCLHNCQUFzQixFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLEdBQUcsQ0FDN0UsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQzdDO1lBQ0QsaUJBQWlCLEVBQUU7Z0JBQ2pCLHdCQUF3QixFQUFFLElB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
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AuditStore } from './audit-trail/types';
|
|
2
2
|
import type { CompositeId, Logger, LoggerLevel } from '@forestadmin/datasource-toolkit';
|
|
3
3
|
import type { ForestAdminClient } from '@forestadmin/forestadmin-client';
|
|
4
|
+
import type { FileUploadsOptions, TokenTtlOptions, ToolName } from '@forestadmin/mcp-server';
|
|
4
5
|
import type { WorkflowExecutorTuningOptions } from '@forestadmin/workflow-executor';
|
|
5
6
|
import type { IncomingMessage, ServerResponse } from 'http';
|
|
6
7
|
export type AuditTrailConfig = {
|
|
@@ -212,6 +213,19 @@ export type BffEmbedOptions = {
|
|
|
212
213
|
*/
|
|
213
214
|
shutdownTimeoutMs?: number;
|
|
214
215
|
};
|
|
216
|
+
export type McpEmbedOptions = {
|
|
217
|
+
enabledTools?: ToolName[];
|
|
218
|
+
basePath?: string;
|
|
219
|
+
tokenTtl?: TokenTtlOptions;
|
|
220
|
+
allowedOAuthClients?: string[];
|
|
221
|
+
fileUploads?: false | FileUploadsOptions;
|
|
222
|
+
};
|
|
223
|
+
export type GatewayOptions = {
|
|
224
|
+
basePath?: string;
|
|
225
|
+
allowedOAuthClients?: string[];
|
|
226
|
+
mcp?: Omit<McpEmbedOptions, 'basePath' | 'allowedOAuthClients'> | boolean;
|
|
227
|
+
api?: BffEmbedOptions | boolean;
|
|
228
|
+
};
|
|
215
229
|
export type AuditTrailRuntime = AuditTrailConfig & {
|
|
216
230
|
store: AuditStore;
|
|
217
231
|
close: () => Promise<void>;
|
package/dist/types.js
CHANGED
|
@@ -22,4 +22,4 @@ var RouteType;
|
|
|
22
22
|
RouteType[RouteType["Authentication"] = 3] = "Authentication";
|
|
23
23
|
RouteType[RouteType["PrivateRoute"] = 4] = "PrivateRoute";
|
|
24
24
|
})(RouteType || (exports.RouteType = RouteType = {}));
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBcVBBLElBQVksUUFVWDtBQVZELFdBQVksUUFBUTtJQUNsQixxREFBZ0IsQ0FBQTtJQUNoQix5REFBa0IsQ0FBQTtJQUNsQixtREFBZSxDQUFBO0lBQ2YsaURBQWMsQ0FBQTtJQUNkLDJEQUFtQixDQUFBO0lBQ25CLCtEQUFxQixDQUFBO0lBQ3JCLHVFQUF5QixDQUFBO0lBQ3pCLG1EQUFlLENBQUE7SUFDZixxQ0FBUSxDQUFBO0FBQ1YsQ0FBQyxFQVZXLFFBQVEsd0JBQVIsUUFBUSxRQVVuQjtBQUVELElBQVksU0FPWDtBQVBELFdBQVksU0FBUztJQUNuQixpR0FBaUc7SUFDakcsMkRBQWlCLENBQUE7SUFDakIseURBQWdCLENBQUE7SUFDaEIsdURBQWUsQ0FBQTtJQUNmLDZEQUFrQixDQUFBO0lBQ2xCLHlEQUFnQixDQUFBO0FBQ2xCLENBQUMsRUFQVyxTQUFTLHlCQUFULFNBQVMsUUFPcEIifQ==
|
|
@@ -20,12 +20,14 @@ exports.default = expressToKoa;
|
|
|
20
20
|
*/
|
|
21
21
|
function expressToKoa(expressApp, shouldHandle) {
|
|
22
22
|
return async (ctx, next) => {
|
|
23
|
+
var _a;
|
|
23
24
|
const url = ctx.url || '/';
|
|
24
25
|
// Skip if shouldHandle returns false
|
|
25
26
|
if (shouldHandle && !shouldHandle(url)) {
|
|
26
27
|
await next();
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
30
|
+
(_a = ctx.req).originalUrl ?? (_a.originalUrl = ctx.originalUrl);
|
|
29
31
|
// Let Express handle the request
|
|
30
32
|
const handled = await new Promise(resolve => {
|
|
31
33
|
// Tell Koa not to respond - Express will handle it
|
|
@@ -46,4 +48,4 @@ function expressToKoa(expressApp, shouldHandle) {
|
|
|
46
48
|
}
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzcy10by1rb2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvZXhwcmVzcy10by1rb2EudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUEwQkEsK0JBc0NDO0FBdkREOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsU0FBd0IsWUFBWSxDQUNsQyxVQUFrQyxFQUNsQyxZQUF1QztJQUV2QyxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7O1FBQ3pCLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDO1FBRTNCLHFDQUFxQztRQUNyQyxJQUFJLFlBQVksSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFFYixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQUMsR0FBRyxDQUFDLEdBQWlELEVBQUMsV0FBVyxRQUFYLFdBQVcsR0FBSyxHQUFHLENBQUMsV0FBVyxFQUFDO1FBRXZGLGlDQUFpQztRQUNqQyxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksT0FBTyxDQUFVLE9BQU8sQ0FBQyxFQUFFO1lBQ25ELG1EQUFtRDtZQUNuRCxHQUFHLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztZQUVwQixNQUFNLFFBQVEsR0FBRyxVQUEwQixDQUFDO1lBQzVDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO2dCQUM5Qix1REFBdUQ7Z0JBQ3ZELEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUNuQixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDakIsQ0FBQyxDQUFDLENBQUM7WUFFSCwyQ0FBMkM7WUFDM0MsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzVDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztRQUVILGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksRUFBRSxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUMsQ0FBQztBQUNKLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forestadmin/agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.110.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"@forestadmin/agent-toolkit": "1.2.1",
|
|
17
17
|
"@forestadmin/datasource-customizer": "1.73.1",
|
|
18
18
|
"@forestadmin/datasource-toolkit": "1.56.1",
|
|
19
|
-
"@forestadmin/forestadmin-client": "1.
|
|
20
|
-
"@forestadmin/mcp-server": "1.
|
|
19
|
+
"@forestadmin/forestadmin-client": "1.44.0",
|
|
20
|
+
"@forestadmin/mcp-server": "1.29.0",
|
|
21
21
|
"@koa/bodyparser": "^6.0.0",
|
|
22
22
|
"@koa/cors": "^5.0.0",
|
|
23
23
|
"@koa/router": "^13.1.0",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@fastify/express": "^1.1.0",
|
|
52
|
-
"@forestadmin/agent-bff": "1.
|
|
52
|
+
"@forestadmin/agent-bff": "1.41.0",
|
|
53
53
|
"@forestadmin/datasource-sql": "1.17.16",
|
|
54
|
-
"@forestadmin/workflow-executor": "1.33.
|
|
54
|
+
"@forestadmin/workflow-executor": "1.33.1",
|
|
55
55
|
"@nestjs/common": "^11.1.24",
|
|
56
56
|
"@nestjs/core": "^11.1.24",
|
|
57
57
|
"@nestjs/platform-express": "^11.1.24",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"@fastify/express": "^1.1.0 || ^2.0.0 || ^3.0.0 || ^4.0.0",
|
|
78
|
-
"@forestadmin/agent-bff": "1.
|
|
79
|
-
"@forestadmin/workflow-executor": "1.33.
|
|
78
|
+
"@forestadmin/agent-bff": "1.41.0",
|
|
79
|
+
"@forestadmin/workflow-executor": "1.33.1"
|
|
80
80
|
},
|
|
81
81
|
"peerDependenciesMeta": {
|
|
82
82
|
"@fastify/express": {
|