braintrust 3.29.0 → 3.30.0

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 (49) hide show
  1. package/dev/dist/index.js +1465 -881
  2. package/dev/dist/index.mjs +846 -262
  3. package/dist/apply-auto-instrumentation.js +217 -217
  4. package/dist/apply-auto-instrumentation.mjs +2 -2
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +13 -1
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  7. package/dist/auto-instrumentations/bundler/next.cjs +13 -1
  8. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +13 -1
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/vite.cjs +13 -1
  12. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +13 -1
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +13 -1
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  16. package/dist/auto-instrumentations/{chunk-DKTGDNA7.mjs → chunk-LW4HDHXT.mjs} +1 -1
  17. package/dist/auto-instrumentations/{chunk-OMCZ3MV2.mjs → chunk-OXINGIEZ.mjs} +1 -1
  18. package/dist/auto-instrumentations/{chunk-AOIYCVEL.mjs → chunk-U64OYU4Q.mjs} +13 -1
  19. package/dist/auto-instrumentations/hook.mjs +16 -4
  20. package/dist/auto-instrumentations/index.cjs +13 -1
  21. package/dist/auto-instrumentations/index.mjs +1 -1
  22. package/dist/browser.d.mts +133 -2
  23. package/dist/browser.d.ts +133 -2
  24. package/dist/browser.js +1143 -297
  25. package/dist/browser.mjs +1143 -297
  26. package/dist/{chunk-6Z5S7VOU.js → chunk-2XDW3UCG.js} +13 -1
  27. package/dist/{chunk-M6XPNJC4.mjs → chunk-BU6SM54N.mjs} +687 -115
  28. package/dist/{chunk-7FA6VP2S.mjs → chunk-N3JKQ3D3.mjs} +13 -1
  29. package/dist/{chunk-XLLGRXGR.js → chunk-TWCDSYJN.js} +1803 -1231
  30. package/dist/cli.js +819 -235
  31. package/dist/edge-light.d.mts +1 -1
  32. package/dist/edge-light.d.ts +1 -1
  33. package/dist/edge-light.js +1143 -297
  34. package/dist/edge-light.mjs +1143 -297
  35. package/dist/index.d.mts +133 -2
  36. package/dist/index.d.ts +133 -2
  37. package/dist/index.js +902 -640
  38. package/dist/index.mjs +336 -74
  39. package/dist/instrumentation/index.d.mts +15 -0
  40. package/dist/instrumentation/index.d.ts +15 -0
  41. package/dist/instrumentation/index.js +857 -262
  42. package/dist/instrumentation/index.mjs +857 -262
  43. package/dist/vitest-evals-reporter.js +16 -16
  44. package/dist/vitest-evals-reporter.mjs +2 -2
  45. package/dist/workerd.d.mts +1 -1
  46. package/dist/workerd.d.ts +1 -1
  47. package/dist/workerd.js +1143 -297
  48. package/dist/workerd.mjs +1143 -297
  49. package/package.json +1 -1
package/dist/browser.mjs CHANGED
@@ -5672,7 +5672,7 @@ var INSTRUMENTATION_NAMES = {
5672
5672
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5673
5673
  "braintrust.spanInstrumentationName"
5674
5674
  );
5675
- var SDK_VERSION = true ? "3.29.0" : "0.0.0";
5675
+ var SDK_VERSION = true ? "3.30.0" : "0.0.0";
5676
5676
  function withSpanInstrumentationName(args, instrumentationName) {
5677
5677
  return {
5678
5678
  ...args,
@@ -9919,6 +9919,15 @@ function _internalStartSpanWithInitialMerge(args) {
9919
9919
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
9920
9920
  }).span;
9921
9921
  }
