@librechat/agents 3.3.9 → 3.3.11

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.
Files changed (61) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +4 -0
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +21 -2
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/langfuseToolOutputTracing.cjs +228 -16
  6. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  7. package/dist/cjs/llm/init.cjs +1 -1
  8. package/dist/cjs/llm/invoke.cjs +14 -7
  9. package/dist/cjs/llm/invoke.cjs.map +1 -1
  10. package/dist/cjs/llm/openai/index.cjs +188 -11
  11. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  12. package/dist/cjs/main.cjs +4 -3
  13. package/dist/cjs/messages/core.cjs +592 -27
  14. package/dist/cjs/messages/core.cjs.map +1 -1
  15. package/dist/cjs/run.cjs +11 -1
  16. package/dist/cjs/run.cjs.map +1 -1
  17. package/dist/cjs/stream.cjs +2 -2
  18. package/dist/cjs/tools/ToolNode.cjs +1 -1
  19. package/dist/cjs/tools/search/tool.cjs +1 -1
  20. package/dist/cjs/utils/index.cjs +1 -1
  21. package/dist/esm/agents/AgentContext.mjs +4 -0
  22. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  23. package/dist/esm/graphs/Graph.mjs +21 -2
  24. package/dist/esm/graphs/Graph.mjs.map +1 -1
  25. package/dist/esm/langfuseToolOutputTracing.mjs +228 -16
  26. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  27. package/dist/esm/llm/init.mjs +1 -1
  28. package/dist/esm/llm/invoke.mjs +14 -7
  29. package/dist/esm/llm/invoke.mjs.map +1 -1
  30. package/dist/esm/llm/openai/index.mjs +190 -13
  31. package/dist/esm/llm/openai/index.mjs.map +1 -1
  32. package/dist/esm/main.mjs +5 -5
  33. package/dist/esm/messages/core.mjs +592 -28
  34. package/dist/esm/messages/core.mjs.map +1 -1
  35. package/dist/esm/run.mjs +11 -1
  36. package/dist/esm/run.mjs.map +1 -1
  37. package/dist/esm/stream.mjs +2 -2
  38. package/dist/esm/tools/ToolNode.mjs +1 -1
  39. package/dist/esm/tools/search/tool.mjs +1 -1
  40. package/dist/esm/utils/index.mjs +1 -1
  41. package/dist/types/agents/AgentContext.d.ts +2 -0
  42. package/dist/types/graphs/Graph.d.ts +5 -0
  43. package/dist/types/langfuseToolOutputTracing.d.ts +1 -0
  44. package/dist/types/llm/invoke.d.ts +1 -1
  45. package/dist/types/messages/core.d.ts +11 -6
  46. package/dist/types/run.d.ts +7 -0
  47. package/package.json +1 -1
  48. package/src/agents/AgentContext.ts +5 -0
  49. package/src/graphs/Graph.ts +39 -0
  50. package/src/langfuseToolOutputTracing.ts +410 -14
  51. package/src/llm/custom-chat-models.smoke.test.ts +747 -0
  52. package/src/llm/invoke.test.ts +98 -0
  53. package/src/llm/invoke.ts +34 -23
  54. package/src/llm/openai/index.ts +334 -25
  55. package/src/llm/openai/llm.spec.ts +107 -6
  56. package/src/messages/core.ts +1290 -42
  57. package/src/messages/formatAgentMessages.test.ts +2623 -0
  58. package/src/run.ts +15 -0
  59. package/src/specs/discovered-tools.test.ts +217 -0
  60. package/src/specs/langfuse-tool-output-tracing.test.ts +887 -0
  61. package/src/specs/preemptSeal.test.ts +374 -5
@@ -310,38 +310,593 @@ function cloneAIMessageWithContent(message, content) {
310
310
  ...lcKwargs,
311
311
  value: {
312
312
  ...lcKwargs.value,
313
- content
313
+ ...message.response_metadata.output_version === "v1" ? {
314
+ content: void 0,
315
+ contentBlocks: content
316
+ } : { content }
314
317
  }
315
318
  };
316
319
  return Object.create(Object.getPrototypeOf(message), descriptors);
317
320
  }
