@veryfront/ext-llm-openai 0.1.1241 → 0.1.1243
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/esm/extensions/ext-llm-openai/src/openai-chat-request-builder.d.ts +4 -1
- package/esm/extensions/ext-llm-openai/src/openai-chat-request-builder.d.ts.map +1 -1
- package/esm/extensions/ext-llm-openai/src/openai-chat-request-builder.js +47 -18
- package/esm/extensions/ext-llm-openai/src/openai-chat-stream.d.ts.map +1 -1
- package/esm/extensions/ext-llm-openai/src/openai-chat-stream.js +6 -3
- package/esm/extensions/ext-llm-openai/src/openai-provider.d.ts +2 -1
- package/esm/extensions/ext-llm-openai/src/openai-provider.d.ts.map +1 -1
- package/esm/extensions/ext-llm-openai/src/openai-provider.js +42 -4
- package/package.json +2 -2
|
@@ -3,6 +3,9 @@ export interface OpenAICompatibleLanguageOptions extends ModelRuntimeCallOptions
|
|
|
3
3
|
serviceTier?: "auto" | "default" | "flex" | "scale";
|
|
4
4
|
parallelToolCalls?: boolean;
|
|
5
5
|
}
|
|
6
|
+
export type OpenAIChatRequestCapabilities = {
|
|
7
|
+
readonly reasoningWithFunctionTools?: boolean;
|
|
8
|
+
};
|
|
6
9
|
/** @deprecated Import `ModelRuntimeToolDefinition` from `veryfront/provider` instead. */
|
|
7
10
|
export type RuntimeToolDefinition = ModelRuntimeToolDefinition;
|
|
8
11
|
type WarningCollector = {
|
|
@@ -19,6 +22,6 @@ type WarningCollector = {
|
|
|
19
22
|
provider: string;
|
|
20
23
|
}>;
|
|
21
24
|
};
|
|
22
|
-
export declare function buildOpenAIChatRequest(modelId: string, providerName: string, options: OpenAICompatibleLanguageOptions, stream: boolean, warnings: WarningCollector): OpenAICompatibleChatRequest;
|
|
25
|
+
export declare function buildOpenAIChatRequest(modelId: string, providerName: string, options: OpenAICompatibleLanguageOptions, stream: boolean, warnings: WarningCollector, capabilities?: OpenAIChatRequestCapabilities): OpenAICompatibleChatRequest;
|
|
23
26
|
export {};
|
|
24
27
|
//# sourceMappingURL=openai-chat-request-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-request-builder.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-chat-request-builder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,2BAA2B,CAAC;AAOnC,MAAM,WAAW,+BAAgC,SAAQ,uBAAuB;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,yFAAyF;AACzF,MAAM,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAE/D,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,OAAO,EAAE;QACZ,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;IACT,KAAK,IAAI,KAAK,CAAC;QACb,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ,CAAC;AAUF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,+BAA+B,EACxC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"openai-chat-request-builder.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-chat-request-builder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,2BAA2B,CAAC;AAOnC,MAAM,WAAW,+BAAgC,SAAQ,uBAAuB;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;CAC/C,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,qBAAqB,GAAG,0BAA0B,CAAC;AAE/D,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,OAAO,EAAE;QACZ,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;IACT,KAAK,IAAI,KAAK,CAAC;QACb,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ,CAAC;AAUF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,+BAA+B,EACxC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,gBAAgB,EAC1B,YAAY,CAAC,EAAE,6BAA6B,GAC3C,2BAA2B,CAiJ7B"}
|
|
@@ -7,8 +7,26 @@ function isNativeOpenAIModel(modelId) {
|
|
|
7
7
|
function isFixedSamplingModel(modelId) {
|
|
8
8
|
return /^kimi-k2\.5/.test(modelId);
|
|
9
9
|
}
|
|
10
|
-
export function buildOpenAIChatRequest(modelId, providerName, options, stream, warnings) {
|
|
11
|
-
const
|
|
10
|
+
export function buildOpenAIChatRequest(modelId, providerName, options, stream, warnings, capabilities) {
|
|
11
|
+
const tools = toOpenAICompatibleTools(options.tools);
|
|
12
|
+
// Env-BYOK users historically registered options under "openai-compatible";
|
|
13
|
+
// keep merging that bucket at the lowest precedence. max_tokens is normalized
|
|
14
|
+
// per bucket BEFORE merging so a higher-precedence bucket's max_tokens
|
|
15
|
+
// override still beats a lower bucket's max_completion_tokens.
|
|
16
|
+
const bucketNames = [
|
|
17
|
+
...(providerName === "openai" ? ["openai-compatible"] : []),
|
|
18
|
+
"openai",
|
|
19
|
+
providerName,
|
|
20
|
+
];
|
|
21
|
+
const providerOpts = {};
|
|
22
|
+
for (const bucketName of bucketNames) {
|
|
23
|
+
defineOpenAIProviderOptions(providerOpts, normalizeNativeMaxTokens(readProviderOptions(options.providerOptions, bucketName), modelId));
|
|
24
|
+
}
|
|
25
|
+
const finalTools = Object.hasOwn(providerOpts, "tools") ? providerOpts.tools : tools;
|
|
26
|
+
const resolvedReasoning = resolveOpenAIReasoningConfig(modelId, providerName, options.reasoning);
|
|
27
|
+
const suppressReasoningForFunctionTools = hasOpenAIFunctionTools(finalTools) &&
|
|
28
|
+
capabilities?.reasoningWithFunctionTools === false;
|
|
29
|
+
const reasoning = suppressReasoningForFunctionTools ? undefined : resolvedReasoning;
|
|
12
30
|
const reasoningEnabled = reasoning !== undefined;
|
|
13
31
|
const samplingRejected = rejectsOpenAISamplingParams(modelId);
|
|
14
32
|
const fixedSampling = isFixedSamplingModel(modelId);
|
|
@@ -63,9 +81,7 @@ export function buildOpenAIChatRequest(modelId, providerName, options, stream, w
|
|
|
63
81
|
...(options.stopSequences && options.stopSequences.length > 0
|
|
64
82
|
? { stop: [...options.stopSequences] }
|
|
65
83
|
: {}),
|
|
66
|
-
...(
|
|
67
|
-
? { tools: toOpenAICompatibleTools(options.tools) }
|
|
68
|
-
: {}),
|
|
84
|
+
...(tools ? { tools } : {}),
|
|
69
85
|
...(options.toolChoice !== undefined ? { tool_choice: options.toolChoice } : {}),
|
|
70
86
|
...(options.seed !== undefined ? { seed: options.seed } : {}),
|
|
71
87
|
...(!dropSamplingParams && options.presencePenalty !== undefined
|
|
@@ -100,19 +116,6 @@ export function buildOpenAIChatRequest(modelId, providerName, options, stream, w
|
|
|
100
116
|
}
|
|
101
117
|
: {}),
|
|
102
118
|
};
|
|
103
|
-
// Env-BYOK users historically registered options under "openai-compatible";
|
|
104
|
-
// keep merging that bucket at the lowest precedence. max_tokens is normalized
|
|
105
|
-
// per bucket BEFORE merging so a higher-precedence bucket's max_tokens
|
|
106
|
-
// override still beats a lower bucket's max_completion_tokens.
|
|
107
|
-
const bucketNames = [
|
|
108
|
-
...(providerName === "openai" ? ["openai-compatible"] : []),
|
|
109
|
-
"openai",
|
|
110
|
-
providerName,
|
|
111
|
-
];
|
|
112
|
-
const providerOpts = {};
|
|
113
|
-
for (const bucketName of bucketNames) {
|
|
114
|
-
defineOpenAIProviderOptions(providerOpts, normalizeNativeMaxTokens(readProviderOptions(options.providerOptions, bucketName), modelId));
|
|
115
|
-
}
|
|
116
119
|
defineOpenAIProviderOptions(body, providerOpts);
|
|
117
120
|
// Provider-native options may tune request behavior, but they must not
|
|
118
121
|
// replace the runtime-owned transport mode, model, or conversation.
|
|
@@ -126,8 +129,34 @@ export function buildOpenAIChatRequest(modelId, providerName, options, stream, w
|
|
|
126
129
|
delete body.stream;
|
|
127
130
|
delete body.stream_options;
|
|
128
131
|
}
|
|
132
|
+
if (suppressReasoningForFunctionTools) {
|
|
133
|
+
if (resolvedReasoning !== undefined || body.reasoning_effort !== undefined) {
|
|
134
|
+
warnings.push({
|
|
135
|
+
type: "unsupported-setting",
|
|
136
|
+
provider: "openai",
|
|
137
|
+
setting: "reasoning",
|
|
138
|
+
details: "Veryfront drops reasoning because this Chat Completions transport " +
|
|
139
|
+
"does not support reasoning alongside function tools.",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
delete body.reasoning_effort;
|
|
143
|
+
}
|
|
129
144
|
return body;
|
|
130
145
|
}
|
|
146
|
+
function hasOpenAIFunctionTools(value) {
|
|
147
|
+
if (!Array.isArray(value)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
for (const tool of value) {
|
|
151
|
+
if (typeof tool === "object" &&
|
|
152
|
+
tool !== null &&
|
|
153
|
+
"type" in tool &&
|
|
154
|
+
tool.type === "function") {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
131
160
|
/** Normalizes max_tokens to max_completion_tokens for native OpenAI models. */
|
|
132
161
|
function normalizeNativeMaxTokens(bucket, modelId) {
|
|
133
162
|
if (!isNativeOpenAIModel(modelId) || !("max_tokens" in bucket)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-stream.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-chat-stream.ts"],"names":[],"mappings":"AA2BA,KAAK,4BAA4B,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAExE,KAAK,uBAAuB,GAAG;IAC7B,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AASF,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AA4KlD,wBAAuB,2BAA2B,CAChD,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,OAAO,GAAE,uBAA4B,GACpC,aAAa,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"openai-chat-stream.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-chat-stream.ts"],"names":[],"mappings":"AA2BA,KAAK,4BAA4B,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAExE,KAAK,uBAAuB,GAAG;IAC7B,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AASF,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AA4KlD,wBAAuB,2BAA2B,CAChD,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,OAAO,GAAE,uBAA4B,GACpC,aAAa,CAAC,OAAO,CAAC,CAyVxB"}
|
|
@@ -186,10 +186,13 @@ export async function* streamOpenAICompatibleParts(stream, context = {}) {
|
|
|
186
186
|
if (!Array.isArray(record.choices)) {
|
|
187
187
|
throw invalidOpenAIStream(context, "choices was not an array");
|
|
188
188
|
}
|
|
189
|
+
// An empty `choices` array carries no content. Usage-only frames use this
|
|
190
|
+
// shape, and so does Azure OpenAI's `prompt_filter_results` preamble, which
|
|
191
|
+
// arrives before the first content chunk with neither choices nor usage.
|
|
192
|
+
// Both are informational, so skip the frame instead of failing the stream.
|
|
193
|
+
// The `choices` key being absent entirely is still rejected above — that is
|
|
194
|
+
// a malformed event rather than a content-free one.
|
|
189
195
|
if (record.choices.length === 0) {
|
|
190
|
-
if (!usageRecord) {
|
|
191
|
-
throw invalidOpenAIStream(context, "empty choices event had no usage");
|
|
192
|
-
}
|
|
193
196
|
return;
|
|
194
197
|
}
|
|
195
198
|
if (sawFinishReason) {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import type { LLMProvider, LLMProviderConfig } from "veryfront/extensions/llm";
|
|
11
11
|
import type { EmbeddingRuntime, ModelRuntime, RuntimeAssistantContentPart } from "veryfront/provider/types";
|
|
12
12
|
import { buildProviderError, isNumberArray, mergeUsage, parseRetryAfterMs, ProviderError, ProviderOverloadedError, ProviderQuotaError, ProviderRateLimitError, ProviderRequestError, TOOL_INPUT_PENDING_THRESHOLD_MS } from "veryfront/provider/shared";
|
|
13
|
-
import { type OpenAICompatibleLanguageOptions } from "./openai-chat-request-builder.js";
|
|
13
|
+
import { type OpenAIChatRequestCapabilities, type OpenAICompatibleLanguageOptions } from "./openai-chat-request-builder.js";
|
|
14
14
|
export { buildProviderError, isNumberArray, mergeUsage, parseRetryAfterMs, ProviderError, ProviderOverloadedError, ProviderQuotaError, ProviderRateLimitError, ProviderRequestError, TOOL_INPUT_PENDING_THRESHOLD_MS, };
|
|
15
15
|
export interface OpenAIRuntimeConfig {
|
|
16
16
|
apiKey: string;
|
|
@@ -19,6 +19,7 @@ export interface OpenAIRuntimeConfig {
|
|
|
19
19
|
name?: string;
|
|
20
20
|
/** Provider identity for OpenAI request defaults. Defaults to `name` in low-level factories. */
|
|
21
21
|
providerName?: string;
|
|
22
|
+
chatRequestCapabilities?: OpenAIChatRequestCapabilities;
|
|
22
23
|
fetch?: typeof globalThis.fetch;
|
|
23
24
|
}
|
|
24
25
|
export declare function createOpenAIModelRuntime(config: OpenAIRuntimeConfig, modelId: string): ModelRuntime<OpenAICompatibleLanguageOptions, RuntimeAssistantContentPart>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAMlB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EAOpB,+BAA+B,EAChC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,kCAAkC,CAAC;AA2B1C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,+BAA+B,GAChC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-llm-openai/src/openai-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAMlB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EAOpB,+BAA+B,EAChC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,+BAA+B,EACrC,MAAM,kCAAkC,CAAC;AA2B1C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,+BAA+B,GAChC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;IACxD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAs7BD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CAkF5E;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CA0F5E;AAwDD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CA2ClB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,EAAE,YAAY;IAEvB,WAAW,CACT,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,GACxB,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC;IAqC7E,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,gBAAgB;IAa7E,eAAe,CACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,GACxB,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC;CAY9E"}
|
|
@@ -38,6 +38,15 @@ function getRuntimeOpenAIProviderName(config) {
|
|
|
38
38
|
function getLLMOpenAIProviderName(config) {
|
|
39
39
|
return normalizeOpenAIProviderName(config.providerName) ?? "openai";
|
|
40
40
|
}
|
|
41
|
+
function getOpenAIModelTransport(config) {
|
|
42
|
+
const transport = config.openAITransport;
|
|
43
|
+
if (transport === undefined)
|
|
44
|
+
return "auto";
|
|
45
|
+
if (transport === "chat-completions" || transport === "responses") {
|
|
46
|
+
return transport;
|
|
47
|
+
}
|
|
48
|
+
throw new TypeError('OpenAI transport must be "chat-completions" or "responses"');
|
|
49
|
+
}
|
|
41
50
|
function getOpenAICompatibleProviderKind(config) {
|
|
42
51
|
const providerName = getRuntimeOpenAIProviderName(config).trim().toLowerCase();
|
|
43
52
|
return providerName === "mistral" || providerName === "moonshotai" ? providerName : "openai";
|
|
@@ -697,7 +706,7 @@ export function createOpenAIModelRuntime(config, modelId) {
|
|
|
697
706
|
doGenerate(options) {
|
|
698
707
|
const url = getOpenAIChatCompletionsUrl(config.baseURL);
|
|
699
708
|
const warnings = createWarningCollector();
|
|
700
|
-
const body = buildOpenAIChatRequest(modelId, providerName, options, false, warnings);
|
|
709
|
+
const body = buildOpenAIChatRequest(modelId, providerName, options, false, warnings, config.chatRequestCapabilities);
|
|
701
710
|
return requestJson({
|
|
702
711
|
url,
|
|
703
712
|
fetchImpl,
|
|
@@ -720,7 +729,7 @@ export function createOpenAIModelRuntime(config, modelId) {
|
|
|
720
729
|
async doStream(options) {
|
|
721
730
|
const url = getOpenAIChatCompletionsUrl(config.baseURL);
|
|
722
731
|
const warnings = createWarningCollector();
|
|
723
|
-
const body = buildOpenAIChatRequest(modelId, providerName, options, true, warnings);
|
|
732
|
+
const body = buildOpenAIChatRequest(modelId, providerName, options, true, warnings, config.chatRequestCapabilities);
|
|
724
733
|
const providerAbortScope = createOpenAIProviderAbortScope(options.abortSignal);
|
|
725
734
|
try {
|
|
726
735
|
const responseStream = await requestStream({
|
|
@@ -829,6 +838,24 @@ function requestUsesOpenAIHostedTool(optionsForRuntime) {
|
|
|
829
838
|
}
|
|
830
839
|
return resolveOpenAIWebSearchDescriptor(options.tools) !== undefined;
|
|
831
840
|
}
|
|
841
|
+
function createOpenAIChatCompletionsOnlyRuntime(chatRuntime) {
|
|
842
|
+
function assertHostedToolsSupported(options) {
|
|
843
|
+
if (requestUsesOpenAIHostedTool(options)) {
|
|
844
|
+
throw new TypeError("OpenAI hosted tools require the Responses API and are unavailable with Chat Completions");
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
return {
|
|
848
|
+
...chatRuntime,
|
|
849
|
+
async doGenerate(optionsForRuntime) {
|
|
850
|
+
assertHostedToolsSupported(optionsForRuntime);
|
|
851
|
+
return await chatRuntime.doGenerate(optionsForRuntime);
|
|
852
|
+
},
|
|
853
|
+
async doStream(optionsForRuntime) {
|
|
854
|
+
assertHostedToolsSupported(optionsForRuntime);
|
|
855
|
+
return await chatRuntime.doStream(optionsForRuntime);
|
|
856
|
+
},
|
|
857
|
+
};
|
|
858
|
+
}
|
|
832
859
|
function createOpenAIAdaptiveModelRuntime(chatRuntime, responsesRuntime) {
|
|
833
860
|
return {
|
|
834
861
|
...chatRuntime,
|
|
@@ -897,13 +924,24 @@ export class OpenAIProvider {
|
|
|
897
924
|
baseURL: config.baseURL,
|
|
898
925
|
name: providerLabel,
|
|
899
926
|
providerName,
|
|
927
|
+
chatRequestCapabilities: typeof config.openAIChatReasoningWithFunctionTools === "boolean"
|
|
928
|
+
? {
|
|
929
|
+
reasoningWithFunctionTools: config.openAIChatReasoningWithFunctionTools,
|
|
930
|
+
}
|
|
931
|
+
: undefined,
|
|
900
932
|
fetch: config.fetch,
|
|
901
933
|
};
|
|
902
934
|
const responsesRuntime = createOpenAIResponsesRuntime(runtimeConfig, modelId);
|
|
903
|
-
|
|
935
|
+
const chatRuntime = createOpenAIModelRuntime(runtimeConfig, modelId);
|
|
936
|
+
const transport = getOpenAIModelTransport(config);
|
|
937
|
+
if (transport === "responses" ||
|
|
938
|
+
(transport === "auto" && isOpenAIReasoningModel(modelId, providerName))) {
|
|
904
939
|
return responsesRuntime;
|
|
905
940
|
}
|
|
906
|
-
|
|
941
|
+
if (transport === "chat-completions") {
|
|
942
|
+
return createOpenAIChatCompletionsOnlyRuntime(chatRuntime);
|
|
943
|
+
}
|
|
944
|
+
return createOpenAIAdaptiveModelRuntime(chatRuntime, responsesRuntime);
|
|
907
945
|
}
|
|
908
946
|
createEmbedding(modelId, config) {
|
|
909
947
|
return createOpenAIEmbeddingRuntime({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veryfront/ext-llm-openai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1243",
|
|
4
4
|
"description": "Veryfront first-party extension package for ext-llm-openai",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"veryfront",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"capabilities": []
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"veryfront": "^0.1.
|
|
48
|
+
"veryfront": "^0.1.1243"
|
|
49
49
|
},
|
|
50
50
|
"type": "module",
|
|
51
51
|
"types": "./esm/extensions/ext-llm-openai/src/index.d.ts",
|