9922
+ function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
9923
+ return startSpanAndIsLogger(
9924
+ {
9925
+ ...args,
9926
+ [INITIAL_SPAN_WRITE_AS_MERGE]: true
9927
+ },
9928
+ { useParentSpanIdsForObjectParent: true }
9929
+ ).span;
9930
+ }
9922
9931
  function _internalStartSpanWithContext(args, context) {
9923
9932
  return startSpanAndIsLogger({
9924
9933
  ...args,
@@ -9932,7 +9941,7 @@ async function flush(options) {
9932
9941
  function setFetch(fetch2) {
9933
9942
  _internalGetGlobalState().setFetch(fetch2);
9934
9943
  }
9935
- function startSpanAndIsLogger(args) {
9944
+ function startSpanAndIsLogger(args, internalOptions) {
9936
9945
  const state = args?.state ?? _globalState;
9937
9946
  const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
9938
9947
  asyncFlush: args?.asyncFlush,
@@ -9946,7 +9955,7 @@ function startSpanAndIsLogger(args) {
9946
9955
  ) ? {
9947
9956
  spanId: parentObject.data.span_id,
9948
9957
  rootSpanId: parentObject.data.root_span_id
9949
- } : void 0;
9958
+ } : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
9950
9959
  const { parent: _ignoredParent, ...spanArgs } = args ?? {};
9951
9960
  const span = new SpanImpl({
9952
9961
  state,
@@ -13390,6 +13399,131 @@ function unsubscribeAll(unsubscribers) {
13390
13399
  return [];
13391
13400
  }
13392
13401
 
13402
+ // src/instrumentation/core/channel-definitions.ts
13403
+ function channel(spec) {
13404
+ return spec;
13405
+ }
13406
+ function defineChannels(pkg, channels, options) {
13407
+ const { instrumentationName } = options;
13408
+ return Object.fromEntries(
13409
+ Object.entries(channels).map(([key, spec]) => {
13410
+ const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13411
+ if (spec.kind === "async") {
13412
+ const asyncSpec = spec;
13413
+ const tracingChannel2 = () => isomorph_default.newTracingChannel(
13414
+ fullChannelName
13415
+ );
13416
+ const intercept2 = (interceptor) => {
13417
+ const hook = tracingChannel2();
13418
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13419
+ };
13420
+ };
13421
+ return [
13422
+ key,
13423
+ {
13424
+ ...asyncSpec,
13425
+ instrumentationName,
13426
+ intercept: intercept2,
13427
+ invoke: (target, thisArg, args, additional) => {
13428
+ const hook = tracingChannel2();
13429
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13430
+ },
13431
+ tracingChannel: tracingChannel2,
13432
+ tracePromise: (fn, context) => tracingChannel2().tracePromise(
13433
+ fn,
13434
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13435
+ context
13436
+ )
13437
+ }
13438
+ ];
13439
+ }
13440
+ const syncSpec = spec;
13441
+ const tracingChannel = () => isomorph_default.newTracingChannel(
13442
+ fullChannelName
13443
+ );
13444
+ const intercept = (interceptor) => {
13445
+ const hook = tracingChannel();
13446
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13447
+ };
13448
+ };
13449
+ return [
13450
+ key,
13451
+ {
13452
+ ...syncSpec,
13453
+ instrumentationName,
13454
+ intercept,
13455
+ invoke: (target, thisArg, args, additional) => {
13456
+ const hook = tracingChannel();
13457
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13458
+ },
13459
+ tracingChannel,
13460
+ traceSync: (fn, context) => tracingChannel().traceSync(
13461
+ fn,
13462
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13463
+ context
13464
+ )
13465
+ }
13466
+ ];
13467
+ })
13468
+ );
13469
+ }
13470
+
13471
+ // src/instrumentation/plugins/openai-channels.ts
13472
+ var openAIChannels = defineChannels(
13473
+ "openai",
13474
+ {
13475
+ filesCreateTraced: channel({
13476
+ channelName: "files.create-traced",
13477
+ kind: "async"
13478
+ }),
13479
+ batchesRetrieveTraced: channel({
13480
+ channelName: "batches.retrieve-traced",
13481
+ kind: "async"
13482
+ }),
13483
+ batchesCompleteTrace: channel({
13484
+ channelName: "batches.complete-trace",
13485
+ kind: "async"
13486
+ }),
13487
+ chatCompletionsCreate: channel({
13488
+ channelName: "chat.completions.create",
13489
+ kind: "async"
13490
+ }),
13491
+ embeddingsCreate: channel({
13492
+ channelName: "embeddings.create",
13493
+ kind: "async"
13494
+ }),
13495
+ betaChatCompletionsParse: channel({
13496
+ channelName: "beta.chat.completions.parse",
13497
+ kind: "async"
13498
+ }),
13499
+ betaChatCompletionsStream: channel({
13500
+ channelName: "beta.chat.completions.stream",
13501
+ kind: "sync-stream"
13502
+ }),
13503
+ moderationsCreate: channel({
13504
+ channelName: "moderations.create",
13505
+ kind: "async"
13506
+ }),
13507
+ responsesCreate: channel({
13508
+ channelName: "responses.create",
13509
+ kind: "async"
13510
+ }),
13511
+ responsesStream: channel({
13512
+ channelName: "responses.stream",
13513
+ kind: "sync-stream"
13514
+ }),
13515
+ responsesParse: channel({
13516
+ channelName: "responses.parse",
13517
+ kind: "async"
13518
+ }),
13519
+ responsesCompact: channel({
13520
+ channelName: "responses.compact",
13521
+ kind: "async"
13522
+ })
13523
+ },
13524
+ { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13525
+ );
13526
+
13393
13527
  // src/wrappers/attachment-utils.ts
13394
13528
  function getExtensionFromMediaType(mediaType) {
13395
13529
  const extensionMap = {
@@ -13565,118 +13699,91 @@ function processInputAttachments(input) {
13565
13699
  return processNode(input);
13566
13700
  }
13567
13701
 
13568
- // src/instrumentation/core/channel-definitions.ts
13569
- function channel(spec) {
13570
- return spec;
13571
- }
13572
- function defineChannels(pkg, channels, options) {
13573
- const { instrumentationName } = options;
13574
- return Object.fromEntries(
13575
- Object.entries(channels).map(([key, spec]) => {
13576
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13577
- if (spec.kind === "async") {
13578
- const asyncSpec = spec;
13579
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
13580
- fullChannelName
13581
- );
13582
- const intercept2 = (interceptor) => {
13583
- const hook = tracingChannel2();
13584
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13585
- };
13586
- };
13587
- return [
13588
- key,
13589
- {
13590
- ...asyncSpec,
13591
- instrumentationName,
13592
- intercept: intercept2,
13593
- invoke: (target, thisArg, args, additional) => {
13594
- const hook = tracingChannel2();
13595
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13596
- },
13597
- tracingChannel: tracingChannel2,
13598
- tracePromise: (fn, context) => tracingChannel2().tracePromise(
13599
- fn,
13600
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13601
- context
13602
- )
13603
- }
13604
- ];
13702
+ // src/instrumentation/plugins/openai-span-data.ts
13703
+ var OPENAI_METADATA_KEYS = [
13704
+ "model",
13705
+ "temperature",
13706
+ "top_p",
13707
+ "max_tokens",
13708
+ "frequency_penalty",
13709
+ "presence_penalty",
13710
+ "stop",
13711
+ "response_format",
13712
+ "tools",
13713
+ "tool_choice",
13714
+ "parallel_tool_calls",
13715
+ "max_tool_calls"
13716
+ ];
13717
+ function batchMetadata(params) {
13718
+ const metadata = { provider: "openai" };
13719
+ for (const key of OPENAI_METADATA_KEYS) {
13720
+ try {
13721
+ const value = Reflect.get(params, key);
13722
+ if (value !== void 0) {
13723
+ metadata[key] = value;
13605
13724
  }
13606
- const syncSpec = spec;
13607
- const tracingChannel = () => isomorph_default.newTracingChannel(
13608
- fullChannelName
13609
- );
13610
- const intercept = (interceptor) => {
13611
- const hook = tracingChannel();
13612
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13613
- };
13614
- };
13615
- return [
13616
- key,
13617
- {
13618
- ...syncSpec,
13619
- instrumentationName,
13620
- intercept,
13621
- invoke: (target, thisArg, args, additional) => {
13622
- const hook = tracingChannel();
13623
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13624
- },
13625
- tracingChannel,
13626
- traceSync: (fn, context) => tracingChannel().traceSync(
13627
- fn,
13628
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13629
- context
13630
- )
13631
- }
13632
- ];
13633
- })
13634
- );
13725
+ } catch {
13726
+ }
13727
+ }
13728
+ return metadata;
13729
+ }
13730
+ function extractOpenAIBatchInput(endpoint, params) {
13731
+ const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
13732
+ return {
13733
+ input: processInputAttachments(input),
13734
+ metadata: batchMetadata(params)
13735
+ };
13736
+ }
13737
+ function extractOpenAIChatInput(params) {
13738
+ const { messages, ...metadata } = params;
13739
+ return {
13740
+ input: processInputAttachments(messages),
13741
+ metadata: { ...metadata, provider: "openai" }
13742
+ };
13743
+ }
13744
+ function extractOpenAIResponsesInput(params) {
13745
+ const { input, ...metadata } = params;
13746
+ return {
13747
+ input: processInputAttachments(input),
13748
+ metadata: { ...metadata, provider: "openai" }
13749
+ };
13750
+ }
13751
+ function extractOpenAIResponsesMetadata(result) {
13752
+ if (!result) {
13753
+ return void 0;
13754
+ }
13755
+ const { output: _output, usage: _usage, ...metadata } = result;
13756
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
13757
+ }
13758
+ function processImagesInOutput(output) {
13759
+ if (Array.isArray(output)) {
13760
+ return output.map(processImagesInOutput);
13761
+ }
13762
+ if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
13763
+ const fileExtension = output.output_format || "png";
13764
+ const contentType = `image/${fileExtension}`;
13765
+ const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13766
+ let binaryString;
13767
+ try {
13768
+ binaryString = atob(output.result);
13769
+ } catch {
13770
+ return output;
13771
+ }
13772
+ const bytes = new Uint8Array(binaryString.length);
13773
+ for (let i = 0; i < binaryString.length; i++) {
13774
+ bytes[i] = binaryString.charCodeAt(i);
13775
+ }
13776
+ return {
13777
+ ...output,
13778
+ result: new Attachment({
13779
+ data: new Blob([bytes], { type: contentType }),
13780
+ filename: `${baseFilename}.${fileExtension}`,
13781
+ contentType
13782
+ })
13783
+ };
13784
+ }
13785
+ return output;
13635
13786
  }
13636
-
13637
- // src/instrumentation/plugins/openai-channels.ts
13638
- var openAIChannels = defineChannels(
13639
- "openai",
13640
- {
13641
- chatCompletionsCreate: channel({
13642
- channelName: "chat.completions.create",
13643
- kind: "async"
13644
- }),
13645
- embeddingsCreate: channel({
13646
- channelName: "embeddings.create",
13647
- kind: "async"
13648
- }),
13649
- betaChatCompletionsParse: channel({
13650
- channelName: "beta.chat.completions.parse",
13651
- kind: "async"
13652
- }),
13653
- betaChatCompletionsStream: channel({
13654
- channelName: "beta.chat.completions.stream",
13655
- kind: "sync-stream"
13656
- }),
13657
- moderationsCreate: channel({
13658
- channelName: "moderations.create",
13659
- kind: "async"
13660
- }),
13661
- responsesCreate: channel({
13662
- channelName: "responses.create",
13663
- kind: "async"
13664
- }),
13665
- responsesStream: channel({
13666
- channelName: "responses.stream",
13667
- kind: "sync-stream"
13668
- }),
13669
- responsesParse: channel({
13670
- channelName: "responses.parse",
13671
- kind: "async"
13672
- }),
13673
- responsesCompact: channel({
13674
- channelName: "responses.compact",
13675
- kind: "async"
13676
- })
13677
- },
13678
- { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13679
- );
13680
13787
 
13681
13788
  // src/openai-utils.ts
13682
13789
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
@@ -13733,23 +13840,573 @@ function getCachedMetricFromHeaders(headers) {
13733
13840
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13734
13841
  }
13735
13842
 
13843
+ // src/instrumentation/plugins/openai-batch-instrumentation.ts
13844
+ var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
13845
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
13846
+ "completed",
13847
+ "failed",
13848
+ "expired",
13849
+ "cancelled"
13850
+ ]);
13851
+ var pendingBatchTraces = /* @__PURE__ */ new Map();
13852
+ function read(value, key) {
13853
+ if (!isObject(value)) {
13854
+ return void 0;
13855
+ }
13856
+ try {
13857
+ return Reflect.get(value, key);
13858
+ } catch {
13859
+ return void 0;
13860
+ }
13861
+ }
13862
+ function isBatchRecordIterable(value) {
13863
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
13864
+ return false;
13865
+ }
13866
+ return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
13867
+ }
13868
+ function validCustomId(value) {
13869
+ return typeof value === "string" && value.length > 0 && value.length <= 64;
13870
+ }
13871
+ function logBatchInstrumentationError(context, error) {
13872
+ debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
13873
+ }
13874
+ async function exportParent(parent) {
13875
+ if ("toStr" in parent && typeof parent.toStr === "function") {
13876
+ return parent.toStr();
13877
+ }
13878
+ if ("export" in parent && typeof parent.export === "function") {
13879
+ return await parent.export();
13880
+ }
13881
+ return void 0;
13882
+ }
13883
+ async function deterministicDigest(namespace, ...parts) {
13884
+ const encoded = new TextEncoder().encode(
13885
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13886
+ );
13887
+ return new Uint8Array(
13888
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
13889
+ );
13890
+ }
13891
+ function digestHex(bytes, length) {
13892
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13893
+ }
13894
+ function digestUuid(bytes) {
13895
+ const hex = digestHex(bytes, 16);
13896
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13897
+ }
13898
+ async function batchSpanIds(inputFileId) {
13899
+ const [row, span, root] = await Promise.all([
13900
+ deterministicDigest("openai:batch:row", inputFileId),
13901
+ deterministicDigest("openai:batch:span", inputFileId),
13902
+ deterministicDigest("openai:batch:root", inputFileId)
13903
+ ]);
13904
+ return {
13905
+ rowId: digestUuid(row),
13906
+ spanId: digestHex(span, 8),
13907
+ rootSpanId: digestHex(root, 16)
13908
+ };
13909
+ }
13910
+ async function childSpanIds(inputFileId, customId) {
13911
+ const [row, span] = await Promise.all([
13912
+ deterministicDigest("openai:batch:child:row", inputFileId, customId),
13913
+ deterministicDigest("openai:batch:child:span", inputFileId, customId)
13914
+ ]);
13915
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
13916
+ }
13917
+ async function startBatchSpan(context) {
13918
+ const ids = await batchSpanIds(context.inputFileId);
13919
+ const parent = SpanComponentsV4.fromStr(context.parent);
13920
+ const hasParentSpan = Boolean(
13921
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
13922
+ );
13923
+ return withCurrent(
13924
+ NOOP_SPAN,
13925
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
13926
+ withSpanInstrumentationName(
13927
+ {
13928
+ name: "openai.batch",
13929
+ type: "task" /* TASK */,
13930
+ parent: context.parent,
13931
+ ...!hasParentSpan ? {
13932
+ parentSpanIds: {
13933
+ parentSpanIds: [],
13934
+ rootSpanId: ids.rootSpanId
13935
+ }
13936
+ } : {},
13937
+ spanId: ids.spanId,
13938
+ startTime: context.taskStartTime,
13939
+ event: {
13940
+ id: ids.rowId,
13941
+ metadata: {
13942
+ endpoint: context.endpoint,
13943
+ input_file_id: context.inputFileId,
13944
+ provider: "openai"
13945
+ }
13946
+ }
13947
+ },
13948
+ INSTRUMENTATION_NAMES.OPENAI
13949
+ )
13950
+ )
13951
+ );
13952
+ }
13953
+ async function startBatchChild(context, taskParent, input) {
13954
+ const ids = await childSpanIds(context.inputFileId, input.customId);
13955
+ return withCurrent(
13956
+ NOOP_SPAN,
13957
+ () => _internalStartSpanWithInitialMerge(
13958
+ withSpanInstrumentationName(
13959
+ {
13960
+ name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
13961
+ type: "llm" /* LLM */,
13962
+ parent: taskParent,
13963
+ spanId: ids.spanId,
13964
+ startTime: context.childStartTime,
13965
+ event: {
13966
+ id: ids.rowId,
13967
+ ...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
13968
+ metadata: {
13969
+ ...input.spanData?.metadata,
13970
+ custom_id: input.customId,
13971
+ provider: "openai"
13972
+ }
13973
+ }
13974
+ },
13975
+ INSTRUMENTATION_NAMES.OPENAI
13976
+ )
13977
+ )
13978
+ );
13979
+ }
13980
+ async function* jsonlRecords(file, onIssue = () => {
13981
+ }) {
13982
+ const resolvedFile = await file;
13983
+ if (typeof resolvedFile === "string") {
13984
+ for (const line of resolvedFile.split("\n")) {
13985
+ if (!line.trim()) {
13986
+ continue;
13987
+ }
13988
+ try {
13989
+ yield JSON.parse(line.replace(/\r$/, ""));
13990
+ } catch (error) {
13991
+ logBatchInstrumentationError("skipped malformed JSONL", error);
13992
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
13993
+ }
13994
+ }
13995
+ return;
13996
+ }
13997
+ const body = read(resolvedFile, "body");
13998
+ const getReader = read(body, "getReader");
13999
+ if (isObject(body) && typeof getReader === "function") {
14000
+ let reader;
14001
+ try {
14002
+ reader = Reflect.apply(getReader, body, []);
14003
+ const decoder2 = new TextDecoder();
14004
+ let pending = "";
14005
+ while (true) {
14006
+ const readChunk = read(reader, "read");
14007
+ if (typeof readChunk !== "function") {
14008
+ throw new Error("Response body stream has no read method");
14009
+ }
14010
+ const chunk = await Reflect.apply(readChunk, reader, []);
14011
+ if (!isObject(chunk)) {
14012
+ throw new Error("Response body stream returned an invalid chunk");
14013
+ }
14014
+ if (chunk.done === true) {
14015
+ pending += decoder2.decode();
14016
+ break;
14017
+ }
14018
+ if (!(chunk.value instanceof Uint8Array)) {
14019
+ throw new Error("Response body stream returned a non-byte chunk");
14020
+ }
14021
+ pending += decoder2.decode(chunk.value, { stream: true });
14022
+ let newline = pending.indexOf("\n");
14023
+ while (newline !== -1) {
14024
+ const line = pending.slice(0, newline).replace(/\r$/, "");
14025
+ pending = pending.slice(newline + 1);
14026
+ if (line.trim()) {
14027
+ try {
14028
+ yield JSON.parse(line);
14029
+ } catch (error) {
14030
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14031
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14032
+ }
14033
+ }
14034
+ newline = pending.indexOf("\n");
14035
+ }
14036
+ }
14037
+ if (pending.trim()) {
14038
+ try {
14039
+ yield JSON.parse(pending.replace(/\r$/, ""));
14040
+ } catch (error) {
14041
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14042
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14043
+ }
14044
+ }
14045
+ } catch (error) {
14046
+ logBatchInstrumentationError("could not read JSONL response body", error);
14047
+ onIssue(new Error("OpenAI Batch response body could not be read"));
14048
+ } finally {
14049
+ const releaseLock = read(reader, "releaseLock");
14050
+ if (typeof releaseLock === "function") {
14051
+ try {
14052
+ Reflect.apply(releaseLock, reader, []);
14053
+ } catch (error) {
14054
+ logBatchInstrumentationError(
14055
+ "could not release stream reader",
14056
+ error
14057
+ );
14058
+ }
14059
+ }
14060
+ }
14061
+ return;
14062
+ }
14063
+ if (isBatchRecordIterable(resolvedFile)) {
14064
+ for await (const record of resolvedFile) {
14065
+ yield record;
14066
+ }
14067
+ return;
14068
+ }
14069
+ logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
14070
+ onIssue(new Error("OpenAI Batch file source is invalid"));
14071
+ }
14072
+ async function readBatchInputs(file) {
14073
+ const inputs = /* @__PURE__ */ new Map();
14074
+ const issues = [];
14075
+ let endpoint;
14076
+ try {
14077
+ for await (const value of jsonlRecords(
14078
+ file,
14079
+ (issue) => issues.push(issue)
14080
+ )) {
14081
+ const customId = read(value, "custom_id");
14082
+ const url = read(value, "url");
14083
+ const body = read(value, "body");
14084
+ if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
14085
+ issues.push(new Error("OpenAI Batch input contains an invalid record"));
14086
+ continue;
14087
+ }
14088
+ endpoint = url;
14089
+ let spanData;
14090
+ try {
14091
+ spanData = extractOpenAIBatchInput(url, body);
14092
+ } catch (error) {
14093
+ logBatchInstrumentationError("could not extract batch input", error);
14094
+ }
14095
+ inputs.set(customId, { customId, spanData });
14096
+ }
14097
+ } catch (error) {
14098
+ logBatchInstrumentationError("could not process input file", error);
14099
+ issues.push(new Error("OpenAI Batch input file could not be processed"));
14100
+ }
14101
+ if (!endpoint || inputs.size === 0) {
14102
+ issues.push(new Error("OpenAI Batch input contains no supported records"));
14103
+ }
14104
+ return { endpoint, inputs, issues };
14105
+ }
14106
+ async function writePendingSpans(trace, endTime) {
14107
+ const task = await startBatchSpan(trace.context);
14108
+ const taskParent = await task.export();
14109
+ for (const input of trace.inputs.values()) {
14110
+ try {
14111
+ const child = await startBatchChild(trace.context, taskParent, input);
14112
+ if (endTime !== void 0) {
14113
+ child.end({ endTime });
14114
+ }
14115
+ } catch (error) {
14116
+ logBatchInstrumentationError("could not write batch request span", error);
14117
+ }
14118
+ }
14119
+ if (endTime !== void 0) {
14120
+ if (trace.status && trace.status !== "completed") {
14121
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14122
+ }
14123
+ task.end({ endTime });
14124
+ }
14125
+ }
14126
+ var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
14127
+ const startTime = getCurrentUnixTimestamp();
14128
+ const inputPromise = readBatchInputs(args[0].inputFileContent);
14129
+ const parentPromise = exportParent(args[0].parent);
14130
+ const file = await Reflect.apply(target, thisArg, args);
14131
+ try {
14132
+ const inputFileId = read(file, "id");
14133
+ const [inputData, exportedParent2] = await Promise.all([
14134
+ inputPromise,
14135
+ parentPromise
14136
+ ]);
14137
+ if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
14138
+ if (inputData.issues[0]) {
14139
+ logBatchInstrumentationError(
14140
+ "skipped invalid input file",
14141
+ inputData.issues[0]
14142
+ );
14143
+ }
14144
+ return file;
14145
+ }
14146
+ const trace = {
14147
+ context: {
14148
+ inputFileId,
14149
+ endpoint: inputData.endpoint,
14150
+ parent: exportedParent2,
14151
+ taskStartTime: startTime,
14152
+ childStartTime: startTime
14153
+ },
14154
+ inputs: inputData.inputs
14155
+ };
14156
+ pendingBatchTraces.set(inputFileId, trace);
14157
+ await writePendingSpans(trace);
14158
+ } catch (error) {
14159
+ logBatchInstrumentationError("could not start batch spans", error);
14160
+ }
14161
+ return file;
14162
+ };
14163
+ function validTimestamp(value) {
14164
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
14165
+ }
14166
+ function terminalEndTime(batch, startTime) {
14167
+ let timestamp;
14168
+ switch (batch.status) {
14169
+ case "completed":
14170
+ timestamp = batch.completed_at;
14171
+ break;
14172
+ case "failed":
14173
+ timestamp = batch.failed_at;
14174
+ break;
14175
+ case "expired":
14176
+ timestamp = batch.expired_at;
14177
+ break;
14178
+ default:
14179
+ timestamp = batch.cancelled_at;
14180
+ }
14181
+ return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
14182
+ }
14183
+ async function updateBatchTimestamps(batch) {
14184
+ const trace = pendingBatchTraces.get(batch.input_file_id);
14185
+ if (!trace || trace.context.endpoint !== batch.endpoint) {
14186
+ return;
14187
+ }
14188
+ if (validTimestamp(batch.created_at)) {
14189
+ trace.context.taskStartTime = batch.created_at;
14190
+ }
14191
+ trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
14192
+ trace.status = batch.status;
14193
+ if (TERMINAL_STATUSES.has(batch.status)) {
14194
+ trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
14195
+ }
14196
+ await writePendingSpans(trace, trace.endTime);
14197
+ }
14198
+ var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
14199
+ try {
14200
+ await updateBatchTimestamps(batch);
14201
+ } catch (error) {
14202
+ logBatchInstrumentationError("could not update batch timestamps", error);
14203
+ }
14204
+ return batch;
14205
+ });
14206
+ function errorFromResult(result) {
14207
+ const error = read(result.value, "error");
14208
+ if (isObject(error)) {
14209
+ const message = read(error, "message");
14210
+ return new Error(
14211
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14212
+ );
14213
+ }
14214
+ const response = read(result.value, "response");
14215
+ const statusCode = read(response, "status_code");
14216
+ if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
14217
+ const message = read(read(read(response, "body"), "error"), "message");
14218
+ return new Error(
14219
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14220
+ );
14221
+ }
14222
+ return void 0;
14223
+ }
14224
+ async function completeBatchResult(context, taskParent, endTime, input, result) {
14225
+ const child = await startBatchChild(context, taskParent, input);
14226
+ try {
14227
+ const resultError = errorFromResult(result);
14228
+ const responseBody = read(read(result.value, "response"), "body");
14229
+ if (resultError) {
14230
+ child.log({ error: resultError });
14231
+ } else if (isObject(responseBody)) {
14232
+ const model = read(responseBody, "model");
14233
+ child.log({
14234
+ output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
14235
+ ...typeof model === "string" ? { metadata: { model } } : {},
14236
+ metrics: parseMetricsFromUsage(read(responseBody, "usage"))
14237
+ });
14238
+ } else {
14239
+ child.log({ error: new Error("OpenAI Batch response body is missing") });
14240
+ }
14241
+ } catch (error) {
14242
+ child.log({ error });
14243
+ } finally {
14244
+ child.end({ endTime });
14245
+ }
14246
+ }
14247
+ async function completeResultFile({
14248
+ context,
14249
+ endTime,
14250
+ file,
14251
+ inputs,
14252
+ issues,
14253
+ seen,
14254
+ source,
14255
+ taskParent
14256
+ }) {
14257
+ if (file === void 0) {
14258
+ return;
14259
+ }
14260
+ for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
14261
+ const customId = read(value, "custom_id");
14262
+ if (!validCustomId(customId) || !isObject(value)) {
14263
+ issues.push(
14264
+ new Error("OpenAI Batch result is missing a valid custom_id")
14265
+ );
14266
+ continue;
14267
+ }
14268
+ if (seen.has(customId)) {
14269
+ issues.push(new Error("OpenAI Batch result contains a duplicate"));
14270
+ continue;
14271
+ }
14272
+ const input = inputs.get(customId);
14273
+ if (!input) {
14274
+ issues.push(
14275
+ new Error("OpenAI Batch result does not match an input record")
14276
+ );
14277
+ continue;
14278
+ }
14279
+ seen.add(customId);
14280
+ await completeBatchResult(context, taskParent, endTime, input, {
14281
+ value,
14282
+ source
14283
+ });
14284
+ }
14285
+ }
14286
+ function sameInputs(first, second) {
14287
+ return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
14288
+ }
14289
+ async function contextForCompletion(inputFileId, inputData) {
14290
+ if (!inputData.endpoint || inputData.issues.length > 0) {
14291
+ return void 0;
14292
+ }
14293
+ const existing = pendingBatchTraces.get(inputFileId);
14294
+ if (existing) {
14295
+ if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
14296
+ return void 0;
14297
+ }
14298
+ return { ...existing, inputs: inputData.inputs };
14299
+ }
14300
+ const parent = await exportParent(getSpanParentObject());
14301
+ if (!parent) {
14302
+ return void 0;
14303
+ }
14304
+ const startTime = getCurrentUnixTimestamp();
14305
+ return {
14306
+ context: {
14307
+ inputFileId,
14308
+ endpoint: inputData.endpoint,
14309
+ parent,
14310
+ taskStartTime: startTime,
14311
+ childStartTime: startTime
14312
+ },
14313
+ inputs: inputData.inputs
14314
+ };
14315
+ }
14316
+ async function completeBatch(args) {
14317
+ const inputData = await readBatchInputs(args.inputFileContent);
14318
+ const trace = await contextForCompletion(args.inputFileId, inputData);
14319
+ if (!trace) {
14320
+ logBatchInstrumentationError(
14321
+ "left batch spans pending",
14322
+ inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
14323
+ );
14324
+ return;
14325
+ }
14326
+ const endTime = trace.endTime ?? getCurrentUnixTimestamp();
14327
+ const task = await startBatchSpan(trace.context);
14328
+ const taskParent = await task.export();
14329
+ const issues = [];
14330
+ const seen = /* @__PURE__ */ new Set();
14331
+ await Promise.all([
14332
+ completeResultFile({
14333
+ context: trace.context,
14334
+ endTime,
14335
+ file: args.outputFileContent,
14336
+ inputs: trace.inputs,
14337
+ issues,
14338
+ seen,
14339
+ source: "output",
14340
+ taskParent
14341
+ }),
14342
+ completeResultFile({
14343
+ context: trace.context,
14344
+ endTime,
14345
+ file: args.errorFileContent,
14346
+ inputs: trace.inputs,
14347
+ issues,
14348
+ seen,
14349
+ source: "error",
14350
+ taskParent
14351
+ })
14352
+ ]);
14353
+ if (issues.length > 0) {
14354
+ logBatchInstrumentationError("left batch spans pending", issues[0]);
14355
+ return;
14356
+ }
14357
+ const missing = [...trace.inputs.values()].filter(
14358
+ ({ customId }) => !seen.has(customId)
14359
+ );
14360
+ if (!trace.status || trace.status === "completed") {
14361
+ if (missing.length > 0) {
14362
+ logBatchInstrumentationError(
14363
+ "left batch spans pending",
14364
+ new Error("OpenAI Batch result files are incomplete")
14365
+ );
14366
+ return;
14367
+ }
14368
+ } else {
14369
+ for (const input of missing) {
14370
+ const child = await startBatchChild(trace.context, taskParent, input);
14371
+ child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14372
+ child.end({ endTime });
14373
+ }
14374
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14375
+ }
14376
+ task.end({ endTime });
14377
+ pendingBatchTraces.delete(args.inputFileId);
14378
+ }
14379
+ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
14380
+ try {
14381
+ await completeBatch(args[0]);
14382
+ } catch (error) {
14383
+ logBatchInstrumentationError("could not complete batch", error);
14384
+ }
14385
+ return result;
14386
+ });
14387
+
13736
14388
  // src/instrumentation/plugins/openai-plugin.ts