321
+ function cloneAIMessageWithResponsesReplayState(message, content, id, additionalKwargs, responseMetadata) {
322
+ const descriptors = Object.getOwnPropertyDescriptors(message);
323
+ const replacements = {
324
+ content,
325
+ id,
326
+ additional_kwargs: additionalKwargs,
327
+ response_metadata: responseMetadata
328
+ };
329
+ for (const [key, value] of Object.entries(replacements)) {
330
+ const descriptor = descriptors[key];
331
+ descriptors[key] = {
332
+ configurable: descriptor?.configurable ?? true,
333
+ enumerable: descriptor?.enumerable ?? true,
334
+ value,
335
+ writable: descriptor?.writable ?? true
336
+ };
337
+ }
338
+ const lcKwargs = descriptors.lc_kwargs;
339
+ if (lcKwargs != null && "value" in lcKwargs && typeof lcKwargs.value === "object" && lcKwargs.value != null) descriptors.lc_kwargs = {
340
+ ...lcKwargs,
341
+ value: {
342
+ ...lcKwargs.value,
343
+ ...replacements,
344
+ ...responseMetadata.output_version === "v1" ? {
345
+ content: void 0,
346
+ contentBlocks: content
347
+ } : {}
348
+ }
349
+ };
350
+ return Object.create(Object.getPrototypeOf(message), descriptors);
351
+ }
352
+ function hasReplayableEncryptedReasoning(reasoning) {
353
+ if (reasoning == null || typeof reasoning !== "object") return false;
354
+ const item = reasoning;
355
+ return item.type === "reasoning" && typeof item.id === "string" && item.id.length > 0 && Array.isArray(item.summary) && typeof item.encrypted_content === "string" && item.encrypted_content.length > 0 && (item.status === void 0 || item.status === "completed" || item.status === "incomplete");
356
+ }
357
+ const OPENAI_RESPONSES_REPLAY_POSITIONS_KEY = "__openai_responses_replay_positions__";
358
+ function isProviderGeneratedImageBlock(block, generatedImages, allowDataFallback = true) {
359
+ if (typeof block.id === "string" && block.id.length > 0) return generatedImages.ids.has(block.id);
360
+ return allowDataFallback && typeof block.data === "string" && generatedImages.data.has(block.data) && block.metadata != null && typeof block.metadata === "object" && block.metadata.status === "completed";
361
+ }
362
+ function hasMeaningfulServerToolOutput(output) {
363
+ if (output == null || output === "") return false;
364
+ if (Array.isArray(output)) return output.length > 0;
365
+ if (typeof output !== "object") return true;
366
+ try {
367
+ return Object.keys(output).length > 0;
368
+ } catch {
369
+ return false;
370
+ }
371
+ }
372
+ function createServerToolResultExtras(toolName) {
373
+ return { librechatServerToolResult: { ...toolName != null ? { toolName } : {} } };
374
+ }
375
+ function createNeutralServerToolResult(output, status, maxChars, toolName) {
376
+ if (!hasMeaningfulServerToolOutput(output)) return;
377
+ return {
378
+ type: "text",
379
+ text: serializeToolContentBounded({ serverToolResult: {
380
+ librechatResponsesReplay: true,
381
+ ...toolName != null ? { toolName } : {},
382
+ status,
383
+ output
384
+ } }, maxChars),
385
+ extras: createServerToolResultExtras(toolName)
386
+ };
387
+ }
388
+ function isCompleteToolStreamContentBlock(block) {
389
+ if (block == null || typeof block !== "object") return true;
390
+ try {
391
+ if (isProxy(block)) return false;
392
+ const type = Object.getOwnPropertyDescriptor(block, "type");
393
+ if (type == null) return true;
394
+ if (type.enumerable !== true || !("value" in type)) return false;
395
+ if (type.value !== "text") return true;
396
+ const text = Object.getOwnPropertyDescriptor(block, "text");
397
+ return text?.enumerable === true && "value" in text && typeof text.value === "string" && text.value !== "";
398
+ } catch {
399
+ return false;
400
+ }
401
+ }
402
+ function projectPreemptedResponsesV1Content(content, reasoning, maxChars, replayProjection, generatedImages, originalImages, serverToolResults, positionedServerToolResultIds, reasoningPosition, textPositions, messagePositions) {
403
+ if (!Array.isArray(content)) return {
404
+ content,
405
+ preservedServerToolResult: false
406
+ };
407
+ const contentBlocks = content;
408
+ const encryptedReasoning = replayProjection === "native" && hasReplayableEncryptedReasoning(reasoning) ? reasoning : void 0;
409
+ const positionedReasoning = encryptedReasoning != null && reasoningPosition != null ? {
410
+ block: {
411
+ type: "non_standard",
412
+ value: encryptedReasoning
413
+ },
414
+ ...reasoningPosition,
415
+ subIndex: 0
416
+ } : void 0;
417
+ const projected = [];
418
+ let changed = false;
419
+ let hasEncryptedReasoning = false;
420
+ let preservedServerToolResult = false;
421
+ let reasoningInsertionIndex;
422
+ let generatedImageIndex = 0;
423
+ let originalImageIndex = 0;
424
+ let reasoningPending = positionedReasoning;
425
+ let serverToolResultIndex = 0;
426
+ let sourceTextIndex = 0;
427
+ const serverToolNamesByCallId = /* @__PURE__ */ new Map();
428
+ const appendOriginalImages = (throughTextIndex) => {
429
+ if (replayProjection !== "native" || originalImages == null) return;
430
+ while (originalImageIndex < originalImages.blocks.length) {
431
+ const positionedImage = originalImages.blocks[originalImageIndex];
432
+ if (throughTextIndex != null && positionedImage.textIndex > throughTextIndex) return;
433
+ originalImageIndex++;
434
+ if (generatedImages != null && isProviderGeneratedImageBlock(positionedImage.block, generatedImages, false)) continue;
435
+ projected.push(positionedImage.block);
436
+ changed = true;
437
+ }
438
+ };
439
+ const appendReplayBlocks = (throughTextIndex, beforeOutputIndex) => {
440
+ for (;;) {
441
+ const generatedImage = generatedImages?.blocks[generatedImageIndex];
442
+ const serverToolResult = serverToolResults?.[serverToolResultIndex];
443
+ const candidates = [];
444
+ if (generatedImage != null) candidates.push({
445
+ kind: "generatedImage",
446
+ value: generatedImage
447
+ });
448
+ if (serverToolResult != null) candidates.push({
449
+ kind: "serverToolResult",
450
+ value: serverToolResult
451
+ });
452
+ if (reasoningPending != null) candidates.push({
453
+ kind: "reasoning",
454
+ value: reasoningPending
455
+ });
456
+ if (candidates.length === 0) return;
457
+ candidates.sort((a, b) => comparePositionedResponsesReplayBlocks(a.value, b.value));
458
+ const selected = candidates[0];
459
+ const positionedResult = selected.value;
460
+ if (throughTextIndex != null && (positionedResult.textIndex == null || positionedResult.textIndex > throughTextIndex)) return;
461
+ if (beforeOutputIndex != null && positionedResult.outputIndex >= beforeOutputIndex) return;
462
+ if (selected.kind === "generatedImage") generatedImageIndex++;
463
+ else if (selected.kind === "serverToolResult") serverToolResultIndex++;
464
+ else reasoningPending = void 0;
465
+ if (replayProjection === "fallback" && positionedResult.block.type === "text") projected.push({
466
+ type: "text",
467
+ text: positionedResult.block.text
468
+ });
469
+ else projected.push(positionedResult.block);
470
+ changed = true;
471
+ preservedServerToolResult ||= selected.kind === "serverToolResult";
472
+ }
473
+ };
474
+ const appendPositionedOriginalImages = (throughTextIndex) => {
475
+ const nextOriginalImage = originalImages?.blocks[originalImageIndex];
476
+ if (nextOriginalImage == null || throughTextIndex != null && nextOriginalImage.textIndex > throughTextIndex) return;
477
+ const followingTextPosition = textPositions?.[nextOriginalImage.textIndex];
478
+ const imageOnlyMessagePosition = originalImages?.textCount === 0 ? messagePositions?.[0] : void 0;
479
+ const outputBoundary = followingTextPosition ?? imageOnlyMessagePosition;
480
+ if (outputBoundary != null) appendReplayBlocks(nextOriginalImage.textIndex, outputBoundary.outputIndex);
481
+ appendOriginalImages(throughTextIndex);
482
+ };
483
+ for (let i = 0; i < contentBlocks.length; i++) {
484
+ const block = contentBlocks[i];
485
+ if (!isCompleteToolStreamContentBlock(block)) {
486
+ changed = true;
487
+ continue;
488
+ }
489
+ if (block.type === "reasoning") {
490
+ reasoningInsertionIndex ??= projected.length;
491
+ changed = true;
492
+ continue;
493
+ }
494
+ if (block.type === "non_standard") {
495
+ if (replayProjection === "native" && !hasEncryptedReasoning && hasReplayableEncryptedReasoning(block.value)) {
496
+ hasEncryptedReasoning = true;
497
+ if (positionedReasoning == null) projected.push(block);
498
+ else changed = true;
499
+ } else changed = true;
500
+ continue;
501
+ }
502
+ if (block.type === "text") {
503
+ appendPositionedOriginalImages(sourceTextIndex);
504
+ appendReplayBlocks(sourceTextIndex);
505
+ if (replayProjection === "fallback") {
506
+ projected.push({
507
+ type: "text",
508
+ text: block.text
509
+ });
510
+ changed = true;
511
+ } else projected.push(block);
512
+ sourceTextIndex++;
513
+ continue;
514
+ }
515
+ if (originalImages != null && sourceTextIndex >= originalImages.textCount) appendPositionedOriginalImages();
516
+ if (block.type === "server_tool_call" || block.type === "server_tool_call_chunk") {
517
+ if (typeof block.id === "string" && block.id.length > 0 && typeof block.name === "string" && block.name.length > 0) serverToolNamesByCallId.set(block.id, block.name);
518
+ changed = true;
519
+ continue;
520
+ }
521
+ if (block.type === "server_tool_call_result") {
522
+ if (positionedServerToolResultIds?.has(block.toolCallId) === true) {
523
+ changed = true;
524
+ continue;
525
+ }
526
+ const result = createNeutralServerToolResult(block.output, block.status, maxChars, serverToolNamesByCallId.get(block.toolCallId));
527
+ changed = true;
528
+ if (result != null) {
529
+ projected.push(replayProjection === "fallback" ? {
530
+ type: "text",
531
+ text: result.text
532
+ } : result);
533
+ preservedServerToolResult = true;
534
+ }
535
+ continue;
536
+ }
537
+ if (block.type === "image") {
538
+ if (replayProjection === "fallback" || generatedImages != null && isProviderGeneratedImageBlock(block, generatedImages)) {
539
+ changed = true;
540
+ continue;
541
+ }
542
+ }
543
+ projected.push(block);
544
+ }
545
+ if (encryptedReasoning != null && !hasEncryptedReasoning && positionedReasoning == null) {
546
+ const reasoningBlock = {
547
+ type: "non_standard",
548
+ value: encryptedReasoning
549
+ };
550
+ projected.splice(reasoningInsertionIndex ?? 0, 0, reasoningBlock);
551
+ changed = true;
552
+ }
553
+ appendPositionedOriginalImages();
554
+ appendReplayBlocks();
555
+ return {
556
+ content: changed ? toLangChainContent(projected) : content,
557
+ preservedServerToolResult
558
+ };
559
+ }
560
+ function getAuthoritativeResponsesOutput(message) {
561
+ const responseOutput = message.response_metadata.output;
562
+ const toolOutputs = message.additional_kwargs.tool_outputs;
563
+ if (Array.isArray(responseOutput) && responseOutput.length > 0) return responseOutput;
564
+ return Array.isArray(toolOutputs) ? toolOutputs : [];
565
+ }
566
+ function isResponsesReplayPosition(value) {
567
+ if (value == null || typeof value !== "object") return false;
568
+ const position = value;
569
+ return (position.kind === "message" || position.kind === "output" || position.kind === "reasoning" || position.kind === "text") && typeof position.itemId === "string" && position.itemId.length > 0 && typeof position.outputIndex === "number" && Number.isSafeInteger(position.outputIndex) && position.outputIndex >= 0 && (position.contentIndex == null || typeof position.contentIndex === "number" && Number.isSafeInteger(position.contentIndex) && position.contentIndex >= 0);
570
+ }
571
+ function getGeneratedImageMimeType(data) {
572
+ const bytes = Buffer.from(data.slice(0, 16), "base64");
573
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
574
+ if (bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) return "image/webp";
575
+ return "image/png";
576
+ }
577
+ function getResponsesReplayItemKey(item) {
578
+ if (typeof item.id === "string" && item.id.length > 0) return item.id;
579
+ return typeof item.call_id === "string" && item.call_id.length > 0 ? item.call_id : void 0;
580
+ }
581
+ function comparePositionedResponsesReplayBlocks(a, b) {
582
+ return (a.textIndex ?? Number.MAX_SAFE_INTEGER) - (b.textIndex ?? Number.MAX_SAFE_INTEGER) || a.outputIndex - b.outputIndex || a.subIndex - b.subIndex;
583
+ }
584
+ const RESPONSES_REPLAY_OUTPUT_TOOL_NAMES = {
585
+ apply_patch_call_output: "apply_patch",
586
+ local_shell_call_output: "local_shell",
587
+ shell_call_output: "shell"
588
+ };
589
+ function getResponsesReplayArtifacts(output, maxChars, replayProjection, replayPositionValue) {
590
+ const blocks = [];
591
+ const data = /* @__PURE__ */ new Set();
592
+ const ids = /* @__PURE__ */ new Set();
593
+ const emittedData = /* @__PURE__ */ new Set();
594
+ const emittedIds = /* @__PURE__ */ new Set();
595
+ const positionedServerToolResultIds = /* @__PURE__ */ new Set();
596
+ const rawOutputIndices = /* @__PURE__ */ new Map();
597
+ const serverToolResults = [];
598
+ const replayPositions = Array.isArray(replayPositionValue) ? replayPositionValue.filter(isResponsesReplayPosition) : [];
599
+ const authoritativeOutputIndicesByItemId = /* @__PURE__ */ new Map();
600
+ const messagePositionsByKey = /* @__PURE__ */ new Map();
601
+ const outputPositionsByItemId = /* @__PURE__ */ new Map();
602
+ const textPositionsByKey = /* @__PURE__ */ new Map();
603
+ for (const position of replayPositions) {
604
+ if (position.kind === "output" || position.kind === "reasoning") {
605
+ outputPositionsByItemId.set(position.itemId, position);
606
+ continue;
607
+ }
608
+ if (position.kind === "message") {
609
+ messagePositionsByKey.set(`${position.itemId}:${position.outputIndex}`, position);
610
+ continue;
611
+ }
612
+ textPositionsByKey.set(`${position.itemId}:${position.outputIndex}:${position.contentIndex ?? 0}`, position);
613
+ }
614
+ let hasAuthoritativeMessage = false;
615
+ for (let outputIndex = 0; outputIndex < output.length; outputIndex++) {
616
+ const item = output[outputIndex];
617
+ if (item == null || typeof item !== "object") continue;
618
+ const itemRecord = item;
619
+ rawOutputIndices.set(itemRecord, outputIndex);
620
+ const itemKey = getResponsesReplayItemKey(itemRecord);
621
+ if (itemKey != null) authoritativeOutputIndicesByItemId.set(itemKey, outputIndex);
622
+ if (!("type" in item) || item.type !== "message") continue;
623
+ hasAuthoritativeMessage = true;
624
+ const messageItemId = "id" in item && typeof item.id === "string" ? item.id : `message-${outputIndex}`;
625
+ messagePositionsByKey.set(`${messageItemId}:${outputIndex}`, {
626
+ itemId: messageItemId,
627
+ kind: "message",
628
+ outputIndex
629
+ });
630
+ if (!("content" in item) || !Array.isArray(item.content)) continue;
631
+ for (let contentIndex = 0; contentIndex < item.content.length; contentIndex++) {
632
+ const content = item.content[contentIndex];
633
+ if (content == null || typeof content !== "object" || !("type" in content) || content.type !== "output_text" || !("text" in content) || typeof content.text !== "string" || content.text.length === 0) continue;
634
+ const itemId = "id" in item && typeof item.id === "string" ? item.id : `message-${outputIndex}`;
635
+ textPositionsByKey.set(`${itemId}:${outputIndex}:${contentIndex}`, {
636
+ contentIndex,
637
+ itemId,
638
+ kind: "text",
639
+ outputIndex
640
+ });
641
+ }
642
+ }
643
+ if (hasAuthoritativeMessage) for (const [itemId, outputIndex] of authoritativeOutputIndicesByItemId) outputPositionsByItemId.set(itemId, {
644
+ itemId,
645
+ kind: "output",
646
+ outputIndex
647
+ });
648
+ const textPositions = [...textPositionsByKey.values()].sort((a, b) => a.outputIndex - b.outputIndex || (a.contentIndex ?? 0) - (b.contentIndex ?? 0));
649
+ const messagePositions = [...messagePositionsByKey.values()].sort((a, b) => a.outputIndex - b.outputIndex);
650
+ const textCountBeforeOutputIndex = /* @__PURE__ */ new Map();
651
+ const positionedOutputIndexSet = /* @__PURE__ */ new Set();
652
+ for (const position of outputPositionsByItemId.values()) positionedOutputIndexSet.add(position.outputIndex);
653
+ if (hasAuthoritativeMessage) for (const outputIndex of rawOutputIndices.values()) positionedOutputIndexSet.add(outputIndex);
654
+ const positionedOutputIndices = [...positionedOutputIndexSet].sort((a, b) => a - b);
655
+ let textPositionIndex = 0;
656
+ for (const outputIndex of positionedOutputIndices) {
657
+ while (textPositionIndex < textPositions.length && textPositions[textPositionIndex].outputIndex < outputIndex) textPositionIndex++;
658
+ textCountBeforeOutputIndex.set(outputIndex, textPositionIndex);
659
+ }
660
+ const positionsByItemId = /* @__PURE__ */ new Map();
661
+ for (const [itemId, position] of outputPositionsByItemId) positionsByItemId.set(itemId, {
662
+ outputIndex: position.outputIndex,
663
+ textIndex: textCountBeforeOutputIndex.get(position.outputIndex) ?? 0
664
+ });
665
+ const getPosition = (item) => {
666
+ const itemId = getResponsesReplayItemKey(item);
667
+ const position = itemId != null ? positionsByItemId.get(itemId) : void 0;
668
+ if (position == null) {
669
+ const rawOutputIndex = rawOutputIndices.get(item);
670
+ return {
671
+ outputIndex: rawOutputIndex ?? Number.MAX_SAFE_INTEGER,
672
+ ...hasAuthoritativeMessage && rawOutputIndex != null ? { textIndex: textCountBeforeOutputIndex.get(rawOutputIndex) ?? 0 } : {}
673
+ };
674
+ }
675
+ return position;
676
+ };
677
+ const pushServerToolResult = (block, item, subIndex = 0) => {
678
+ if (block == null) return;
679
+ const itemId = getResponsesReplayItemKey(item);
680
+ if (itemId != null) positionedServerToolResultIds.add(itemId);
681
+ serverToolResults.push({
682
+ block,
683
+ ...getPosition(item),
684
+ subIndex
685
+ });
686
+ };
687
+ for (const item of output) {
688
+ if (item == null || typeof item !== "object" || !("type" in item)) continue;
689
+ if (item.type === "code_interpreter_call") {
690
+ if (!("outputs" in item) || !Array.isArray(item.outputs) || !("status" in item)) continue;
691
+ const resultStatus = item.status === "completed" ? "success" : "error";
692
+ const returnCode = item.status === "completed" ? 0 : 1;
693
+ for (let resultIndex = 0; resultIndex < item.outputs.length; resultIndex++) {
694
+ const result = item.outputs[resultIndex];
695
+ if (result == null || typeof result !== "object" || !("type" in result)) continue;
696
+ if (result.type === "logs" && "logs" in result && typeof result.logs === "string") {
697
+ pushServerToolResult(createNeutralServerToolResult({
698
+ type: "code_interpreter_output",
699
+ returnCode,
700
+ stdout: result.logs
701
+ }, resultStatus, maxChars, "code_interpreter"), item, resultIndex);
702
+ continue;
703
+ }
704
+ if (result.type !== "image" || !("url" in result) || typeof result.url !== "string" || result.url.length === 0) continue;
705
+ const resultUrl = result.url;
706
+ if (replayProjection === "native" && resultUrl.startsWith("data:image/")) {
707
+ pushServerToolResult({
708
+ type: "image",
709
+ url: resultUrl,
710
+ extras: createServerToolResultExtras("code_interpreter")
711
+ }, item, resultIndex);
712
+ continue;
713
+ }
714
+ pushServerToolResult(createNeutralServerToolResult({
715
+ type: "code_interpreter_image",
716
+ url: resultUrl
717
+ }, resultStatus, maxChars, "code_interpreter"), item, resultIndex);
718
+ }
719
+ continue;
720
+ }
721
+ if (item.type === "file_search_call") {
722
+ pushServerToolResult(createNeutralServerToolResult("results" in item && Array.isArray(item.results) ? { results: item.results } : void 0, "status" in item && item.status === "completed" ? "success" : "error", maxChars, "file_search"), item);
723
+ continue;
724
+ }
725
+ if (item.type === "web_search_call") {
726
+ pushServerToolResult(createNeutralServerToolResult({
727
+ ..."action" in item ? { action: item.action } : {},
728
+ ..."results" in item && Array.isArray(item.results) ? { results: item.results } : {}
729
+ }, "status" in item && item.status === "completed" ? "success" : "error", maxChars, "web_search"), item);
730
+ continue;
731
+ }
732
+ if (item.type === "tool_search_output") {
733
+ pushServerToolResult(createNeutralServerToolResult("tools" in item && Array.isArray(item.tools) ? { tools: item.tools } : void 0, "status" in item && item.status === "completed" ? "success" : "error", maxChars, "tool_search"), item);
734
+ continue;
735
+ }
736
+ if (item.type === "mcp_list_tools") {
737
+ const hasError = "error" in item && typeof item.error === "string" && item.error.length > 0;
738
+ pushServerToolResult(createNeutralServerToolResult({
739
+ ..."server_label" in item && typeof item.server_label === "string" ? { serverLabel: item.server_label } : {},
740
+ ..."tools" in item && Array.isArray(item.tools) ? { tools: item.tools } : {},
741
+ ...hasError ? { error: item.error } : {}
742
+ }, hasError ? "error" : "success", maxChars, "mcp_list_tools"), item);
743
+ continue;
744
+ }
745
+ if (item.type === "mcp_call") {
746
+ const hasOutput = "output" in item && typeof item.output === "string" && item.output.length > 0;
747
+ const hasError = "error" in item && typeof item.error === "string" && item.error.length > 0;
748
+ if (!hasOutput && !hasError) continue;
749
+ pushServerToolResult(createNeutralServerToolResult({
750
+ ..."name" in item && typeof item.name === "string" ? { name: item.name } : {},
751
+ ..."server_label" in item && typeof item.server_label === "string" ? { serverLabel: item.server_label } : {},
752
+ ..."output" in item && typeof item.output === "string" ? { output: item.output } : {},
753
+ ..."error" in item && typeof item.error === "string" ? { error: item.error } : {}
754
+ }, hasError || "status" in item && (item.status === "failed" || item.status === "incomplete") ? "error" : "success", maxChars, "name" in item && typeof item.name === "string" && item.name.length > 0 ? item.name : "mcp"), item);
755
+ continue;
756
+ }
757
+ if (item.type === "local_shell_call_output" || item.type === "shell_call_output" || item.type === "apply_patch_call_output") {
758
+ if (!("output" in item)) continue;
759
+ pushServerToolResult(createNeutralServerToolResult(item.output, "status" in item && (item.status === "failed" || item.status === "incomplete") ? "error" : "success", maxChars, RESPONSES_REPLAY_OUTPUT_TOOL_NAMES[item.type]), item);
760
+ continue;
761
+ }
762
+ if (item.type === "program_output") {
763
+ if (!("result" in item)) continue;
764
+ pushServerToolResult(createNeutralServerToolResult(item.result, "status" in item && item.status === "incomplete" ? "error" : "success", maxChars, "program"), item);
765
+ continue;
766
+ }
767
+ if (item.type !== "image_generation_call") continue;
768
+ if ("id" in item && typeof item.id === "string" && item.id.length > 0) ids.add(item.id);
769
+ if (!("result" in item) || typeof item.result !== "string" || item.result.length === 0) continue;
770
+ data.add(item.result);
771
+ if ("status" in item && item.status === "completed") {
772
+ const itemId = "id" in item && typeof item.id === "string" && item.id.length > 0 ? item.id : void 0;
773
+ if (itemId != null && emittedIds.has(itemId) || itemId == null && emittedData.has(item.result)) continue;
774
+ if (itemId != null) emittedIds.add(itemId);
775
+ else emittedData.add(item.result);
776
+ blocks.push({
777
+ block: {
778
+ type: "image",
779
+ mimeType: getGeneratedImageMimeType(item.result),
780
+ data: item.result,
781
+ extras: createServerToolResultExtras("image_generation")
782
+ },
783
+ ...getPosition(item),
784
+ subIndex: 0
785
+ });
786
+ }
787
+ }
788
+ return {
789
+ generatedImages: {
790
+ blocks: blocks.sort(comparePositionedResponsesReplayBlocks),
791
+ data,
792
+ ids
793
+ },
794
+ messagePositions,
795
+ positionedServerToolResultIds,
796
+ positionsByItemId,
797
+ serverToolResults: serverToolResults.sort(comparePositionedResponsesReplayBlocks),
798
+ textPositions
799
+ };
800
+ }
801
+ function getSelfContainedResponsesV0Images(message) {
802
+ if (!Array.isArray(message.content)) return {
803
+ blocks: [],
804
+ textCount: 0
805
+ };
806
+ const images = [];
807
+ let textCount = 0;
808
+ for (const block of message.content) {
809
+ if (block.type === "text") {
810
+ if (isCompleteToolStreamContentBlock(block)) textCount++;
811
+ continue;
812
+ }
813
+ if (block.type === "image" && ("fileId" in block && typeof block.fileId === "string" && block.fileId.length > 0 || "url" in block && typeof block.url === "string" && block.url.length > 0 || "data" in block && (typeof block.data === "string" && block.data.length > 0 || block.data instanceof Uint8Array && block.data.length > 0))) images.push({
814
+ block,
815
+ textIndex: textCount
816
+ });
817
+ }
818
+ return {
819
+ blocks: images,
820
+ textCount
821
+ };
822
+ }
823
+ function getResponsesV0ContentBlocks(message, authoritativeOutput) {
824
+ let content = message.content;
825
+ if (typeof content === "string") content = toLangChainContent(content.length > 0 ? [{
826
+ type: "text",
827
+ text: content
828
+ }] : []);
829
+ return toLangChainContent(cloneAIMessageWithResponsesReplayState(message, content, message.id, {
830
+ ...message.additional_kwargs,
831
+ tool_outputs: authoritativeOutput
832
+ }, {
833
+ ...message.response_metadata,
834
+ model_provider: "openai"
835
+ }).contentBlocks);
836
+ }
837
+ function isPreemptedOpenAIResponsesMessage(message) {
838
+ const metadata = message.response_metadata;
839
+ if (metadata.preempted !== true || metadata.model_provider !== "openai") return false;
840
+ if (message.id?.startsWith("msg_") === true || message.id?.startsWith("resp_") === true || typeof metadata.id === "string" && metadata.id.startsWith("resp_") || Array.isArray(metadata.output) || metadata.tool_outputs != null || Array.isArray(message.additional_kwargs.tool_outputs) || message.additional_kwargs["__openai_responses_replay_positions__"] != null || message.additional_kwargs.__openai_function_call_ids__ != null || message.additional_kwargs.__openai_custom_tool_call_ids__ != null || message.additional_kwargs.reasoning != null && typeof message.additional_kwargs.reasoning === "object") return true;
841
+ return false;
842
+ }
318
843
  /**
319
- * Drops incomplete streamed text-input fragments that some providers retain
320
- * beside the assembled parsed tool call. They are neither user-visible text
321
- * nor valid content blocks for a subsequent provider.
844
+ * A sealed Responses turn cannot prove that provider-side item ids were
845
+ * retained: the response object does not echo the request's `store` flag.
846
+ * Project a provider-neutral clone while preserving self-contained encrypted
847
+ * reasoning and the original graph/checkpoint message.
322
848
  */
