@forestadmin/ai-proxy 1.4.3 → 1.5.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.
@@ -0,0 +1,27 @@
1
+ import type { OpenAIMessage } from './langchain-adapter';
2
+ import type { ChatCompletionTool, ChatCompletionToolChoice } from './provider';
3
+ import type { ChatAnthropic } from '@langchain/anthropic';
4
+ import type { BaseMessage } from '@langchain/core/messages';
5
+ export default class AnthropicAdapter {
6
+ static convertMessages(messages: OpenAIMessage[]): BaseMessage[];
7
+ /** Cast `as string` works around LangChain's AnthropicToolChoice missing `disable_parallel_tool_use`. */
8
+ static bindTools(model: ChatAnthropic, tools: ChatCompletionTool[], { toolChoice, parallelToolCalls, }: {
9
+ toolChoice?: ChatCompletionToolChoice;
10
+ parallelToolCalls?: boolean;
11
+ }): ChatAnthropic;
12
+ /**
13
+ * Convert OpenAI tool_choice to Anthropic format, applying parallel tool restriction.
14
+ *
15
+ * Converts to LangChain format first, then applies `disable_parallel_tool_use`
16
+ * when `parallelToolCalls` is explicitly `false` (not just falsy — `undefined` means
17
+ * no restriction).
18
+ */
19
+ private static convertToolChoice;
20
+ /**
21
+ * Merge all system messages into a single one placed first.
22
+ *
23
+ * Anthropic only allows a single system message at the beginning of the conversation.
24
+ */
25
+ private static mergeSystemMessages;
26
+ }
27
+ //# sourceMappingURL=anthropic-adapter.d.ts.map
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const langchain_adapter_1 = require("./langchain-adapter");
4
+ class AnthropicAdapter {
5
+ static convertMessages(messages) {
6
+ return langchain_adapter_1.LangChainAdapter.convertMessages(AnthropicAdapter.mergeSystemMessages(messages));
7
+ }
8
+ /** Cast `as string` works around LangChain's AnthropicToolChoice missing `disable_parallel_tool_use`. */
9
+ static bindTools(model, tools, { toolChoice, parallelToolCalls, }) {
10
+ return model.bindTools(tools, {
11
+ tool_choice: AnthropicAdapter.convertToolChoice({ toolChoice, parallelToolCalls }),
12
+ });
13
+ }
14
+ /**
15
+ * Convert OpenAI tool_choice to Anthropic format, applying parallel tool restriction.
16
+ *
17
+ * Converts to LangChain format first, then applies `disable_parallel_tool_use`
18
+ * when `parallelToolCalls` is explicitly `false` (not just falsy — `undefined` means
19
+ * no restriction).
20
+ */
21
+ static convertToolChoice({ toolChoice, parallelToolCalls, } = {}) {
22
+ const base = langchain_adapter_1.LangChainAdapter.convertToolChoice(toolChoice);
23
+ if (parallelToolCalls !== false)
24
+ return base;
25
+ // Anthropic requires object form to set disable_parallel_tool_use
26
+ if (base === undefined || base === 'auto') {
27
+ return { type: 'auto', disable_parallel_tool_use: true };
28
+ }
29
+ if (base === 'any') {
30
+ return { type: 'any', disable_parallel_tool_use: true };
31
+ }
32
+ if (base === 'none')
33
+ return 'none';
34
+ return { ...base, disable_parallel_tool_use: true };
35
+ }
36
+ /**
37
+ * Merge all system messages into a single one placed first.
38
+ *
39
+ * Anthropic only allows a single system message at the beginning of the conversation.
40
+ */
41
+ static mergeSystemMessages(messages) {
42
+ const systemContents = messages.filter(m => m.role === 'system').map(m => m.content || '');
43
+ if (systemContents.length <= 1)
44
+ return messages;
45
+ const merged = { role: 'system', content: systemContents.join('\n\n') };
46
+ const nonSystem = messages.filter(m => m.role !== 'system');
47
+ return [merged, ...nonSystem];
48
+ }
49
+ }
50
+ exports.default = AnthropicAdapter;
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW50aHJvcGljLWFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYW50aHJvcGljLWFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSwyREFBdUQ7QUFldkQsTUFBcUIsZ0JBQWdCO0lBQ25DLE1BQU0sQ0FBQyxlQUFlLENBQUMsUUFBeUI7UUFDOUMsT0FBTyxvQ0FBZ0IsQ0FBQyxlQUFlLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMxRixDQUFDO0lBRUQseUdBQXlHO0lBQ3pHLE1BQU0sQ0FBQyxTQUFTLENBQ2QsS0FBb0IsRUFDcEIsS0FBMkIsRUFDM0IsRUFDRSxVQUFVLEVBQ1YsaUJBQWlCLEdBQ3NEO1FBRXpFLE9BQU8sS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUU7WUFDNUIsV0FBVyxFQUFFLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDLEVBQUUsVUFBVSxFQUFFLGlCQUFpQixFQUFFLENBQVc7U0FDN0YsQ0FBa0IsQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssTUFBTSxDQUFDLGlCQUFpQixDQUFDLEVBQy9CLFVBQVUsRUFDVixpQkFBaUIsTUFJZixFQUFFO1FBQ0osTUFBTSxJQUFJLEdBQUcsb0NBQWdCLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFNUQsSUFBSSxpQkFBaUIsS0FBSyxLQUFLO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFN0Msa0VBQWtFO1FBQ2xFLElBQUksSUFBSSxLQUFLLFNBQVMsSUFBSSxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDMUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUseUJBQXlCLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDM0QsQ0FBQztRQUVELElBQUksSUFBSSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ25CLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxDQUFDO1FBQzFELENBQUM7UUFFRCxJQUFJLElBQUksS0FBSyxNQUFNO1lBQUUsT0FBTyxNQUFNLENBQUM7UUFFbkMsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssTUFBTSxDQUFDLG1CQUFtQixDQUFDLFFBQXlCO1FBQzFELE1BQU0sY0FBYyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7UUFFM0YsSUFBSSxjQUFjLENBQUMsTUFBTSxJQUFJLENBQUM7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUVoRCxNQUFNLE1BQU0sR0FBa0IsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDdkYsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUM7UUFFNUQsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDRjtBQWxFRCxtQ0FrRUMifQ==
@@ -0,0 +1,4 @@
1
+ import type { AiConfiguration } from './provider';
2
+ import type { AiProviderDefinition } from '@forestadmin/agent-toolkit';
3
+ export declare function createAiProvider(config: AiConfiguration): AiProviderDefinition;
4
+ //# sourceMappingURL=create-ai-provider.d.ts.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAiProvider = createAiProvider;
4
+ const oauth_token_injector_1 = require("./oauth-token-injector");
5
+ const router_1 = require("./router");
6
+ function resolveMcpConfigs(args) {
7
+ const tokensByMcpServerName = args.headers
8
+ ? (0, oauth_token_injector_1.extractMcpOauthTokensFromHeaders)(args.headers)
9
+ : undefined;
10
+ return (0, oauth_token_injector_1.injectOauthTokens)({
11
+ mcpConfigs: args.mcpServerConfigs,
12
+ tokensByMcpServerName,
13
+ });
14
+ }
15
+ // eslint-disable-next-line import/prefer-default-export
16
+ function createAiProvider(config) {
17
+ return {
18
+ providers: [{ name: config.name, provider: config.provider, model: config.model }],
19
+ init(logger) {
20
+ const router = new router_1.Router({ aiConfigurations: [config], logger });
21
+ return {
22
+ // Cast is safe: AiRouter.route accepts any string, but Router validates
23
+ // it at runtime via Zod against the allowed literal union (RouterRouteArgs).
24
+ route: args => router.route({
25
+ route: args.route,
26
+ body: args.body,
27
+ query: args.query,
28
+ mcpConfigs: resolveMcpConfigs(args),
29
+ }),
30
+ };
31
+ },
32
+ };
33
+ }
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLWFpLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NyZWF0ZS1haS1wcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW9CQSw0Q0FtQkM7QUFsQ0QsaUVBQTZGO0FBQzdGLHFDQUFrQztBQUVsQyxTQUFTLGlCQUFpQixDQUFDLElBQXNDO0lBQy9ELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLE9BQU87UUFDeEMsQ0FBQyxDQUFDLElBQUEsdURBQWdDLEVBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNoRCxDQUFDLENBQUMsU0FBUyxDQUFDO0lBRWQsT0FBTyxJQUFBLHdDQUFpQixFQUFDO1FBQ3ZCLFVBQVUsRUFBRSxJQUFJLENBQUMsZ0JBQWdEO1FBQ2pFLHFCQUFxQjtLQUN0QixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsd0RBQXdEO0FBQ3hELFNBQWdCLGdCQUFnQixDQUFDLE1BQXVCO0lBQ3RELE9BQU87UUFDTCxTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbEYsSUFBSSxDQUFDLE1BQU07WUFDVCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUVsRSxPQUFPO2dCQUNMLHdFQUF3RTtnQkFDeEUsNkVBQTZFO2dCQUM3RSxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FDWixNQUFNLENBQUMsS0FBSyxDQUFDO29CQUNYLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztvQkFDakIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO29CQUNmLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztvQkFDakIsVUFBVSxFQUFFLGlCQUFpQixDQUFDLElBQUksQ0FBQztpQkFDakIsQ0FBQzthQUN4QixDQUFDO1FBQ0osQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDIn0=
package/dist/errors.d.ts CHANGED
@@ -1,36 +1,30 @@
1
1
  /**
2
- * -------------------------------------
3
- * -------------------------------------
4
- * -------------------------------------
5
- * All custom errors must extend the AIError class.
6
- * This inheritance is crucial for proper error translation
7
- * and consistent handling throughout the system.
8
- * -------------------------------------
9
- * -------------------------------------
10
- * -------------------------------------
2
+ * All custom AI errors extend HTTP-status error classes (BadRequestError, NotFoundError,
3
+ * UnprocessableError) from datasource-toolkit. This allows the agent's error middleware
4
+ * to map them to their natural HTTP status codes automatically.
11
5
  */
