@code-yeongyu/senpi-ai 2026.7.28 → 2026.7.29-4
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/dist/api/openai-client-auth.d.ts +7 -0
- package/dist/api/openai-client-auth.d.ts.map +1 -0
- package/dist/api/openai-client-auth.js +15 -0
- package/dist/api/openai-client-auth.js.map +1 -0
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +125 -58
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +9 -22
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/auth/headers.d.ts +5 -0
- package/dist/auth/headers.d.ts.map +1 -0
- package/dist/auth/headers.js +41 -0
- package/dist/auth/headers.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/tool-call-middleware/context-transformer.d.ts.map +1 -1
- package/dist/tool-call-middleware/context-transformer.js +9 -0
- package/dist/tool-call-middleware/context-transformer.js.map +1 -1
- package/dist/tool-call-middleware/index.d.ts +5 -0
- package/dist/tool-call-middleware/index.d.ts.map +1 -1
- package/dist/tool-call-middleware/index.js +12 -2
- package/dist/tool-call-middleware/index.js.map +1 -1
- package/dist/tool-call-middleware/protocols/kimi-xtml/format.d.ts +5 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/format.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/format.js +54 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/format.js.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/index.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/index.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/index.js +4 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/index.js.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/markers.d.ts +10 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/markers.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/markers.js +30 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/markers.js.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/parse.d.ts +12 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/parse.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/parse.js +95 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/parse.js.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.d.ts +5 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js +207 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/recovery-stream.js.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/stream.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/stream.js +181 -0
- package/dist/tool-call-middleware/protocols/kimi-xtml/stream.js.map +1 -0
- package/dist/tool-call-middleware/recovery-diagnostics.d.ts +2 -1
- package/dist/tool-call-middleware/recovery-diagnostics.d.ts.map +1 -1
- package/dist/tool-call-middleware/recovery-diagnostics.js +2 -2
- package/dist/tool-call-middleware/recovery-diagnostics.js.map +1 -1
- package/dist/tool-call-middleware/recovery-native-projection.d.ts +3 -2
- package/dist/tool-call-middleware/recovery-native-projection.d.ts.map +1 -1
- package/dist/tool-call-middleware/recovery-native-projection.js +3 -2
- package/dist/tool-call-middleware/recovery-native-projection.js.map +1 -1
- package/dist/tool-call-middleware/recovery-stream-failure.d.ts +6 -1
- package/dist/tool-call-middleware/recovery-stream-failure.d.ts.map +1 -1
- package/dist/tool-call-middleware/recovery-stream-failure.js +3 -2
- package/dist/tool-call-middleware/recovery-stream-failure.js.map +1 -1
- package/dist/tool-call-middleware/recovery-stream-wrapper.d.ts +7 -1
- package/dist/tool-call-middleware/recovery-stream-wrapper.d.ts.map +1 -1
- package/dist/tool-call-middleware/recovery-stream-wrapper.js +12 -5
- package/dist/tool-call-middleware/recovery-stream-wrapper.js.map +1 -1
- package/dist/tool-call-middleware/recovery-text-projection.d.ts +7 -1
- package/dist/tool-call-middleware/recovery-text-projection.d.ts.map +1 -1
- package/dist/tool-call-middleware/recovery-text-projection.js +6 -4
- package/dist/tool-call-middleware/recovery-text-projection.js.map +1 -1
- package/dist/tool-call-middleware/types.d.ts +2 -1
- package/dist/tool-call-middleware/types.d.ts.map +1 -1
- package/dist/tool-call-middleware/types.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/retry.d.ts +7 -0
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +29 -0
- package/dist/utils/retry.js.map +1 -1
- package/package.json +14 -14
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ProviderHeaders } from "../types.ts";
|
|
2
|
+
export interface OpenAIClientAuth {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
headers?: ProviderHeaders;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveOpenAIClientAuth(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): OpenAIClientAuth;
|
|
7
|
+
//# sourceMappingURL=openai-client-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-client-auth.d.ts","sourceRoot":"","sources":["../../src/api/openai-client-auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,eAAe,GAAG,SAAS,GAClC,gBAAgB,CAUlB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { hasCredentialHeaders, hasHeader } from "../auth/headers.js";
|
|
2
|
+
export function resolveOpenAIClientAuth(provider, apiKey, headers) {
|
|
3
|
+
if (apiKey)
|
|
4
|
+
return { apiKey, headers };
|
|
5
|
+
if (!hasCredentialHeaders(headers))
|
|
6
|
+
throw new Error(`No API key for provider: ${provider}`);
|
|
7
|
+
if (hasHeader(headers, "authorization") || hasHeader(headers, "cf-aig-authorization")) {
|
|
8
|
+
return { apiKey: "unused", headers };
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
apiKey: "unused",
|
|
12
|
+
headers: { Authorization: null, ...headers },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=openai-client-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-client-auth.js","sourceRoot":"","sources":["../../src/api/openai-client-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQrE,MAAM,UAAU,uBAAuB,CACtC,QAAgB,EAChB,MAA0B,EAC1B,OAAoC;IAEpC,IAAI,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACvC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IAC5F,IAAI,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,CAAC;QACvF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACtC,CAAC;IACD,OAAO;QACN,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE;KAC5C,CAAC;AACH,CAAC","sourcesContent":["import { hasCredentialHeaders, hasHeader } from \"../auth/headers.ts\";\nimport type { ProviderHeaders } from \"../types.ts\";\n\nexport interface OpenAIClientAuth {\n\tapiKey: string;\n\theaders?: ProviderHeaders;\n}\n\nexport function resolveOpenAIClientAuth(\n\tprovider: string,\n\tapiKey: string | undefined,\n\theaders: ProviderHeaders | undefined,\n): OpenAIClientAuth {\n\tif (apiKey) return { apiKey, headers };\n\tif (!hasCredentialHeaders(headers)) throw new Error(`No API key for provider: ${provider}`);\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) {\n\t\treturn { apiKey: \"unused\", headers };\n\t}\n\treturn {\n\t\tapiKey: \"unused\",\n\t\theaders: { Authorization: null, ...headers },\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-completions.d.ts","sourceRoot":"","sources":["../../src/api/openai-completions.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAOX,0BAA0B,EAI1B,MAAM,sCAAsC,CAAC;AAG9C,OAAO,KAAK,EAIX,OAAO,EAGP,KAAK,EAIL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AAMrB,OAAO,EAEN,KAAK,+BAA+B,EACpC,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-completions.d.ts","sourceRoot":"","sources":["../../src/api/openai-completions.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAOX,0BAA0B,EAI1B,MAAM,sCAAsC,CAAC;AAG9C,OAAO,KAAK,EAIX,OAAO,EAGP,KAAK,EAIL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AAMrB,OAAO,EAEN,KAAK,+BAA+B,EACpC,MAAM,8BAA8B,CAAC;AA4BtC,OAAO,EACN,0BAA0B,IAAI,SAAS,EACvC,KAAK,+BAA+B,GACpC,MAAM,8BAA8B,CAAC;AA4MtC,MAAM,WAAW,wBAAyB,SAAQ,aAAa;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,8BAA8B,CAAC;IACpE,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;CAC1E;AAED,MAAM,WAAW,iCAAiC;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0BAA0B,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAwCD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,wBAAwB,CA0fjF,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CAyBlF,CAAC;AA8XF,wBAAgB,eAAe,CAC9B,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,EAClC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,+BAA+B,EACvC,OAAO,GAAE,iCAAsC,GAC7C,0BAA0B,EAAE,CAgS9B"}
|
|
@@ -13,6 +13,7 @@ import { isForcedToolChoiceUnsupportedError, omitToolChoiceParam } from "../util
|
|
|
13
13
|
import { normalizeToolParametersForMoonshot, normalizeToolParametersForOpenAICompat, } from "../utils/tool-schema-compat.js";
|
|
14
14
|
import { appendGrammarToolInputJsonDelta, createGrammarToolInputProperties, getGrammarToolInput, resolveGrammarConstrainedSampling, resolveJsonSchemaStrictSampling, } from "./constrained-sampling.js";
|
|
15
15
|
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
16
|
+
import { resolveOpenAIClientAuth } from "./openai-client-auth.js";
|
|
16
17
|
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
|
|
17
18
|
import { applyExtraBody, buildBaseOptions, clampMaxForOpenAI, OPENAI_COMPLETIONS_RESERVED_BODY_KEYS, } from "./simple-options.js";
|
|
18
19
|
import { transformMessages } from "./transform-messages.js";
|
|
@@ -103,23 +104,6 @@ function resolveReasoningEffort(thinkingLevelMap, effort) {
|
|
|
103
104
|
* This is needed because Anthropic (via proxy) requires the tools param
|
|
104
105
|
* to be present when messages include tool_calls or tool role messages.
|
|
105
106
|
*/
|
|
106
|
-
function hasHeader(headers, name) {
|
|
107
|
-
if (!headers)
|
|
108
|
-
return false;
|
|
109
|
-
const expected = name.toLowerCase();
|
|
110
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
111
|
-
if (key.toLowerCase() === expected && value !== null && value.trim().length > 0)
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
function getClientApiKey(provider, apiKey, headers) {
|
|
117
|
-
if (apiKey)
|
|
118
|
-
return apiKey;
|
|
119
|
-
if (hasHeader(headers, "authorization") || hasHeader(headers, "cf-aig-authorization"))
|
|
120
|
-
return "unused";
|
|
121
|
-
throw new Error(`No API key for provider: ${provider}`);
|
|
122
|
-
}
|
|
123
107
|
function hasToolHistory(messages) {
|
|
124
108
|
for (const msg of messages) {
|
|
125
109
|
if (msg.role === "toolResult") {
|
|
@@ -217,12 +201,12 @@ export const stream = (model, context, options) => {
|
|
|
217
201
|
timestamp: Date.now(),
|
|
218
202
|
};
|
|
219
203
|
try {
|
|
220
|
-
const
|
|
204
|
+
const clientAuth = resolveOpenAIClientAuth(model.provider, options?.apiKey, options?.headers);
|
|
221
205
|
const compat = getCompat(model);
|
|
222
206
|
const grammarToolInputProperties = createGrammarToolInputProperties(context.tools, compat.supportsOpenAIGrammarTools);
|
|
223
207
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention ?? model.cacheRetention, options?.env);
|
|
224
208
|
const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
|
|
225
|
-
const client = createClient(model, context, apiKey,
|
|
209
|
+
const client = createClient(model, context, clientAuth.apiKey, clientAuth.headers, cacheSessionId, compat);
|
|
226
210
|
let params = buildParams(model, context, options, compat, cacheRetention, grammarToolInputProperties);
|
|
227
211
|
const nextParams = await options?.onPayload?.(params, model);
|
|
228
212
|
if (nextParams !== undefined) {
|
|
@@ -256,7 +240,12 @@ export const stream = (model, context, options) => {
|
|
|
256
240
|
stream.push({ type: "start", partial: output });
|
|
257
241
|
let textBlock = null;
|
|
258
242
|
let thinkingBlock = null;
|
|
243
|
+
let activeBlock = null;
|
|
244
|
+
let deferMixedEvents = false;
|
|
259
245
|
let hasFinishReason = false;
|
|
246
|
+
const deferredTextDeltas = [];
|
|
247
|
+
const deferredThinkingDeltas = [];
|
|
248
|
+
const deferredToolCallDeltas = new Map();
|
|
260
249
|
const toolCallBlocksByIndex = new Map();
|
|
261
250
|
const toolCallBlocksById = new Map();
|
|
262
251
|
const pendingReasoningDetailsByToolCallId = new Map();
|
|
@@ -326,23 +315,47 @@ export const stream = (model, context, options) => {
|
|
|
326
315
|
});
|
|
327
316
|
}
|
|
328
317
|
};
|
|
318
|
+
const finishActiveBlock = () => {
|
|
319
|
+
if (!activeBlock)
|
|
320
|
+
return;
|
|
321
|
+
finishBlock(activeBlock);
|
|
322
|
+
activeBlock = null;
|
|
323
|
+
};
|
|
329
324
|
const ensureTextBlock = () => {
|
|
330
325
|
if (!textBlock) {
|
|
326
|
+
if (!deferMixedEvents) {
|
|
327
|
+
finishActiveBlock();
|
|
328
|
+
thinkingBlock = null;
|
|
329
|
+
}
|
|
331
330
|
textBlock = { type: "text", text: "" };
|
|
332
331
|
blocks.push(textBlock);
|
|
333
|
-
|
|
332
|
+
if (!deferMixedEvents) {
|
|
333
|
+
activeBlock = textBlock;
|
|
334
|
+
stream.push({ type: "text_start", contentIndex: getContentIndex(textBlock), partial: output });
|
|
335
|
+
}
|
|
334
336
|
}
|
|
335
337
|
return textBlock;
|
|
336
338
|
};
|
|
337
339
|
const ensureThinkingBlock = (thinkingSignature) => {
|
|
338
340
|
if (!thinkingBlock) {
|
|
341
|
+
if (!deferMixedEvents) {
|
|
342
|
+
finishActiveBlock();
|
|
343
|
+
textBlock = null;
|
|
344
|
+
}
|
|
339
345
|
thinkingBlock = {
|
|
340
346
|
type: "thinking",
|
|
341
347
|
thinking: "",
|
|
342
348
|
thinkingSignature,
|
|
343
349
|
};
|
|
344
350
|
blocks.push(thinkingBlock);
|
|
345
|
-
|
|
351
|
+
if (!deferMixedEvents) {
|
|
352
|
+
activeBlock = thinkingBlock;
|
|
353
|
+
stream.push({
|
|
354
|
+
type: "thinking_start",
|
|
355
|
+
contentIndex: getContentIndex(thinkingBlock),
|
|
356
|
+
partial: output,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
346
359
|
}
|
|
347
360
|
return thinkingBlock;
|
|
348
361
|
};
|
|
@@ -364,6 +377,11 @@ export const stream = (model, context, options) => {
|
|
|
364
377
|
block = toolCallBlocksById.get(toolCall.id);
|
|
365
378
|
}
|
|
366
379
|
if (!block) {
|
|
380
|
+
if (!deferMixedEvents) {
|
|
381
|
+
finishActiveBlock();
|
|
382
|
+
textBlock = null;
|
|
383
|
+
thinkingBlock = null;
|
|
384
|
+
}
|
|
367
385
|
// Note: the "input" fallback here should/must not be taken. in case the LLM makes up
|
|
368
386
|
// a tool we don't knwo about, we at least have a place to stash our stuff.
|
|
369
387
|
const customInputProperty = toolCall.custom
|
|
@@ -388,11 +406,14 @@ export const stream = (model, context, options) => {
|
|
|
388
406
|
toolCallBlocksById.set(toolCall.id, block);
|
|
389
407
|
}
|
|
390
408
|
blocks.push(block);
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
409
|
+
if (!deferMixedEvents) {
|
|
410
|
+
activeBlock = block;
|
|
411
|
+
stream.push({
|
|
412
|
+
type: "toolcall_start",
|
|
413
|
+
contentIndex: getContentIndex(block),
|
|
414
|
+
partial: output,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
396
417
|
}
|
|
397
418
|
if (streamIndex !== undefined && block.streamIndex === undefined) {
|
|
398
419
|
block.streamIndex = streamIndex;
|
|
@@ -416,6 +437,30 @@ export const stream = (model, context, options) => {
|
|
|
416
437
|
applyPendingReasoningDetail(block);
|
|
417
438
|
return block;
|
|
418
439
|
};
|
|
440
|
+
const flushDeferredBlocks = () => {
|
|
441
|
+
for (const block of blocks) {
|
|
442
|
+
const contentIndex = getContentIndex(block);
|
|
443
|
+
if (block.type === "text") {
|
|
444
|
+
stream.push({ type: "text_start", contentIndex, partial: output });
|
|
445
|
+
for (const delta of deferredTextDeltas) {
|
|
446
|
+
stream.push({ type: "text_delta", contentIndex, delta, partial: output });
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
else if (block.type === "thinking") {
|
|
450
|
+
stream.push({ type: "thinking_start", contentIndex, partial: output });
|
|
451
|
+
for (const delta of deferredThinkingDeltas) {
|
|
452
|
+
stream.push({ type: "thinking_delta", contentIndex, delta, partial: output });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
stream.push({ type: "toolcall_start", contentIndex, partial: output });
|
|
457
|
+
for (const delta of deferredToolCallDeltas.get(block) ?? []) {
|
|
458
|
+
stream.push({ type: "toolcall_delta", contentIndex, delta, partial: output });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
finishBlock(block);
|
|
462
|
+
}
|
|
463
|
+
};
|
|
419
464
|
for await (const chunk of openaiStream) {
|
|
420
465
|
if (!chunk || typeof chunk !== "object")
|
|
421
466
|
continue;
|
|
@@ -446,22 +491,9 @@ export const stream = (model, context, options) => {
|
|
|
446
491
|
hasFinishReason = true;
|
|
447
492
|
}
|
|
448
493
|
if (choice.delta) {
|
|
449
|
-
|
|
450
|
-
choice.delta.content
|
|
451
|
-
|
|
452
|
-
const block = ensureTextBlock();
|
|
453
|
-
block.text += choice.delta.content;
|
|
454
|
-
stream.push({
|
|
455
|
-
type: "text_delta",
|
|
456
|
-
contentIndex: getContentIndex(block),
|
|
457
|
-
delta: choice.delta.content,
|
|
458
|
-
partial: output,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
// Some endpoints return reasoning in reasoning_content (llama.cpp),
|
|
462
|
-
// or reasoning (other openai compatible endpoints)
|
|
463
|
-
// Use the first non-empty reasoning field to avoid duplication
|
|
464
|
-
// (e.g., chutes.ai returns both reasoning_content and reasoning with same content)
|
|
494
|
+
const contentDelta = typeof choice.delta.content === "string" && choice.delta.content.length > 0
|
|
495
|
+
? choice.delta.content
|
|
496
|
+
: null;
|
|
465
497
|
const reasoningFields = ["reasoning_content", "reasoning", "reasoning_text"];
|
|
466
498
|
const deltaFields = choice.delta;
|
|
467
499
|
let foundReasoningField = null;
|
|
@@ -472,6 +504,28 @@ export const stream = (model, context, options) => {
|
|
|
472
504
|
break;
|
|
473
505
|
}
|
|
474
506
|
}
|
|
507
|
+
if (blocks.length === 0 && contentDelta && foundReasoningField) {
|
|
508
|
+
deferMixedEvents = true;
|
|
509
|
+
}
|
|
510
|
+
if (contentDelta) {
|
|
511
|
+
const block = ensureTextBlock();
|
|
512
|
+
block.text += contentDelta;
|
|
513
|
+
if (deferMixedEvents) {
|
|
514
|
+
deferredTextDeltas.push(contentDelta);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
stream.push({
|
|
518
|
+
type: "text_delta",
|
|
519
|
+
contentIndex: getContentIndex(block),
|
|
520
|
+
delta: contentDelta,
|
|
521
|
+
partial: output,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// Some endpoints return reasoning in reasoning_content (llama.cpp),
|
|
526
|
+
// or reasoning (other openai compatible endpoints)
|
|
527
|
+
// Use the first non-empty reasoning field to avoid duplication
|
|
528
|
+
// (e.g., chutes.ai returns both reasoning_content and reasoning with same content)
|
|
475
529
|
if (foundReasoningField) {
|
|
476
530
|
const delta = deltaFields[foundReasoningField];
|
|
477
531
|
if (typeof delta === "string" && delta.length > 0) {
|
|
@@ -480,12 +534,17 @@ export const stream = (model, context, options) => {
|
|
|
480
534
|
: foundReasoningField;
|
|
481
535
|
const block = ensureThinkingBlock(thinkingSignature);
|
|
482
536
|
block.thinking += delta;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
537
|
+
if (deferMixedEvents) {
|
|
538
|
+
deferredThinkingDeltas.push(delta);
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
stream.push({
|
|
542
|
+
type: "thinking_delta",
|
|
543
|
+
contentIndex: getContentIndex(block),
|
|
544
|
+
delta,
|
|
545
|
+
partial: output,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
489
548
|
}
|
|
490
549
|
}
|
|
491
550
|
if (choice?.delta?.tool_calls) {
|
|
@@ -509,12 +568,19 @@ export const stream = (model, context, options) => {
|
|
|
509
568
|
const nextInput = getCustomToolCallInput(block) + toolCall.custom.input;
|
|
510
569
|
delta = appendCustomToolCallInput(block, nextInput, false) ?? "";
|
|
511
570
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
571
|
+
if (deferMixedEvents) {
|
|
572
|
+
const deltas = deferredToolCallDeltas.get(block) ?? [];
|
|
573
|
+
deltas.push(delta);
|
|
574
|
+
deferredToolCallDeltas.set(block, deltas);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
stream.push({
|
|
578
|
+
type: "toolcall_delta",
|
|
579
|
+
contentIndex: getContentIndex(block),
|
|
580
|
+
delta,
|
|
581
|
+
partial: output,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
518
584
|
}
|
|
519
585
|
}
|
|
520
586
|
const reasoningDetails = choice.delta.reasoning_details;
|
|
@@ -534,9 +600,10 @@ export const stream = (model, context, options) => {
|
|
|
534
600
|
}
|
|
535
601
|
}
|
|
536
602
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
603
|
+
if (deferMixedEvents)
|
|
604
|
+
flushDeferredBlocks();
|
|
605
|
+
else
|
|
606
|
+
finishActiveBlock();
|
|
540
607
|
if (options?.signal?.aborted) {
|
|
541
608
|
throw new Error("Request was aborted");
|
|
542
609
|
}
|
|
@@ -577,7 +644,7 @@ export const stream = (model, context, options) => {
|
|
|
577
644
|
return stream;
|
|
578
645
|
};
|
|
579
646
|
export const streamSimple = (model, context, options) => {
|
|
580
|
-
|
|
647
|
+
resolveOpenAIClientAuth(model.provider, options?.apiKey, options?.headers);
|
|
581
648
|
const base = buildBaseOptions(model, context, options, options?.apiKey);
|
|
582
649
|
const compat = getCompat(model);
|
|
583
650
|
const thinkingLevelMap = getThinkingLevelMap(model, compat);
|