@veryfront/ext-llm-openai 0.1.1240 → 0.1.1242

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.
@@ -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,CA0UxB"}
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) {
@@ -219,11 +222,16 @@ export async function* streamOpenAICompatibleParts(stream, context = {}) {
219
222
  }
220
223
  delta = deltaRecord;
221
224
  }
222
- if (delta.role !== undefined &&
225
+ // Optional delta fields are `null` rather than absent on many
226
+ // OpenAI-compatible gateways (Moonshot/Kimi sends `reasoning_content: null`
227
+ // on both the opening and the finish chunk). Treat `null` as "not present
228
+ // on this chunk", matching how `content`, `refusal`, `tool_calls`, and
229
+ // `finish_reason` are already handled below.
230
+ if (delta.role !== undefined && delta.role !== null &&
223
231
  delta.role !== "assistant") {
224
232
  throw invalidOpenAIStream(context, "choice delta role was not assistant");
225
233
  }
226
- if (delta.reasoning_content !== undefined &&
234
+ if (delta.reasoning_content !== undefined && delta.reasoning_content !== null &&
227
235
  typeof delta.reasoning_content !== "string") {
228
236
  throw invalidOpenAIStream(context, "reasoning delta was malformed");
229
237
  }
@@ -272,11 +280,15 @@ export async function* streamOpenAICompatibleParts(stream, context = {}) {
272
280
  throw invalidOpenAIStream(context, "tool call index was malformed");
273
281
  }
274
282
  const toolCallIndex = index;
275
- if (toolCallRecord.id !== undefined &&
283
+ // As with the reasoning delta above, gateways repeat `id`, `type`, and
284
+ // `function.name` as `null` on continuation fragments instead of omitting
285
+ // them; only the opening fragment carries real values. Treat `null` as
286
+ // absent so the fragment merges into the call already being assembled.
287
+ if (toolCallRecord.id !== undefined && toolCallRecord.id !== null &&
276
288
  !isBoundedOpenAIStreamString(toolCallRecord.id, MAX_OPENAI_STREAM_IDENTIFIER_BYTES)) {
277
289
  throw invalidOpenAIStream(context, "tool call id was malformed");
278
290
  }
279
- if (toolCallRecord.type !== undefined &&
291
+ if (toolCallRecord.type !== undefined && toolCallRecord.type !== null &&
280
292
  toolCallRecord.type !== "function") {
281
293
  throw invalidOpenAIStream(context, "tool call type was not function");
282
294
  }
@@ -306,7 +318,7 @@ export async function* streamOpenAICompatibleParts(stream, context = {}) {
306
318
  if (!fn) {
307
319
  throw invalidOpenAIStream(context, "tool call function was not an object");
308
320
  }
309
- if (fn.name !== undefined &&
321
+ if (fn.name !== undefined && fn.name !== null &&
310
322
  !isBoundedOpenAIStreamString(fn.name, MAX_OPENAI_STREAM_TOOL_NAME_BYTES)) {
311
323
  throw invalidOpenAIStream(context, "tool call function name was malformed");
312
324
  }
@@ -324,7 +336,8 @@ export async function* streamOpenAICompatibleParts(stream, context = {}) {
324
336
  toolName: current.name,
325
337
  };
326
338
  }
327
- if (fn.arguments !== undefined && typeof fn.arguments !== "string") {
339
+ if (fn.arguments !== undefined && fn.arguments !== null &&
340
+ typeof fn.arguments !== "string") {
328
341
  throw invalidOpenAIStream(context, "tool call arguments delta was malformed");
329
342
  }
330
343
  if (typeof fn.arguments === "string") {
@@ -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;AA26BD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CAgF5E;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CA0F5E;AAgCD,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;IAwB7E,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"}
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;AAs7BD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CAgF5E;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;IAgC7E,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";
@@ -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,
@@ -900,10 +927,16 @@ export class OpenAIProvider {
900
927
  fetch: config.fetch,
901
928
  };
902
929
  const responsesRuntime = createOpenAIResponsesRuntime(runtimeConfig, modelId);
903
- if (isOpenAIReasoningModel(modelId, providerName)) {
930
+ const chatRuntime = createOpenAIModelRuntime(runtimeConfig, modelId);
931
+ const transport = getOpenAIModelTransport(config);
932
+ if (transport === "responses" ||
933
+ (transport === "auto" && isOpenAIReasoningModel(modelId, providerName))) {
904
934
  return responsesRuntime;
905
935
  }
906
- return createOpenAIAdaptiveModelRuntime(createOpenAIModelRuntime(runtimeConfig, modelId), responsesRuntime);
936
+ if (transport === "chat-completions") {
937
+ return createOpenAIChatCompletionsOnlyRuntime(chatRuntime);
938
+ }
939
+ return createOpenAIAdaptiveModelRuntime(chatRuntime, responsesRuntime);
907
940
  }
908
941
  createEmbedding(modelId, config) {
909
942
  return createOpenAIEmbeddingRuntime({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veryfront/ext-llm-openai",
3
- "version": "0.1.1240",
3
+ "version": "0.1.1242",
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.1240"
48
+ "veryfront": "^0.1.1242"
49
49
  },
50
50
  "type": "module",
51
51
  "types": "./esm/extensions/ext-llm-openai/src/index.d.ts",