@caupulican/pi-ai 0.90.12 → 0.91.3
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/providers/amazon-bedrock.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.js +4 -4
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/dist/providers/openai-codex-responses.js +0 -6
- package/dist/providers/openai-codex-responses.js.map +1 -1
- package/dist/providers/openai-completions.d.ts.map +1 -1
- package/dist/providers/openai-completions.js +4 -4
- package/dist/providers/openai-completions.js.map +1 -1
- package/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/dist/providers/openai-responses-shared.js +351 -191
- package/dist/providers/openai-responses-shared.js.map +1 -1
- package/dist/providers/provider-runtime.d.ts +10 -1
- package/dist/providers/provider-runtime.d.ts.map +1 -1
- package/dist/providers/provider-runtime.js +22 -3
- package/dist/providers/provider-runtime.js.map +1 -1
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +28 -1
- package/dist/stream.js.map +1 -1
- package/dist/utils/event-stream.d.ts +8 -0
- package/dist/utils/event-stream.d.ts.map +1 -1
- package/dist/utils/event-stream.js +58 -3
- package/dist/utils/event-stream.js.map +1 -1
- package/dist/utils/tool-repair/registry.d.ts +18 -0
- package/dist/utils/tool-repair/registry.d.ts.map +1 -1
- package/dist/utils/tool-repair/registry.js +29 -0
- package/dist/utils/tool-repair/registry.js.map +1 -1
- package/package.json +2 -2
|
@@ -3,6 +3,7 @@ import { shortHash } from "../utils/hash.js";
|
|
|
3
3
|
import { parseStreamingJson } from "../utils/json-parse.js";
|
|
4
4
|
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
5
5
|
import { createToolNameMap } from "../utils/tool-names.js";
|
|
6
|
+
import { commitSuccessfulAssistantParse } from "./provider-runtime.js";
|
|
6
7
|
import { joinTextContent, transformMessages } from "./transform-messages.js";
|
|
7
8
|
// =============================================================================
|
|
8
9
|
// Utilities
|
|
@@ -279,6 +280,7 @@ export async function processResponsesStream(openaiStream, output, stream, model
|
|
|
279
280
|
let currentBlock = null;
|
|
280
281
|
let currentReasoningSummaryPartText = "";
|
|
281
282
|
let sawTerminalResponseEvent = false;
|
|
283
|
+
let committedSuccessfulTerminal = false;
|
|
282
284
|
const reasoningBlocksById = new Map();
|
|
283
285
|
const blocks = output.content;
|
|
284
286
|
const blockIndex = () => blocks.length - 1;
|
|
@@ -315,6 +317,196 @@ export async function processResponsesStream(openaiStream, output, stream, model
|
|
|
315
317
|
block.thinkingSignature = JSON.stringify({ ...storedItem, encrypted_content: item.encrypted_content });
|
|
316
318
|
}
|
|
317
319
|
};
|
|
320
|
+
const finalizedOutputItemKeys = new Set();
|
|
321
|
+
const functionCallBlocksByItemId = new Map();
|
|
322
|
+
const functionCallBlocksByCallId = new Map();
|
|
323
|
+
const outputItemKeys = (item) => {
|
|
324
|
+
if (item.type === "reasoning" || item.type === "message") {
|
|
325
|
+
return item.id ? [`${item.type}:${item.id}`] : [];
|
|
326
|
+
}
|
|
327
|
+
if (item.type === "function_call") {
|
|
328
|
+
const keys = [];
|
|
329
|
+
if (item.id)
|
|
330
|
+
keys.push(`function_call:id:${item.id}`);
|
|
331
|
+
if (item.call_id)
|
|
332
|
+
keys.push(`function_call:call:${item.call_id}`);
|
|
333
|
+
keys.push(`function_call:${item.call_id ?? ""}|${item.id ?? ""}`);
|
|
334
|
+
return keys;
|
|
335
|
+
}
|
|
336
|
+
return [];
|
|
337
|
+
};
|
|
338
|
+
const registerFunctionCallBlock = (item, block) => {
|
|
339
|
+
if (item.id)
|
|
340
|
+
functionCallBlocksByItemId.set(item.id, block);
|
|
341
|
+
if (item.call_id)
|
|
342
|
+
functionCallBlocksByCallId.set(item.call_id, block);
|
|
343
|
+
};
|
|
344
|
+
const findFunctionCallBlock = (item) => {
|
|
345
|
+
const id = `${item.call_id}|${item.id}`;
|
|
346
|
+
const byExactId = output.content.find((candidate) => candidate.type === "toolCall" && candidate.id === id);
|
|
347
|
+
if (byExactId)
|
|
348
|
+
return byExactId;
|
|
349
|
+
if (item.id) {
|
|
350
|
+
const byItemId = functionCallBlocksByItemId.get(item.id);
|
|
351
|
+
if (byItemId)
|
|
352
|
+
return byItemId;
|
|
353
|
+
}
|
|
354
|
+
if (item.call_id) {
|
|
355
|
+
const byCallId = functionCallBlocksByCallId.get(item.call_id);
|
|
356
|
+
if (byCallId)
|
|
357
|
+
return byCallId;
|
|
358
|
+
}
|
|
359
|
+
if (currentBlock?.type === "toolCall")
|
|
360
|
+
return currentBlock;
|
|
361
|
+
return undefined;
|
|
362
|
+
};
|
|
363
|
+
const contentIndexOf = (block) => output.content.indexOf(block);
|
|
364
|
+
const applyCompletedOutputItem = (item, emit) => {
|
|
365
|
+
const keys = outputItemKeys(item);
|
|
366
|
+
if (keys.some((key) => finalizedOutputItemKeys.has(key)))
|
|
367
|
+
return;
|
|
368
|
+
if (item.type === "reasoning") {
|
|
369
|
+
if (item.summary) {
|
|
370
|
+
item.summary = item.summary
|
|
371
|
+
.map((part) => ({ ...part, text: cleanReasoningSummaryText(part.text ?? "") }))
|
|
372
|
+
.filter((part) => part.text.trim().length > 0);
|
|
373
|
+
}
|
|
374
|
+
const summaryText = normalizeReasoningSummaryText(item.summary);
|
|
375
|
+
const contentText = item.content?.map((part) => part.text).join("\n\n") || "";
|
|
376
|
+
let block = item.id ? reasoningBlocksById.get(item.id) : undefined;
|
|
377
|
+
if (!block && currentBlock?.type === "thinking")
|
|
378
|
+
block = currentBlock;
|
|
379
|
+
const isNew = !block;
|
|
380
|
+
if (!block) {
|
|
381
|
+
block = { type: "thinking", thinking: "" };
|
|
382
|
+
output.content.push(block);
|
|
383
|
+
}
|
|
384
|
+
block.thinking = summaryText || contentText || block.thinking;
|
|
385
|
+
block.thinkingSignature = JSON.stringify(item);
|
|
386
|
+
if (item.id)
|
|
387
|
+
reasoningBlocksById.set(item.id, block);
|
|
388
|
+
if (emit) {
|
|
389
|
+
const contentIndex = contentIndexOf(block);
|
|
390
|
+
if (isNew) {
|
|
391
|
+
stream.push({ type: "thinking_start", contentIndex, partial: output });
|
|
392
|
+
}
|
|
393
|
+
stream.push({
|
|
394
|
+
type: "thinking_end",
|
|
395
|
+
contentIndex,
|
|
396
|
+
content: block.thinking,
|
|
397
|
+
partial: output,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
if (currentBlock === block)
|
|
401
|
+
currentBlock = null;
|
|
402
|
+
for (const key of keys)
|
|
403
|
+
finalizedOutputItemKeys.add(key);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (item.type === "message") {
|
|
407
|
+
const text = (item.content ?? [])
|
|
408
|
+
.map((part) => (part.type === "output_text" ? part.text : part.refusal))
|
|
409
|
+
.join("");
|
|
410
|
+
let block;
|
|
411
|
+
if (currentBlock?.type === "text") {
|
|
412
|
+
block = currentBlock;
|
|
413
|
+
}
|
|
414
|
+
else if (item.id) {
|
|
415
|
+
block = output.content.find((candidate) => candidate.type === "text" && parseTextSignature(candidate.textSignature)?.id === item.id);
|
|
416
|
+
}
|
|
417
|
+
// xAI/Grok emits message.added + deltas, then function_call items, then
|
|
418
|
+
// message.done / response.output. currentBlock has already moved to the
|
|
419
|
+
// tool; the live text block must be reused or the same sentence is stored
|
|
420
|
+
// twice (unsigned before tools, signed after).
|
|
421
|
+
if (!block) {
|
|
422
|
+
block = [...output.content]
|
|
423
|
+
.reverse()
|
|
424
|
+
.find((candidate) => candidate.type === "text" &&
|
|
425
|
+
!candidate.textSignature &&
|
|
426
|
+
(candidate.text === "" ||
|
|
427
|
+
text === "" ||
|
|
428
|
+
text.startsWith(candidate.text) ||
|
|
429
|
+
candidate.text.startsWith(text)));
|
|
430
|
+
}
|
|
431
|
+
const isNew = !block;
|
|
432
|
+
if (!block) {
|
|
433
|
+
block = { type: "text", text: "" };
|
|
434
|
+
output.content.push(block);
|
|
435
|
+
}
|
|
436
|
+
if (text.length > 0)
|
|
437
|
+
block.text = text;
|
|
438
|
+
if (item.id)
|
|
439
|
+
block.textSignature = encodeTextSignatureV1(item.id, item.phase ?? undefined);
|
|
440
|
+
if (emit) {
|
|
441
|
+
const contentIndex = contentIndexOf(block);
|
|
442
|
+
if (isNew) {
|
|
443
|
+
stream.push({ type: "text_start", contentIndex, partial: output });
|
|
444
|
+
}
|
|
445
|
+
stream.push({ type: "text_end", contentIndex, content: block.text, partial: output });
|
|
446
|
+
}
|
|
447
|
+
if (currentBlock === block)
|
|
448
|
+
currentBlock = null;
|
|
449
|
+
for (const key of keys)
|
|
450
|
+
finalizedOutputItemKeys.add(key);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const id = `${item.call_id}|${item.id}`;
|
|
454
|
+
let block = findFunctionCallBlock(item);
|
|
455
|
+
const isNew = !block;
|
|
456
|
+
if (!block) {
|
|
457
|
+
block = {
|
|
458
|
+
type: "toolCall",
|
|
459
|
+
id,
|
|
460
|
+
name: options?.toolNameMap?.toOriginalName(item.name) ?? item.name,
|
|
461
|
+
arguments: {},
|
|
462
|
+
};
|
|
463
|
+
output.content.push(block);
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
block.id = id;
|
|
467
|
+
block.name = options?.toolNameMap?.toOriginalName(item.name) ?? item.name;
|
|
468
|
+
}
|
|
469
|
+
block.arguments = parseStreamingJson(block.partialJson || item.arguments || "{}");
|
|
470
|
+
delete block.partialJson;
|
|
471
|
+
registerFunctionCallBlock(item, block);
|
|
472
|
+
if (emit) {
|
|
473
|
+
const contentIndex = contentIndexOf(block);
|
|
474
|
+
if (isNew) {
|
|
475
|
+
stream.push({ type: "toolcall_start", contentIndex, partial: output });
|
|
476
|
+
}
|
|
477
|
+
stream.push({ type: "toolcall_end", contentIndex, toolCall: block, partial: output });
|
|
478
|
+
}
|
|
479
|
+
if (currentBlock === block)
|
|
480
|
+
currentBlock = null;
|
|
481
|
+
for (const key of keys)
|
|
482
|
+
finalizedOutputItemKeys.add(key);
|
|
483
|
+
};
|
|
484
|
+
const applyResponseOutput = (responseOutput) => {
|
|
485
|
+
for (const item of responseOutput) {
|
|
486
|
+
if (item.type === "reasoning" || item.type === "message" || item.type === "function_call") {
|
|
487
|
+
applyCompletedOutputItem(item, true);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (!currentBlock)
|
|
491
|
+
return;
|
|
492
|
+
const contentIndex = blockIndex();
|
|
493
|
+
if (currentBlock.type === "text") {
|
|
494
|
+
stream.push({ type: "text_end", contentIndex, content: currentBlock.text, partial: output });
|
|
495
|
+
}
|
|
496
|
+
else if (currentBlock.type === "thinking") {
|
|
497
|
+
stream.push({
|
|
498
|
+
type: "thinking_end",
|
|
499
|
+
contentIndex,
|
|
500
|
+
content: currentBlock.thinking,
|
|
501
|
+
partial: output,
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
delete currentBlock.partialJson;
|
|
506
|
+
stream.push({ type: "toolcall_end", contentIndex, toolCall: currentBlock, partial: output });
|
|
507
|
+
}
|
|
508
|
+
currentBlock = null;
|
|
509
|
+
};
|
|
318
510
|
const finalizeResponse = (response) => {
|
|
319
511
|
sawTerminalResponseEvent = true;
|
|
320
512
|
backfillReasoningSignatures((response.output ?? []).filter((item) => item.type === "reasoning"));
|
|
@@ -362,235 +554,203 @@ export async function processResponsesStream(openaiStream, output, stream, model
|
|
|
362
554
|
: (response?.service_tier ?? options.serviceTier);
|
|
363
555
|
options.applyServiceTierPricing(output.usage, serviceTier);
|
|
364
556
|
}
|
|
557
|
+
applyResponseOutput(response.output ?? []);
|
|
365
558
|
// Map status to stop reason
|
|
366
559
|
output.stopReason = mapStopReason(response?.status);
|
|
367
560
|
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") {
|
|
368
561
|
output.stopReason = "toolUse";
|
|
369
562
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
output.responseId = event.response.id;
|
|
374
|
-
}
|
|
375
|
-
else if (event.type === "response.output_item.added") {
|
|
376
|
-
const item = event.item;
|
|
377
|
-
if (item.type === "reasoning") {
|
|
378
|
-
currentItem = item;
|
|
379
|
-
currentBlock = { type: "thinking", thinking: "" };
|
|
380
|
-
currentReasoningSummaryPartText = "";
|
|
381
|
-
output.content.push(currentBlock);
|
|
382
|
-
stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
|
|
383
|
-
}
|
|
384
|
-
else if (item.type === "message") {
|
|
385
|
-
currentItem = item;
|
|
386
|
-
currentBlock = { type: "text", text: "" };
|
|
387
|
-
output.content.push(currentBlock);
|
|
388
|
-
stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
|
|
389
|
-
}
|
|
390
|
-
else if (item.type === "function_call") {
|
|
391
|
-
currentItem = item;
|
|
392
|
-
currentBlock = {
|
|
393
|
-
type: "toolCall",
|
|
394
|
-
id: `${item.call_id}|${item.id}`,
|
|
395
|
-
name: options?.toolNameMap?.toOriginalName(item.name) ?? item.name,
|
|
396
|
-
arguments: {},
|
|
397
|
-
partialJson: item.arguments || "",
|
|
398
|
-
};
|
|
399
|
-
output.content.push(currentBlock);
|
|
400
|
-
stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
|
|
401
|
-
}
|
|
563
|
+
if (output.stopReason !== "error" && output.stopReason !== "aborted") {
|
|
564
|
+
committedSuccessfulTerminal = true;
|
|
565
|
+
commitSuccessfulAssistantParse(output);
|
|
402
566
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
567
|
+
};
|
|
568
|
+
try {
|
|
569
|
+
for await (const event of openaiStream) {
|
|
570
|
+
if (event.type === "response.created") {
|
|
571
|
+
output.responseId = event.response.id;
|
|
408
572
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
573
|
+
else if (event.type === "response.output_item.added") {
|
|
574
|
+
const item = event.item;
|
|
575
|
+
if (item.type === "reasoning") {
|
|
576
|
+
currentItem = item;
|
|
577
|
+
currentBlock = { type: "thinking", thinking: "" };
|
|
578
|
+
currentReasoningSummaryPartText = "";
|
|
579
|
+
output.content.push(currentBlock);
|
|
580
|
+
if (item.id)
|
|
581
|
+
reasoningBlocksById.set(item.id, currentBlock);
|
|
582
|
+
stream.push({ type: "thinking_start", contentIndex: blockIndex(), partial: output });
|
|
417
583
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
lastPart.text = partText;
|
|
584
|
+
else if (item.type === "message") {
|
|
585
|
+
currentItem = item;
|
|
586
|
+
currentBlock = { type: "text", text: "" };
|
|
587
|
+
if (item.id) {
|
|
588
|
+
currentBlock.textSignature = encodeTextSignatureV1(item.id, item.phase ?? undefined);
|
|
589
|
+
}
|
|
590
|
+
output.content.push(currentBlock);
|
|
591
|
+
stream.push({ type: "text_start", contentIndex: blockIndex(), partial: output });
|
|
427
592
|
}
|
|
428
|
-
if (
|
|
429
|
-
|
|
430
|
-
currentBlock
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
593
|
+
else if (item.type === "function_call") {
|
|
594
|
+
currentItem = item;
|
|
595
|
+
currentBlock = {
|
|
596
|
+
type: "toolCall",
|
|
597
|
+
id: `${item.call_id}|${item.id}`,
|
|
598
|
+
name: options?.toolNameMap?.toOriginalName(item.name) ?? item.name,
|
|
599
|
+
arguments: {},
|
|
600
|
+
partialJson: item.arguments || "",
|
|
601
|
+
};
|
|
602
|
+
output.content.push(currentBlock);
|
|
603
|
+
registerFunctionCallBlock(item, currentBlock);
|
|
604
|
+
stream.push({ type: "toolcall_start", contentIndex: blockIndex(), partial: output });
|
|
437
605
|
}
|
|
438
|
-
currentReasoningSummaryPartText = "";
|
|
439
606
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
contentIndex: blockIndex(),
|
|
447
|
-
delta: event.delta,
|
|
448
|
-
partial: output,
|
|
449
|
-
});
|
|
607
|
+
else if (event.type === "response.reasoning_summary_part.added") {
|
|
608
|
+
if (currentItem && currentItem.type === "reasoning") {
|
|
609
|
+
currentItem.summary = currentItem.summary || [];
|
|
610
|
+
currentItem.summary.push(event.part);
|
|
611
|
+
currentReasoningSummaryPartText = event.part.text ?? "";
|
|
612
|
+
}
|
|
450
613
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
614
|
+
else if (event.type === "response.reasoning_summary_text.delta") {
|
|
615
|
+
if (currentItem?.type === "reasoning") {
|
|
616
|
+
currentItem.summary = currentItem.summary || [];
|
|
617
|
+
const lastPart = currentItem.summary[currentItem.summary.length - 1];
|
|
618
|
+
if (lastPart) {
|
|
619
|
+
lastPart.text += event.delta;
|
|
620
|
+
currentReasoningSummaryPartText += event.delta;
|
|
621
|
+
}
|
|
458
622
|
}
|
|
459
623
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
624
|
+
else if (event.type === "response.reasoning_summary_part.done") {
|
|
625
|
+
if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
|
|
626
|
+
currentItem.summary = currentItem.summary || [];
|
|
627
|
+
const lastPart = currentItem.summary[currentItem.summary.length - 1];
|
|
628
|
+
const partText = cleanReasoningSummaryText(lastPart?.text ?? currentReasoningSummaryPartText);
|
|
629
|
+
if (lastPart) {
|
|
630
|
+
lastPart.text = partText;
|
|
631
|
+
}
|
|
632
|
+
if (partText.trim().length > 0) {
|
|
633
|
+
const delta = `${partText}\n\n`;
|
|
634
|
+
currentBlock.thinking += delta;
|
|
635
|
+
stream.push({
|
|
636
|
+
type: "thinking_delta",
|
|
637
|
+
contentIndex: blockIndex(),
|
|
638
|
+
delta,
|
|
639
|
+
partial: output,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
currentReasoningSummaryPartText = "";
|
|
473
643
|
}
|
|
474
644
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
const lastPart = ensureMessageRefusalPart();
|
|
479
|
-
if (lastPart) {
|
|
480
|
-
currentBlock.text += event.delta;
|
|
481
|
-
lastPart.refusal += event.delta;
|
|
645
|
+
else if (event.type === "response.reasoning_text.delta") {
|
|
646
|
+
if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
|
|
647
|
+
currentBlock.thinking += event.delta;
|
|
482
648
|
stream.push({
|
|
483
|
-
type: "
|
|
649
|
+
type: "thinking_delta",
|
|
484
650
|
contentIndex: blockIndex(),
|
|
485
651
|
delta: event.delta,
|
|
486
652
|
partial: output,
|
|
487
653
|
});
|
|
488
654
|
}
|
|
489
655
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
delta: event.delta,
|
|
499
|
-
partial: output,
|
|
500
|
-
});
|
|
656
|
+
else if (event.type === "response.content_part.added") {
|
|
657
|
+
if (currentItem?.type === "message") {
|
|
658
|
+
currentItem.content = currentItem.content || [];
|
|
659
|
+
// Filter out ReasoningText, only accept output_text and refusal
|
|
660
|
+
if (event.part.type === "output_text" || event.part.type === "refusal") {
|
|
661
|
+
currentItem.content.push(event.part);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
501
664
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
if (event.arguments.startsWith(previousPartialJson)) {
|
|
509
|
-
const delta = event.arguments.slice(previousPartialJson.length);
|
|
510
|
-
if (delta.length > 0) {
|
|
665
|
+
else if (event.type === "response.output_text.delta") {
|
|
666
|
+
if (currentItem?.type === "message" && currentBlock?.type === "text") {
|
|
667
|
+
const lastPart = ensureMessageOutputTextPart();
|
|
668
|
+
if (lastPart) {
|
|
669
|
+
currentBlock.text += event.delta;
|
|
670
|
+
lastPart.text += event.delta;
|
|
511
671
|
stream.push({
|
|
512
|
-
type: "
|
|
672
|
+
type: "text_delta",
|
|
513
673
|
contentIndex: blockIndex(),
|
|
514
|
-
delta,
|
|
674
|
+
delta: event.delta,
|
|
515
675
|
partial: output,
|
|
516
676
|
});
|
|
517
677
|
}
|
|
518
678
|
}
|
|
519
679
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
.
|
|
527
|
-
|
|
680
|
+
else if (event.type === "response.refusal.delta") {
|
|
681
|
+
if (currentItem?.type === "message" && currentBlock?.type === "text") {
|
|
682
|
+
const lastPart = ensureMessageRefusalPart();
|
|
683
|
+
if (lastPart) {
|
|
684
|
+
currentBlock.text += event.delta;
|
|
685
|
+
lastPart.refusal += event.delta;
|
|
686
|
+
stream.push({
|
|
687
|
+
type: "text_delta",
|
|
688
|
+
contentIndex: blockIndex(),
|
|
689
|
+
delta: event.delta,
|
|
690
|
+
partial: output,
|
|
691
|
+
});
|
|
692
|
+
}
|
|
528
693
|
}
|
|
529
|
-
const summaryText = normalizeReasoningSummaryText(item.summary);
|
|
530
|
-
const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
|
|
531
|
-
currentBlock.thinking = summaryText || contentText || currentBlock.thinking;
|
|
532
|
-
currentBlock.thinkingSignature = JSON.stringify(item);
|
|
533
|
-
reasoningBlocksById.set(item.id, currentBlock);
|
|
534
|
-
stream.push({
|
|
535
|
-
type: "thinking_end",
|
|
536
|
-
contentIndex: blockIndex(),
|
|
537
|
-
content: currentBlock.thinking,
|
|
538
|
-
partial: output,
|
|
539
|
-
});
|
|
540
|
-
currentBlock = null;
|
|
541
694
|
}
|
|
542
|
-
else if (
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
695
|
+
else if (event.type === "response.function_call_arguments.delta") {
|
|
696
|
+
if (currentItem?.type === "function_call" && currentBlock?.type === "toolCall") {
|
|
697
|
+
currentBlock.partialJson = (currentBlock.partialJson ?? "") + event.delta;
|
|
698
|
+
currentBlock.arguments = parseStreamingJson(currentBlock.partialJson);
|
|
699
|
+
stream.push({
|
|
700
|
+
type: "toolcall_delta",
|
|
701
|
+
contentIndex: blockIndex(),
|
|
702
|
+
delta: event.delta,
|
|
703
|
+
partial: output,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
552
706
|
}
|
|
553
|
-
else if (
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
707
|
+
else if (event.type === "response.function_call_arguments.done") {
|
|
708
|
+
if (currentItem?.type === "function_call" && currentBlock?.type === "toolCall") {
|
|
709
|
+
const previousPartialJson = currentBlock.partialJson;
|
|
710
|
+
currentBlock.partialJson = event.arguments;
|
|
711
|
+
currentBlock.arguments = parseStreamingJson(currentBlock.partialJson);
|
|
712
|
+
if (previousPartialJson !== undefined && event.arguments.startsWith(previousPartialJson)) {
|
|
713
|
+
const delta = event.arguments.slice(previousPartialJson.length);
|
|
714
|
+
if (delta.length > 0) {
|
|
715
|
+
stream.push({
|
|
716
|
+
type: "toolcall_delta",
|
|
717
|
+
contentIndex: blockIndex(),
|
|
718
|
+
delta,
|
|
719
|
+
partial: output,
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
564
723
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
arguments: args,
|
|
571
|
-
};
|
|
724
|
+
}
|
|
725
|
+
else if (event.type === "response.output_item.done") {
|
|
726
|
+
const item = event.item;
|
|
727
|
+
if (item.type === "reasoning" || item.type === "message" || item.type === "function_call") {
|
|
728
|
+
applyCompletedOutputItem(item, true);
|
|
572
729
|
}
|
|
573
|
-
|
|
574
|
-
|
|
730
|
+
}
|
|
731
|
+
else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
732
|
+
finalizeResponse(event.response);
|
|
733
|
+
}
|
|
734
|
+
else if (event.type === "error") {
|
|
735
|
+
throw new Error(`Error Code ${event.code}: ${event.message}` || "Unknown error");
|
|
736
|
+
}
|
|
737
|
+
else if (event.type === "response.failed") {
|
|
738
|
+
sawTerminalResponseEvent = true;
|
|
739
|
+
const error = event.response?.error;
|
|
740
|
+
const details = event.response?.incomplete_details;
|
|
741
|
+
const msg = error
|
|
742
|
+
? `${error.code || "unknown"}: ${error.message || "no message"}`
|
|
743
|
+
: details?.reason
|
|
744
|
+
? `incomplete: ${details.reason}`
|
|
745
|
+
: "Unknown error (no error details in response)";
|
|
746
|
+
throw new Error(msg);
|
|
575
747
|
}
|
|
576
748
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}
|
|
583
|
-
else if (event.type === "response.failed") {
|
|
584
|
-
sawTerminalResponseEvent = true;
|
|
585
|
-
const error = event.response?.error;
|
|
586
|
-
const details = event.response?.incomplete_details;
|
|
587
|
-
const msg = error
|
|
588
|
-
? `${error.code || "unknown"}: ${error.message || "no message"}`
|
|
589
|
-
: details?.reason
|
|
590
|
-
? `incomplete: ${details.reason}`
|
|
591
|
-
: "Unknown error (no error details in response)";
|
|
592
|
-
throw new Error(msg);
|
|
593
|
-
}
|
|
749
|
+
}
|
|
750
|
+
catch (error) {
|
|
751
|
+
if (committedSuccessfulTerminal)
|
|
752
|
+
return;
|
|
753
|
+
throw error;
|
|
594
754
|
}
|
|
595
755
|
if (!sawTerminalResponseEvent) {
|
|
596
756
|
throw new Error("OpenAI Responses stream ended before a terminal response event");
|