12
- export declare class AIError extends Error {
13
- readonly status: number;
14
- constructor(message: string, status?: number);
6
+ import { BadRequestError, NotFoundError, UnprocessableError } from '@forestadmin/datasource-toolkit';
7
+ export declare class AIError extends UnprocessableError {
8
+ constructor(message: string);
15
9
  }
16
- export declare class AIBadRequestError extends AIError {
10
+ export declare class AIBadRequestError extends BadRequestError {
17
11
  constructor(message: string);
18
12
  }
19
13
  export declare class AIModelNotSupportedError extends AIBadRequestError {
20
14
  constructor(model: string);
21
15
  }
22
- export declare class AINotFoundError extends AIError {
16
+ export declare class AINotFoundError extends NotFoundError {
23
17
  constructor(message: string);
24
18
  }
25
- export declare class AIUnprocessableError extends AIError {
26
- constructor(message: string);
19
+ export declare class AIUnprocessableError extends UnprocessableError {
20
+ readonly cause?: Error;
21
+ constructor(message: string, options?: {
22
+ cause?: Error;
23
+ });
27
24
  }
28
25
  export declare class AINotConfiguredError extends AIError {
29
26
  constructor(message?: string);
30
27
  }
31
- export declare class OpenAIUnprocessableError extends AIUnprocessableError {
32
- constructor(message: string);
33
- }
34
28
  export declare class AIToolUnprocessableError extends AIUnprocessableError {
35
29
  constructor(message: string);
36
30
  }
package/dist/errors.js CHANGED
@@ -1,32 +1,23 @@
1
1
  "use strict";
2
2
  /**
3
- * -------------------------------------
4
- * -------------------------------------
5
- * -------------------------------------
6
- * All custom errors must extend the AIError class.
7
- * This inheritance is crucial for proper error translation
8
- * and consistent handling throughout the system.
9
- * -------------------------------------
10
- * -------------------------------------
11
- * -------------------------------------
3
+ * All custom AI errors extend HTTP-status error classes (BadRequestError, NotFoundError,
4
+ * UnprocessableError) from datasource-toolkit. This allows the agent's error middleware
5
+ * to map them to their natural HTTP status codes automatically.
12
6
  */
13
7
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.McpConfigError = exports.McpConflictError = exports.McpConnectionError = exports.McpError = exports.AIToolNotFoundError = exports.AIToolUnprocessableError = exports.OpenAIUnprocessableError = exports.AINotConfiguredError = exports.AIUnprocessableError = exports.AINotFoundError = exports.AIModelNotSupportedError = exports.AIBadRequestError = exports.AIError = void 0;
8
+ exports.McpConfigError = exports.McpConflictError = exports.McpConnectionError = exports.McpError = exports.AIToolNotFoundError = exports.AIToolUnprocessableError = exports.AINotConfiguredError = exports.AIUnprocessableError = exports.AINotFoundError = exports.AIModelNotSupportedError = exports.AIBadRequestError = exports.AIError = void 0;
15
9
  // eslint-disable-next-line max-classes-per-file
16
- class AIError extends Error {
17
- constructor(message, status = 422) {
18
- if (status < 100 || status > 599) {
19
- throw new RangeError(`Invalid HTTP status code: ${status}`);
20
- }
10
+ const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
11
+ class AIError extends datasource_toolkit_1.UnprocessableError {
12
+ constructor(message) {
21
13
  super(message);
22
14
  this.name = 'AIError';
23
- this.status = status;
24
15
  }
25
16
  }
26
17
  exports.AIError = AIError;
27
- class AIBadRequestError extends AIError {
18
+ class AIBadRequestError extends datasource_toolkit_1.BadRequestError {
28
19
  constructor(message) {
29
- super(message, 400);
20
+ super(message);
30
21
  this.name = 'AIBadRequestError';
31
22
  }
32
23
  }
@@ -38,38 +29,33 @@ class AIModelNotSupportedError extends AIBadRequestError {
38
29
  }
39
30
  }
40
31
  exports.AIModelNotSupportedError = AIModelNotSupportedError;
41
- class AINotFoundError extends AIError {
32
+ class AINotFoundError extends datasource_toolkit_1.NotFoundError {
42
33
  constructor(message) {
43
- super(message, 404);
34
+ super(message);
44
35
  this.name = 'AINotFoundError';
45
36
  }
46
37
  }
47
38
  exports.AINotFoundError = AINotFoundError;
48
- class AIUnprocessableError extends AIError {
49
- constructor(message) {
50
- super(message, 422);
39
+ class AIUnprocessableError extends datasource_toolkit_1.UnprocessableError {
40
+ constructor(message, options) {
41
+ super(message);
51
42
  this.name = 'AIUnprocessableError';
43
+ if (options?.cause)
44
+ this.cause = options.cause;
52
45
  }
53
46
  }
54
47
  exports.AIUnprocessableError = AIUnprocessableError;
55
48
  class AINotConfiguredError extends AIError {
56
49
  constructor(message = 'AI is not configured') {
57
- super(message, 422);
50
+ super(message);
58
51
  this.name = 'AINotConfiguredError';
59
52
  }
60
53
  }
61
54
  exports.AINotConfiguredError = AINotConfiguredError;
62
- class OpenAIUnprocessableError extends AIUnprocessableError {
63
- constructor(message) {
64
- super(message);
65
- this.name = 'OpenAIError';
66
- }
67
- }
68
- exports.OpenAIUnprocessableError = OpenAIUnprocessableError;
69
55
  class AIToolUnprocessableError extends AIUnprocessableError {
70
56
  constructor(message) {
71
57
  super(message);
72
- this.name = 'AIToolError';
58
+ this.name = 'AIToolUnprocessableError';
73
59
  }
74
60
  }
75
61
  exports.AIToolUnprocessableError = AIToolUnprocessableError;
@@ -108,4 +94,4 @@ class McpConfigError extends McpError {
108
94
  }
109
95
  }
110
96
  exports.McpConfigError = McpConfigError;
111
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7R0FVRzs7O0FBRUgsZ0RBQWdEO0FBQ2hELE1BQWEsT0FBUSxTQUFRLEtBQUs7SUFHaEMsWUFBWSxPQUFlLEVBQUUsTUFBTSxHQUFHLEdBQUc7UUFDdkMsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUNqQyxNQUFNLElBQUksVUFBVSxDQUFDLDZCQUE2QixNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0NBQ0Y7QUFaRCwwQkFZQztBQUVELE1BQWEsaUJBQWtCLFNBQVEsT0FBTztJQUM1QyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLG1CQUFtQixDQUFDO0lBQ2xDLENBQUM7Q0FDRjtBQUxELDhDQUtDO0FBRUQsTUFBYSx3QkFBeUIsU0FBUSxpQkFBaUI7SUFDN0QsWUFBWSxLQUFhO1FBQ3ZCLEtBQUssQ0FDSCxVQUFVLEtBQUssOEVBQThFLENBQzlGLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxHQUFHLDBCQUEwQixDQUFDO0lBQ3pDLENBQUM7Q0FDRjtBQVBELDREQU9DO0FBRUQsTUFBYSxlQUFnQixTQUFRLE9BQU87SUFDMUMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0NBQ0Y7QUFMRCwwQ0FLQztBQUVELE1BQWEsb0JBQXFCLFNBQVEsT0FBTztJQUMvQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQUxELG9EQUtDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxPQUFPO0lBQy9DLFlBQVksT0FBTyxHQUFHLHNCQUFzQjtRQUMxQyxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxJQUFJLEdBQUcsc0JBQXNCLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBTEQsb0RBS0M7QUFFRCxNQUFhLHdCQUF5QixTQUFRLG9CQUFvQjtJQUNoRSxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBTEQsNERBS0M7QUFFRCxNQUFhLHdCQUF5QixTQUFRLG9CQUFvQjtJQUNoRSxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBTEQsNERBS0M7QUFFRCxNQUFhLG1CQUFvQixTQUFRLGVBQWU7SUFDdEQsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUM7SUFDcEMsQ0FBQztDQUNGO0FBTEQsa0RBS0M7QUFFRCxNQUFhLFFBQVMsU0FBUSxPQUFPO0lBQ25DLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFMRCw0QkFLQztBQUVELE1BQWEsa0JBQW1CLFNBQVEsUUFBUTtJQUM5QyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxvQkFBb0IsQ0FBQztJQUNuQyxDQUFDO0NBQ0Y7QUFMRCxnREFLQztBQUVELE1BQWEsZ0JBQWlCLFNBQVEsUUFBUTtJQUM1QyxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyxJQUFJLFVBQVUsbUNBQW1DLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQUxELDRDQUtDO0FBRUQsTUFBYSxjQUFlLFNBQVEsUUFBUTtJQUMxQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxnQkFBZ0IsQ0FBQztJQUMvQixDQUFDO0NBQ0Y7QUFMRCx3Q0FLQyJ9
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7R0FJRzs7O0FBRUgsZ0RBQWdEO0FBQ2hELHdFQUl5QztBQUV6QyxNQUFhLE9BQVEsU0FBUSx1Q0FBa0I7SUFDN0MsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQ3hCLENBQUM7Q0FDRjtBQUxELDBCQUtDO0FBRUQsTUFBYSxpQkFBa0IsU0FBUSxvQ0FBZTtJQUNwRCxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxtQkFBbUIsQ0FBQztJQUNsQyxDQUFDO0NBQ0Y7QUFMRCw4Q0FLQztBQUVELE1BQWEsd0JBQXlCLFNBQVEsaUJBQWlCO0lBQzdELFlBQVksS0FBYTtRQUN2QixLQUFLLENBQ0gsVUFBVSxLQUFLLDhFQUE4RSxDQUM5RixDQUFDO1FBQ0YsSUFBSSxDQUFDLElBQUksR0FBRywwQkFBMEIsQ0FBQztJQUN6QyxDQUFDO0NBQ0Y7QUFQRCw0REFPQztBQUVELE1BQWEsZUFBZ0IsU0FBUSxrQ0FBYTtJQUNoRCxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0NBQ0Y7QUFMRCwwQ0FLQztBQUVELE1BQWEsb0JBQXFCLFNBQVEsdUNBQWtCO0lBRzFELFlBQVksT0FBZSxFQUFFLE9BQTJCO1FBQ3RELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsc0JBQXNCLENBQUM7UUFDbkMsSUFBSSxPQUFPLEVBQUUsS0FBSztZQUFFLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUNqRCxDQUFDO0NBQ0Y7QUFSRCxvREFRQztBQUVELE1BQWEsb0JBQXFCLFNBQVEsT0FBTztJQUMvQyxZQUFZLE9BQU8sR0FBRyxzQkFBc0I7UUFDMUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxzQkFBc0IsQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUFMRCxvREFLQztBQUVELE1BQWEsd0JBQXlCLFNBQVEsb0JBQW9CO0lBQ2hFLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLDBCQUEwQixDQUFDO0lBQ3pDLENBQUM7Q0FDRjtBQUxELDREQUtDO0FBRUQsTUFBYSxtQkFBb0IsU0FBUSxlQUFlO0lBQ3RELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDO0lBQ3BDLENBQUM7Q0FDRjtBQUxELGtEQUtDO0FBRUQsTUFBYSxRQUFTLFNBQVEsT0FBTztJQUNuQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUM7SUFDekIsQ0FBQztDQUNGO0FBTEQsNEJBS0M7QUFFRCxNQUFhLGtCQUFtQixTQUFRLFFBQVE7SUFDOUMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsb0JBQW9CLENBQUM7SUFDbkMsQ0FBQztDQUNGO0FBTEQsZ0RBS0M7QUFFRCxNQUFhLGdCQUFpQixTQUFRLFFBQVE7SUFDNUMsWUFBWSxVQUFrQjtRQUM1QixLQUFLLENBQUMsSUFBSSxVQUFVLG1DQUFtQyxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLElBQUksR0FBRyxrQkFBa0IsQ0FBQztJQUNqQyxDQUFDO0NBQ0Y7QUFMRCw0Q0FLQztBQUVELE1BQWEsY0FBZSxTQUFRLFFBQVE7SUFDMUMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsZ0JBQWdCLENBQUM7SUFDL0IsQ0FBQztDQUNGO0FBTEQsd0NBS0MifQ==
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { McpConfiguration } from './mcp-client';
2
+ export { createAiProvider } from './create-ai-provider';
3
+ export { default as ProviderDispatcher } from './provider-dispatcher';
2
4
  export * from './provider-dispatcher';
3
5
  export * from './remote-tools';
4
6
  export * from './router';
package/dist/index.js CHANGED
@@ -17,8 +17,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.ProviderDispatcher = exports.createAiProvider = void 0;
20
21
  exports.validMcpConfigurationOrThrow = validMcpConfigurationOrThrow;
21
22
  const mcp_config_checker_1 = __importDefault(require("./mcp-config-checker"));
23
+ var create_ai_provider_1 = require("./create-ai-provider");
24
+ Object.defineProperty(exports, "createAiProvider", { enumerable: true, get: function () { return create_ai_provider_1.createAiProvider; } });
25
+ var provider_dispatcher_1 = require("./provider-dispatcher");
26
+ Object.defineProperty(exports, "ProviderDispatcher", { enumerable: true, get: function () { return __importDefault(provider_dispatcher_1).default; } });
22
27
  __exportStar(require("./provider-dispatcher"), exports);
23
28
  __exportStar(require("./remote-tools"), exports);
24
29
  __exportStar(require("./router"), exports);
@@ -28,4 +33,4 @@ __exportStar(require("./errors"), exports);
28
33
  function validMcpConfigurationOrThrow(mcpConfig) {
29
34
  return mcp_config_checker_1.default.check(mcpConfig);
30
35
  }
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVdBLG9FQUVDO0FBWEQsOEVBQW9EO0FBRXBELHdEQUFzQztBQUN0QyxpREFBK0I7QUFDL0IsMkNBQXlCO0FBQ3pCLCtDQUE2QjtBQUM3Qix5REFBdUM7QUFDdkMsMkNBQXlCO0FBRXpCLFNBQWdCLDRCQUE0QixDQUFDLFNBQTJCO0lBQ3RFLE9BQU8sNEJBQWdCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzNDLENBQUMifQ==
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFhQSxvRUFFQztBQWJELDhFQUFvRDtBQUVwRCwyREFBd0Q7QUFBL0Msc0hBQUEsZ0JBQWdCLE9BQUE7QUFDekIsNkRBQXNFO0FBQTdELDBJQUFBLE9BQU8sT0FBc0I7QUFDdEMsd0RBQXNDO0FBQ3RDLGlEQUErQjtBQUMvQiwyQ0FBeUI7QUFDekIsK0NBQTZCO0FBQzdCLHlEQUF1QztBQUN2QywyQ0FBeUI7QUFFekIsU0FBZ0IsNEJBQTRCLENBQUMsU0FBMkI7SUFDdEUsT0FBTyw0QkFBZ0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDM0MsQ0FBQyJ9
@@ -0,0 +1,45 @@
1
+ import type { ChatCompletionResponse, ChatCompletionToolChoice } from './provider';
2
+ import type { BaseMessage } from '@langchain/core/messages';
3
+ import { AIMessage } from '@langchain/core/messages';
4
+ interface OpenAISystemMessage {
5
+ role: 'system';
6
+ content: string | null;
7
+ }
8
+ interface OpenAIUserMessage {
9
+ role: 'user';
10
+ content: string | null;
11
+ }
12
+ interface OpenAIAssistantMessage {
13
+ role: 'assistant';
14
+ content: string | null;
15
+ tool_calls?: Array<{
16
+ id: string;
17
+ function: {
18
+ name: string;
19
+ arguments: string;
20
+ };
21
+ }>;
22
+ }
23
+ interface OpenAIToolMessage {
24
+ role: 'tool';
25
+ content: string | null;
26
+ tool_call_id: string;
27
+ }
28
+ export type OpenAIMessage = OpenAISystemMessage | OpenAIUserMessage | OpenAIAssistantMessage | OpenAIToolMessage;
29
+ export type LangChainToolChoice = 'auto' | 'any' | 'none' | {
30
+ type: 'tool';
31
+ name: string;
32
+ } | undefined;
33
+ /** Handles generic format conversions between OpenAI and LangChain. */
34
+ export declare class LangChainAdapter {
35
+ /** Convert OpenAI-format messages to LangChain messages. */
36
+ static convertMessages(messages: OpenAIMessage[]): BaseMessage[];
37
+ /** Convert a LangChain AIMessage to an OpenAI-compatible ChatCompletionResponse. */
38
+ static convertResponse(response: AIMessage, modelName: string | null): ChatCompletionResponse;
39
+ /** Convert OpenAI tool_choice to LangChain format. */
40
+ static convertToolChoice(toolChoice: ChatCompletionToolChoice | undefined): LangChainToolChoice;
41
+ private static extractTextContent;
42
+ private static parseToolArguments;
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=langchain-adapter.d.ts.map
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LangChainAdapter = void 0;
7
+ const messages_1 = require("@langchain/core/messages");
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const errors_1 = require("./errors");
10
+ /** Handles generic format conversions between OpenAI and LangChain. */
11
+ class LangChainAdapter {
12
+ /** Convert OpenAI-format messages to LangChain messages. */
13
+ static convertMessages(messages) {
14
+ const result = [];
15
+ for (const msg of messages) {
16
+ switch (msg.role) {
17
+ case 'system':
18
+ result.push(new messages_1.SystemMessage(msg.content || ''));
19
+ break;
20
+ case 'user':
21
+ result.push(new messages_1.HumanMessage(msg.content || ''));
22
+ break;
23
+ case 'assistant':
24
+ if (msg.tool_calls) {
25
+ result.push(new messages_1.AIMessage({
26
+ content: msg.content || '',
27
+ tool_calls: msg.tool_calls.map(tc => ({
28
+ id: tc.id,
29
+ name: tc.function.name,
30
+ args: LangChainAdapter.parseToolArguments(tc.function.name, tc.function.arguments),
31
+ })),
32
+ }));
33
+ }
34
+ else {
35
+ result.push(new messages_1.AIMessage(msg.content || ''));
36
+ }
37
+ break;
38
+ case 'tool':
39
+ if (!msg.tool_call_id) {
40
+ throw new errors_1.AIBadRequestError('Tool message is missing required "tool_call_id" field.');
41
+ }
42
+ result.push(new messages_1.ToolMessage({
43
+ content: msg.content || '',
44
+ tool_call_id: msg.tool_call_id,
45
+ }));
46
+ break;
47
+ default:
48
+ throw new errors_1.AIBadRequestError(`Unsupported message role '${msg.role}'. Expected: system, user, assistant, or tool.`);
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ /** Convert a LangChain AIMessage to an OpenAI-compatible ChatCompletionResponse. */
54
+ static convertResponse(response, modelName) {
55
+ const toolCalls = response.tool_calls?.map(tc => ({
56
+ id: tc.id || `call_${crypto_1.default.randomUUID()}`,
57
+ type: 'function',
58
+ function: {
59
+ name: tc.name,
60
+ arguments: JSON.stringify(tc.args),
61
+ },
62
+ }));
63
+ const usageMetadata = response.usage_metadata;
64
+ return {
65
+ id: response.id || `msg_${crypto_1.default.randomUUID()}`,
66
+ object: 'chat.completion',
67
+ created: Math.floor(Date.now() / 1000),
68
+ model: modelName,
69
+ choices: [
70
+ {
71
+ index: 0,
72
+ message: {
73
+ role: 'assistant',
74
+ content: LangChainAdapter.extractTextContent(response.content),
75
+ refusal: null,
76
+ tool_calls: toolCalls?.length ? toolCalls : undefined,
77
+ },
78
+ finish_reason: toolCalls?.length ? 'tool_calls' : 'stop',
79
+ logprobs: null,
80
+ },
81
+ ],
82
+ usage: {
83
+ prompt_tokens: usageMetadata?.input_tokens ?? 0,
84
+ completion_tokens: usageMetadata?.output_tokens ?? 0,
85
+ total_tokens: usageMetadata?.total_tokens ?? 0,
86
+ },
87
+ };
88
+ }
89
+ /** Convert OpenAI tool_choice to LangChain format. */
90
+ static convertToolChoice(toolChoice) {
91
+ if (!toolChoice)
92
+ return undefined;
93
+ if (toolChoice === 'auto')
94
+ return 'auto';
95
+ if (toolChoice === 'none')
96
+ return 'none';
97
+ if (toolChoice === 'required')
98
+ return 'any';
99
+ if (typeof toolChoice === 'object' && toolChoice.type === 'function') {
100
+ return { type: 'tool', name: toolChoice.function.name };
101
+ }
102
+ throw new errors_1.AIBadRequestError(`Unsupported tool_choice value. Expected: 'auto', 'none', 'required', or {type: 'function', function: {name: '...'}}.`);
103
+ }
104
+ static extractTextContent(content) {
105
+ if (typeof content === 'string')
106
+ return content || null;
107
+ if (Array.isArray(content)) {
108
+ const text = content
109
+ .filter(block => block.type === 'text')
110
+ .map(block => ('text' in block ? block.text : ''))
111
+ .join('');
112
+ return text || null;
113
+ }
114
+ return null;
115
+ }
116
+ static parseToolArguments(toolName, args) {
117
+ try {
118
+ return JSON.parse(args);
119
+ }
120
+ catch {
121
+ throw new errors_1.AIBadRequestError(`Invalid JSON in tool_calls arguments for tool '${toolName}': ${args}`);
122
+ }
123
+ }
124
+ }
125
+ exports.LangChainAdapter = LangChainAdapter;
126
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFuZ2NoYWluLWFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbGFuZ2NoYWluLWFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBR0EsdURBQStGO0FBQy9GLG9EQUE0QjtBQUU1QixxQ0FBNkM7QUEyQzdDLHVFQUF1RTtBQUN2RSxNQUFhLGdCQUFnQjtJQUMzQiw0REFBNEQ7SUFDNUQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxRQUF5QjtRQUM5QyxNQUFNLE1BQU0sR0FBa0IsRUFBRSxDQUFDO1FBRWpDLEtBQUssTUFBTSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7WUFDM0IsUUFBUSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2pCLEtBQUssUUFBUTtvQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksd0JBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ2xELE1BQU07Z0JBQ1IsS0FBSyxNQUFNO29CQUNULE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSx1QkFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztvQkFDakQsTUFBTTtnQkFDUixLQUFLLFdBQVc7b0JBQ2QsSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUM7d0JBQ25CLE1BQU0sQ0FBQyxJQUFJLENBQ1QsSUFBSSxvQkFBUyxDQUFDOzRCQUNaLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUU7NEJBQzFCLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Z0NBQ3BDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRTtnQ0FDVCxJQUFJLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJO2dDQUN0QixJQUFJLEVBQUUsZ0JBQWdCLENBQUMsa0JBQWtCLENBQ3ZDLEVB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
@@ -1,13 +1,29 @@
1
1
  import type { AiConfiguration, ChatCompletionResponse } from './provider';
2
2
  import type { RemoteTools } from './remote-tools';
3
3
  import type { DispatchBody } from './schemas/route';
4
- export type { AiConfiguration, AiProvider, BaseAiConfiguration, ChatCompletionMessage, ChatCompletionResponse, ChatCompletionTool, ChatCompletionToolChoice, OpenAiConfiguration, } from './provider';
4
+ export type { AiConfiguration, AiProvider, AnthropicConfiguration, BaseAiConfiguration, ChatCompletionMessage, ChatCompletionResponse, ChatCompletionTool, ChatCompletionToolChoice, OpenAiConfiguration, } from './provider';
5
5
  export type { DispatchBody } from './schemas/route';
6
- export declare class ProviderDispatcher {
7
- private readonly chatModel;
6
+ export default class ProviderDispatcher {
7
+ private readonly openaiModel;
8
+ private readonly anthropicModel;
9
+ private readonly modelName;
8
10
  private readonly remoteTools;
9
11
  constructor(configuration: AiConfiguration | null, remoteTools: RemoteTools);
10
12
  dispatch(body: DispatchBody): Promise<ChatCompletionResponse>;
13
+ private dispatchOpenAI;
14
+ private dispatchAnthropic;
15
+ /**
16
+ * Wraps provider errors into AI-specific error types.
17
+ *
18
+ * TODO: Currently all provider errors are wrapped as AIUnprocessableError,
19
+ * losing the original HTTP semantics (429 rate limit, 401 auth failure).
20
+ * To fix this properly we need to:
21
+ * 1. Add UnauthorizedError and TooManyRequestsError to datasource-toolkit
22
+ * 2. Add corresponding cases in the agent's error-handling middleware
23
+ * 3. Create AIProviderError, AIRateLimitError, AIAuthenticationError in ai-proxy
24
+ * with baseBusinessErrorName overrides for correct HTTP status mapping
25
+ */
26
+ private static wrapProviderError;
11
27
  private enrichToolDefinitions;
12
28
  }
13
29
  //# sourceMappingURL=provider-dispatcher.d.ts.map
@@ -1,58 +1,129 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProviderDispatcher = void 0;
6
+ const anthropic_1 = require("@langchain/anthropic");
4
7
  const function_calling_1 = require("@langchain/core/utils/function_calling");
5
8
  const openai_1 = require("@langchain/openai");
9
+ const anthropic_adapter_1 = __importDefault(require("./anthropic-adapter"));
6
10
  const errors_1 = require("./errors");
11
+ const langchain_adapter_1 = require("./langchain-adapter");
7
12
  class ProviderDispatcher {
8
13
  constructor(configuration, remoteTools) {
9
- this.chatModel = null;
14
+ this.openaiModel = null;
15
+ this.anthropicModel = null;
16
+ this.modelName = null;
10
17
  this.remoteTools = remoteTools;
11
18
  if (configuration?.provider === 'openai') {
12
19
  const { provider, name, ...chatOpenAIOptions } = configuration;
13
- this.chatModel = new openai_1.ChatOpenAI({
20
+ this.openaiModel = new openai_1.ChatOpenAI({
14
21
  maxRetries: 0, // No retries by default - this lib is a passthrough
15
22
  ...chatOpenAIOptions,
16
23
  __includeRawResponse: true,
17
24
  });
18
25
  }
26
+ else if (configuration?.provider === 'anthropic') {
27
+ const { provider, name, model, ...clientOptions } = configuration;
28
+ this.anthropicModel = new anthropic_1.ChatAnthropic({
29
+ maxRetries: 0, // No retries by default - this lib is a passthrough
30
+ ...clientOptions,
31
+ model,
32
+ });
33
+ this.modelName = model;
34
+ }
35
+ else if (configuration) {
36
+ throw new errors_1.AIBadRequestError(`Unsupported AI provider '${configuration.provider}'.`);
37
+ }
19
38
  }
20
39
  async dispatch(body) {
21
- if (!this.chatModel) {
22
- throw new errors_1.AINotConfiguredError();
40
+ if (this.openaiModel) {
41
+ return this.dispatchOpenAI(body);
42
+ }
43
+ if (this.anthropicModel) {
44
+ return this.dispatchAnthropic(body);
23
45
  }
46
+ throw new errors_1.AINotConfiguredError();
47
+ }
48
+ async dispatchOpenAI(body) {
24
49
  const { tools, messages, tool_choice: toolChoice, parallel_tool_calls: parallelToolCalls, } = body;
25
50
  const enrichedTools = this.enrichToolDefinitions(tools);
26
51
  const model = enrichedTools?.length
27
- ? this.chatModel.bindTools(enrichedTools, {
52
+ ? this.openaiModel.bindTools(enrichedTools, {
28
53
  tool_choice: toolChoice,
29
54
  parallel_tool_calls: parallelToolCalls,
30
55
  })
31
- : this.chatModel;
56
+ : this.openaiModel;
57
+ let response;
32
58
  try {
33
- const response = await model.invoke(messages);
34
- // eslint-disable-next-line no-underscore-dangle
35
- const rawResponse = response.additional_kwargs.__raw_response;
36
- if (!rawResponse) {
37
- throw new errors_1.OpenAIUnprocessableError('OpenAI response missing raw response data. This may indicate an API change.');
38
- }
39
- return rawResponse;
59
+ response = await model.invoke(messages);
40
60
  }
41
61
  catch (error) {
42
- if (error instanceof errors_1.OpenAIUnprocessableError)
43
- throw error;
44
- const err = error;
45
- if (err.status === 429) {
46
- throw new errors_1.OpenAIUnprocessableError(`Rate limit exceeded: ${err.message}`);
47
- }
48
- if (err.status === 401) {
49
- throw new errors_1.OpenAIUnprocessableError(`Authentication failed: ${err.message}`);
50
- }
51
- throw new errors_1.OpenAIUnprocessableError(`Error while calling OpenAI: ${err.message}`);
62
+ throw ProviderDispatcher.wrapProviderError(error, 'OpenAI');
52
63
  }
64
+ // eslint-disable-next-line no-underscore-dangle
65
+ const rawResponse = response.additional_kwargs.__raw_response;
66
+ if (!rawResponse) {
67
+ throw new errors_1.AIUnprocessableError('OpenAI response missing raw response data. This may indicate an API change.');
68
+ }
69
+ return rawResponse;
70
+ }
71
+ async dispatchAnthropic(body) {
72
+ const { tools, messages, tool_choice: toolChoice, parallel_tool_calls: parallelToolCalls, } = body;
73
+ // Convert messages outside try-catch so input validation errors propagate directly
74
+ const langChainMessages = anthropic_adapter_1.default.convertMessages(messages);
75
+ const enrichedTools = this.enrichToolDefinitions(tools);
76
+ const model = enrichedTools?.length
77
+ ? anthropic_adapter_1.default.bindTools(this.anthropicModel, enrichedTools, {
78
+ toolChoice,
79
+ parallelToolCalls,
80
+ })
81
+ : this.anthropicModel;
82
+ let response;
83
+ try {
84
+ response = (await model.invoke(langChainMessages));
85
+ }
86
+ catch (error) {
87
+ throw ProviderDispatcher.wrapProviderError(error, 'Anthropic');
88
+ }
89
+ return langchain_adapter_1.LangChainAdapter.convertResponse(response, this.modelName);
90
+ }
91
+ /**
92
+ * Wraps provider errors into AI-specific error types.
93
+ *
94
+ * TODO: Currently all provider errors are wrapped as AIUnprocessableError,
95
+ * losing the original HTTP semantics (429 rate limit, 401 auth failure).
96
+ * To fix this properly we need to:
97
+ * 1. Add UnauthorizedError and TooManyRequestsError to datasource-toolkit
98
+ * 2. Add corresponding cases in the agent's error-handling middleware
99
+ * 3. Create AIProviderError, AIRateLimitError, AIAuthenticationError in ai-proxy
100
+ * with baseBusinessErrorName overrides for correct HTTP status mapping
101
+ */
102
+ static wrapProviderError(error, providerName) {
103
+ if (error instanceof errors_1.AIUnprocessableError)
104
+ return error;
105
+ if (error instanceof errors_1.AIBadRequestError)
106
+ return error;
107
+ if (!(error instanceof Error)) {
108
+ return new errors_1.AIUnprocessableError(`Error while calling ${providerName}: ${String(error)}`);
109
+ }
110
+ const { status } = error;
111
+ if (status === 429) {
112
+ return new errors_1.AIUnprocessableError(`${providerName} rate limit exceeded: ${error.message}`, {
113
+ cause: error,
114
+ });
115
+ }
116
+ if (status === 401) {
117
+ return new errors_1.AIUnprocessableError(`${providerName} authentication failed: ${error.message}`, {
118
+ cause: error,
119
+ });
120
+ }
121
+ return new errors_1.AIUnprocessableError(`Error while calling ${providerName}: ${error.message}`, {
122
+ cause: error,
123
+ });
53
124
  }
54
125
  enrichToolDefinitions(tools) {
55
- if (!tools || !Array.isArray(tools))
126
+ if (!tools)
56
127
  return tools;
57
128
  const remoteToolSchemas = this.remoteTools.tools.map(remoteTool => (0, function_calling_1.convertToOpenAIFunction)(remoteTool.base));
58
129
  return tools.map(tool => {
@@ -65,5 +136,5 @@ class ProviderDispatcher {
65
136
  });
66
137
  }
67
138
  }
68
- exports.ProviderDispatcher = ProviderDispatcher;
69
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItZGlzcGF0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92aWRlci1kaXNwYXRjaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUtBLDZFQUFpRjtBQUNqRiw4Q0FBK0M7QUFFL0MscUNBQTBFO0FBZTFFLE1BQWEsa0JBQWtCO0lBSzdCLFlBQVksYUFBcUMsRUFBRSxXQUF3QjtRQUoxRCxjQUFTLEdBQXNCLElBQUksQ0FBQztRQUtuRCxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUUvQixJQUFJLGFBQWEsRUFBRSxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDekMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxpQkFBaUIsRUFBRSxHQUFHLGFBQWEsQ0FBQztZQUMvRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksbUJBQVUsQ0FBQztnQkFDOUIsVUFBVSxFQUFFLENBQUMsRUFBRSxvREFBb0Q7Z0JBQ25FLEdBQUcsaUJBQWlCO2dCQUNwQixvQkFBb0IsRUFBRSxJQUFJO2FBQzNCLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFrQjtRQUMvQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSw2QkFBb0IsRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFFRCxNQUFNLEVBQ0osS0FBSyxFQUNMLFFBQVEsRUFDUixXQUFXLEVBQUUsVUFBVSxFQUN2QixtQkFBbUIsRUFBRSxpQkFBaUIsR0FDdkMsR0FBRyxJQUFJLENBQUM7UUFFVCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEQsTUFBTSxLQUFLLEdBQUcsYUFBYSxFQUFFLE1BQU07WUFDakMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRTtnQkFDdEMsV0FBVyxFQUFFLFVBQVU7Z0JBQ3ZCLG1CQUFtQixFQUFFLGlCQUFpQjthQUN2QyxDQUFDO1lBQ0osQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7UUFFbkIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQTZCLENBQUMsQ0FBQztZQUVuRSxnREFBZ0Q7WUFDaEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGlCQUFpQixDQUFDLGNBQXdDLENBQUM7WUFFeEYsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUksaUNBQXdCLENBQ2hDLDZFQUE2RSxDQUM5RSxDQUFDO1lBQ0osQ0FBQztZQUVELE9BQU8sV0FBVyxDQUFDO1FBQ3JCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksaUNBQXdCO2dCQUFFLE1BQU0sS0FBSyxDQUFDO1lBRTNELE1BQU0sR0FBRyxHQUFHLEtBQW9DLENBQUM7WUFFakQsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUN2QixNQUFNLElBQUksaUNBQXdCLENBQUMsd0JBQXdCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQzVFLENBQUM7WUFFRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQ3ZCLE1BQU0sSUFBSSxpQ0FBd0IsQ0FBQywwQkFBMEIsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDOUUsQ0FBQztZQUVELE1BQU0sSUFBSSxpQ0FBd0IsQ0FBQywrQkFBK0IsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDbkYsQ0FBQztJQUNILENBQUM7SUFFTyxxQkFBcUIsQ0FBQyxLQUE0QjtRQUN4RCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUVsRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUNoRSxJQUFBLDBDQUF1QixFQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FDekMsQ0FBQztRQUVGLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN0QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssVUFBVTtnQkFBRSxPQUFPLElBQUksQ0FBQztZQUUxQyxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUYsSUFBSSxZQUFZO2dCQUFFLE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLENBQUM7WUFFN0QsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXBGRCxnREFvRkMifQ==
139
+ exports.default = ProviderDispatcher;
140
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItZGlzcGF0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92aWRlci1kaXNwYXRjaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBTUEsb0RBQXFEO0FBQ3JELDZFQUFpRjtBQUNqRiw4Q0FBK0M7QUFFL0MsNEVBQW1EO0FBQ25ELHFDQUF5RjtBQUN6RiwyREFBdUQ7QUFnQnZELE1BQXFCLGtCQUFrQjtJQVNyQyxZQUFZLGFBQXFDLEVBQUUsV0FBd0I7UUFSMUQsZ0JBQVcsR0FBc0IsSUFBSSxDQUFDO1FBRXRDLG1CQUFjLEdBQXlCLElBQUksQ0FBQztRQUU1QyxjQUFTLEdBQWtCLElBQUksQ0FBQztRQUsvQyxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUUvQixJQUFJLGFBQWEsRUFBRSxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDekMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxpQkFBaUIsRUFBRSxHQUFHLGFBQWEsQ0FBQztZQUMvRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksbUJBQVUsQ0FBQztnQkFDaEMsVUFBVSxFQUFFLENBQUMsRUFBRSxvREFBb0Q7Z0JBQ25FLEdBQUcsaUJBQWlCO2dCQUNwQixvQkFBb0IsRUFBRSxJQUFJO2FBQzNCLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxJQUFJLGFBQWEsRUFBRSxRQUFRLEtBQUssV0FBVyxFQUFFLENBQUM7WUFDbkQsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsYUFBYSxFQUFFLEdBQUcsYUFBYSxDQUFDO1lBQ2xFLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSx5QkFBYSxDQUFDO2dCQUN0QyxVQUFVLEVBQUUsQ0FBQyxFQUFFLG9EQUFvRDtnQkFDbkUsR0FBRyxhQUFhO2dCQUNoQixLQUFLO2FBQ04sQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLFNBQVMsR0FB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
@@ -1,10 +1,12 @@
1
- import type { ChatOpenAIFields, OpenAIChatModelId } from '@langchain/openai';
1
+ import type Anthropic from '@anthropic-ai/sdk';
2
+ import type { AnthropicInput } from '@langchain/anthropic';
3
+ import type { ChatOpenAIFields } from '@langchain/openai';
2
4
  import type OpenAI from 'openai';
3
5
  export type ChatCompletionResponse = OpenAI.Chat.Completions.ChatCompletion;
4
6
  export type ChatCompletionMessage = OpenAI.Chat.Completions.ChatCompletionMessageParam;
5
7
  export type ChatCompletionTool = OpenAI.Chat.Completions.ChatCompletionTool;
6
8
  export type ChatCompletionToolChoice = OpenAI.Chat.Completions.ChatCompletionToolChoiceOption;
7
- export type AiProvider = 'openai';
9
+ export type AiProvider = 'openai' | 'anthropic';
8
10
  /**
9
11
  * Base configuration common to all AI providers.
10
12
  */
@@ -18,9 +20,18 @@ export type BaseAiConfiguration = {
18
20
  * OpenAI-specific configuration.
19
21
  * Extends base with all ChatOpenAI options (temperature, maxTokens, configuration, etc.)
20
22
  */
21
- export type OpenAiConfiguration = BaseAiConfiguration & Omit<ChatOpenAIFields, 'model' | 'apiKey'> & {
23
+ export type OpenAiConfiguration = Omit<BaseAiConfiguration, 'model'> & Omit<ChatOpenAIFields, 'model' | 'apiKey'> & {
22
24
  provider: 'openai';
23
- model: OpenAIChatModelId | (string & NonNullable<unknown>);
25
+ model: OpenAI.ChatModel | (string & NonNullable<unknown>);
24
26
  };
25
- export type AiConfiguration = OpenAiConfiguration;
27
+ /**
28
+ * Anthropic-specific configuration.
29
+ * Extends base with all ChatAnthropic options (temperature, maxTokens, etc.)
30
+ * Supports both `apiKey` (unified) and `anthropicApiKey` (native) for flexibility.
31
+ */
32
+ export type AnthropicConfiguration = Omit<BaseAiConfiguration, 'model'> & Omit<AnthropicInput, 'model' | 'apiKey'> & {
33
+ provider: 'anthropic';
34
+ model: Anthropic.Messages.Model;
35
+ };
36
+ export type AiConfiguration = OpenAiConfiguration | AnthropicConfiguration;
26
37
  //# sourceMappingURL=provider.d.ts.map
package/dist/router.js CHANGED
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Router = void 0;
7
7
  const errors_1 = require("./errors");
8
8
  const mcp_client_1 = __importDefault(require("./mcp-client"));
9
- const provider_dispatcher_1 = require("./provider-dispatcher");
9
+ const provider_dispatcher_1 = __importDefault(require("./provider-dispatcher"));
10
10
  const remote_tools_1 = require("./remote-tools");
11
11
  const route_1 = require("./schemas/route");
12
12
  const supported_models_1 = __importDefault(require("./supported-models"));
@@ -19,7 +19,7 @@ class Router {
19
19
  }
20
20
  validateConfigurations() {
21
21
  for (const config of this.aiConfigurations) {
22
- if (!(0, supported_models_1.default)(config.model)) {
22
+ if (!(0, supported_models_1.default)(config.model, config.provider)) {
23
23
  throw new errors_1.AIModelNotSupportedError(config.model);
24
24
  }
25
25
  }
@@ -48,7 +48,7 @@ class Router {
48
48
  switch (validatedArgs.route) {
49
49
  case 'ai-query': {
50
50
  const aiConfiguration = this.getAiConfiguration(validatedArgs.query?.['ai-name']);
51
- return await new provider_dispatcher_1.ProviderDispatcher(aiConfiguration, remoteTools).dispatch(validatedArgs.body);
51
+ return await new provider_dispatcher_1.default(aiConfiguration, remoteTools).dispatch(validatedArgs.body);
52
52
  }
53
53
  case 'invoke-remote-tool':
54
54
  return await remoteTools.invokeTool(validatedArgs.query['tool-name'], validatedArgs.body.inputs);
@@ -100,7 +100,7 @@ class Router {
100
100
  const config = this.aiConfigurations.find(c => c.name === aiName);
101
101
  if (!config) {
102
102
  const fallback = this.aiConfigurations[0];
103
- this.logger?.('Warn', `AI configuration '${aiName}' not found. Falling back to '${fallback.name}'.`);
103
+ this.logger?.('Warn', `AI configuration '${aiName}' not found. Falling back to '${fallback.name}' (provider: ${fallback.provider}, model: ${fallback.model})`);
104
104
  return fallback;
105
105
  }
106
106
  return config;
@@ -109,4 +109,4 @@ class Router {
109
109
  }
110
110
  }
111
111
  exports.Router = Router;
112
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFPQSxxQ0FBdUU7QUFDdkUsOERBQXFDO0FBQ3JDLCtEQUEyRDtBQUMzRCxpREFBNkM7QUFDN0MsMkNBQWtEO0FBQ2xELDBFQUF3RDtBQWdCeEQsTUFBYSxNQUFNO0lBS2pCLFlBQVksTUFJWDtRQUNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLEVBQUUsZ0JBQWdCLElBQUksRUFBRSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLEVBQUUsaUJBQWlCLENBQUM7UUFDbkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLEVBQUUsTUFBTSxDQUFDO1FBRTdCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsSUFBQSwwQkFBc0IsRUFBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDMUMsTUFBTSxJQUFJLGlDQUF3QixDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFtRDtRQUM3RCxpQ0FBaUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsdUJBQWUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksMEJBQWlCLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNuRSxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsTUFB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
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFPQSxxQ0FBdUU7QUFDdkUsOERBQXFDO0FBQ3JDLGdGQUF1RDtBQUN2RCxpREFBNkM7QUFDN0MsMkNBQWtEO0FBQ2xELDBFQUF3RDtBQWdCeEQsTUFBYSxNQUFNO0lBS2pCLFlBQVksTUFJWDtRQUNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLEVBQUUsZ0JBQWdCLElBQUksRUFBRSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLEVBQUUsaUJBQWlCLENBQUM7UUFDbkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLEVBQUUsTUFBTSxDQUFDO1FBRTdCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsSUFBQSwwQkFBc0IsRUFBQyxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUMzRCxNQUFNLElBQUksaUNBQXdCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25ELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsS0FBSyxDQUFDLElBQW1EO1FBQzdELGlDQUFpQztRQUNqQyxNQUFNLE1BQU0sR0FBRyx1QkFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSwwQkFBaUIsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFF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
@@ -1,3 +1,4 @@
1
+ import type { McpConfiguration } from '../mcp-client';
1
2
  import { z } from 'zod';
2
3
  declare const baseQuerySchema: z.ZodObject<{
3
4
  'ai-name': z.ZodOptional<z.ZodString>;
@@ -74,6 +75,9 @@ export type AiQueryArgs = z.infer<typeof aiQuerySchema>;
74
75
  export type InvokeRemoteToolArgs = z.infer<typeof invokeRemoteToolSchema>;
75
76
  export type RemoteToolsArgs = z.infer<typeof remoteToolsSchema>;
76
77
  export type DispatchBody = AiQueryArgs['body'];
78
+ export type RouterRouteArgs = RouteArgs & {
79
+ mcpConfigs?: McpConfiguration;
80
+ };
77
81
  export type InvokeRemoteToolBody = InvokeRemoteToolArgs['body'];
78
82
  export type Body = DispatchBody | InvokeRemoteToolBody | undefined;
79
83
  export type Query = z.infer<typeof baseQuerySchema>;
@@ -61,4 +61,4 @@ exports.routeArgsSchema = zod_1.z.discriminatedUnion('route', [
61
61
  invokeRemoteToolSchema,
62
62
  remoteToolsSchema,
63
63
  ]);
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NoZW1hcy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2QkFBd0I7QUFFeEIsb0RBQW9EO0FBQ3BELE1BQU0sZUFBZSxHQUFHLE9BQUMsQ0FBQyxNQUFNLENBQUM7SUFDL0IsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDaEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDbkMsQ0FBQyxDQUFDO0FBRUg7Ozs7OztHQU1HO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUNoQztJQUNFLFFBQVEsRUFBRSxPQUFDLENBQUMsS0FBSyxDQUFDLE9BQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUN6QixPQUFPLEVBQUUsMkNBQTJDO0tBQ3JELENBQUM7SUFDRixLQUFLLEVBQUUsT0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDbEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDL0IsbUJBQW1CLEVBQUUsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUM1QyxFQUNELEVBQUUsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLENBQ2hELENBQUM7QUFFRixNQUFNLGFBQWEsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQzdCLEtBQUssRUFBRSxPQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1QixLQUFLLEVBQUUsZUFBZSxDQUFDLFFBQVEsRUFBRTtJQUNqQyxJQUFJLEVBQUUsaUJBQWlCO0NBQ3hCLENBQUMsQ0FBQztBQUVILDhEQUE4RDtBQUM5RCxNQUFNLDJCQUEyQixHQUFHLE9BQUMsQ0FBQyxNQUFNLENBQzFDO0lBQ0UsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDaEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsNkNBQTZDLEVBQUUsQ0FBQztDQUNsRixFQUNELEVBQUUsT0FBTyxFQUFFLG1DQUFtQyxFQUFFLENBQ2pELENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxzQkFBc0IsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3RDLEtBQUssRUFBRSxPQUFDLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDO0lBQ3RDLEtBQUssRUFBRSwyQkFBMkI7SUFDbEMsSUFBSSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQ1o7UUFDRSw4REFBOEQ7UUFDOUQsTUFBTSxFQUFFLE9BQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFRLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLElBQUksRUFBRTtZQUN0RSxPQUFPLEVBQUUseUNBQXlDO1NBQ25ELENBQUM7S0FDSCxFQUNELEVBQUUsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLENBQ2hEO0NBQ0YsQ0FBQyxDQUFDO0FBRUgseUNBQXlDO0FBQ3pDLE1BQU0saUJBQWlCLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNqQyxLQUFLLEVBQUUsT0FBQyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUM7SUFDaEMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxRQUFRLEVBQUU7Q0FDbEMsQ0FBQyxDQUFDO0FBRUgsaUNBQWlDO0FBQ3BCLFFBQUEsZUFBZSxHQUFHLE9BQUMsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7SUFDM0QsYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixpQkFBaUI7Q0FDbEIsQ0FBQyxDQUFDIn0=
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NoZW1hcy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSw2QkFBd0I7QUFFeEIsb0RBQW9EO0FBQ3BELE1BQU0sZUFBZSxHQUFHLE9BQUMsQ0FBQyxNQUFNLENBQUM7SUFDL0IsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDaEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDbkMsQ0FBQyxDQUFDO0FBRUg7Ozs7OztHQU1HO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUNoQztJQUNFLFFBQVEsRUFBRSxPQUFDLENBQUMsS0FBSyxDQUFDLE9BQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUN6QixPQUFPLEVBQUUsMkNBQTJDO0tBQ3JELENBQUM7SUFDRixLQUFLLEVBQUUsT0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDbEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDL0IsbUJBQW1CLEVBQUUsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUM1QyxFQUNELEVBQUUsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLENBQ2hELENBQUM7QUFFRixNQUFNLGFBQWEsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQzdCLEtBQUssRUFBRSxPQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUM1QixLQUFLLEVBQUUsZUFBZSxDQUFDLFFBQVEsRUFBRTtJQUNqQyxJQUFJLEVBQUUsaUJBQWlCO0NBQ3hCLENBQUMsQ0FBQztBQUVILDhEQUE4RDtBQUM5RCxNQUFNLDJCQUEyQixHQUFHLE9BQUMsQ0FBQyxNQUFNLENBQzFDO0lBQ0UsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDaEMsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsNkNBQTZDLEVBQUUsQ0FBQztDQUNsRixFQUNELEVBQUUsT0FBTyxFQUFFLG1DQUFtQyxFQUFFLENBQ2pELENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxzQkFBc0IsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3RDLEtBQUssRUFBRSxPQUFDLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDO0lBQ3RDLEtBQUssRUFBRSwyQkFBMkI7SUFDbEMsSUFBSSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQ1o7UUFDRSw4REFBOEQ7UUFDOUQsTUFBTSxFQUFFLE9BQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFRLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLElBQUksRUFBRTtZQUN0RSxPQUFPLEVBQUUseUNBQXlDO1NBQ25ELENBQUM7S0FDSCxFQUNELEVBQUUsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLENBQ2hEO0NBQ0YsQ0FBQyxDQUFDO0FBRUgseUNBQXlDO0FBQ3pDLE1BQU0saUJBQWlCLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNqQyxLQUFLLEVBQUUsT0FBQyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUM7SUFDaEMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxRQUFRLEVBQUU7Q0FDbEMsQ0FBQyxDQUFDO0FBRUgsaUNBQWlDO0FBQ3BCLFFBQUEsZUFBZSxHQUFHLE9BQUMsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7SUFDM0QsYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixpQkFBaUI7Q0FDbEIsQ0FBQyxDQUFDIn0=
@@ -1,7 +1,3 @@
1
- /**
2
- * Checks if a model is compatible with Forest Admin AI.
3
- *
4
- * Supported models must handle tool calls and the parallel_tool_calls parameter.
5
- */
6
- export default function isModelSupportingTools(model: string): boolean;
1
+ import type { AiProvider } from './provider';
2
+ export default function isModelSupportingTools(model: string, provider?: AiProvider): boolean;
7
3
  //# sourceMappingURL=supported-models.d.ts.map
@@ -1,17 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = isModelSupportingTools;
4
- /**
5
- * OpenAI model prefixes that do NOT support tool calls via the chat completions API.
6
- *
7
- * Uses prefix matching: model === prefix OR model.startsWith(prefix + '-')
8
- *
9
- * Unknown models are allowed by default.
10
- * If a model fails the integration test, add it here.
11
- *
12
- * @see https://platform.openai.com/docs/guides/function-calling
13
- */
14
- const UNSUPPORTED_MODEL_PREFIXES = [
4
+ // ─── OpenAI ──────────────────────────────────────────────────────────────────
5
+ // If a model fails the llm.integration test, add it here.
6
+ const OPENAI_UNSUPPORTED_PREFIXES = [
15
7
  // Legacy models
16
8
  'gpt-4', // Base gpt-4 doesn't honor tool_choice: required
17
9
  'text-davinci',
@@ -37,11 +29,7 @@ const UNSUPPORTED_MODEL_PREFIXES = [
37
29
  'sora', // sora-2, sora-2-pro
38
30
  'codex', // codex-mini-latest
39
31
  ];
40
- /**
41
- * OpenAI model patterns that do NOT support tool calls.
42
- * Uses contains matching: model.includes(pattern)
43
- */
44
- const UNSUPPORTED_MODEL_PATTERNS = [
32
+ const OPENAI_UNSUPPORTED_PATTERNS = [
45
33
  // Non-chat model variants (can appear in the middle of model names)
46
34
  '-realtime',
47
35
  '-audio',
@@ -54,28 +42,37 @@ const UNSUPPORTED_MODEL_PATTERNS = [
54
42
  '-pro',
55
43
  '-deep-research',
56
44
  ];
57
- /**
58
- * Models that DO support tool calls even though they match an unsupported prefix.
59
- * These override the UNSUPPORTED_MODEL_PREFIXES list.
60
- */
61
- const SUPPORTED_MODEL_OVERRIDES = ['gpt-4-turbo', 'gpt-4o', 'gpt-4.1'];
62
- /**
63
- * Checks if a model is compatible with Forest Admin AI.
64
- *
65
- * Supported models must handle tool calls and the parallel_tool_calls parameter.
66
- */
67
- function isModelSupportingTools(model) {
68
- // Check pattern matches first (contains) - these NEVER support tools
69
- const matchesUnsupportedPattern = UNSUPPORTED_MODEL_PATTERNS.some(pattern => model.includes(pattern));
70
- if (matchesUnsupportedPattern)
45
+ const OPENAI_UNSUPPORTED_MODELS = [
46
+ 'us-40-51r-vm-ev3', // Not a chat model (v1/completions only)
47
+ ];
48
+ const OPENAI_SUPPORTED_OVERRIDES = ['gpt-4-turbo', 'gpt-4o', 'gpt-4.1'];
49
+ function isOpenAIModelSupported(model) {
50
+ if (OPENAI_UNSUPPORTED_MODELS.includes(model))
71
51
  return false;
72
- // Check unsupported prefixes
73
- const matchesUnsupportedPrefix = UNSUPPORTED_MODEL_PREFIXES.some(prefix => model === prefix || model.startsWith(`${prefix}-`));
74
- // Check if model is in the supported overrides list
75
- const isSupportedOverride = SUPPORTED_MODEL_OVERRIDES.some(override => model === override || model.startsWith(`${override}-`));
76
- // If it matches an unsupported prefix but is not in overrides, reject it
77
- if (matchesUnsupportedPrefix && !isSupportedOverride)
52
+ const matchesPattern = OPENAI_UNSUPPORTED_PATTERNS.some(p => model.includes(p));
53
+ if (matchesPattern)
78
54
  return false;
79
- return true;
55
+ const matchesPrefix = OPENAI_UNSUPPORTED_PREFIXES.some(prefix => model === prefix || model.startsWith(`${prefix}-`));
56
+ const isOverride = OPENAI_SUPPORTED_OVERRIDES.some(override => model === override || model.startsWith(`${override}-`));
57
+ return !matchesPrefix || isOverride;
58
+ }
59
+ // ─── Anthropic ───────────────────────────────────────────────────────────────
60
+ // If a model fails the llm.integration test, add it here.
61
+ const ANTHROPIC_UNSUPPORTED_MODELS = [
62
+ 'claude-3-haiku-20240307', // EOL 2025-03-14
63
+ 'claude-3-5-haiku-20241022', // EOL 2026-02-19
64
+ 'claude-3-5-haiku-latest', // Points to deprecated claude-3-5-haiku-20241022
65
+ 'claude-3-7-sonnet-20250219', // EOL 2026-02-19
66
+ 'claude-opus-4-20250514', // Requires streaming (non-streaming times out)
67
+ 'claude-opus-4-1-20250805', // Requires streaming (non-streaming times out)
68
+ ];
69
+ function isAnthropicModelSupported(model) {
70
+ return !ANTHROPIC_UNSUPPORTED_MODELS.includes(model);
71
+ }
72
+ // ─── Public API ──────────────────────────────────────────────────────────────
73
+ function isModelSupportingTools(model, provider) {
74
+ if (provider === 'anthropic')
75
+ return isAnthropicModelSupported(model);
76
+ return isOpenAIModelSupported(model);
80
77
  }
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VwcG9ydGVkLW1vZGVscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zdXBwb3J0ZWQtbW9kZWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBa0VBLHlDQXFCQztBQXZGRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLDBCQUEwQixHQUFHO0lBQ2pDLGdCQUFnQjtJQUNoQixPQUFPLEVBQUUsaURBQWlEO0lBQzFELGNBQWM7SUFDZCxTQUFTO0lBQ1QsT0FBTztJQUNQLFNBQVM7SUFDVCxLQUFLO0lBQ0wsZ0VBQWdFO0lBQ2hFLElBQUk7SUFDSixJQUFJO0lBQ0osSUFBSTtJQUNKLDBCQUEwQjtJQUMxQixRQUFRO0lBQ1IsU0FBUztJQUNULEtBQUs7SUFDTCxnQkFBZ0I7SUFDaEIsaUJBQWlCO0lBQ2pCLFNBQVMsRUFBRSwwQ0FBMEM7SUFDckQsY0FBYyxFQUFFLHVCQUF1QjtJQUN2QyxXQUFXLEVBQUUsNkJBQTZCO0lBQzFDLGNBQWMsRUFBRSxrQ0FBa0M7SUFDbEQsV0FBVyxFQUFFLFlBQVk7SUFDekIsTUFBTSxFQUFFLHFCQUFxQjtJQUM3QixPQUFPLEVBQUUsb0JBQW9CO0NBQzlCLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLDBCQUEwQixHQUFHO0lBQ2pDLG9FQUFvRTtJQUNwRSxXQUFXO0lBQ1gsUUFBUTtJQUNSLGFBQWE7SUFDYixNQUFNO0lBQ04sU0FBUztJQUNULFFBQVE7SUFDUixXQUFXO0lBQ1gsaUVBQWlFO0lBQ2pFLE1BQU07SUFDTixnQkFBZ0I7Q0FDakIsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxhQUFhLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBRXZFOzs7O0dBSUc7QUFDSCxTQUF3QixzQkFBc0IsQ0FBQyxLQUFhO0lBQzFELHFFQUFxRTtJQUNyRSxNQUFNLHlCQUF5QixHQUFHLDBCQUEwQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUMxRSxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUN4QixDQUFDO0lBQ0YsSUFBSSx5QkFBeUI7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUU1Qyw2QkFBNkI7SUFDN0IsTUFBTSx3QkFBd0IsR0FBRywwQkFBMEIsQ0FBQyxJQUFJLENBQzlELE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FDN0QsQ0FBQztJQUVGLG9EQUFvRDtJQUNwRCxNQUFNLG1CQUFtQixHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FDeEQsUUFBUSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxRQUFRLEdBQUcsQ0FBQyxDQUNuRSxDQUFDO0lBRUYseUVBQXlFO0lBQ3pFLElBQUksd0JBQXdCLElBQUksQ0FBQyxtQkFBbUI7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUVuRSxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMifQ==
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VwcG9ydGVkLW1vZGVscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zdXBwb3J0ZWQtbW9kZWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBdUZBLHlDQUlDO0FBekZELGdGQUFnRjtBQUNoRiwwREFBMEQ7QUFFMUQsTUFBTSwyQkFBMkIsR0FBRztJQUNsQyxnQkFBZ0I7SUFDaEIsT0FBTyxFQUFFLGlEQUFpRDtJQUMxRCxjQUFjO0lBQ2QsU0FBUztJQUNULE9BQU87SUFDUCxTQUFTO0lBQ1QsS0FBSztJQUNMLGdFQUFnRTtJQUNoRSxJQUFJO0lBQ0osSUFBSTtJQUNKLElBQUk7SUFDSiwwQkFBMEI7SUFDMUIsUUFBUTtJQUNSLFNBQVM7SUFDVCxLQUFLO0lBQ0wsZ0JBQWdCO0lBQ2hCLGlCQUFpQjtJQUNqQixTQUFTLEVBQUUsMENBQTBDO0lBQ3JELGNBQWMsRUFBRSx1QkFBdUI7SUFDdkMsV0FBVyxFQUFFLDZCQUE2QjtJQUMxQyxjQUFjLEVBQUUsa0NBQWtDO0lBQ2xELFdBQVcsRUFBRSxZQUFZO0lBQ3pCLE1BQU0sRUFBRSxxQkFBcUI7SUFDN0IsT0FBTyxFQUFFLG9CQUFvQjtDQUM5QixDQUFDO0FBRUYsTUFBTSwyQkFBMkIsR0FBRztJQUNsQyxvRUFBb0U7SUFDcEUsV0FBVztJQUNYLFFBQVE7SUFDUixhQUFhO0lBQ2IsTUFBTTtJQUNOLFNBQVM7SUFDVCxRQUFRO0lBQ1IsV0FBVztJQUNYLGlFQUFpRTtJQUNqRSxNQUFNO0lBQ04sZ0JBQWdCO0NBQ2pCLENBQUM7QUFFRixNQUFNLHlCQUF5QixHQUFHO0lBQ2hDLGtCQUFrQixFQUFFLHlDQUF5QztDQUM5RCxDQUFDO0FBRUYsTUFBTSwwQkFBMEIsR0FBRyxDQUFDLGFBQWEsRUFBRSxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFFeEUsU0FBUyxzQkFBc0IsQ0FBQyxLQUFhO0lBQzNDLElBQUkseUJBQXlCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBRTVELE1BQU0sY0FBYyxHQUFHLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRixJQUFJLGNBQWM7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUVqQyxNQUFNLGFBQWEsR0FBRywyQkFBMkIsQ0FBQyxJQUFJLENBQ3BELE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FDN0QsQ0FBQztJQUVGLE1BQU0sVUFBVSxHQUFHLDBCQUEwQixDQUFDLElBQUksQ0FDaEQsUUFBUSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxRQUFRLEdBQUcsQ0FBQyxDQUNuRSxDQUFDO0lBRUYsT0FBTyxDQUFDLGFBQWEsSUFBSSxVQUFVLENBQUM7QUFDdEMsQ0FBQztBQUVELGdGQUFnRjtBQUNoRiwwREFBMEQ7QUFFMUQsTUFBTSw0QkFBNEIsR0FBRztJQUNuQyx5QkFBeUIsRUFBRSxpQkFBaUI7SUFDNUMsMkJBQTJCLEVBQUUsaUJBQWlCO0lBQzlDLHlCQUF5QixFQUFFLGlEQUFpRDtJQUM1RSw0QkFBNEIsRUFBRSxpQkFBaUI7SUFDL0Msd0JBQXdCLEVBQUUsK0NBQStDO0lBQ3pFLDBCQUEwQixFQUFFLCtDQUErQztDQUM1RSxDQUFDO0FBRUYsU0FBUyx5QkFBeUIsQ0FBQyxLQUFhO0lBQzlDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELGdGQUFnRjtBQUVoRixTQUF3QixzQkFBc0IsQ0FBQyxLQUFhLEVBQUUsUUFBcUI7SUFDakYsSUFBSSxRQUFRLEtBQUssV0FBVztRQUFFLE9BQU8seUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFdEUsT0FBTyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN2QyxDQUFDIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestadmin/ai-proxy",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "main": "dist/index.js",
5
5
  "license": "GPL-3.0",
6
6
  "publishConfig": {
@@ -12,7 +12,9 @@
12
12
  "directory": "packages/ai-proxy"
13
13
  },
14
14
  "dependencies": {
15
+ "@forestadmin/agent-toolkit": "1.0.0",
15
16
  "@forestadmin/datasource-toolkit": "1.50.1",
17
+ "@langchain/anthropic": "1.3.17",
16
18
  "@langchain/community": "1.1.4",
17
19
  "@langchain/core": "1.1.15",
18
20
  "@langchain/langgraph": "^1.1.0",