13737
14389
  var OpenAIPlugin = class extends BasePlugin {
13738
14390
  constructor() {
13739
14391
  super();
13740
14392
  }
13741
14393
  onEnable() {
14394
+ this.unsubscribers.push(
14395
+ openAIChannels.filesCreateTraced.intercept(
14396
+ interceptOpenAIFilesCreateTraced
14397
+ ),
14398
+ openAIChannels.batchesRetrieveTraced.intercept(
14399
+ interceptOpenAIBatchesRetrieveTraced
14400
+ ),
14401
+ openAIChannels.batchesCompleteTrace.intercept(
14402
+ interceptOpenAIBatchTraceComplete
14403
+ )
14404
+ );
13742
14405
  this.unsubscribers.push(
13743
14406
  traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
13744
14407
  name: "Chat Completion",
13745
14408
  type: "llm" /* LLM */,
13746
- extractInput: ([params]) => {
13747
- const { messages, ...metadata } = params;
13748
- return {
13749
- input: processInputAttachments(messages),
13750
- metadata: { ...metadata, provider: "openai" }
13751
- };
13752
- },
14409
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13753
14410
  extractOutput: (result) => {
13754
14411
  return result?.choices;
13755
14412
  },
@@ -13795,13 +14452,7 @@ var OpenAIPlugin = class extends BasePlugin {
13795
14452
  traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
13796
14453
  name: "Chat Completion",
13797
14454
  type: "llm" /* LLM */,
13798
- extractInput: ([params]) => {
13799
- const { messages, ...metadata } = params;
13800
- return {
13801
- input: processInputAttachments(messages),
13802
- metadata: { ...metadata, provider: "openai" }
13803
- };
13804
- },
14455
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13805
14456
  extractOutput: (result) => {
13806
14457
  return result?.choices;
13807
14458
  },
@@ -13823,13 +14474,7 @@ var OpenAIPlugin = class extends BasePlugin {
13823
14474
  traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
13824
14475
  name: "Chat Completion",
13825
14476
  type: "llm" /* LLM */,
13826
- extractInput: ([params]) => {
13827
- const { messages, ...metadata } = params;
13828
- return {
13829
- input: processInputAttachments(messages),
13830
- metadata: { ...metadata, provider: "openai" }
13831
- };
13832
- }
14477
+ extractInput: ([params]) => extractOpenAIChatInput(params)
13833
14478
  })
13834
14479
  );
13835
14480
  this.unsubscribers.push(
@@ -13859,23 +14504,11 @@ var OpenAIPlugin = class extends BasePlugin {
13859
14504
  traceStreamingChannel(openAIChannels.responsesCreate, {
13860
14505
  name: "openai.responses.create",
13861
14506
  type: "llm" /* LLM */,
13862
- extractInput: ([params]) => {
13863
- const { input, ...metadata } = params;
13864
- return {
13865
- input: processInputAttachments(input),
13866
- metadata: { ...metadata, provider: "openai" }
13867
- };
13868
- },
14507
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13869
14508
  extractOutput: (result) => {
13870
14509
  return processImagesInOutput(result?.output);
13871
14510
  },
13872
- extractMetadata: (result) => {
13873
- if (!result) {
13874
- return void 0;
13875
- }
13876
- const { output: _output, usage: _usage, ...metadata } = result;
13877
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13878
- },
14511
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13879
14512
  extractMetrics: (result, startTime, endEvent) => {
13880
14513
  const metrics = withCachedMetric(
13881
14514
  parseMetricsFromUsage(result?.usage),
@@ -13894,13 +14527,7 @@ var OpenAIPlugin = class extends BasePlugin {
13894
14527
  traceSyncStreamChannel(openAIChannels.responsesStream, {
13895
14528
  name: "openai.responses.create",
13896
14529
  type: "llm" /* LLM */,
13897
- extractInput: ([params]) => {
13898
- const { input, ...metadata } = params;
13899
- return {
13900
- input: processInputAttachments(input),
13901
- metadata: { ...metadata, provider: "openai" }
13902
- };
13903
- },
14530
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13904
14531
  extractFromEvent: (event) => {
13905
14532
  if (event.type !== "response.completed" || !event.response) {
13906
14533
  return {};
@@ -13923,23 +14550,11 @@ var OpenAIPlugin = class extends BasePlugin {
13923
14550
  traceStreamingChannel(openAIChannels.responsesParse, {
13924
14551
  name: "openai.responses.parse",
13925
14552
  type: "llm" /* LLM */,
13926
- extractInput: ([params]) => {
13927
- const { input, ...metadata } = params;
13928
- return {
13929
- input: processInputAttachments(input),
13930
- metadata: { ...metadata, provider: "openai" }
13931
- };
13932
- },
14553
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13933
14554
  extractOutput: (result) => {
13934
14555
  return processImagesInOutput(result?.output);
13935
14556
  },
13936
- extractMetadata: (result) => {
13937
- if (!result) {
13938
- return void 0;
13939
- }
13940
- const { output: _output, usage: _usage, ...metadata } = result;
13941
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13942
- },
14557
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13943
14558
  extractMetrics: (result, startTime, endEvent) => {
13944
14559
  const metrics = withCachedMetric(
13945
14560
  parseMetricsFromUsage(result?.usage),
@@ -13958,23 +14573,11 @@ var OpenAIPlugin = class extends BasePlugin {
13958
14573
  traceAsyncChannel(openAIChannels.responsesCompact, {
13959
14574
  name: "openai.responses.compact",
13960
14575
  type: "llm" /* LLM */,
13961
- extractInput: ([params]) => {
13962
- const { input, ...metadata } = params;
13963
- return {
13964
- input: processInputAttachments(input),
13965
- metadata: { ...metadata, provider: "openai" }
13966
- };
13967
- },
14576
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13968
14577
  extractOutput: (result) => {
13969
14578
  return processImagesInOutput(result?.output);
13970
14579
  },
13971
- extractMetadata: (result) => {
13972
- if (!result) {
13973
- return void 0;
13974
- }
13975
- const { output: _output, usage: _usage, ...metadata } = result;
13976
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13977
- },
14580
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13978
14581
  extractMetrics: (result, startTime, endEvent) => {
13979
14582
  const metrics = withCachedMetric(
13980
14583
  parseMetricsFromUsage(result?.usage),
@@ -14030,35 +14633,6 @@ function withCachedMetric(metrics, result, endEvent) {
14030
14633
  cached
14031
14634
  };
14032
14635
  }
14033
- function processImagesInOutput(output) {
14034
- if (Array.isArray(output)) {
14035
- return output.map(processImagesInOutput);
14036
- }
14037
- if (isObject(output)) {
14038
- if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
14039
- const fileExtension = output.output_format || "png";
14040
- const contentType = `image/${fileExtension}`;
14041
- const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
14042
- const filename = `${baseFilename}.${fileExtension}`;
14043
- const binaryString = atob(output.result);
14044
- const bytes = new Uint8Array(binaryString.length);
14045
- for (let i = 0; i < binaryString.length; i++) {
14046
- bytes[i] = binaryString.charCodeAt(i);
14047
- }
14048
- const blob = new Blob([bytes], { type: contentType });
14049
- const attachment = new Attachment({
14050
- data: blob,
14051
- filename,
14052
- contentType
14053
- });
14054
- return {
14055
- ...output,
14056
- result: attachment
14057
- };
14058
- }
14059
- }
14060
- return output;
14061
- }
14062
14636
  function mergeLogprobTokens(existing, incoming) {
14063
14637
  if (incoming === void 0) {
14064
14638
  return existing;
@@ -34091,7 +34665,7 @@ function extractSession(event) {
34091
34665
  return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
34092
34666
  }
34093
34667
  function isPiAgent(value) {
34094
- return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
34668
+ return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
34095
34669
  }
34096
34670
  function promptContextStore() {
34097
34671
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
@@ -34101,17 +34675,21 @@ function currentPiPromptState() {
34101
34675
  return promptContextStore().getStore();
34102
34676
  }
34103
34677
  function installPiAgentInstrumentation(agent) {
34678
+ const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
34679
+ const streamFunction = agent[property];
34104
34680
  const existing = piAgentPatchStates.get(agent);
34105
- if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
34681
+ if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
34106
34682
  const patchState = {
34107
- originalStreamFn: agent.streamFn,
34108
- wrappedStreamFn: agent.streamFn
34683
+ originalStreamFunction: streamFunction,
34684
+ property,
34685
+ wrappedStreamFunction: streamFunction
34109
34686
  };
34110
- patchState.wrappedStreamFn = makeInstrumentedStreamFn(
34687
+ patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
34111
34688
  agent,
34112
- patchState.originalStreamFn
34689
+ patchState.originalStreamFunction,
34690
+ property
34113
34691
  );
34114
- agent.streamFn = patchState.wrappedStreamFn;
34692
+ agent[property] = patchState.wrappedStreamFunction;
34115
34693
  piAgentPatchStates.set(agent, patchState);
34116
34694
  }
34117
34695
  if (piAgentEventSubscriptions.has(agent)) {
@@ -34136,15 +34714,21 @@ function installPiAgentInstrumentation(agent) {
34136
34714
  logInstrumentationError4("Pi Coding Agent event subscription", error);
34137
34715
  }
34138
34716
  }
34139
- function makeInstrumentedStreamFn(agent, originalStreamFn) {
34140
- return async function instrumentedPiStreamFn(model, context, options) {
34141
- const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
34717
+ function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
34718
+ return async function instrumentedPiStreamFunction(model, context, options) {
34719
+ const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
34142
34720
  const state = currentPiPromptState();
34143
34721
  if (!state || state.agent !== agent || state.finalized) {
34144
34722
  return invokeOriginal();
34145
34723
  }
34146
34724
  wrapPiToolExecutors(context.tools);
34147
- const llmState = await startPiLlmSpan(state, model, context, options);
34725
+ const llmState = await startPiLlmSpan(
34726
+ state,
34727
+ model,
34728
+ context,
34729
+ property,
34730
+ options
34731
+ );
34148
34732
  try {
34149
34733
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
34150
34734
  return patchAssistantMessageStream(stream, state, llmState);
@@ -34181,12 +34765,12 @@ function wrapPiToolExecutors(tools) {
34181
34765
  }
34182
34766
  }
34183
34767
  }
34184
- async function startPiLlmSpan(state, model, context, options) {
34768
+ async function startPiLlmSpan(state, model, context, property, options) {
34185
34769
  const metadata = {
34186
34770
  ...extractModelMetadata2(model),
34187
34771
  ...extractStreamOptionsMetadata(options),
34188
34772
  ...extractToolMetadata(context.tools),
34189
- "pi_coding_agent.operation": "agent.streamFn"
34773
+ "pi_coding_agent.operation": `agent.${property}`
34190
34774
  };
34191
34775
  const span = startSpan(
34192
34776
  withSpanInstrumentationName(
@@ -37204,6 +37788,7 @@ __export(exports_exports, {
37204
37788
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
37205
37789
  buildLocalSummary: () => buildLocalSummary,
37206
37790
  collectAnthropicSession: () => collectAnthropicSession,
37791
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
37207
37792
  configureInstrumentation: () => configureInstrumentation,
37208
37793
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
37209
37794
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -37242,6 +37827,8 @@ __export(exports_exports, {
37242
37827
  loginToState: () => loginToState,
37243
37828
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
37244
37829
  newId: () => newId,
37830
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
37831
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
37245
37832
  parseCachedHeader: () => parseCachedHeader,
37246
37833
  parseTemplateFormat: () => parseTemplateFormat,
37247
37834
  permalink: () => permalink,
@@ -37406,6 +37993,260 @@ async function registerSandbox(options) {
37406
37993
  };
37407
37994
  }
37408
37995
 
37996
+ // src/wrappers/openai-promise-utils.ts
37997
+ function splitSpanInfo(allParams) {
37998
+ const { span_info, ...params } = allParams;
37999
+ return {
38000
+ params,
38001
+ span_info
38002
+ };
38003
+ }
38004
+ function createChannelContext(_channel, params, span_info) {
38005
+ return {
38006
+ arguments: (
38007
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38008
+ [params]
38009
+ ),
38010
+ span_info
38011
+ };
38012
+ }
38013
+ async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
38014
+ let enhancedResponse;
38015
+ const tracePromise = (
38016
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38017
+ channel2.tracePromise
38018
+ );
38019
+ const data = await tracePromise(async () => {
38020
+ enhancedResponse = await apiPromise.withResponse();
38021
+ traceContext.response = enhancedResponse.response;
38022
+ return enhancedResponse.data;
38023
+ }, traceContext);
38024
+ if (!enhancedResponse) {
38025
+ throw new Error("Expected withResponse() to provide response");
38026
+ }
38027
+ return {
38028
+ data,
38029
+ response: enhancedResponse.response,
38030
+ request_id: enhancedResponse.request_id
38031
+ };
38032
+ }
38033
+ async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
38034
+ const tracePromise = (
38035
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38036
+ channel2.tracePromise
38037
+ );
38038
+ let response;
38039
+ await tracePromise(async () => {
38040
+ response = await apiPromise.asResponse();
38041
+ traceContext.response = response;
38042
+ return void 0;
38043
+ }, traceContext);
38044
+ if (!response) {
38045
+ throw new Error("Expected asResponse() to provide response");
38046
+ }
38047
+ return response;
38048
+ }
38049
+ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
38050
+ let firstConsumption;
38051
+ let enhancedResponsePromise;
38052
+ let dataPromise;
38053
+ let responsePromise;
38054
+ const withResponse = () => {
38055
+ firstConsumption ??= "data";
38056
+ enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
38057
+ return enhancedResponsePromise;
38058
+ };
38059
+ const asResponse = () => {
38060
+ firstConsumption ??= "response";
38061
+ responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
38062
+ return responsePromise;
38063
+ };
38064
+ return new Proxy({}, {
38065
+ get(target, prop, receiver) {
38066
+ if (prop === "withResponse") {
38067
+ return withResponse;
38068
+ }
38069
+ if (prop === "asResponse") {
38070
+ return asResponse;
38071
+ }
38072
+ if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
38073
+ dataPromise ??= withResponse().then((result) => result.data);
38074
+ const value = Reflect.get(dataPromise, prop, receiver);
38075
+ return typeof value === "function" ? value.bind(dataPromise) : value;
38076
+ }
38077
+ return Reflect.get(target, prop, receiver);
38078
+ }
38079
+ });
38080
+ }
38081
+
38082
+ // src/openai-batch.ts
38083
+ function read2(value, key) {
38084
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
38085
+ return void 0;
38086
+ }
38087
+ try {
38088
+ return Reflect.get(value, key);
38089
+ } catch {
38090
+ return void 0;
38091
+ }
38092
+ }
38093
+ function isAsyncIterable5(value) {
38094
+ return typeof read2(value, Symbol.asyncIterator) === "function";
38095
+ }
38096
+ function teeAsyncIterable(source) {
38097
+ const iterator = source[Symbol.asyncIterator]();
38098
+ const stream = new ReadableStream({
38099
+ async pull(controller) {
38100
+ try {
38101
+ const result = await iterator.next();
38102
+ if (result.done) {
38103
+ controller.close();
38104
+ return;
38105
+ }
38106
+ if (!(result.value instanceof Uint8Array)) {
38107
+ throw new TypeError(
38108
+ "OpenAI upload streams must yield Uint8Array chunks"
38109
+ );
38110
+ }
38111
+ controller.enqueue(result.value);
38112
+ } catch (error) {
38113
+ controller.error(error);
38114
+ }
38115
+ },
38116
+ async cancel(reason) {
38117
+ await iterator.return?.(reason);
38118
+ }
38119
+ });
38120
+ const [uploadStream, trace] = stream.tee();
38121
+ const upload = {
38122
+ async *[Symbol.asyncIterator]() {
38123
+ const reader = uploadStream.getReader();
38124
+ try {
38125
+ while (true) {
38126
+ const result = await reader.read();
38127
+ if (result.done) {
38128
+ return;
38129
+ }
38130
+ yield result.value;
38131
+ }
38132
+ } finally {
38133
+ reader.releaseLock();
38134
+ }
38135
+ }
38136
+ };
38137
+ const path = read2(source, "path");
38138
+ if (typeof path === "string") {
38139
+ Object.defineProperty(upload, "path", { value: path });
38140
+ }
38141
+ return { upload, trace: new Response(trace) };
38142
+ }
38143
+ function teeUpload(upload) {
38144
+ if (upload instanceof Blob) {
38145
+ return { upload, trace: new Response(upload) };
38146
+ }
38147
+ if (upload instanceof Response) {
38148
+ return { upload, trace: upload.clone() };
38149
+ }
38150
+ if (isAsyncIterable5(upload)) {
38151
+ return teeAsyncIterable(upload);
38152
+ }
38153
+ return void 0;
38154
+ }
38155
+ function openaiFilesCreateTraced(files) {
38156
+ return (params, options) => {
38157
+ const parent = getSpanParentObject();
38158
+ const purpose = read2(params, "purpose");
38159
+ const file = read2(params, "file");
38160
+ if (purpose !== "batch") {
38161
+ return files.create(params, options);
38162
+ }
38163
+ let branches;
38164
+ try {
38165
+ branches = teeUpload(file);
38166
+ } catch {
38167
+ return files.create(params, options);
38168
+ }
38169
+ if (!branches) {
38170
+ return files.create(params, options);
38171
+ }
38172
+ const tracedParams = {
38173
+ ...Object(params),
38174
+ file: branches.upload
38175
+ };
38176
+ const apiPromise = files.create(tracedParams, options);
38177
+ let enhancedResponse;
38178
+ const tracedResponse = openAIChannels.filesCreateTraced.invoke(
38179
+ async () => {
38180
+ enhancedResponse = await apiPromise.withResponse();
38181
+ return enhancedResponse.data;
38182
+ },
38183
+ files,
38184
+ [{ params, inputFileContent: branches.trace, parent }],
38185
+ {}
38186
+ ).then((data) => {
38187
+ if (!enhancedResponse) {
38188
+ throw new Error(
38189
+ "Expected OpenAI withResponse() to provide a response"
38190
+ );
38191
+ }
38192
+ return { ...enhancedResponse, data };
38193
+ });
38194
+ return createLazyAPIPromise(
38195
+ () => tracedResponse,
38196
+ () => tracedResponse.then(({ response }) => response),
38197
+ () => apiPromise
38198
+ );
38199
+ };
38200
+ }
38201
+ function openaiBatchesRetrieveTraced(batches) {
38202
+ return (batchId, options) => {
38203
+ const apiPromise = batches.retrieve(batchId, options);
38204
+ let enhancedResponse;
38205
+ const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
38206
+ async () => {
38207
+ enhancedResponse = await apiPromise.withResponse();
38208
+ return enhancedResponse.data;
38209
+ },
38210
+ batches,
38211
+ [{ batchId }],
38212
+ {}
38213
+ ).then((data) => {
38214
+ if (!enhancedResponse) {
38215
+ throw new Error(
38216
+ "Expected OpenAI withResponse() to provide a response"
38217
+ );
38218
+ }
38219
+ return { ...enhancedResponse, data };
38220
+ });
38221
+ return createLazyAPIPromise(
38222
+ () => tracedResponse,
38223
+ () => tracedResponse.then(({ response }) => response),
38224
+ () => apiPromise
38225
+ );
38226
+ };
38227
+ }
38228
+ async function completeOpenAIBatchTrace(args) {
38229
+ const inputFileContent = Promise.resolve(args.inputFileContent);
38230
+ const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
38231
+ const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
38232
+ void inputFileContent.catch(() => void 0);
38233
+ void outputFileContent?.catch(() => void 0);
38234
+ void errorFileContent?.catch(() => void 0);
38235
+ await openAIChannels.batchesCompleteTrace.invoke(
38236
+ async () => void 0,
38237
+ void 0,
38238
+ [
38239
+ {
38240
+ ...args,
38241
+ inputFileContent,
38242
+ outputFileContent,
38243
+ errorFileContent
38244
+ }
38245
+ ],
38246
+ {}
38247
+ );
38248
+ }
38249
+
37409
38250
  // src/functions/invoke.ts
37410
38251
  async function invoke(args) {
37411
38252
  const {
@@ -37508,58 +38349,6 @@ function initFunction({
37508
38349
  return f;
37509
38350
  }
37510
38351
 
37511
- // src/wrappers/openai-promise-utils.ts
37512
- function splitSpanInfo(allParams) {
37513
- const { span_info, ...params } = allParams;
37514
- return {
37515
- params,
37516
- span_info
37517
- };
37518
- }
37519
- function createChannelContext(_channel, params, span_info) {
37520
- return {
37521
- arguments: (
37522
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37523
- [params]
37524
- ),
37525
- span_info
37526
- };
37527
- }
37528
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
37529
- let enhancedResponse;
37530
- const tracePromise = (
37531
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37532
- channel2.tracePromise
37533
- );
37534
- const data = await tracePromise(async () => {
37535
- enhancedResponse = await apiPromise.withResponse();
37536
- traceContext.response = enhancedResponse.response;
37537
- return enhancedResponse.data;
37538
- }, traceContext);
37539
- if (!enhancedResponse) {
37540
- throw new Error("Expected withResponse() to provide response");
37541
- }
37542
- return { data, response: enhancedResponse.response };
37543
- }
37544
- function createLazyAPIPromise(ensureExecuted) {
37545
- let dataPromise = null;
37546
- return new Proxy({}, {
37547
- get(target, prop, receiver) {
37548
- if (prop === "withResponse") {
37549
- return () => ensureExecuted();
37550
- }
37551
- if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
37552
- if (!dataPromise) {
37553
- dataPromise = ensureExecuted().then((result) => result.data);
37554
- }
37555
- const value = Reflect.get(dataPromise, prop, receiver);
37556
- return typeof value === "function" ? value.bind(dataPromise) : value;
37557
- }
37558
- return Reflect.get(target, prop, receiver);
37559
- }
37560
- });
37561
- }
37562
-
37563
38352
  // src/wrappers/oai_responses.ts
37564
38353
  function responsesProxy(openai) {
37565
38354
  if (!openai.responses) {
@@ -37596,17 +38385,33 @@ function wrapResponsesAsync(target, channel2) {
37596
38385
  return (allParams, options) => {
37597
38386
  const { span_info, params } = splitSpanInfo(allParams);
37598
38387
  let executionPromise = null;
38388
+ let apiPromise = null;
38389
+ const getAPIPromise = () => {
38390
+ apiPromise ??= target(params, options);
38391
+ return apiPromise;
38392
+ };
37599
38393
  const ensureExecuted = () => {
37600
38394
  if (!executionPromise) {
37601
38395
  executionPromise = (async () => {
37602
38396
  const traceContext = createChannelContext(channel2, params, span_info);
37603
- const apiPromise = target(params, options);
37604
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
38397
+ return tracePromiseWithResponse(
38398
+ channel2,
38399
+ traceContext,
38400
+ getAPIPromise()
38401
+ );
37605
38402
  })();
37606
38403
  }
37607
38404
  return executionPromise;
37608
38405
  };
37609
- return createLazyAPIPromise(ensureExecuted);
38406
+ return createLazyAPIPromise(
38407
+ ensureExecuted,
38408
+ () => tracePromiseAsResponse(
38409
+ channel2,
38410
+ createChannelContext(channel2, params, span_info),
38411
+ getAPIPromise()
38412
+ ),
38413
+ getAPIPromise
38414
+ );
37610
38415
  };
37611
38416
  }
37612
38417
  function wrapResponsesSyncStream(target, channel2) {
@@ -37752,6 +38557,11 @@ function wrapChatCompletion(completion) {
37752
38557
  allParams
37753
38558
  );
37754
38559
  let executionPromise = null;
38560
+ let apiPromise = null;
38561
+ const getAPIPromise = () => {
38562
+ apiPromise ??= completion(params, options);
38563
+ return apiPromise;
38564
+ };
37755
38565
  const ensureExecuted = () => {
37756
38566
  if (!executionPromise) {
37757
38567
  executionPromise = (async () => {
@@ -37761,32 +38571,44 @@ function wrapChatCompletion(completion) {
37761
38571
  span_info
37762
38572
  );
37763
38573
  if (params.stream) {
37764
- const completionPromise = completion(
37765
- params,
37766
- options
38574
+ const completionPromise = (
38575
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38576
+ getAPIPromise()
37767
38577
  );
37768
- const { data: data2, response: response2 } = await tracePromiseWithResponse(
38578
+ const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
37769
38579
  openAIChannels.chatCompletionsCreate,
37770
38580
  traceContext,
37771
38581
  completionPromise
37772
38582
  );
37773
- return { data: data2, response: response2 };
38583
+ return { data: data2, response: response2, request_id: request_id2 };
37774
38584
  }
37775
- const completionResponse = completion(
37776
- params,
37777
- options
38585
+ const completionResponse = (
38586
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38587
+ getAPIPromise()
37778
38588
  );
37779
- const { data, response } = await tracePromiseWithResponse(
38589
+ const { data, response, request_id } = await tracePromiseWithResponse(
37780
38590
  openAIChannels.chatCompletionsCreate,
37781
38591
  traceContext,
37782
38592
  completionResponse
37783
38593
  );
37784
- return { data, response };
38594
+ return { data, response, request_id };
37785
38595
  })();
37786
38596
  }
37787
38597
  return executionPromise;
37788
38598
  };
37789
- return createLazyAPIPromise(ensureExecuted);
38599
+ return createLazyAPIPromise(
38600
+ ensureExecuted,
38601
+ () => tracePromiseAsResponse(
38602
+ openAIChannels.chatCompletionsCreate,
38603
+ createChannelContext(
38604
+ openAIChannels.chatCompletionsCreate,
38605
+ params,
38606
+ span_info
38607
+ ),
38608
+ getAPIPromise()
38609
+ ),
38610
+ getAPIPromise
38611
+ );
37790
38612
  };
37791
38613
  }
37792
38614
  function createEndpointProxy(target, wrapperFn) {
@@ -37804,6 +38626,11 @@ function wrapApiCreateWithChannel(create, channel2) {
37804
38626
  return (allParams, options) => {
37805
38627
  const { span_info, params } = splitSpanInfo(allParams);
37806
38628
  let executionPromise = null;
38629
+ let apiPromise = null;
38630
+ const getAPIPromise = () => {
38631
+ apiPromise ??= create(params, options);
38632
+ return apiPromise;
38633
+ };
37807
38634
  const ensureExecuted = () => {
37808
38635
  if (!executionPromise) {
37809
38636
  executionPromise = (async () => {
@@ -37811,13 +38638,21 @@ function wrapApiCreateWithChannel(create, channel2) {
37811
38638
  return tracePromiseWithResponse(
37812
38639
  channel2,
37813
38640
  traceContext,
37814
- create(params, options)
38641
+ getAPIPromise()
37815
38642
  );
37816
38643
  })();
37817
38644
  }
37818
38645
  return executionPromise;
37819
38646
  };
37820
- return createLazyAPIPromise(ensureExecuted);
38647
+ return createLazyAPIPromise(
38648
+ ensureExecuted,
38649
+ () => tracePromiseAsResponse(
38650
+ channel2,
38651
+ createChannelContext(channel2, params, span_info),
38652
+ getAPIPromise()
38653
+ ),
38654
+ getAPIPromise
38655
+ );
37821
38656
  };
37822
38657
  }
37823
38658
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -40512,7 +41347,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
40512
41347
  function createEveInstrumentationProvider(options = {}) {
40513
41348
  const bridge = new EveProviderBridge(options.metadata);
40514
41349
  return {
41350
+ // Eve versions before tracePolicy use capture to decide whether provider
41351
+ // events include content. Newer versions prefer tracePolicy when both are
41352
+ // present, so keep the deprecated field for backwards compatibility.
40515
41353
  capture: "content",
41354
+ tracePolicy: () => ({
41355
+ emit: true,
41356
+ recordInputs: true,
41357
+ recordOutputs: true
41358
+ }),
40516
41359
  events: {
40517
41360
  "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
40518
41361
  "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
@@ -44941,7 +45784,7 @@ function isAsync(fn) {
44941
45784
  function isAsyncGenerator2(fn) {
44942
45785
  return fn[Symbol.toStringTag] === "AsyncGenerator";
44943
45786
  }
44944
- function isAsyncIterable5(obj) {
45787
+ function isAsyncIterable6(obj) {
44945
45788
  return typeof obj[Symbol.asyncIterator] === "function";
44946
45789
  }
44947
45790
  function wrapAsync(asyncFn) {
@@ -45113,7 +45956,7 @@ var eachOfLimit$2 = (limit) => {
45113
45956
  if (isAsyncGenerator2(obj)) {
45114
45957
  return asyncEachOfLimit(obj, limit, iteratee, callback);
45115
45958
  }
45116
- if (isAsyncIterable5(obj)) {
45959
+ if (isAsyncIterable6(obj)) {
45117
45960
  return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
45118
45961
  }
45119
45962
  var nextElem = createIterator(obj);
@@ -46468,7 +47311,7 @@ function callEvaluatorData(data) {
46468
47311
  baseExperiment
46469
47312
  };
46470
47313
  }
46471
- function isAsyncIterable6(value) {
47314
+ function isAsyncIterable7(value) {
46472
47315
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
46473
47316
  }
46474
47317
  function isIterable(value) {
@@ -46503,7 +47346,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
46503
47346
  }).asDataset();
46504
47347
  }
46505
47348
  const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
46506
- if (isAsyncIterable6(resolvedDataResult)) {
47349
+ if (isAsyncIterable7(resolvedDataResult)) {
46507
47350
  return resolvedDataResult;
46508
47351
  }
46509
47352
  if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
@@ -49551,6 +50394,7 @@ export {
49551
50394
  braintrustStreamChunkSchema,
49552
50395
  buildLocalSummary,
49553
50396
  collectAnthropicSession,
50397
+ completeOpenAIBatchTrace,
49554
50398
  configureInstrumentation,
49555
50399
  constructLogs3OverflowRequest,
49556
50400
  createFinalValuePassThroughStream,
@@ -49590,6 +50434,8 @@ export {
49590
50434
  loginToState,
49591
50435
  logs3OverflowUploadSchema,
49592
50436
  newId,
50437
+ openaiBatchesRetrieveTraced,
50438
+ openaiFilesCreateTraced,
49593
50439
  parseCachedHeader,
49594
50440
  parseTemplateFormat,
49595
50441
  permalink,