@lobehub/chat 1.92.3 → 1.93.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/CHANGELOG.md +25 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/changelog/v1.json +9 -0
- package/docs/development/database-schema.dbml +51 -1
- package/locales/ar/modelProvider.json +4 -0
- package/locales/ar/models.json +64 -34
- package/locales/ar/providers.json +3 -0
- package/locales/bg-BG/modelProvider.json +4 -0
- package/locales/bg-BG/models.json +64 -34
- package/locales/bg-BG/providers.json +3 -0
- package/locales/de-DE/modelProvider.json +4 -0
- package/locales/de-DE/models.json +64 -34
- package/locales/de-DE/providers.json +3 -0
- package/locales/en-US/modelProvider.json +4 -0
- package/locales/en-US/models.json +64 -34
- package/locales/en-US/providers.json +3 -0
- package/locales/es-ES/modelProvider.json +4 -0
- package/locales/es-ES/models.json +64 -34
- package/locales/es-ES/providers.json +3 -0
- package/locales/fa-IR/modelProvider.json +4 -0
- package/locales/fa-IR/models.json +64 -34
- package/locales/fa-IR/providers.json +3 -0
- package/locales/fr-FR/modelProvider.json +4 -0
- package/locales/fr-FR/models.json +64 -34
- package/locales/fr-FR/providers.json +3 -0
- package/locales/it-IT/modelProvider.json +4 -0
- package/locales/it-IT/models.json +64 -34
- package/locales/it-IT/providers.json +3 -0
- package/locales/ja-JP/modelProvider.json +4 -0
- package/locales/ja-JP/models.json +64 -34
- package/locales/ja-JP/providers.json +3 -0
- package/locales/ko-KR/modelProvider.json +4 -0
- package/locales/ko-KR/models.json +64 -34
- package/locales/ko-KR/providers.json +3 -0
- package/locales/nl-NL/modelProvider.json +4 -0
- package/locales/nl-NL/models.json +64 -34
- package/locales/nl-NL/providers.json +3 -0
- package/locales/pl-PL/modelProvider.json +4 -0
- package/locales/pl-PL/models.json +64 -34
- package/locales/pl-PL/providers.json +3 -0
- package/locales/pt-BR/modelProvider.json +4 -0
- package/locales/pt-BR/models.json +64 -34
- package/locales/pt-BR/providers.json +3 -0
- package/locales/ru-RU/modelProvider.json +4 -0
- package/locales/ru-RU/models.json +63 -33
- package/locales/ru-RU/providers.json +3 -0
- package/locales/tr-TR/modelProvider.json +4 -0
- package/locales/tr-TR/models.json +64 -34
- package/locales/tr-TR/providers.json +3 -0
- package/locales/vi-VN/modelProvider.json +4 -0
- package/locales/vi-VN/models.json +64 -34
- package/locales/vi-VN/providers.json +3 -0
- package/locales/zh-CN/modelProvider.json +4 -0
- package/locales/zh-CN/models.json +59 -29
- package/locales/zh-CN/providers.json +3 -0
- package/locales/zh-TW/modelProvider.json +4 -0
- package/locales/zh-TW/models.json +64 -34
- package/locales/zh-TW/providers.json +3 -0
- package/package.json +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +16 -0
- package/src/config/modelProviders/openai.ts +3 -1
- package/src/database/client/migrations.json +25 -0
- package/src/database/migrations/0025_add_provider_config.sql +1 -0
- package/src/database/migrations/meta/0025_snapshot.json +5703 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/models/__tests__/aiProvider.test.ts +2 -0
- package/src/database/models/aiProvider.ts +5 -2
- package/src/database/repositories/tableViewer/index.test.ts +1 -1
- package/src/database/schemas/_helpers.ts +5 -1
- package/src/database/schemas/aiInfra.ts +5 -1
- package/src/libs/model-runtime/openai/index.ts +21 -2
- package/src/libs/model-runtime/types/chat.ts +6 -9
- package/src/libs/model-runtime/utils/openaiCompatibleFactory/index.ts +79 -5
- package/src/libs/model-runtime/utils/openaiHelpers.test.ts +145 -1
- package/src/libs/model-runtime/utils/openaiHelpers.ts +59 -0
- package/src/libs/model-runtime/utils/streams/openai/__snapshots__/responsesStream.test.ts.snap +193 -0
- package/src/libs/model-runtime/utils/streams/openai/index.ts +2 -0
- package/src/libs/model-runtime/utils/streams/{openai.test.ts → openai/openai.test.ts} +1 -1
- package/src/libs/model-runtime/utils/streams/{openai.ts → openai/openai.ts} +5 -5
- package/src/libs/model-runtime/utils/streams/openai/responsesStream.test.ts +826 -0
- package/src/libs/model-runtime/utils/streams/openai/responsesStream.ts +166 -0
- package/src/libs/model-runtime/utils/streams/protocol.ts +4 -1
- package/src/libs/model-runtime/utils/streams/utils.ts +20 -0
- package/src/libs/model-runtime/utils/usageConverter.ts +59 -0
- package/src/locales/default/modelProvider.ts +4 -0
- package/src/services/__tests__/chat.test.ts +27 -0
- package/src/services/chat.ts +8 -2
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +11 -0
- package/src/types/aiProvider.ts +13 -1
@@ -0,0 +1,166 @@
|
|
1
|
+
import OpenAI from 'openai';
|
2
|
+
import type { Stream } from 'openai/streaming';
|
3
|
+
|
4
|
+
import { ChatMessageError } from '@/types/message';
|
5
|
+
|
6
|
+
import { AgentRuntimeErrorType } from '../../../error';
|
7
|
+
import { convertResponseUsage } from '../../usageConverter';
|
8
|
+
import {
|
9
|
+
FIRST_CHUNK_ERROR_KEY,
|
10
|
+
StreamContext,
|
11
|
+
StreamProtocolChunk,
|
12
|
+
StreamProtocolToolCallChunk,
|
13
|
+
StreamToolCallChunkData,
|
14
|
+
convertIterableToStream,
|
15
|
+
createCallbacksTransformer,
|
16
|
+
createFirstErrorHandleTransformer,
|
17
|
+
createSSEProtocolTransformer,
|
18
|
+
createTokenSpeedCalculator,
|
19
|
+
} from '../protocol';
|
20
|
+
import { OpenAIStreamOptions } from './openai';
|
21
|
+
|
22
|
+
const transformOpenAIStream = (
|
23
|
+
chunk: OpenAI.Responses.ResponseStreamEvent,
|
24
|
+
streamContext: StreamContext,
|
25
|
+
): StreamProtocolChunk | StreamProtocolChunk[] => {
|
26
|
+
// handle the first chunk error
|
27
|
+
if (FIRST_CHUNK_ERROR_KEY in chunk) {
|
28
|
+
delete chunk[FIRST_CHUNK_ERROR_KEY];
|
29
|
+
// @ts-ignore
|
30
|
+
delete chunk['name'];
|
31
|
+
// @ts-ignore
|
32
|
+
delete chunk['stack'];
|
33
|
+
|
34
|
+
const errorData = {
|
35
|
+
body: chunk,
|
36
|
+
type: 'errorType' in chunk ? chunk.errorType : AgentRuntimeErrorType.ProviderBizError,
|
37
|
+
} as ChatMessageError;
|
38
|
+
return { data: errorData, id: 'first_chunk_error', type: 'error' };
|
39
|
+
}
|
40
|
+
|
41
|
+
try {
|
42
|
+
switch (chunk.type) {
|
43
|
+
case 'response.created': {
|
44
|
+
streamContext.id = chunk.response.id;
|
45
|
+
|
46
|
+
return { data: chunk.response.status, id: streamContext.id, type: 'data' };
|
47
|
+
}
|
48
|
+
|
49
|
+
case 'response.output_item.added': {
|
50
|
+
switch (chunk.item.type) {
|
51
|
+
case 'function_call': {
|
52
|
+
streamContext.toolIndex =
|
53
|
+
typeof streamContext.toolIndex === 'undefined' ? 0 : streamContext.toolIndex + 1;
|
54
|
+
streamContext.tool = {
|
55
|
+
id: chunk.item.call_id,
|
56
|
+
index: streamContext.toolIndex,
|
57
|
+
name: chunk.item.name,
|
58
|
+
};
|
59
|
+
|
60
|
+
return {
|
61
|
+
data: [
|
62
|
+
{
|
63
|
+
function: { arguments: chunk.item.arguments, name: chunk.item.name },
|
64
|
+
id: chunk.item.call_id,
|
65
|
+
index: streamContext.toolIndex!,
|
66
|
+
type: 'function',
|
67
|
+
} satisfies StreamToolCallChunkData,
|
68
|
+
],
|
69
|
+
id: streamContext.id,
|
70
|
+
type: 'tool_calls',
|
71
|
+
} satisfies StreamProtocolToolCallChunk;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
return { data: chunk.item, id: streamContext.id, type: 'data' };
|
76
|
+
}
|
77
|
+
|
78
|
+
case 'response.function_call_arguments.delta': {
|
79
|
+
return {
|
80
|
+
data: [
|
81
|
+
{
|
82
|
+
function: { arguments: chunk.delta, name: streamContext.tool?.name },
|
83
|
+
id: streamContext.tool?.id,
|
84
|
+
index: streamContext.toolIndex!,
|
85
|
+
type: 'function',
|
86
|
+
} satisfies StreamToolCallChunkData,
|
87
|
+
],
|
88
|
+
id: streamContext.id,
|
89
|
+
type: 'tool_calls',
|
90
|
+
} satisfies StreamProtocolToolCallChunk;
|
91
|
+
}
|
92
|
+
case 'response.output_text.delta': {
|
93
|
+
return { data: chunk.delta, id: chunk.item_id, type: 'text' };
|
94
|
+
}
|
95
|
+
|
96
|
+
case 'response.reasoning_summary_part.added': {
|
97
|
+
if (!streamContext.startReasoning) {
|
98
|
+
streamContext.startReasoning = true;
|
99
|
+
return { data: '', id: chunk.item_id, type: 'reasoning' };
|
100
|
+
} else {
|
101
|
+
return { data: '\n', id: chunk.item_id, type: 'reasoning' };
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
case 'response.reasoning_summary_text.delta': {
|
106
|
+
return { data: chunk.delta, id: chunk.item_id, type: 'reasoning' };
|
107
|
+
}
|
108
|
+
|
109
|
+
case 'response.completed': {
|
110
|
+
if (chunk.response.usage) {
|
111
|
+
return {
|
112
|
+
data: convertResponseUsage(chunk.response.usage),
|
113
|
+
id: chunk.response.id,
|
114
|
+
type: 'usage',
|
115
|
+
};
|
116
|
+
}
|
117
|
+
|
118
|
+
return { data: chunk, id: streamContext.id, type: 'data' };
|
119
|
+
}
|
120
|
+
|
121
|
+
default: {
|
122
|
+
return { data: chunk, id: streamContext.id, type: 'data' };
|
123
|
+
}
|
124
|
+
}
|
125
|
+
} catch (e) {
|
126
|
+
const errorName = 'StreamChunkError';
|
127
|
+
console.error(`[${errorName}]`, e);
|
128
|
+
console.error(`[${errorName}] raw chunk:`, chunk);
|
129
|
+
|
130
|
+
const err = e as Error;
|
131
|
+
|
132
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
133
|
+
const errorData = {
|
134
|
+
body: {
|
135
|
+
message:
|
136
|
+
'chat response streaming chunk parse error, please contact your API Provider to fix it.',
|
137
|
+
context: { error: { message: err.message, name: err.name }, chunk },
|
138
|
+
},
|
139
|
+
type: errorName,
|
140
|
+
} as ChatMessageError;
|
141
|
+
/* eslint-enable */
|
142
|
+
|
143
|
+
return { data: errorData, id: streamContext.id, type: 'error' };
|
144
|
+
}
|
145
|
+
};
|
146
|
+
|
147
|
+
export const OpenAIResponsesStream = (
|
148
|
+
stream: Stream<OpenAI.Responses.ResponseStreamEvent> | ReadableStream,
|
149
|
+
{ callbacks, provider, bizErrorTypeTransformer, inputStartAt }: OpenAIStreamOptions = {},
|
150
|
+
) => {
|
151
|
+
const streamStack: StreamContext = { id: '' };
|
152
|
+
|
153
|
+
const readableStream =
|
154
|
+
stream instanceof ReadableStream ? stream : convertIterableToStream(stream);
|
155
|
+
|
156
|
+
return (
|
157
|
+
readableStream
|
158
|
+
// 1. handle the first error if exist
|
159
|
+
// provider like huggingface or minimax will return error in the stream,
|
160
|
+
// so in the first Transformer, we need to handle the error
|
161
|
+
.pipeThrough(createFirstErrorHandleTransformer(bizErrorTypeTransformer, provider))
|
162
|
+
.pipeThrough(createTokenSpeedCalculator(transformOpenAIStream, { inputStartAt, streamStack }))
|
163
|
+
.pipeThrough(createSSEProtocolTransformer((c) => c, streamStack))
|
164
|
+
.pipeThrough(createCallbacksTransformer(callbacks))
|
165
|
+
);
|
166
|
+
};
|
@@ -23,6 +23,10 @@ export interface StreamContext {
|
|
23
23
|
* This array accumulates all citation items received during the streaming response.
|
24
24
|
*/
|
25
25
|
returnedCitationArray?: CitationItem[];
|
26
|
+
/**
|
27
|
+
* O series models need a condition to separate part
|
28
|
+
*/
|
29
|
+
startReasoning?: boolean;
|
26
30
|
thinking?: {
|
27
31
|
id: string;
|
28
32
|
name: string;
|
@@ -78,7 +82,6 @@ export interface StreamToolCallChunkData {
|
|
78
82
|
export interface StreamProtocolToolCallChunk {
|
79
83
|
data: StreamToolCallChunkData[];
|
80
84
|
id: string;
|
81
|
-
index: number;
|
82
85
|
type: 'tool_calls';
|
83
86
|
}
|
84
87
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
export const createReadableStream = <T>(chunks: T[]) =>
|
2
|
+
new ReadableStream({
|
3
|
+
start(controller) {
|
4
|
+
chunks.forEach((chunk) => controller.enqueue(chunk));
|
5
|
+
|
6
|
+
controller.close();
|
7
|
+
},
|
8
|
+
});
|
9
|
+
|
10
|
+
export const readStreamChunk = async (stream: ReadableStream) => {
|
11
|
+
const decoder = new TextDecoder();
|
12
|
+
const chunks = [];
|
13
|
+
|
14
|
+
// @ts-ignore
|
15
|
+
for await (const chunk of stream) {
|
16
|
+
chunks.push(decoder.decode(chunk, { stream: true }));
|
17
|
+
}
|
18
|
+
|
19
|
+
return chunks;
|
20
|
+
};
|
@@ -48,3 +48,62 @@ export const convertUsage = (usage: OpenAI.Completions.CompletionUsage): ModelTo
|
|
48
48
|
|
49
49
|
return finalData;
|
50
50
|
};
|
51
|
+
|
52
|
+
export const convertResponseUsage = (usage: OpenAI.Responses.ResponseUsage): ModelTokensUsage => {
|
53
|
+
// 1. Extract and default primary values
|
54
|
+
const totalInputTokens = usage.input_tokens || 0;
|
55
|
+
const inputCachedTokens = usage.input_tokens_details?.cached_tokens || 0;
|
56
|
+
|
57
|
+
const totalOutputTokens = usage.output_tokens || 0;
|
58
|
+
const outputReasoningTokens = usage.output_tokens_details?.reasoning_tokens || 0;
|
59
|
+
|
60
|
+
const overallTotalTokens = usage.total_tokens || 0;
|
61
|
+
|
62
|
+
// 2. Calculate derived values
|
63
|
+
const inputCacheMissTokens = totalInputTokens - inputCachedTokens;
|
64
|
+
|
65
|
+
// For ResponseUsage, inputTextTokens is effectively totalInputTokens as no further breakdown is given.
|
66
|
+
const inputTextTokens = totalInputTokens;
|
67
|
+
|
68
|
+
// For ResponseUsage, outputTextTokens is totalOutputTokens minus reasoning, as no audio output tokens are specified.
|
69
|
+
const outputTextTokens = totalOutputTokens - outputReasoningTokens;
|
70
|
+
|
71
|
+
// 3. Construct the comprehensive data object (matching ModelTokensUsage structure)
|
72
|
+
const data = {
|
73
|
+
// Fields from ModelTokensUsage that are not in ResponseUsage will be undefined or 0
|
74
|
+
// and potentially filtered out later.
|
75
|
+
acceptedPredictionTokens: undefined, // Not in ResponseUsage
|
76
|
+
inputAudioTokens: undefined, // Not in ResponseUsage
|
77
|
+
inputCacheMissTokens: inputCacheMissTokens,
|
78
|
+
inputCachedTokens: inputCachedTokens,
|
79
|
+
inputCitationTokens: undefined, // Not in ResponseUsage
|
80
|
+
inputTextTokens: inputTextTokens,
|
81
|
+
outputAudioTokens: undefined, // Not in ResponseUsage
|
82
|
+
outputReasoningTokens: outputReasoningTokens,
|
83
|
+
outputTextTokens: outputTextTokens,
|
84
|
+
rejectedPredictionTokens: undefined, // Not in ResponseUsage
|
85
|
+
totalInputTokens: totalInputTokens,
|
86
|
+
totalOutputTokens: totalOutputTokens,
|
87
|
+
totalTokens: overallTotalTokens,
|
88
|
+
} satisfies ModelTokensUsage; // This helps ensure all keys of ModelTokensUsage are considered
|
89
|
+
|
90
|
+
// 4. Filter out zero/falsy values, as done in the reference implementation
|
91
|
+
const finalData: Partial<ModelTokensUsage> = {}; // Use Partial for type safety during construction
|
92
|
+
Object.entries(data).forEach(([key, value]) => {
|
93
|
+
if (
|
94
|
+
value !== undefined &&
|
95
|
+
value !== null &&
|
96
|
+
(typeof value !== 'number' || value !== 0) && // A more explicit check than `!!value` if we want to be very specific about
|
97
|
+
// keeping non-numeric truthy values, but the reference uses `!!value`.
|
98
|
+
// `!!value` will filter out 0, which is often desired for token counts.
|
99
|
+
// Let's stick to the reference's behavior:
|
100
|
+
!!value
|
101
|
+
) {
|
102
|
+
// @ts-ignore - We are building an object that will conform to ModelTokensUsage
|
103
|
+
// by selectively adding properties.
|
104
|
+
finalData[key as keyof ModelTokensUsage] = value as number;
|
105
|
+
}
|
106
|
+
});
|
107
|
+
|
108
|
+
return finalData as ModelTokensUsage; // Cast because we've built it to match
|
109
|
+
};
|
@@ -618,6 +618,32 @@ describe('ChatService', () => {
|
|
618
618
|
stream: true,
|
619
619
|
...DEFAULT_AGENT_CONFIG.params,
|
620
620
|
...params,
|
621
|
+
apiMode: 'responses',
|
622
|
+
};
|
623
|
+
|
624
|
+
await chatService.getChatCompletion(params, options);
|
625
|
+
|
626
|
+
expect(global.fetch).toHaveBeenCalledWith(expect.any(String), {
|
627
|
+
body: JSON.stringify(expectedPayload),
|
628
|
+
headers: expect.any(Object),
|
629
|
+
method: 'POST',
|
630
|
+
});
|
631
|
+
});
|
632
|
+
it('should make a POST request without response in non-openai provider payload', async () => {
|
633
|
+
const params: Partial<ChatStreamPayload> = {
|
634
|
+
model: 'deepseek-reasoner',
|
635
|
+
provider: 'deepseek',
|
636
|
+
messages: [],
|
637
|
+
};
|
638
|
+
|
639
|
+
const options = {};
|
640
|
+
|
641
|
+
const expectedPayload = {
|
642
|
+
model: 'deepseek-reasoner',
|
643
|
+
stream: true,
|
644
|
+
...DEFAULT_AGENT_CONFIG.params,
|
645
|
+
messages: [],
|
646
|
+
provider: undefined,
|
621
647
|
};
|
622
648
|
|
623
649
|
await chatService.getChatCompletion(params, options);
|
@@ -656,6 +682,7 @@ describe('ChatService', () => {
|
|
656
682
|
stream: true,
|
657
683
|
...DEFAULT_AGENT_CONFIG.params,
|
658
684
|
...params,
|
685
|
+
apiMode: 'responses',
|
659
686
|
};
|
660
687
|
|
661
688
|
const result = await chatService.getChatCompletion(params, options);
|
package/src/services/chat.ts
CHANGED
@@ -37,11 +37,11 @@ import { ChatErrorType } from '@/types/fetch';
|
|
37
37
|
import { ChatMessage, MessageToolCall } from '@/types/message';
|
38
38
|
import type { ChatStreamPayload, OpenAIChatMessage } from '@/types/openai/chat';
|
39
39
|
import { UserMessageContentPart } from '@/types/openai/chat';
|
40
|
+
import { parsePlaceholderVariablesMessages } from '@/utils/client/parserPlaceholder';
|
40
41
|
import { createErrorResponse } from '@/utils/errorResponse';
|
41
42
|
import { FetchSSEOptions, fetchSSE, getMessageError } from '@/utils/fetch';
|
42
43
|
import { genToolCallingName } from '@/utils/toolCall';
|
43
44
|
import { createTraceHeader, getTraceId } from '@/utils/trace';
|
44
|
-
import { parsePlaceholderVariablesMessages } from '@/utils/client/parserPlaceholder';
|
45
45
|
|
46
46
|
import { createHeaderWithAuth, createPayloadWithKeyVaults } from './_auth';
|
47
47
|
import { API_ENDPOINTS } from './_url';
|
@@ -315,9 +315,15 @@ class ChatService {
|
|
315
315
|
model = findDeploymentName(model, provider);
|
316
316
|
}
|
317
317
|
|
318
|
+
const apiMode = aiProviderSelectors.isProviderEnableResponseApi(provider)(
|
319
|
+
getAiInfraStoreState(),
|
320
|
+
)
|
321
|
+
? 'responses'
|
322
|
+
: undefined;
|
323
|
+
|
318
324
|
const payload = merge(
|
319
325
|
{ model: DEFAULT_AGENT_CONFIG.model, stream: true, ...DEFAULT_AGENT_CONFIG.params },
|
320
|
-
{ ...res, model },
|
326
|
+
{ ...res, apiMode, model },
|
321
327
|
);
|
322
328
|
|
323
329
|
/**
|
@@ -99,6 +99,16 @@ const isProviderHasBuiltinSearchConfig = (id: string) => (s: AIProviderStoreStat
|
|
99
99
|
return !!providerCfg?.settings.searchMode && providerCfg?.settings.searchMode !== 'internal';
|
100
100
|
};
|
101
101
|
|
102
|
+
const isProviderEnableResponseApi = (id: string) => (s: AIProviderStoreState) => {
|
103
|
+
const providerCfg = providerConfigById(id)(s);
|
104
|
+
|
105
|
+
const enableResponseApi = providerCfg?.config?.enableResponseApi;
|
106
|
+
|
107
|
+
if (typeof enableResponseApi === 'boolean') return enableResponseApi;
|
108
|
+
|
109
|
+
return id === 'openai';
|
110
|
+
};
|
111
|
+
|
102
112
|
export const aiProviderSelectors = {
|
103
113
|
activeProviderConfig,
|
104
114
|
disabledAiProviderList,
|
@@ -107,6 +117,7 @@ export const aiProviderSelectors = {
|
|
107
117
|
isActiveProviderEndpointNotEmpty,
|
108
118
|
isAiProviderConfigLoading,
|
109
119
|
isProviderConfigUpdating,
|
120
|
+
isProviderEnableResponseApi,
|
110
121
|
isProviderEnabled,
|
111
122
|
isProviderFetchOnClient,
|
112
123
|
isProviderHasBuiltinSearch,
|
package/src/types/aiProvider.ts
CHANGED
@@ -79,6 +79,7 @@ export interface AiProviderSettings {
|
|
79
79
|
* whether to smoothing the output
|
80
80
|
*/
|
81
81
|
smoothing?: SmoothingParams;
|
82
|
+
supportResponsesApi?: boolean;
|
82
83
|
}
|
83
84
|
|
84
85
|
const AiProviderSettingsSchema = z.object({
|
@@ -106,8 +107,13 @@ const AiProviderSettingsSchema = z.object({
|
|
106
107
|
toolsCalling: z.boolean().optional(),
|
107
108
|
})
|
108
109
|
.optional(),
|
110
|
+
supportResponsesApi: z.boolean().optional(),
|
109
111
|
});
|
110
112
|
|
113
|
+
export interface AiProviderConfig {
|
114
|
+
enableResponseApi?: boolean;
|
115
|
+
}
|
116
|
+
|
111
117
|
// create
|
112
118
|
export const CreateAiProviderSchema = z.object({
|
113
119
|
config: z.object({}).passthrough().optional(),
|
@@ -206,8 +212,13 @@ export type UpdateAiProviderParams = z.infer<typeof UpdateAiProviderSchema>;
|
|
206
212
|
|
207
213
|
export const UpdateAiProviderConfigSchema = z.object({
|
208
214
|
checkModel: z.string().optional(),
|
215
|
+
config: z
|
216
|
+
.object({
|
217
|
+
enableResponseApi: z.boolean().optional(),
|
218
|
+
})
|
219
|
+
.optional(),
|
209
220
|
fetchOnClient: z.boolean().nullable().optional(),
|
210
|
-
keyVaults: z.
|
221
|
+
keyVaults: z.record(z.string(), z.string().optional()).optional(),
|
211
222
|
});
|
212
223
|
|
213
224
|
export type UpdateAiProviderConfigParams = z.infer<typeof UpdateAiProviderConfigSchema>;
|
@@ -235,6 +246,7 @@ export interface EnabledProviderWithModels {
|
|
235
246
|
}
|
236
247
|
|
237
248
|
export interface AiProviderRuntimeConfig {
|
249
|
+
config: AiProviderConfig;
|
238
250
|
fetchOnClient?: boolean;
|
239
251
|
keyVaults: Record<string, string>;
|
240
252
|
settings: AiProviderSettings;
|