@robota-sdk/agent-provider 3.0.0-beta.64
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/LICENSE +21 -0
- package/dist/browser/index.d.ts +1104 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +7 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/loggers/index.cjs +1 -0
- package/dist/loggers/index.d.ts +151 -0
- package/dist/loggers/index.d.ts.map +1 -0
- package/dist/loggers/index.js +2 -0
- package/dist/loggers/index.js.map +1 -0
- package/dist/node/anthropic/index.cjs +1 -0
- package/dist/node/anthropic/index.d.ts +158 -0
- package/dist/node/anthropic/index.d.ts.map +1 -0
- package/dist/node/anthropic/index.js +1 -0
- package/dist/node/anthropic--1vgLC-e.js +5 -0
- package/dist/node/anthropic--1vgLC-e.js.map +1 -0
- package/dist/node/anthropic-BFQ6DSCP.cjs +4 -0
- package/dist/node/bytedance/index.cjs +1 -0
- package/dist/node/bytedance/index.d.ts +74 -0
- package/dist/node/bytedance/index.d.ts.map +1 -0
- package/dist/node/bytedance/index.js +1 -0
- package/dist/node/bytedance-C_0sF_pJ.js +2 -0
- package/dist/node/bytedance-C_0sF_pJ.js.map +1 -0
- package/dist/node/bytedance-DVPxqEiC.cjs +1 -0
- package/dist/node/chunk-Bmb41Sf3.cjs +1 -0
- package/dist/node/deepseek/index.cjs +1 -0
- package/dist/node/deepseek/index.d.ts +2 -0
- package/dist/node/deepseek/index.js +1 -0
- package/dist/node/deepseek-_8Ixx7rA.js +2 -0
- package/dist/node/deepseek-_8Ixx7rA.js.map +1 -0
- package/dist/node/deepseek-oA2Y6bD0.cjs +1 -0
- package/dist/node/gemini/index.cjs +1 -0
- package/dist/node/gemini/index.d.ts +173 -0
- package/dist/node/gemini/index.d.ts.map +1 -0
- package/dist/node/gemini/index.js +1 -0
- package/dist/node/gemini-Bh2U87MY.js +4 -0
- package/dist/node/gemini-Bh2U87MY.js.map +1 -0
- package/dist/node/gemini-DSaNCxZj.cjs +3 -0
- package/dist/node/gemma/index.cjs +1 -0
- package/dist/node/gemma/index.d.ts +2 -0
- package/dist/node/gemma/index.js +1 -0
- package/dist/node/gemma-Dp_AfCUR.js +2 -0
- package/dist/node/gemma-Dp_AfCUR.js.map +1 -0
- package/dist/node/gemma-G-Pf_PnX.cjs +1 -0
- package/dist/node/google/index.cjs +1 -0
- package/dist/node/google/index.d.ts +14 -0
- package/dist/node/google/index.d.ts.map +1 -0
- package/dist/node/google/index.js +2 -0
- package/dist/node/google/index.js.map +1 -0
- package/dist/node/index-B6PnlDMd.d.ts +82 -0
- package/dist/node/index-B6PnlDMd.d.ts.map +1 -0
- package/dist/node/index-B7UvPJcI.d.ts +315 -0
- package/dist/node/index-B7UvPJcI.d.ts.map +1 -0
- package/dist/node/index-BLPOTNb5.d.ts +98 -0
- package/dist/node/index-BLPOTNb5.d.ts.map +1 -0
- package/dist/node/index-BqixM_XD.d.ts +231 -0
- package/dist/node/index-BqixM_XD.d.ts.map +1 -0
- package/dist/node/index-C3beaqKO.d.ts +231 -0
- package/dist/node/index-C3beaqKO.d.ts.map +1 -0
- package/dist/node/index-Cp2XRh9G.d.ts +82 -0
- package/dist/node/index-Cp2XRh9G.d.ts.map +1 -0
- package/dist/node/index-DSv5xruI.d.ts +98 -0
- package/dist/node/index-DSv5xruI.d.ts.map +1 -0
- package/dist/node/index-w0bV1uaP.d.ts +315 -0
- package/dist/node/index-w0bV1uaP.d.ts.map +1 -0
- package/dist/node/index.cjs +1 -0
- package/dist/node/index.d.ts +8 -0
- package/dist/node/index.js +1 -0
- package/dist/node/openai/index.cjs +1 -0
- package/dist/node/openai/index.d.ts +2 -0
- package/dist/node/openai/index.js +1 -0
- package/dist/node/openai-CRQjg4xF.js +2 -0
- package/dist/node/openai-CRQjg4xF.js.map +1 -0
- package/dist/node/openai-compatible-BYfyY5lb.cjs +1 -0
- package/dist/node/openai-compatible-Dm4Sof9e.js +2 -0
- package/dist/node/openai-compatible-Dm4Sof9e.js.map +1 -0
- package/dist/node/openai-xWC6pY7r.cjs +1 -0
- package/dist/node/qwen/index.cjs +1 -0
- package/dist/node/qwen/index.d.ts +2 -0
- package/dist/node/qwen/index.js +1 -0
- package/dist/node/qwen-ChUZobTL.js +2 -0
- package/dist/node/qwen-ChUZobTL.js.map +1 -0
- package/dist/node/qwen-CjT71vSM.cjs +1 -0
- package/package.json +157 -0
- package/src/anthropic/__tests__/abort-streaming.test.ts +199 -0
- package/src/anthropic/__tests__/model-catalog-refresh.test.ts +92 -0
- package/src/anthropic/__tests__/provider-definition.test.ts +55 -0
- package/src/anthropic/__tests__/provider.test.ts +1357 -0
- package/src/anthropic/__tests__/response-parser.test.ts +326 -0
- package/src/anthropic/index.ts +22 -0
- package/src/anthropic/message-converter.ts +181 -0
- package/src/anthropic/model-catalog-refresh.ts +128 -0
- package/src/anthropic/parsers/response-parser.ts +184 -0
- package/src/anthropic/provider-definition.ts +93 -0
- package/src/anthropic/provider.ts +290 -0
- package/src/anthropic/streaming-handler.ts +204 -0
- package/src/anthropic/types/api-types.ts +158 -0
- package/src/anthropic/types.ts +79 -0
- package/src/bytedance/http-client.test.ts +288 -0
- package/src/bytedance/http-client.ts +163 -0
- package/src/bytedance/index.ts +2 -0
- package/src/bytedance/provider.spec.ts +320 -0
- package/src/bytedance/provider.ts +171 -0
- package/src/bytedance/status-mapper.test.ts +299 -0
- package/src/bytedance/status-mapper.ts +141 -0
- package/src/bytedance/types.ts +68 -0
- package/src/deepseek/defaults.ts +4 -0
- package/src/deepseek/index.ts +22 -0
- package/src/deepseek/model-catalog-refresh.test.ts +57 -0
- package/src/deepseek/model-catalog-refresh.ts +105 -0
- package/src/deepseek/model-catalog.ts +55 -0
- package/src/deepseek/provider-definition.test.ts +109 -0
- package/src/deepseek/provider-definition.ts +132 -0
- package/src/deepseek/provider.test.ts +324 -0
- package/src/deepseek/provider.ts +298 -0
- package/src/deepseek/types.ts +37 -0
- package/src/gemini/execution-helpers.ts +233 -0
- package/src/gemini/genai-transport.test.ts +208 -0
- package/src/gemini/image-operations.test.ts +448 -0
- package/src/gemini/image-operations.ts +261 -0
- package/src/gemini/index.ts +11 -0
- package/src/gemini/message-converter.test.ts +616 -0
- package/src/gemini/message-converter.ts +140 -0
- package/src/gemini/model-catalog-refresh.test.ts +107 -0
- package/src/gemini/model-catalog-refresh.ts +92 -0
- package/src/gemini/provider-definition.test.ts +70 -0
- package/src/gemini/provider-definition.ts +78 -0
- package/src/gemini/provider-extended.test.ts +898 -0
- package/src/gemini/provider.spec.ts +216 -0
- package/src/gemini/provider.ts +279 -0
- package/src/gemini/request-converter.ts +226 -0
- package/src/gemini/tool-schema-converter.ts +78 -0
- package/src/gemini/types/api-types.ts +235 -0
- package/src/gemini/types.ts +121 -0
- package/src/gemma/index.ts +5 -0
- package/src/gemma/message-factory.ts +38 -0
- package/src/gemma/provider-definition.test.ts +43 -0
- package/src/gemma/provider-definition.ts +84 -0
- package/src/gemma/provider-projection.ts +49 -0
- package/src/gemma/provider.test.ts +628 -0
- package/src/gemma/provider.ts +308 -0
- package/src/gemma/pseudo-command-envelope.ts +58 -0
- package/src/gemma/pseudo-tool-call-projector.ts +243 -0
- package/src/gemma/pseudo-tool-call-tag-parser.ts +153 -0
- package/src/gemma/pseudo-tool-call-types.ts +31 -0
- package/src/gemma/reasoning-projector.test.ts +52 -0
- package/src/gemma/reasoning-projector.ts +144 -0
- package/src/gemma/streaming-projection.ts +79 -0
- package/src/gemma/tool-call-argument-parser.ts +126 -0
- package/src/gemma/tool-call-projector.test.ts +227 -0
- package/src/gemma/tool-call-projector.ts +264 -0
- package/src/gemma/types.ts +27 -0
- package/src/google/index.ts +11 -0
- package/src/google/provider-compat.test.ts +19 -0
- package/src/google/provider-definition.ts +6 -0
- package/src/google/provider.ts +10 -0
- package/src/google/types.ts +5 -0
- package/src/index.ts +9 -0
- package/src/openai/adapter.test.ts +494 -0
- package/src/openai/adapter.ts +145 -0
- package/src/openai/chat-completions-chat.ts +189 -0
- package/src/openai/executor-integration.test.ts +206 -0
- package/src/openai/index.ts +21 -0
- package/src/openai/interfaces/payload-logger.ts +48 -0
- package/src/openai/loggers/console-payload-logger.test.ts +173 -0
- package/src/openai/loggers/console-payload-logger.ts +94 -0
- package/src/openai/loggers/console.ts +9 -0
- package/src/openai/loggers/file-payload-logger.test.ts +238 -0
- package/src/openai/loggers/file-payload-logger.ts +112 -0
- package/src/openai/loggers/file.ts +9 -0
- package/src/openai/loggers/index.ts +12 -0
- package/src/openai/loggers/sanitize-openai-log-data.test.ts +89 -0
- package/src/openai/loggers/sanitize-openai-log-data.ts +14 -0
- package/src/openai/message-converter.ts +22 -0
- package/src/openai/model-catalog-refresh.test.ts +92 -0
- package/src/openai/model-catalog-refresh.ts +115 -0
- package/src/openai/openai-request-format.ts +92 -0
- package/src/openai/parsers/response-parser.test.ts +407 -0
- package/src/openai/parsers/response-parser.ts +47 -0
- package/src/openai/provider-definition.test.ts +75 -0
- package/src/openai/provider-definition.ts +132 -0
- package/src/openai/provider.test.ts +1402 -0
- package/src/openai/provider.ts +237 -0
- package/src/openai/responses-chat.ts +258 -0
- package/src/openai/responses-converter.ts +112 -0
- package/src/openai/responses-parser.ts +285 -0
- package/src/openai/responses-stream-utils.ts +45 -0
- package/src/openai/responses-types.ts +195 -0
- package/src/openai/streaming/stream-assembler.ts +3 -0
- package/src/openai/streaming/stream-handler.test.ts +367 -0
- package/src/openai/streaming/stream-handler.ts +119 -0
- package/src/openai/types/api-types.ts +112 -0
- package/src/openai/types.ts +194 -0
- package/src/qwen/defaults.ts +26 -0
- package/src/qwen/index.ts +5 -0
- package/src/qwen/model-catalog-refresh.test.ts +91 -0
- package/src/qwen/model-catalog-refresh.ts +97 -0
- package/src/qwen/provider-capabilities.ts +34 -0
- package/src/qwen/provider-definition.test.ts +139 -0
- package/src/qwen/provider-definition.ts +173 -0
- package/src/qwen/provider-streaming-assembly.ts +40 -0
- package/src/qwen/provider.test.ts +640 -0
- package/src/qwen/provider.ts +293 -0
- package/src/qwen/responses-chat.ts +194 -0
- package/src/qwen/responses-converter.ts +104 -0
- package/src/qwen/responses-parser.ts +299 -0
- package/src/qwen/responses-stream-utils.ts +38 -0
- package/src/qwen/types.ts +228 -0
- package/src/shared/openai-compatible/endpoint-probe.test.ts +52 -0
- package/src/shared/openai-compatible/endpoint-probe.ts +43 -0
- package/src/shared/openai-compatible/index.ts +6 -0
- package/src/shared/openai-compatible/message-converter.test.ts +111 -0
- package/src/shared/openai-compatible/message-converter.ts +84 -0
- package/src/shared/openai-compatible/native-payload-observer.test.ts +43 -0
- package/src/shared/openai-compatible/native-payload-observer.ts +26 -0
- package/src/shared/openai-compatible/response-parser.test.ts +172 -0
- package/src/shared/openai-compatible/response-parser.ts +180 -0
- package/src/shared/openai-compatible/stream-assembler.test.ts +266 -0
- package/src/shared/openai-compatible/stream-assembler.ts +248 -0
- package/src/shared/openai-compatible/types.ts +59 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
|
+
import type { ILogger, TUniversalMessage } from '@robota-sdk/agent-core';
|
|
3
|
+
import { OpenAICompatibleResponseParser } from '../../shared/openai-compatible/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* OpenAI response parser compatibility wrapper.
|
|
7
|
+
*
|
|
8
|
+
* The implementation delegates to the shared OpenAI-compatible parser while
|
|
9
|
+
* preserving the OpenAI-branded error messages that are part of this package's
|
|
10
|
+
* current test contract.
|
|
11
|
+
*/
|
|
12
|
+
export class OpenAIResponseParser {
|
|
13
|
+
private readonly parser: OpenAICompatibleResponseParser;
|
|
14
|
+
|
|
15
|
+
constructor(logger?: ILogger) {
|
|
16
|
+
this.parser = new OpenAICompatibleResponseParser({ logger });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
parseResponse(response: OpenAI.Chat.ChatCompletion): TUniversalMessage {
|
|
20
|
+
try {
|
|
21
|
+
return this.parser.parseResponse(response);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
const message = normalizeParserMessage(
|
|
24
|
+
error instanceof Error ? error.message : 'OpenAI response parsing failed',
|
|
25
|
+
);
|
|
26
|
+
throw new Error(`OpenAI response parsing failed: ${message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
parseStreamingChunk(chunk: OpenAI.Chat.ChatCompletionChunk): TUniversalMessage | null {
|
|
31
|
+
try {
|
|
32
|
+
return this.parser.parseStreamingChunk(chunk);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message = normalizeParserMessage(
|
|
35
|
+
error instanceof Error ? error.message : 'OpenAI chunk parsing failed',
|
|
36
|
+
);
|
|
37
|
+
throw new Error(`OpenAI chunk parsing failed: ${message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function normalizeParserMessage(message: string): string {
|
|
43
|
+
return message
|
|
44
|
+
.replace(/^OpenAI-compatible response parsing failed: /, '')
|
|
45
|
+
.replace(/^OpenAI-compatible chunk parsing failed: /, '')
|
|
46
|
+
.replace('OpenAI-compatible response', 'OpenAI response');
|
|
47
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
createOpenAIProviderDefinition,
|
|
4
|
+
DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE,
|
|
5
|
+
DEFAULT_OPENAI_PROVIDER_MODEL,
|
|
6
|
+
} from './index';
|
|
7
|
+
|
|
8
|
+
describe('createOpenAIProviderDefinition', () => {
|
|
9
|
+
it('uses official OpenAI setup defaults without a model-family default', () => {
|
|
10
|
+
const definition = createOpenAIProviderDefinition();
|
|
11
|
+
const modelStep = definition.setupSteps?.find((step) => step.key === 'model');
|
|
12
|
+
const apiKeyStep = definition.setupSteps?.find((step) => step.key === 'apiKey');
|
|
13
|
+
|
|
14
|
+
expect(DEFAULT_OPENAI_PROVIDER_MODEL).toBeUndefined();
|
|
15
|
+
expect(definition.defaults?.model).toBeUndefined();
|
|
16
|
+
expect(definition.defaults?.apiKey).toBe(DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE);
|
|
17
|
+
expect(definition.defaults?.baseURL).toBeUndefined();
|
|
18
|
+
expect(definition.displayName).toBe('OpenAI');
|
|
19
|
+
expect(definition.setupHelpLinks).toEqual([
|
|
20
|
+
{
|
|
21
|
+
kind: 'api-key',
|
|
22
|
+
label: 'OpenAI API keys',
|
|
23
|
+
url: 'https://platform.openai.com/api-keys',
|
|
24
|
+
sourceUrl: 'https://developers.openai.com/api/reference/overview#authentication',
|
|
25
|
+
lastVerifiedAt: '2026-05-08',
|
|
26
|
+
},
|
|
27
|
+
]);
|
|
28
|
+
expect(modelStep).toMatchObject({
|
|
29
|
+
key: 'model',
|
|
30
|
+
title: 'OpenAI model',
|
|
31
|
+
required: true,
|
|
32
|
+
});
|
|
33
|
+
expect(modelStep?.defaultValue).toBeUndefined();
|
|
34
|
+
expect(apiKeyStep).toMatchObject({
|
|
35
|
+
key: 'apiKey',
|
|
36
|
+
title: 'OpenAI API key',
|
|
37
|
+
defaultValue: '$ENV:OPENAI_API_KEY',
|
|
38
|
+
});
|
|
39
|
+
expect(typeof definition.refreshModelCatalog).toBe('function');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('passes explicit apiSurface provider options into construction', () => {
|
|
43
|
+
const definition = createOpenAIProviderDefinition();
|
|
44
|
+
|
|
45
|
+
const provider = definition.createProvider({
|
|
46
|
+
name: 'openai',
|
|
47
|
+
model: 'gpt-4o',
|
|
48
|
+
apiKey: 'sk-test',
|
|
49
|
+
options: { apiSurface: 'chat-completions' },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(provider.name).toBe('openai');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('rejects native web tools for OpenAI-compatible baseURL profiles', () => {
|
|
56
|
+
const definition = createOpenAIProviderDefinition();
|
|
57
|
+
|
|
58
|
+
expect(() =>
|
|
59
|
+
definition.createProvider({
|
|
60
|
+
name: 'openai',
|
|
61
|
+
model: 'local-model',
|
|
62
|
+
apiKey: 'lm-studio',
|
|
63
|
+
baseURL: 'http://localhost:1234/v1',
|
|
64
|
+
options: {
|
|
65
|
+
builtInWebTools: {
|
|
66
|
+
webSearch: true,
|
|
67
|
+
webFetch: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
).toThrow(
|
|
72
|
+
'Provider openai profile uses an OpenAI-compatible Chat Completions endpoint; native web search/fetch is not supported for this profile.',
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { IProviderDefinition, TUniversalValue } from '@robota-sdk/agent-core';
|
|
2
|
+
import { probeOpenAICompatibleProfile } from '../shared/openai-compatible/index.js';
|
|
3
|
+
import { refreshOpenAIModelCatalog } from './model-catalog-refresh';
|
|
4
|
+
import { OpenAIProvider } from './provider';
|
|
5
|
+
import type { IOpenAINativeWebToolsOptions, TOpenAIApiSurface } from './types';
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_OPENAI_PROVIDER_MODEL: string | undefined = undefined;
|
|
8
|
+
export const DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE = '$ENV:OPENAI_API_KEY';
|
|
9
|
+
const OPENAI_API_KEY_URL = 'https://platform.openai.com/api-keys';
|
|
10
|
+
const OPENAI_SETUP_SOURCE_URL =
|
|
11
|
+
'https://developers.openai.com/api/reference/overview#authentication';
|
|
12
|
+
const OPENAI_SETUP_LAST_VERIFIED_AT = '2026-05-08';
|
|
13
|
+
const OPENAI_SETUP_HELP_LINKS: NonNullable<IProviderDefinition['setupHelpLinks']> = [
|
|
14
|
+
{
|
|
15
|
+
kind: 'api-key',
|
|
16
|
+
label: 'OpenAI API keys',
|
|
17
|
+
url: OPENAI_API_KEY_URL,
|
|
18
|
+
sourceUrl: OPENAI_SETUP_SOURCE_URL,
|
|
19
|
+
lastVerifiedAt: OPENAI_SETUP_LAST_VERIFIED_AT,
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export function createOpenAIProviderDefinition(): IProviderDefinition {
|
|
24
|
+
return {
|
|
25
|
+
type: 'openai',
|
|
26
|
+
displayName: 'OpenAI',
|
|
27
|
+
description: 'Official OpenAI Responses API provider',
|
|
28
|
+
defaults: {
|
|
29
|
+
apiKey: DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE,
|
|
30
|
+
},
|
|
31
|
+
modelCatalog: {
|
|
32
|
+
status: 'unavailable',
|
|
33
|
+
sourceUrl: 'https://platform.openai.com/docs/api-reference/models/list',
|
|
34
|
+
message: 'OpenAI model availability should be discovered live from GET /v1/models.',
|
|
35
|
+
},
|
|
36
|
+
setupHelpLinks: OPENAI_SETUP_HELP_LINKS,
|
|
37
|
+
setupSteps: [
|
|
38
|
+
{
|
|
39
|
+
key: 'model',
|
|
40
|
+
title: 'OpenAI model',
|
|
41
|
+
required: true,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'apiKey',
|
|
45
|
+
title: 'OpenAI API key',
|
|
46
|
+
defaultValue: DEFAULT_OPENAI_PROVIDER_API_KEY_REFERENCE,
|
|
47
|
+
masked: true,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
requiresApiKey: true,
|
|
51
|
+
probeProfile: probeOpenAICompatibleProfile,
|
|
52
|
+
refreshModelCatalog: ({ profile }) => refreshOpenAIModelCatalog(profile),
|
|
53
|
+
modelCatalogCacheTtlSeconds: 86400,
|
|
54
|
+
createProvider: (config) => {
|
|
55
|
+
const apiSurface = readApiSurface(config.options);
|
|
56
|
+
const nativeWebTools = readNativeWebTools(config.options);
|
|
57
|
+
validateOpenAINativeWebTools(config.baseURL, apiSurface, nativeWebTools);
|
|
58
|
+
return new OpenAIProvider({
|
|
59
|
+
apiKey: requireApiKey(config.apiKey),
|
|
60
|
+
...(config.baseURL !== undefined && { baseURL: config.baseURL }),
|
|
61
|
+
...(config.timeout !== undefined && { timeout: config.timeout }),
|
|
62
|
+
...(apiSurface !== undefined && { apiSurface }),
|
|
63
|
+
...(nativeWebTools !== undefined && { nativeWebTools }),
|
|
64
|
+
defaultModel: config.model,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function requireApiKey(apiKey: string | undefined): string {
|
|
71
|
+
if (!apiKey) {
|
|
72
|
+
throw new Error('Provider openai requires apiKey');
|
|
73
|
+
}
|
|
74
|
+
return apiKey;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function readApiSurface(
|
|
78
|
+
options: Record<string, TUniversalValue> | undefined,
|
|
79
|
+
): TOpenAIApiSurface | undefined {
|
|
80
|
+
const apiSurface = options?.['apiSurface'];
|
|
81
|
+
if (apiSurface === 'responses' || apiSurface === 'chat-completions') {
|
|
82
|
+
return apiSurface;
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readNativeWebTools(
|
|
88
|
+
options: Record<string, TUniversalValue> | undefined,
|
|
89
|
+
): IOpenAINativeWebToolsOptions | undefined {
|
|
90
|
+
const nativeWebTools =
|
|
91
|
+
readNativeWebToolsRecord(options?.['nativeWebTools']) ??
|
|
92
|
+
readNativeWebToolsRecord(options?.['builtInWebTools']);
|
|
93
|
+
if (nativeWebTools === undefined) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
return nativeWebTools;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function readNativeWebToolsRecord(
|
|
100
|
+
value: TUniversalValue | undefined,
|
|
101
|
+
): IOpenAINativeWebToolsOptions | undefined {
|
|
102
|
+
if (value === null || value === undefined || value instanceof Date || Array.isArray(value)) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
if (typeof value !== 'object') {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const webSearch = value['webSearch'];
|
|
109
|
+
const webFetch = value['webFetch'];
|
|
110
|
+
return {
|
|
111
|
+
...(typeof webSearch === 'boolean' && { webSearch }),
|
|
112
|
+
...(typeof webFetch === 'boolean' && { webFetch }),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function validateOpenAINativeWebTools(
|
|
117
|
+
baseURL: string | undefined,
|
|
118
|
+
apiSurface: TOpenAIApiSurface | undefined,
|
|
119
|
+
nativeWebTools: IOpenAINativeWebToolsOptions | undefined,
|
|
120
|
+
): void {
|
|
121
|
+
if (nativeWebTools?.webSearch !== true && nativeWebTools?.webFetch !== true) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (baseURL !== undefined || apiSurface === 'chat-completions') {
|
|
125
|
+
throw new Error(
|
|
126
|
+
'Provider openai profile uses an OpenAI-compatible Chat Completions endpoint; native web search/fetch is not supported for this profile. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support.',
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
throw new Error(
|
|
130
|
+
'Provider openai native web search/fetch is not wired in this Robota provider version. Use Robota local WebSearch/WebFetch tools or a provider with documented hosted web support.',
|
|
131
|
+
);
|
|
132
|
+
}
|