323
- function projectToolStreamContentForProvider(messages) {
849
+ function projectPreemptedOpenAIResponsesMessage(message, maxChars, replayProjection) {
850
+ if (!isPreemptedOpenAIResponsesMessage(message)) return message;
851
+ const metadata = message.response_metadata;
852
+ const additionalKwargs = { ...message.additional_kwargs };
853
+ const retainsEncryptedReasoning = replayProjection === "native" && hasReplayableEncryptedReasoning(additionalKwargs.reasoning);
854
+ const authoritativeOutput = getAuthoritativeResponsesOutput(message);
855
+ const { generatedImages, messagePositions, positionedServerToolResultIds, positionsByItemId, serverToolResults, textPositions } = getResponsesReplayArtifacts(authoritativeOutput, maxChars, replayProjection, additionalKwargs[OPENAI_RESPONSES_REPLAY_POSITIONS_KEY]);
856
+ const reasoningItemId = retainsEncryptedReasoning && additionalKwargs.reasoning != null && typeof additionalKwargs.reasoning === "object" && "id" in additionalKwargs.reasoning && typeof additionalKwargs.reasoning.id === "string" ? additionalKwargs.reasoning.id : void 0;
857
+ const reasoningPosition = reasoningItemId != null ? positionsByItemId.get(reasoningItemId) : void 0;
858
+ const isV1 = metadata.output_version === "v1";
859
+ const translatesV0 = !isV1 && (replayProjection === "fallback" || authoritativeOutput.length > 0);
860
+ const originalImages = replayProjection === "native" && translatesV0 ? getSelfContainedResponsesV0Images(message) : void 0;
861
+ let contentForProjection = message.content;
862
+ if (!isV1 && translatesV0) contentForProjection = getResponsesV0ContentBlocks(message, authoritativeOutput);
863
+ const projectedContent = projectPreemptedResponsesV1Content(contentForProjection, isV1 || translatesV0 ? additionalKwargs.reasoning : void 0, maxChars, replayProjection, replayProjection === "native" ? generatedImages : void 0, originalImages, serverToolResults, positionedServerToolResultIds, reasoningPosition, textPositions, messagePositions);
864
+ const promotesV0 = !isV1 && (replayProjection === "fallback" || generatedImages.blocks.length > 0 || projectedContent.preservedServerToolResult);
865
+ const unpromotedV0Content = contentForProjection === message.content ? projectedContent.content : projectPreemptedResponsesV1Content(message.content, void 0, maxChars, replayProjection).content;
866
+ const content = isV1 || promotesV0 ? projectedContent.content : unpromotedV0Content;
867
+ if (!(content !== message.content || message.id?.startsWith("msg_") === true || !retainsEncryptedReasoning && additionalKwargs.reasoning != null || additionalKwargs.tool_outputs != null || additionalKwargs["__openai_responses_replay_positions__"] != null || additionalKwargs.__openai_function_call_ids__ != null || additionalKwargs.__openai_custom_tool_call_ids__ != null || metadata.id != null || metadata.output != null || metadata.tool_outputs != null)) return message;
868
+ if (!retainsEncryptedReasoning) delete additionalKwargs.reasoning;
869
+ delete additionalKwargs.tool_outputs;
870
+ delete additionalKwargs[OPENAI_RESPONSES_REPLAY_POSITIONS_KEY];
871
+ delete additionalKwargs.__openai_function_call_ids__;
872
+ delete additionalKwargs.__openai_custom_tool_call_ids__;
873
+ const responseMetadata = { ...metadata };
874
+ delete responseMetadata.id;
875
+ delete responseMetadata.output;
876
+ delete responseMetadata.tool_outputs;
877
+ if (promotesV0) responseMetadata.output_version = "v1";
878
+ return cloneAIMessageWithResponsesReplayState(message, content, message.id?.startsWith("msg_") === true ? void 0 : message.id, additionalKwargs, responseMetadata);
879
+ }
880
+ /** Applies sealed-Responses safety and drops incomplete streamed text input. */
881
+ function projectToolStreamContentForProvider(messages, responsesReplayProjection, maxChars = HARD_MAX_TOOL_RESULT_CHARS) {
324
882
  let projected;
325
883
  for (let i = 0; i < messages.length; i++) {
326
884
  const message = messages[i];
327
- if (message.getType() !== "ai" || !Array.isArray(message.content)) continue;
328
- const content = message.content.filter((block) => {
329
- if (block == null || typeof block !== "object") return true;
330
- try {
331
- if (isProxy(block)) return false;
332
- const type = Object.getOwnPropertyDescriptor(block, "type");
333
- if (type == null) return true;
334
- if (type.enumerable !== true || !("value" in type)) return false;
335
- if (type.value !== "text") return true;
336
- const text = Object.getOwnPropertyDescriptor(block, "text");
337
- return text?.enumerable === true && "value" in text && typeof text.value === "string" && text.value !== "";
338
- } catch {
339
- return false;
885
+ if (message.getType() !== "ai") continue;
886
+ const assistantMessage = message;
887
+ if (responsesReplayProjection != null && isPreemptedOpenAIResponsesMessage(assistantMessage)) {
888
+ const replaySafeMessage = projectPreemptedOpenAIResponsesMessage(assistantMessage, maxChars, responsesReplayProjection);
889
+ if (replaySafeMessage !== assistantMessage) {
890
+ projected ??= [...messages];
891
+ projected[i] = replaySafeMessage;
340
892
  }
341
- });
342
- if (content.length === message.content.length) continue;
893
+ continue;
894
+ }
895
+ if (!Array.isArray(assistantMessage.content)) continue;
896
+ const content = assistantMessage.content.filter(isCompleteToolStreamContentBlock);
897
+ if (content.length === assistantMessage.content.length) continue;
343
898
  projected ??= [...messages];
344
- projected[i] = cloneAIMessageWithContent(message, toLangChainContent(content));
899
+ projected[i] = cloneAIMessageWithContent(assistantMessage, toLangChainContent(content));
345
900
  }
346
901
  return projected ?? messages;
347
902
  }
@@ -362,7 +917,7 @@ function projectStructuredOpenAIToolContent(content, maxChars, cacheControlledTe
362
917
  * the budget guard counted. Native Responses computer screenshots stay
363
918
  * structured because their dedicated converter sends the media block directly.
364
919
  */
365
- function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicateResponsesComputerCalls, cacheControlledTextProjection) {
920
+ function projectOpenAIToolMessageContentInternal(messages, maxChars, nativeResponsesProjection, cacheControlledTextProjection) {
366
921
  const pendingComputerCallIds = [];
367
922
  const seenComputerCallIds = /* @__PURE__ */ new Set();
368
923
  let projected;
@@ -370,8 +925,17 @@ function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicate
370
925
  const message = messages[i];
371
926
  const messageRole = message.role;
372
927
  if (message.getType() === "ai" || messageRole === "assistant") {
928
+ let assistantMessage = message;
929
+ if (nativeResponsesProjection) {
930
+ const replaySafeMessage = projectPreemptedOpenAIResponsesMessage(assistantMessage, maxChars, "native");
931
+ if (replaySafeMessage !== assistantMessage) {
932
+ projected ??= [...messages];
933
+ projected[i] = replaySafeMessage;
934
+ assistantMessage = replaySafeMessage;
935
+ }
936
+ }
373
937
  const parsedComputerCallIds = /* @__PURE__ */ new Set();
374
- const toolCalls = message.tool_calls;
938
+ const toolCalls = assistantMessage.tool_calls;
375
939
  if (Array.isArray(toolCalls)) for (const toolCall of toolCalls) {
376
940
  const record = toolCall;
377
941
  if (record.type !== "tool_call" || record.isComputerTool !== true || typeof record.id !== "string" || record.id === "") continue;
@@ -381,8 +945,8 @@ function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicate
381
945
  seenComputerCallIds.add(record.id);
382
946
  pendingComputerCallIds.push(record.id);
383
947
  }
384
- const rawOutput = message.response_metadata.output;
385
- const fallbackOutput = message.additional_kwargs.tool_outputs;
948
+ const rawOutput = assistantMessage.response_metadata.output;
949
+ const fallbackOutput = assistantMessage.additional_kwargs.tool_outputs;
386
950
  let actualToolOutputs = [];
387
951
  if (Array.isArray(rawOutput) && rawOutput.length > 0) actualToolOutputs = rawOutput;
388
952
  else if (Array.isArray(fallbackOutput)) actualToolOutputs = fallbackOutput;
@@ -398,7 +962,7 @@ function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicate
398
962
  seenComputerCallIds.add(record.call_id);
399
963
  pendingComputerCallIds.push(record.call_id);
400
964
  }
401
- if (deduplicateResponsesComputerCalls && Array.isArray(toolCalls) && rawComputerCallIds.size > 0) {
965
+ if (nativeResponsesProjection && Array.isArray(toolCalls) && rawComputerCallIds.size > 0) {
402
966
  /**
403
967
  * The non-streaming Responses converter marks parsed computer calls,
404
968
  * but the streaming converter currently emits the same call as an
@@ -409,7 +973,7 @@ function projectOpenAIToolMessageContentInternal(messages, maxChars, deduplicate
409
973
  const projectedToolCalls = toolCalls.filter((toolCall) => typeof toolCall.id !== "string" || !rawComputerCallIds.has(toolCall.id));
410
974
  if (projectedToolCalls.length !== toolCalls.length) {
411
975
  projected ??= [...messages];
412
- projected[i] = cloneAIMessageWithToolCalls(message, projectedToolCalls, rawComputerCallIds);
976
+ projected[i] = cloneAIMessageWithToolCalls(assistantMessage, projectedToolCalls, rawComputerCallIds);
413
977
  }
414
978
  }
415
979
  }
@@ -571,6 +1135,6 @@ function findLastIndex(array, predicate) {
571
1135
  return -1;
572
1136
  }
573
1137
  //#endregion
574
- export { convertMessagesToContent, findLastIndex, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, getConverseOverrideMessage, modifyDeltaProperties, projectAnthropicArtifactContent, projectArtifactPayload, projectCacheControlledToolOutputsToText, projectComputerCallOutputsToText, projectOpenAIChatToolMessageContent, projectOpenAIResponsesToolMessageContent, projectOpenAIToolMessageContent, projectOpenRouterToolMessageContent, projectSingleTextToolOutputsToText, projectStructuredToolOutputsToText, projectToolStreamContentForProvider };
1138
+ export { OPENAI_RESPONSES_REPLAY_POSITIONS_KEY, convertMessagesToContent, findLastIndex, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, getConverseOverrideMessage, modifyDeltaProperties, projectAnthropicArtifactContent, projectArtifactPayload, projectCacheControlledToolOutputsToText, projectComputerCallOutputsToText, projectOpenAIChatToolMessageContent, projectOpenAIResponsesToolMessageContent, projectOpenAIToolMessageContent, projectOpenRouterToolMessageContent, projectSingleTextToolOutputsToText, projectStructuredToolOutputsToText, projectToolStreamContentForProvider };
575
1139
 
576
1140
  //# sourceMappingURL=core.mjs.map