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
@@ -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,
@@ -13424,6 +13433,131 @@ function unsubscribeAll(unsubscribers) {
13424
13433
  return [];
13425
13434
  }
13426
13435
 
13436
+ // src/instrumentation/core/channel-definitions.ts
13437
+ function channel(spec) {
13438
+ return spec;
13439
+ }
13440
+ function defineChannels(pkg, channels, options) {
13441
+ const { instrumentationName } = options;
13442
+ return Object.fromEntries(
13443
+ Object.entries(channels).map(([key, spec]) => {
13444
+ const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13445
+ if (spec.kind === "async") {
13446
+ const asyncSpec = spec;
13447
+ const tracingChannel2 = () => isomorph_default.newTracingChannel(
13448
+ fullChannelName
13449
+ );
13450
+ const intercept2 = (interceptor) => {
13451
+ const hook = tracingChannel2();
13452
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13453
+ };
13454
+ };
13455
+ return [
13456
+ key,
13457
+ {
13458
+ ...asyncSpec,
13459
+ instrumentationName,
13460
+ intercept: intercept2,
13461
+ invoke: (target, thisArg, args, additional) => {
13462
+ const hook = tracingChannel2();
13463
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13464
+ },
13465
+ tracingChannel: tracingChannel2,
13466
+ tracePromise: (fn, context) => tracingChannel2().tracePromise(
13467
+ fn,
13468
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13469
+ context
13470
+ )
13471
+ }
13472
+ ];
13473
+ }
13474
+ const syncSpec = spec;
13475
+ const tracingChannel = () => isomorph_default.newTracingChannel(
13476
+ fullChannelName
13477
+ );
13478
+ const intercept = (interceptor) => {
13479
+ const hook = tracingChannel();
13480
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13481
+ };
13482
+ };
13483
+ return [
13484
+ key,
13485
+ {
13486
+ ...syncSpec,
13487
+ instrumentationName,
13488
+ intercept,
13489
+ invoke: (target, thisArg, args, additional) => {
13490
+ const hook = tracingChannel();
13491
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13492
+ },
13493
+ tracingChannel,
13494
+ traceSync: (fn, context) => tracingChannel().traceSync(
13495
+ fn,
13496
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13497
+ context
13498
+ )
13499
+ }
13500
+ ];
13501
+ })
13502
+ );
13503
+ }
13504
+
13505
+ // src/instrumentation/plugins/openai-channels.ts
13506
+ var openAIChannels = defineChannels(
13507
+ "openai",
13508
+ {
13509
+ filesCreateTraced: channel({
13510
+ channelName: "files.create-traced",
13511
+ kind: "async"
13512
+ }),
13513
+ batchesRetrieveTraced: channel({
13514
+ channelName: "batches.retrieve-traced",
13515
+ kind: "async"
13516
+ }),
13517
+ batchesCompleteTrace: channel({
13518
+ channelName: "batches.complete-trace",
13519
+ kind: "async"
13520
+ }),
13521
+ chatCompletionsCreate: channel({
13522
+ channelName: "chat.completions.create",
13523
+ kind: "async"
13524
+ }),
13525
+ embeddingsCreate: channel({
13526
+ channelName: "embeddings.create",
13527
+ kind: "async"
13528
+ }),
13529
+ betaChatCompletionsParse: channel({
13530
+ channelName: "beta.chat.completions.parse",
13531
+ kind: "async"
13532
+ }),
13533
+ betaChatCompletionsStream: channel({
13534
+ channelName: "beta.chat.completions.stream",
13535
+ kind: "sync-stream"
13536
+ }),
13537
+ moderationsCreate: channel({
13538
+ channelName: "moderations.create",
13539
+ kind: "async"
13540
+ }),
13541
+ responsesCreate: channel({
13542
+ channelName: "responses.create",
13543
+ kind: "async"
13544
+ }),
13545
+ responsesStream: channel({
13546
+ channelName: "responses.stream",
13547
+ kind: "sync-stream"
13548
+ }),
13549
+ responsesParse: channel({
13550
+ channelName: "responses.parse",
13551
+ kind: "async"
13552
+ }),
13553
+ responsesCompact: channel({
13554
+ channelName: "responses.compact",
13555
+ kind: "async"
13556
+ })
13557
+ },
13558
+ { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13559
+ );
13560
+
13427
13561
  // src/wrappers/attachment-utils.ts
13428
13562
  function getExtensionFromMediaType(mediaType) {
13429
13563
  const extensionMap = {
@@ -13599,118 +13733,91 @@ function processInputAttachments(input) {
13599
13733
  return processNode(input);
13600
13734
  }
13601
13735
 
13602
- // src/instrumentation/core/channel-definitions.ts
13603
- function channel(spec) {
13604
- return spec;
13605
- }
13606
- function defineChannels(pkg, channels, options) {
13607
- const { instrumentationName } = options;
13608
- return Object.fromEntries(
13609
- Object.entries(channels).map(([key, spec]) => {
13610
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13611
- if (spec.kind === "async") {
13612
- const asyncSpec = spec;
13613
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
13614
- fullChannelName
13615
- );
13616
- const intercept2 = (interceptor) => {
13617
- const hook = tracingChannel2();
13618
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13619
- };
13620
- };
13621
- return [
13622
- key,
13623
- {
13624
- ...asyncSpec,
13625
- instrumentationName,
13626
- intercept: intercept2,
13627
- invoke: (target, thisArg, args, additional) => {
13628
- const hook = tracingChannel2();
13629
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13630
- },
13631
- tracingChannel: tracingChannel2,
13632
- tracePromise: (fn, context) => tracingChannel2().tracePromise(
13633
- fn,
13634
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13635
- context
13636
- )
13637
- }
13638
- ];
13736
+ // src/instrumentation/plugins/openai-span-data.ts
13737
+ var OPENAI_METADATA_KEYS = [
13738
+ "model",
13739
+ "temperature",
13740
+ "top_p",
13741
+ "max_tokens",
13742
+ "frequency_penalty",
13743
+ "presence_penalty",
13744
+ "stop",
13745
+ "response_format",
13746
+ "tools",
13747
+ "tool_choice",
13748
+ "parallel_tool_calls",
13749
+ "max_tool_calls"
13750
+ ];
13751
+ function batchMetadata(params) {
13752
+ const metadata = { provider: "openai" };
13753
+ for (const key of OPENAI_METADATA_KEYS) {
13754
+ try {
13755
+ const value = Reflect.get(params, key);
13756
+ if (value !== void 0) {
13757
+ metadata[key] = value;
13639
13758
  }
13640
- const syncSpec = spec;
13641
- const tracingChannel = () => isomorph_default.newTracingChannel(
13642
- fullChannelName
13643
- );
13644
- const intercept = (interceptor) => {
13645
- const hook = tracingChannel();
13646
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13647
- };
13648
- };
13649
- return [
13650
- key,
13651
- {
13652
- ...syncSpec,
13653
- instrumentationName,
13654
- intercept,
13655
- invoke: (target, thisArg, args, additional) => {
13656
- const hook = tracingChannel();
13657
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13658
- },
13659
- tracingChannel,
13660
- traceSync: (fn, context) => tracingChannel().traceSync(
13661
- fn,
13662
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13663
- context
13664
- )
13665
- }
13666
- ];
13667
- })
13668
- );
13759
+ } catch {
13760
+ }
13761
+ }
13762
+ return metadata;
13763
+ }
13764
+ function extractOpenAIBatchInput(endpoint, params) {
13765
+ const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
13766
+ return {
13767
+ input: processInputAttachments(input),
13768
+ metadata: batchMetadata(params)
13769
+ };
13770
+ }
13771
+ function extractOpenAIChatInput(params) {
13772
+ const { messages, ...metadata } = params;
13773
+ return {
13774
+ input: processInputAttachments(messages),
13775
+ metadata: { ...metadata, provider: "openai" }
13776
+ };
13777
+ }
13778
+ function extractOpenAIResponsesInput(params) {
13779
+ const { input, ...metadata } = params;
13780
+ return {
13781
+ input: processInputAttachments(input),
13782
+ metadata: { ...metadata, provider: "openai" }
13783
+ };
13784
+ }
13785
+ function extractOpenAIResponsesMetadata(result) {
13786
+ if (!result) {
13787
+ return void 0;
13788
+ }
13789
+ const { output: _output, usage: _usage, ...metadata } = result;
13790
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
13791
+ }
13792
+ function processImagesInOutput(output) {
13793
+ if (Array.isArray(output)) {
13794
+ return output.map(processImagesInOutput);
13795
+ }
13796
+ if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
13797
+ const fileExtension = output.output_format || "png";
13798
+ const contentType = `image/${fileExtension}`;
13799
+ const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13800
+ let binaryString;
13801
+ try {
13802
+ binaryString = atob(output.result);
13803
+ } catch {
13804
+ return output;
13805
+ }
13806
+ const bytes = new Uint8Array(binaryString.length);
13807
+ for (let i = 0; i < binaryString.length; i++) {
13808
+ bytes[i] = binaryString.charCodeAt(i);
13809
+ }
13810
+ return {
13811
+ ...output,
13812
+ result: new Attachment({
13813
+ data: new Blob([bytes], { type: contentType }),
13814
+ filename: `${baseFilename}.${fileExtension}`,
13815
+ contentType
13816
+ })
13817
+ };
13818
+ }
13819
+ return output;
13669
13820
  }
13670
-
13671
- // src/instrumentation/plugins/openai-channels.ts
13672
- var openAIChannels = defineChannels(
13673
- "openai",
13674
- {
13675
- chatCompletionsCreate: channel({
13676
- channelName: "chat.completions.create",
13677
- kind: "async"
13678
- }),
13679
- embeddingsCreate: channel({
13680
- channelName: "embeddings.create",
13681
- kind: "async"
13682
- }),
13683
- betaChatCompletionsParse: channel({
13684
- channelName: "beta.chat.completions.parse",
13685
- kind: "async"
13686
- }),
13687
- betaChatCompletionsStream: channel({
13688
- channelName: "beta.chat.completions.stream",
13689
- kind: "sync-stream"
13690
- }),
13691
- moderationsCreate: channel({
13692
- channelName: "moderations.create",
13693
- kind: "async"
13694
- }),
13695
- responsesCreate: channel({
13696
- channelName: "responses.create",
13697
- kind: "async"
13698
- }),
13699
- responsesStream: channel({
13700
- channelName: "responses.stream",
13701
- kind: "sync-stream"
13702
- }),
13703
- responsesParse: channel({
13704
- channelName: "responses.parse",
13705
- kind: "async"
13706
- }),
13707
- responsesCompact: channel({
13708
- channelName: "responses.compact",
13709
- kind: "async"
13710
- })
13711
- },
13712
- { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13713
- );
13714
13821
 
13715
13822
  // src/openai-utils.ts
13716
13823
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
@@ -13767,23 +13874,573 @@ function getCachedMetricFromHeaders(headers) {
13767
13874
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13768
13875
  }
13769
13876
 
13877
+ // src/instrumentation/plugins/openai-batch-instrumentation.ts
13878
+ var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
13879
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
13880
+ "completed",
13881
+ "failed",
13882
+ "expired",
13883
+ "cancelled"
13884
+ ]);
13885
+ var pendingBatchTraces = /* @__PURE__ */ new Map();
13886
+ function read(value, key) {
13887
+ if (!isObject(value)) {
13888
+ return void 0;
13889
+ }
13890
+ try {
13891
+ return Reflect.get(value, key);
13892
+ } catch {
13893
+ return void 0;
13894
+ }
13895
+ }
13896
+ function isBatchRecordIterable(value) {
13897
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
13898
+ return false;
13899
+ }
13900
+ return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
13901
+ }
13902
+ function validCustomId(value) {
13903
+ return typeof value === "string" && value.length > 0 && value.length <= 64;
13904
+ }
13905
+ function logBatchInstrumentationError(context, error) {
13906
+ debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
13907
+ }
13908
+ async function exportParent(parent) {
13909
+ if ("toStr" in parent && typeof parent.toStr === "function") {
13910
+ return parent.toStr();
13911
+ }
13912
+ if ("export" in parent && typeof parent.export === "function") {
13913
+ return await parent.export();
13914
+ }
13915
+ return void 0;
13916
+ }
13917
+ async function deterministicDigest(namespace, ...parts) {
13918
+ const encoded = new TextEncoder().encode(
13919
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13920
+ );
13921
+ return new Uint8Array(
13922
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
13923
+ );
13924
+ }
13925
+ function digestHex(bytes, length) {
13926
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13927
+ }
13928
+ function digestUuid(bytes) {
13929
+ const hex = digestHex(bytes, 16);
13930
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13931
+ }
13932
+ async function batchSpanIds(inputFileId) {
13933
+ const [row, span, root] = await Promise.all([
13934
+ deterministicDigest("openai:batch:row", inputFileId),
13935
+ deterministicDigest("openai:batch:span", inputFileId),
13936
+ deterministicDigest("openai:batch:root", inputFileId)
13937
+ ]);
13938
+ return {
13939
+ rowId: digestUuid(row),
13940
+ spanId: digestHex(span, 8),
13941
+ rootSpanId: digestHex(root, 16)
13942
+ };
13943
+ }
13944
+ async function childSpanIds(inputFileId, customId) {
13945
+ const [row, span] = await Promise.all([
13946
+ deterministicDigest("openai:batch:child:row", inputFileId, customId),
13947
+ deterministicDigest("openai:batch:child:span", inputFileId, customId)
13948
+ ]);
13949
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
13950
+ }
13951
+ async function startBatchSpan(context) {
13952
+ const ids = await batchSpanIds(context.inputFileId);
13953
+ const parent = SpanComponentsV4.fromStr(context.parent);
13954
+ const hasParentSpan = Boolean(
13955
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
13956
+ );
13957
+ return withCurrent(
13958
+ NOOP_SPAN,
13959
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
13960
+ withSpanInstrumentationName(
13961
+ {
13962
+ name: "openai.batch",
13963
+ type: "task" /* TASK */,
13964
+ parent: context.parent,
13965
+ ...!hasParentSpan ? {
13966
+ parentSpanIds: {
13967
+ parentSpanIds: [],
13968
+ rootSpanId: ids.rootSpanId
13969
+ }
13970
+ } : {},
13971
+ spanId: ids.spanId,
13972
+ startTime: context.taskStartTime,
13973
+ event: {
13974
+ id: ids.rowId,
13975
+ metadata: {
13976
+ endpoint: context.endpoint,
13977
+ input_file_id: context.inputFileId,
13978
+ provider: "openai"
13979
+ }
13980
+ }
13981
+ },
13982
+ INSTRUMENTATION_NAMES.OPENAI
13983
+ )
13984
+ )
13985
+ );
13986
+ }
13987
+ async function startBatchChild(context, taskParent, input) {
13988
+ const ids = await childSpanIds(context.inputFileId, input.customId);
13989
+ return withCurrent(
13990
+ NOOP_SPAN,
13991
+ () => _internalStartSpanWithInitialMerge(
13992
+ withSpanInstrumentationName(
13993
+ {
13994
+ name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
13995
+ type: "llm" /* LLM */,
13996
+ parent: taskParent,
13997
+ spanId: ids.spanId,
13998
+ startTime: context.childStartTime,
13999
+ event: {
14000
+ id: ids.rowId,
14001
+ ...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
14002
+ metadata: {
14003
+ ...input.spanData?.metadata,
14004
+ custom_id: input.customId,
14005
+ provider: "openai"
14006
+ }
14007
+ }
14008
+ },
14009
+ INSTRUMENTATION_NAMES.OPENAI
14010
+ )
14011
+ )
14012
+ );
14013
+ }
14014
+ async function* jsonlRecords(file, onIssue = () => {
14015
+ }) {
14016
+ const resolvedFile = await file;
14017
+ if (typeof resolvedFile === "string") {
14018
+ for (const line of resolvedFile.split("\n")) {
14019
+ if (!line.trim()) {
14020
+ continue;
14021
+ }
14022
+ try {
14023
+ yield JSON.parse(line.replace(/\r$/, ""));
14024
+ } catch (error) {
14025
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14026
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14027
+ }
14028
+ }
14029
+ return;
14030
+ }
14031
+ const body = read(resolvedFile, "body");
14032
+ const getReader = read(body, "getReader");
14033
+ if (isObject(body) && typeof getReader === "function") {
14034
+ let reader;
14035
+ try {
14036
+ reader = Reflect.apply(getReader, body, []);
14037
+ const decoder2 = new TextDecoder();
14038
+ let pending = "";
14039
+ while (true) {
14040
+ const readChunk = read(reader, "read");
14041
+ if (typeof readChunk !== "function") {
14042
+ throw new Error("Response body stream has no read method");
14043
+ }
14044
+ const chunk = await Reflect.apply(readChunk, reader, []);
14045
+ if (!isObject(chunk)) {
14046
+ throw new Error("Response body stream returned an invalid chunk");
14047
+ }
14048
+ if (chunk.done === true) {
14049
+ pending += decoder2.decode();
14050
+ break;
14051
+ }
14052
+ if (!(chunk.value instanceof Uint8Array)) {
14053
+ throw new Error("Response body stream returned a non-byte chunk");
14054
+ }
14055
+ pending += decoder2.decode(chunk.value, { stream: true });
14056
+ let newline = pending.indexOf("\n");
14057
+ while (newline !== -1) {
14058
+ const line = pending.slice(0, newline).replace(/\r$/, "");
14059
+ pending = pending.slice(newline + 1);
14060
+ if (line.trim()) {
14061
+ try {
14062
+ yield JSON.parse(line);
14063
+ } catch (error) {
14064
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14065
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14066
+ }
14067
+ }
14068
+ newline = pending.indexOf("\n");
14069
+ }
14070
+ }
14071
+ if (pending.trim()) {
14072
+ try {
14073
+ yield JSON.parse(pending.replace(/\r$/, ""));
14074
+ } catch (error) {
14075
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14076
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14077
+ }
14078
+ }
14079
+ } catch (error) {
14080
+ logBatchInstrumentationError("could not read JSONL response body", error);
14081
+ onIssue(new Error("OpenAI Batch response body could not be read"));
14082
+ } finally {
14083
+ const releaseLock = read(reader, "releaseLock");
14084
+ if (typeof releaseLock === "function") {
14085
+ try {
14086
+ Reflect.apply(releaseLock, reader, []);
14087
+ } catch (error) {
14088
+ logBatchInstrumentationError(
14089
+ "could not release stream reader",
14090
+ error
14091
+ );
14092
+ }
14093
+ }
14094
+ }
14095
+ return;
14096
+ }
14097
+ if (isBatchRecordIterable(resolvedFile)) {
14098
+ for await (const record of resolvedFile) {
14099
+ yield record;
14100
+ }
14101
+ return;
14102
+ }
14103
+ logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
14104
+ onIssue(new Error("OpenAI Batch file source is invalid"));
14105
+ }
14106
+ async function readBatchInputs(file) {
14107
+ const inputs = /* @__PURE__ */ new Map();
14108
+ const issues = [];
14109
+ let endpoint;
14110
+ try {
14111
+ for await (const value of jsonlRecords(
14112
+ file,
14113
+ (issue) => issues.push(issue)
14114
+ )) {
14115
+ const customId = read(value, "custom_id");
14116
+ const url = read(value, "url");
14117
+ const body = read(value, "body");
14118
+ if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
14119
+ issues.push(new Error("OpenAI Batch input contains an invalid record"));
14120
+ continue;
14121
+ }
14122
+ endpoint = url;
14123
+ let spanData;
14124
+ try {
14125
+ spanData = extractOpenAIBatchInput(url, body);
14126
+ } catch (error) {
14127
+ logBatchInstrumentationError("could not extract batch input", error);
14128
+ }
14129
+ inputs.set(customId, { customId, spanData });
14130
+ }
14131
+ } catch (error) {
14132
+ logBatchInstrumentationError("could not process input file", error);
14133
+ issues.push(new Error("OpenAI Batch input file could not be processed"));
14134
+ }
14135
+ if (!endpoint || inputs.size === 0) {
14136
+ issues.push(new Error("OpenAI Batch input contains no supported records"));
14137
+ }
14138
+ return { endpoint, inputs, issues };
14139
+ }
14140
+ async function writePendingSpans(trace, endTime) {
14141
+ const task = await startBatchSpan(trace.context);
14142
+ const taskParent = await task.export();
14143
+ for (const input of trace.inputs.values()) {
14144
+ try {
14145
+ const child = await startBatchChild(trace.context, taskParent, input);
14146
+ if (endTime !== void 0) {
14147
+ child.end({ endTime });
14148
+ }
14149
+ } catch (error) {
14150
+ logBatchInstrumentationError("could not write batch request span", error);
14151
+ }
14152
+ }
14153
+ if (endTime !== void 0) {
14154
+ if (trace.status && trace.status !== "completed") {
14155
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14156
+ }
14157
+ task.end({ endTime });
14158
+ }
14159
+ }
14160
+ var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
14161
+ const startTime = getCurrentUnixTimestamp();
14162
+ const inputPromise = readBatchInputs(args[0].inputFileContent);
14163
+ const parentPromise = exportParent(args[0].parent);
14164
+ const file = await Reflect.apply(target, thisArg, args);
14165
+ try {
14166
+ const inputFileId = read(file, "id");
14167
+ const [inputData, exportedParent2] = await Promise.all([
14168
+ inputPromise,
14169
+ parentPromise
14170
+ ]);
14171
+ if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
14172
+ if (inputData.issues[0]) {
14173
+ logBatchInstrumentationError(
14174
+ "skipped invalid input file",
14175
+ inputData.issues[0]
14176
+ );
14177
+ }
14178
+ return file;
14179
+ }
14180
+ const trace = {
14181
+ context: {
14182
+ inputFileId,
14183
+ endpoint: inputData.endpoint,
14184
+ parent: exportedParent2,
14185
+ taskStartTime: startTime,
14186
+ childStartTime: startTime
14187
+ },
14188
+ inputs: inputData.inputs
14189
+ };
14190
+ pendingBatchTraces.set(inputFileId, trace);
14191
+ await writePendingSpans(trace);
14192
+ } catch (error) {
14193
+ logBatchInstrumentationError("could not start batch spans", error);
14194
+ }
14195
+ return file;
14196
+ };
14197
+ function validTimestamp(value) {
14198
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
14199
+ }
14200
+ function terminalEndTime(batch, startTime) {
14201
+ let timestamp;
14202
+ switch (batch.status) {
14203
+ case "completed":
14204
+ timestamp = batch.completed_at;
14205
+ break;
14206
+ case "failed":
14207
+ timestamp = batch.failed_at;
14208
+ break;
14209
+ case "expired":
14210
+ timestamp = batch.expired_at;
14211
+ break;
14212
+ default:
14213
+ timestamp = batch.cancelled_at;
14214
+ }
14215
+ return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
14216
+ }
14217
+ async function updateBatchTimestamps(batch) {
14218
+ const trace = pendingBatchTraces.get(batch.input_file_id);
14219
+ if (!trace || trace.context.endpoint !== batch.endpoint) {
14220
+ return;
14221
+ }
14222
+ if (validTimestamp(batch.created_at)) {
14223
+ trace.context.taskStartTime = batch.created_at;
14224
+ }
14225
+ trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
14226
+ trace.status = batch.status;
14227
+ if (TERMINAL_STATUSES.has(batch.status)) {
14228
+ trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
14229
+ }
14230
+ await writePendingSpans(trace, trace.endTime);
14231
+ }
14232
+ var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
14233
+ try {
14234
+ await updateBatchTimestamps(batch);
14235
+ } catch (error) {
14236
+ logBatchInstrumentationError("could not update batch timestamps", error);
14237
+ }
14238
+ return batch;
14239
+ });
14240
+ function errorFromResult(result) {
14241
+ const error = read(result.value, "error");
14242
+ if (isObject(error)) {
14243
+ const message = read(error, "message");
14244
+ return new Error(
14245
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14246
+ );
14247
+ }
14248
+ const response = read(result.value, "response");
14249
+ const statusCode = read(response, "status_code");
14250
+ if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
14251
+ const message = read(read(read(response, "body"), "error"), "message");
14252
+ return new Error(
14253
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14254
+ );
14255
+ }
14256
+ return void 0;
14257
+ }
14258
+ async function completeBatchResult(context, taskParent, endTime, input, result) {
14259
+ const child = await startBatchChild(context, taskParent, input);
14260
+ try {
14261
+ const resultError = errorFromResult(result);
14262
+ const responseBody = read(read(result.value, "response"), "body");
14263
+ if (resultError) {
14264
+ child.log({ error: resultError });
14265
+ } else if (isObject(responseBody)) {
14266
+ const model = read(responseBody, "model");
14267
+ child.log({
14268
+ output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
14269
+ ...typeof model === "string" ? { metadata: { model } } : {},
14270
+ metrics: parseMetricsFromUsage(read(responseBody, "usage"))
14271
+ });
14272
+ } else {
14273
+ child.log({ error: new Error("OpenAI Batch response body is missing") });
14274
+ }
14275
+ } catch (error) {
14276
+ child.log({ error });
14277
+ } finally {
14278
+ child.end({ endTime });
14279
+ }
14280
+ }
14281
+ async function completeResultFile({
14282
+ context,
14283
+ endTime,
14284
+ file,
14285
+ inputs,
14286
+ issues,
14287
+ seen,
14288
+ source,
14289
+ taskParent
14290
+ }) {
14291
+ if (file === void 0) {
14292
+ return;
14293
+ }
14294
+ for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
14295
+ const customId = read(value, "custom_id");
14296
+ if (!validCustomId(customId) || !isObject(value)) {
14297
+ issues.push(
14298
+ new Error("OpenAI Batch result is missing a valid custom_id")
14299
+ );
14300
+ continue;
14301
+ }
14302
+ if (seen.has(customId)) {
14303
+ issues.push(new Error("OpenAI Batch result contains a duplicate"));
14304
+ continue;
14305
+ }
14306
+ const input = inputs.get(customId);
14307
+ if (!input) {
14308
+ issues.push(
14309
+ new Error("OpenAI Batch result does not match an input record")
14310
+ );
14311
+ continue;
14312
+ }
14313
+ seen.add(customId);
14314
+ await completeBatchResult(context, taskParent, endTime, input, {
14315
+ value,
14316
+ source
14317
+ });
14318
+ }
14319
+ }
14320
+ function sameInputs(first, second) {
14321
+ return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
14322
+ }
14323
+ async function contextForCompletion(inputFileId, inputData) {
14324
+ if (!inputData.endpoint || inputData.issues.length > 0) {
14325
+ return void 0;
14326
+ }
14327
+ const existing = pendingBatchTraces.get(inputFileId);
14328
+ if (existing) {
14329
+ if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
14330
+ return void 0;
14331
+ }
14332
+ return { ...existing, inputs: inputData.inputs };
14333
+ }
14334
+ const parent = await exportParent(getSpanParentObject());
14335
+ if (!parent) {
14336
+ return void 0;
14337
+ }
14338
+ const startTime = getCurrentUnixTimestamp();
14339
+ return {
14340
+ context: {
14341
+ inputFileId,
14342
+ endpoint: inputData.endpoint,
14343
+ parent,
14344
+ taskStartTime: startTime,
14345
+ childStartTime: startTime
14346
+ },
14347
+ inputs: inputData.inputs
14348
+ };
14349
+ }
14350
+ async function completeBatch(args) {
14351
+ const inputData = await readBatchInputs(args.inputFileContent);
14352
+ const trace = await contextForCompletion(args.inputFileId, inputData);
14353
+ if (!trace) {
14354
+ logBatchInstrumentationError(
14355
+ "left batch spans pending",
14356
+ inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
14357
+ );
14358
+ return;
14359
+ }
14360
+ const endTime = trace.endTime ?? getCurrentUnixTimestamp();
14361
+ const task = await startBatchSpan(trace.context);
14362
+ const taskParent = await task.export();
14363
+ const issues = [];
14364
+ const seen = /* @__PURE__ */ new Set();
14365
+ await Promise.all([
14366
+ completeResultFile({
14367
+ context: trace.context,
14368
+ endTime,
14369
+ file: args.outputFileContent,
14370
+ inputs: trace.inputs,
14371
+ issues,
14372
+ seen,
14373
+ source: "output",
14374
+ taskParent
14375
+ }),
14376
+ completeResultFile({
14377
+ context: trace.context,
14378
+ endTime,
14379
+ file: args.errorFileContent,
14380
+ inputs: trace.inputs,
14381
+ issues,
14382
+ seen,
14383
+ source: "error",
14384
+ taskParent
14385
+ })
14386
+ ]);
14387
+ if (issues.length > 0) {
14388
+ logBatchInstrumentationError("left batch spans pending", issues[0]);
14389
+ return;
14390
+ }
14391
+ const missing = [...trace.inputs.values()].filter(
14392
+ ({ customId }) => !seen.has(customId)
14393
+ );
14394
+ if (!trace.status || trace.status === "completed") {
14395
+ if (missing.length > 0) {
14396
+ logBatchInstrumentationError(
14397
+ "left batch spans pending",
14398
+ new Error("OpenAI Batch result files are incomplete")
14399
+ );
14400
+ return;
14401
+ }
14402
+ } else {
14403
+ for (const input of missing) {
14404
+ const child = await startBatchChild(trace.context, taskParent, input);
14405
+ child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14406
+ child.end({ endTime });
14407
+ }
14408
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14409
+ }
14410
+ task.end({ endTime });
14411
+ pendingBatchTraces.delete(args.inputFileId);
14412
+ }
14413
+ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
14414
+ try {
14415
+ await completeBatch(args[0]);
14416
+ } catch (error) {
14417
+ logBatchInstrumentationError("could not complete batch", error);
14418
+ }
14419
+ return result;
14420
+ });
14421
+
13770
14422
  // src/instrumentation/plugins/openai-plugin.ts
13771
14423
  var OpenAIPlugin = class extends BasePlugin {
13772
14424
  constructor() {
13773
14425
  super();
13774
14426
  }
13775
14427
  onEnable() {
14428
+ this.unsubscribers.push(
14429
+ openAIChannels.filesCreateTraced.intercept(
14430
+ interceptOpenAIFilesCreateTraced
14431
+ ),
14432
+ openAIChannels.batchesRetrieveTraced.intercept(
14433
+ interceptOpenAIBatchesRetrieveTraced
14434
+ ),
14435
+ openAIChannels.batchesCompleteTrace.intercept(
14436
+ interceptOpenAIBatchTraceComplete
14437
+ )
14438
+ );
13776
14439
  this.unsubscribers.push(
13777
14440
  traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
13778
14441
  name: "Chat Completion",
13779
14442
  type: "llm" /* LLM */,
13780
- extractInput: ([params]) => {
13781
- const { messages, ...metadata } = params;
13782
- return {
13783
- input: processInputAttachments(messages),
13784
- metadata: { ...metadata, provider: "openai" }
13785
- };
13786
- },
14443
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13787
14444
  extractOutput: (result) => {
13788
14445
  return result?.choices;
13789
14446
  },
@@ -13829,13 +14486,7 @@ var OpenAIPlugin = class extends BasePlugin {
13829
14486
  traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
13830
14487
  name: "Chat Completion",
13831
14488
  type: "llm" /* LLM */,
13832
- extractInput: ([params]) => {
13833
- const { messages, ...metadata } = params;
13834
- return {
13835
- input: processInputAttachments(messages),
13836
- metadata: { ...metadata, provider: "openai" }
13837
- };
13838
- },
14489
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13839
14490
  extractOutput: (result) => {
13840
14491
  return result?.choices;
13841
14492
  },
@@ -13857,13 +14508,7 @@ var OpenAIPlugin = class extends BasePlugin {
13857
14508
  traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
13858
14509
  name: "Chat Completion",
13859
14510
  type: "llm" /* LLM */,
13860
- extractInput: ([params]) => {
13861
- const { messages, ...metadata } = params;
13862
- return {
13863
- input: processInputAttachments(messages),
13864
- metadata: { ...metadata, provider: "openai" }
13865
- };
13866
- }
14511
+ extractInput: ([params]) => extractOpenAIChatInput(params)
13867
14512
  })
13868
14513
  );
13869
14514
  this.unsubscribers.push(
@@ -13893,23 +14538,11 @@ var OpenAIPlugin = class extends BasePlugin {
13893
14538
  traceStreamingChannel(openAIChannels.responsesCreate, {
13894
14539
  name: "openai.responses.create",
13895
14540
  type: "llm" /* LLM */,
13896
- extractInput: ([params]) => {
13897
- const { input, ...metadata } = params;
13898
- return {
13899
- input: processInputAttachments(input),
13900
- metadata: { ...metadata, provider: "openai" }
13901
- };
13902
- },
14541
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13903
14542
  extractOutput: (result) => {
13904
14543
  return processImagesInOutput(result?.output);
13905
14544
  },
13906
- extractMetadata: (result) => {
13907
- if (!result) {
13908
- return void 0;
13909
- }
13910
- const { output: _output, usage: _usage, ...metadata } = result;
13911
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13912
- },
14545
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13913
14546
  extractMetrics: (result, startTime, endEvent) => {
13914
14547
  const metrics = withCachedMetric(
13915
14548
  parseMetricsFromUsage(result?.usage),
@@ -13928,13 +14561,7 @@ var OpenAIPlugin = class extends BasePlugin {
13928
14561
  traceSyncStreamChannel(openAIChannels.responsesStream, {
13929
14562
  name: "openai.responses.create",
13930
14563
  type: "llm" /* LLM */,
13931
- extractInput: ([params]) => {
13932
- const { input, ...metadata } = params;
13933
- return {
13934
- input: processInputAttachments(input),
13935
- metadata: { ...metadata, provider: "openai" }
13936
- };
13937
- },
14564
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13938
14565
  extractFromEvent: (event) => {
13939
14566
  if (event.type !== "response.completed" || !event.response) {
13940
14567
  return {};
@@ -13957,23 +14584,11 @@ var OpenAIPlugin = class extends BasePlugin {
13957
14584
  traceStreamingChannel(openAIChannels.responsesParse, {
13958
14585
  name: "openai.responses.parse",
13959
14586
  type: "llm" /* LLM */,
13960
- extractInput: ([params]) => {
13961
- const { input, ...metadata } = params;
13962
- return {
13963
- input: processInputAttachments(input),
13964
- metadata: { ...metadata, provider: "openai" }
13965
- };
13966
- },
14587
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13967
14588
  extractOutput: (result) => {
13968
14589
  return processImagesInOutput(result?.output);
13969
14590
  },
13970
- extractMetadata: (result) => {
13971
- if (!result) {
13972
- return void 0;
13973
- }
13974
- const { output: _output, usage: _usage, ...metadata } = result;
13975
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13976
- },
14591
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13977
14592
  extractMetrics: (result, startTime, endEvent) => {
13978
14593
  const metrics = withCachedMetric(
13979
14594
  parseMetricsFromUsage(result?.usage),
@@ -13992,23 +14607,11 @@ var OpenAIPlugin = class extends BasePlugin {
13992
14607
  traceAsyncChannel(openAIChannels.responsesCompact, {
13993
14608
  name: "openai.responses.compact",
13994
14609
  type: "llm" /* LLM */,
13995
- extractInput: ([params]) => {
13996
- const { input, ...metadata } = params;
13997
- return {
13998
- input: processInputAttachments(input),
13999
- metadata: { ...metadata, provider: "openai" }
14000
- };
14001
- },
14610
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
14002
14611
  extractOutput: (result) => {
14003
14612
  return processImagesInOutput(result?.output);
14004
14613
  },
14005
- extractMetadata: (result) => {
14006
- if (!result) {
14007
- return void 0;
14008
- }
14009
- const { output: _output, usage: _usage, ...metadata } = result;
14010
- return Object.keys(metadata).length > 0 ? metadata : void 0;
14011
- },
14614
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
14012
14615
  extractMetrics: (result, startTime, endEvent) => {
14013
14616
  const metrics = withCachedMetric(
14014
14617
  parseMetricsFromUsage(result?.usage),
@@ -14064,35 +14667,6 @@ function withCachedMetric(metrics, result, endEvent) {
14064
14667
  cached
14065
14668
  };
14066
14669
  }
14067
- function processImagesInOutput(output) {
14068
- if (Array.isArray(output)) {
14069
- return output.map(processImagesInOutput);
14070
- }
14071
- if (isObject(output)) {
14072
- if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
14073
- const fileExtension = output.output_format || "png";
14074
- const contentType = `image/${fileExtension}`;
14075
- const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
14076
- const filename = `${baseFilename}.${fileExtension}`;
14077
- const binaryString = atob(output.result);
14078
- const bytes = new Uint8Array(binaryString.length);
14079
- for (let i = 0; i < binaryString.length; i++) {
14080
- bytes[i] = binaryString.charCodeAt(i);
14081
- }
14082
- const blob = new Blob([bytes], { type: contentType });
14083
- const attachment = new Attachment({
14084
- data: blob,
14085
- filename,
14086
- contentType
14087
- });
14088
- return {
14089
- ...output,
14090
- result: attachment
14091
- };
14092
- }
14093
- }
14094
- return output;
14095
- }
14096
14670
  function mergeLogprobTokens(existing, incoming) {
14097
14671
  if (incoming === void 0) {
14098
14672
  return existing;
@@ -34125,7 +34699,7 @@ function extractSession(event) {
34125
34699
  return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
34126
34700
  }
34127
34701
  function isPiAgent(value) {
34128
- return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
34702
+ return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
34129
34703
  }
34130
34704
  function promptContextStore() {
34131
34705
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
@@ -34135,17 +34709,21 @@ function currentPiPromptState() {
34135
34709
  return promptContextStore().getStore();
34136
34710
  }
34137
34711
  function installPiAgentInstrumentation(agent) {
34712
+ const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
34713
+ const streamFunction = agent[property];
34138
34714
  const existing = piAgentPatchStates.get(agent);
34139
- if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
34715
+ if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
34140
34716
  const patchState = {
34141
- originalStreamFn: agent.streamFn,
34142
- wrappedStreamFn: agent.streamFn
34717
+ originalStreamFunction: streamFunction,
34718
+ property,
34719
+ wrappedStreamFunction: streamFunction
34143
34720
  };
34144
- patchState.wrappedStreamFn = makeInstrumentedStreamFn(
34721
+ patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
34145
34722
  agent,
34146
- patchState.originalStreamFn
34723
+ patchState.originalStreamFunction,
34724
+ property
34147
34725
  );
34148
- agent.streamFn = patchState.wrappedStreamFn;
34726
+ agent[property] = patchState.wrappedStreamFunction;
34149
34727
  piAgentPatchStates.set(agent, patchState);
34150
34728
  }
34151
34729
  if (piAgentEventSubscriptions.has(agent)) {
@@ -34170,15 +34748,21 @@ function installPiAgentInstrumentation(agent) {
34170
34748
  logInstrumentationError4("Pi Coding Agent event subscription", error);
34171
34749
  }
34172
34750
  }
34173
- function makeInstrumentedStreamFn(agent, originalStreamFn) {
34174
- return async function instrumentedPiStreamFn(model, context, options) {
34175
- const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
34751
+ function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
34752
+ return async function instrumentedPiStreamFunction(model, context, options) {
34753
+ const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
34176
34754
  const state = currentPiPromptState();
34177
34755
  if (!state || state.agent !== agent || state.finalized) {
34178
34756
  return invokeOriginal();
34179
34757
  }
34180
34758
  wrapPiToolExecutors(context.tools);
34181
- const llmState = await startPiLlmSpan(state, model, context, options);
34759
+ const llmState = await startPiLlmSpan(
34760
+ state,
34761
+ model,
34762
+ context,
34763
+ property,
34764
+ options
34765
+ );
34182
34766
  try {
34183
34767
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
34184
34768
  return patchAssistantMessageStream(stream, state, llmState);
@@ -34215,12 +34799,12 @@ function wrapPiToolExecutors(tools) {
34215
34799
  }
34216
34800
  }
34217
34801
  }
34218
- async function startPiLlmSpan(state, model, context, options) {
34802
+ async function startPiLlmSpan(state, model, context, property, options) {
34219
34803
  const metadata = {
34220
34804
  ...extractModelMetadata2(model),
34221
34805
  ...extractStreamOptionsMetadata(options),
34222
34806
  ...extractToolMetadata(context.tools),
34223
- "pi_coding_agent.operation": "agent.streamFn"
34807
+ "pi_coding_agent.operation": `agent.${property}`
34224
34808
  };
34225
34809
  const span = startSpan(
34226
34810
  withSpanInstrumentationName(
@@ -37236,6 +37820,7 @@ __export(exports_exports, {
37236
37820
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
37237
37821
  buildLocalSummary: () => buildLocalSummary,
37238
37822
  collectAnthropicSession: () => collectAnthropicSession,
37823
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
37239
37824
  configureInstrumentation: () => configureInstrumentation,
37240
37825
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
37241
37826
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -37274,6 +37859,8 @@ __export(exports_exports, {
37274
37859
  loginToState: () => loginToState,
37275
37860
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
37276
37861
  newId: () => newId,
37862
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
37863
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
37277
37864
  parseCachedHeader: () => parseCachedHeader,
37278
37865
  parseTemplateFormat: () => parseTemplateFormat,
37279
37866
  permalink: () => permalink,
@@ -37438,6 +38025,260 @@ async function registerSandbox(options) {
37438
38025
  };
37439
38026
  }
37440
38027
 
38028
+ // src/wrappers/openai-promise-utils.ts
38029
+ function splitSpanInfo(allParams) {
38030
+ const { span_info, ...params } = allParams;
38031
+ return {
38032
+ params,
38033
+ span_info
38034
+ };
38035
+ }
38036
+ function createChannelContext(_channel, params, span_info) {
38037
+ return {
38038
+ arguments: (
38039
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38040
+ [params]
38041
+ ),
38042
+ span_info
38043
+ };
38044
+ }
38045
+ async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
38046
+ let enhancedResponse;
38047
+ const tracePromise = (
38048
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38049
+ channel2.tracePromise
38050
+ );
38051
+ const data = await tracePromise(async () => {
38052
+ enhancedResponse = await apiPromise.withResponse();
38053
+ traceContext.response = enhancedResponse.response;
38054
+ return enhancedResponse.data;
38055
+ }, traceContext);
38056
+ if (!enhancedResponse) {
38057
+ throw new Error("Expected withResponse() to provide response");
38058
+ }
38059
+ return {
38060
+ data,
38061
+ response: enhancedResponse.response,
38062
+ request_id: enhancedResponse.request_id
38063
+ };
38064
+ }
38065
+ async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
38066
+ const tracePromise = (
38067
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38068
+ channel2.tracePromise
38069
+ );
38070
+ let response;
38071
+ await tracePromise(async () => {
38072
+ response = await apiPromise.asResponse();
38073
+ traceContext.response = response;
38074
+ return void 0;
38075
+ }, traceContext);
38076
+ if (!response) {
38077
+ throw new Error("Expected asResponse() to provide response");
38078
+ }
38079
+ return response;
38080
+ }
38081
+ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
38082
+ let firstConsumption;
38083
+ let enhancedResponsePromise;
38084
+ let dataPromise;
38085
+ let responsePromise;
38086
+ const withResponse = () => {
38087
+ firstConsumption ??= "data";
38088
+ enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
38089
+ return enhancedResponsePromise;
38090
+ };
38091
+ const asResponse = () => {
38092
+ firstConsumption ??= "response";
38093
+ responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
38094
+ return responsePromise;
38095
+ };
38096
+ return new Proxy({}, {
38097
+ get(target, prop, receiver) {
38098
+ if (prop === "withResponse") {
38099
+ return withResponse;
38100
+ }
38101
+ if (prop === "asResponse") {
38102
+ return asResponse;
38103
+ }
38104
+ if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
38105
+ dataPromise ??= withResponse().then((result) => result.data);
38106
+ const value = Reflect.get(dataPromise, prop, receiver);
38107
+ return typeof value === "function" ? value.bind(dataPromise) : value;
38108
+ }
38109
+ return Reflect.get(target, prop, receiver);
38110
+ }
38111
+ });
38112
+ }
38113
+
38114
+ // src/openai-batch.ts
38115
+ function read2(value, key) {
38116
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
38117
+ return void 0;
38118
+ }
38119
+ try {
38120
+ return Reflect.get(value, key);
38121
+ } catch {
38122
+ return void 0;
38123
+ }
38124
+ }
38125
+ function isAsyncIterable5(value) {
38126
+ return typeof read2(value, Symbol.asyncIterator) === "function";
38127
+ }
38128
+ function teeAsyncIterable(source) {
38129
+ const iterator = source[Symbol.asyncIterator]();
38130
+ const stream = new ReadableStream({
38131
+ async pull(controller) {
38132
+ try {
38133
+ const result = await iterator.next();
38134
+ if (result.done) {
38135
+ controller.close();
38136
+ return;
38137
+ }
38138
+ if (!(result.value instanceof Uint8Array)) {
38139
+ throw new TypeError(
38140
+ "OpenAI upload streams must yield Uint8Array chunks"
38141
+ );
38142
+ }
38143
+ controller.enqueue(result.value);
38144
+ } catch (error) {
38145
+ controller.error(error);
38146
+ }
38147
+ },
38148
+ async cancel(reason) {
38149
+ await iterator.return?.(reason);
38150
+ }
38151
+ });
38152
+ const [uploadStream, trace] = stream.tee();
38153
+ const upload = {
38154
+ async *[Symbol.asyncIterator]() {
38155
+ const reader = uploadStream.getReader();
38156
+ try {
38157
+ while (true) {
38158
+ const result = await reader.read();
38159
+ if (result.done) {
38160
+ return;
38161
+ }
38162
+ yield result.value;
38163
+ }
38164
+ } finally {
38165
+ reader.releaseLock();
38166
+ }
38167
+ }
38168
+ };
38169
+ const path = read2(source, "path");
38170
+ if (typeof path === "string") {
38171
+ Object.defineProperty(upload, "path", { value: path });
38172
+ }
38173
+ return { upload, trace: new Response(trace) };
38174
+ }
38175
+ function teeUpload(upload) {
38176
+ if (upload instanceof Blob) {
38177
+ return { upload, trace: new Response(upload) };
38178
+ }
38179
+ if (upload instanceof Response) {
38180
+ return { upload, trace: upload.clone() };
38181
+ }
38182
+ if (isAsyncIterable5(upload)) {
38183
+ return teeAsyncIterable(upload);
38184
+ }
38185
+ return void 0;
38186
+ }
38187
+ function openaiFilesCreateTraced(files) {
38188
+ return (params, options) => {
38189
+ const parent = getSpanParentObject();
38190
+ const purpose = read2(params, "purpose");
38191
+ const file = read2(params, "file");
38192
+ if (purpose !== "batch") {
38193
+ return files.create(params, options);
38194
+ }
38195
+ let branches;
38196
+ try {
38197
+ branches = teeUpload(file);
38198
+ } catch {
38199
+ return files.create(params, options);
38200
+ }
38201
+ if (!branches) {
38202
+ return files.create(params, options);
38203
+ }
38204
+ const tracedParams = {
38205
+ ...Object(params),
38206
+ file: branches.upload
38207
+ };
38208
+ const apiPromise = files.create(tracedParams, options);
38209
+ let enhancedResponse;
38210
+ const tracedResponse = openAIChannels.filesCreateTraced.invoke(
38211
+ async () => {
38212
+ enhancedResponse = await apiPromise.withResponse();
38213
+ return enhancedResponse.data;
38214
+ },
38215
+ files,
38216
+ [{ params, inputFileContent: branches.trace, parent }],
38217
+ {}
38218
+ ).then((data) => {
38219
+ if (!enhancedResponse) {
38220
+ throw new Error(
38221
+ "Expected OpenAI withResponse() to provide a response"
38222
+ );
38223
+ }
38224
+ return { ...enhancedResponse, data };
38225
+ });
38226
+ return createLazyAPIPromise(
38227
+ () => tracedResponse,
38228
+ () => tracedResponse.then(({ response }) => response),
38229
+ () => apiPromise
38230
+ );
38231
+ };
38232
+ }
38233
+ function openaiBatchesRetrieveTraced(batches) {
38234
+ return (batchId, options) => {
38235
+ const apiPromise = batches.retrieve(batchId, options);
38236
+ let enhancedResponse;
38237
+ const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
38238
+ async () => {
38239
+ enhancedResponse = await apiPromise.withResponse();
38240
+ return enhancedResponse.data;
38241
+ },
38242
+ batches,
38243
+ [{ batchId }],
38244
+ {}
38245
+ ).then((data) => {
38246
+ if (!enhancedResponse) {
38247
+ throw new Error(
38248
+ "Expected OpenAI withResponse() to provide a response"
38249
+ );
38250
+ }
38251
+ return { ...enhancedResponse, data };
38252
+ });
38253
+ return createLazyAPIPromise(
38254
+ () => tracedResponse,
38255
+ () => tracedResponse.then(({ response }) => response),
38256
+ () => apiPromise
38257
+ );
38258
+ };
38259
+ }
38260
+ async function completeOpenAIBatchTrace(args) {
38261
+ const inputFileContent = Promise.resolve(args.inputFileContent);
38262
+ const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
38263
+ const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
38264
+ void inputFileContent.catch(() => void 0);
38265
+ void outputFileContent?.catch(() => void 0);
38266
+ void errorFileContent?.catch(() => void 0);
38267
+ await openAIChannels.batchesCompleteTrace.invoke(
38268
+ async () => void 0,
38269
+ void 0,
38270
+ [
38271
+ {
38272
+ ...args,
38273
+ inputFileContent,
38274
+ outputFileContent,
38275
+ errorFileContent
38276
+ }
38277
+ ],
38278
+ {}
38279
+ );
38280
+ }
38281
+
37441
38282
  // src/functions/invoke.ts
37442
38283
  async function invoke(args) {
37443
38284
  const {
@@ -37540,58 +38381,6 @@ function initFunction({
37540
38381
  return f;
37541
38382
  }
37542
38383
 
37543
- // src/wrappers/openai-promise-utils.ts
37544
- function splitSpanInfo(allParams) {
37545
- const { span_info, ...params } = allParams;
37546
- return {
37547
- params,
37548
- span_info
37549
- };
37550
- }
37551
- function createChannelContext(_channel, params, span_info) {
37552
- return {
37553
- arguments: (
37554
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37555
- [params]
37556
- ),
37557
- span_info
37558
- };
37559
- }
37560
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
37561
- let enhancedResponse;
37562
- const tracePromise = (
37563
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37564
- channel2.tracePromise
37565
- );
37566
- const data = await tracePromise(async () => {
37567
- enhancedResponse = await apiPromise.withResponse();
37568
- traceContext.response = enhancedResponse.response;
37569
- return enhancedResponse.data;
37570
- }, traceContext);
37571
- if (!enhancedResponse) {
37572
- throw new Error("Expected withResponse() to provide response");
37573
- }
37574
- return { data, response: enhancedResponse.response };
37575
- }
37576
- function createLazyAPIPromise(ensureExecuted) {
37577
- let dataPromise = null;
37578
- return new Proxy({}, {
37579
- get(target, prop, receiver) {
37580
- if (prop === "withResponse") {
37581
- return () => ensureExecuted();
37582
- }
37583
- if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
37584
- if (!dataPromise) {
37585
- dataPromise = ensureExecuted().then((result) => result.data);
37586
- }
37587
- const value = Reflect.get(dataPromise, prop, receiver);
37588
- return typeof value === "function" ? value.bind(dataPromise) : value;
37589
- }
37590
- return Reflect.get(target, prop, receiver);
37591
- }
37592
- });
37593
- }
37594
-
37595
38384
  // src/wrappers/oai_responses.ts
37596
38385
  function responsesProxy(openai) {
37597
38386
  if (!openai.responses) {
@@ -37628,17 +38417,33 @@ function wrapResponsesAsync(target, channel2) {
37628
38417
  return (allParams, options) => {
37629
38418
  const { span_info, params } = splitSpanInfo(allParams);
37630
38419
  let executionPromise = null;
38420
+ let apiPromise = null;
38421
+ const getAPIPromise = () => {
38422
+ apiPromise ??= target(params, options);
38423
+ return apiPromise;
38424
+ };
37631
38425
  const ensureExecuted = () => {
37632
38426
  if (!executionPromise) {
37633
38427
  executionPromise = (async () => {
37634
38428
  const traceContext = createChannelContext(channel2, params, span_info);
37635
- const apiPromise = target(params, options);
37636
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
38429
+ return tracePromiseWithResponse(
38430
+ channel2,
38431
+ traceContext,
38432
+ getAPIPromise()
38433
+ );
37637
38434
  })();
37638
38435
  }
37639
38436
  return executionPromise;
37640
38437
  };
37641
- return createLazyAPIPromise(ensureExecuted);
38438
+ return createLazyAPIPromise(
38439
+ ensureExecuted,
38440
+ () => tracePromiseAsResponse(
38441
+ channel2,
38442
+ createChannelContext(channel2, params, span_info),
38443
+ getAPIPromise()
38444
+ ),
38445
+ getAPIPromise
38446
+ );
37642
38447
  };
37643
38448
  }
37644
38449
  function wrapResponsesSyncStream(target, channel2) {
@@ -37784,6 +38589,11 @@ function wrapChatCompletion(completion) {
37784
38589
  allParams
37785
38590
  );
37786
38591
  let executionPromise = null;
38592
+ let apiPromise = null;
38593
+ const getAPIPromise = () => {
38594
+ apiPromise ??= completion(params, options);
38595
+ return apiPromise;
38596
+ };
37787
38597
  const ensureExecuted = () => {
37788
38598
  if (!executionPromise) {
37789
38599
  executionPromise = (async () => {
@@ -37793,32 +38603,44 @@ function wrapChatCompletion(completion) {
37793
38603
  span_info
37794
38604
  );
37795
38605
  if (params.stream) {
37796
- const completionPromise = completion(
37797
- params,
37798
- options
38606
+ const completionPromise = (
38607
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38608
+ getAPIPromise()
37799
38609
  );
37800
- const { data: data2, response: response2 } = await tracePromiseWithResponse(
38610
+ const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
37801
38611
  openAIChannels.chatCompletionsCreate,
37802
38612
  traceContext,
37803
38613
  completionPromise
37804
38614
  );
37805
- return { data: data2, response: response2 };
38615
+ return { data: data2, response: response2, request_id: request_id2 };
37806
38616
  }
37807
- const completionResponse = completion(
37808
- params,
37809
- options
38617
+ const completionResponse = (
38618
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38619
+ getAPIPromise()
37810
38620
  );
37811
- const { data, response } = await tracePromiseWithResponse(
38621
+ const { data, response, request_id } = await tracePromiseWithResponse(
37812
38622
  openAIChannels.chatCompletionsCreate,
37813
38623
  traceContext,
37814
38624
  completionResponse
37815
38625
  );
37816
- return { data, response };
38626
+ return { data, response, request_id };
37817
38627
  })();
37818
38628
  }
37819
38629
  return executionPromise;
37820
38630
  };
37821
- return createLazyAPIPromise(ensureExecuted);
38631
+ return createLazyAPIPromise(
38632
+ ensureExecuted,
38633
+ () => tracePromiseAsResponse(
38634
+ openAIChannels.chatCompletionsCreate,
38635
+ createChannelContext(
38636
+ openAIChannels.chatCompletionsCreate,
38637
+ params,
38638
+ span_info
38639
+ ),
38640
+ getAPIPromise()
38641
+ ),
38642
+ getAPIPromise
38643
+ );
37822
38644
  };
37823
38645
  }
37824
38646
  function createEndpointProxy(target, wrapperFn) {
@@ -37836,6 +38658,11 @@ function wrapApiCreateWithChannel(create, channel2) {
37836
38658
  return (allParams, options) => {
37837
38659
  const { span_info, params } = splitSpanInfo(allParams);
37838
38660
  let executionPromise = null;
38661
+ let apiPromise = null;
38662
+ const getAPIPromise = () => {
38663
+ apiPromise ??= create(params, options);
38664
+ return apiPromise;
38665
+ };
37839
38666
  const ensureExecuted = () => {
37840
38667
  if (!executionPromise) {
37841
38668
  executionPromise = (async () => {
@@ -37843,13 +38670,21 @@ function wrapApiCreateWithChannel(create, channel2) {
37843
38670
  return tracePromiseWithResponse(
37844
38671
  channel2,
37845
38672
  traceContext,
37846
- create(params, options)
38673
+ getAPIPromise()
37847
38674
  );
37848
38675
  })();
37849
38676
  }
37850
38677
  return executionPromise;
37851
38678
  };
37852
- return createLazyAPIPromise(ensureExecuted);
38679
+ return createLazyAPIPromise(
38680
+ ensureExecuted,
38681
+ () => tracePromiseAsResponse(
38682
+ channel2,
38683
+ createChannelContext(channel2, params, span_info),
38684
+ getAPIPromise()
38685
+ ),
38686
+ getAPIPromise
38687
+ );
37853
38688
  };
37854
38689
  }
37855
38690
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -40544,7 +41379,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
40544
41379
  function createEveInstrumentationProvider(options = {}) {
40545
41380
  const bridge = new EveProviderBridge(options.metadata);
40546
41381
  return {
41382
+ // Eve versions before tracePolicy use capture to decide whether provider
41383
+ // events include content. Newer versions prefer tracePolicy when both are
41384
+ // present, so keep the deprecated field for backwards compatibility.
40547
41385
  capture: "content",
41386
+ tracePolicy: () => ({
41387
+ emit: true,
41388
+ recordInputs: true,
41389
+ recordOutputs: true
41390
+ }),
40548
41391
  events: {
40549
41392
  "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
40550
41393
  "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
@@ -44973,7 +45816,7 @@ function isAsync(fn) {
44973
45816
  function isAsyncGenerator2(fn) {
44974
45817
  return fn[Symbol.toStringTag] === "AsyncGenerator";
44975
45818
  }
44976
- function isAsyncIterable5(obj) {
45819
+ function isAsyncIterable6(obj) {
44977
45820
  return typeof obj[Symbol.asyncIterator] === "function";
44978
45821
  }
44979
45822
  function wrapAsync(asyncFn) {
@@ -45145,7 +45988,7 @@ var eachOfLimit$2 = (limit) => {
45145
45988
  if (isAsyncGenerator2(obj)) {
45146
45989
  return asyncEachOfLimit(obj, limit, iteratee, callback);
45147
45990
  }
45148
- if (isAsyncIterable5(obj)) {
45991
+ if (isAsyncIterable6(obj)) {
45149
45992
  return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
45150
45993
  }
45151
45994
  var nextElem = createIterator(obj);
@@ -46500,7 +47343,7 @@ function callEvaluatorData(data) {
46500
47343
  baseExperiment
46501
47344
  };
46502
47345
  }
46503
- function isAsyncIterable6(value) {
47346
+ function isAsyncIterable7(value) {
46504
47347
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
46505
47348
  }
46506
47349
  function isIterable(value) {
@@ -46535,7 +47378,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
46535
47378
  }).asDataset();
46536
47379
  }
46537
47380
  const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
46538
- if (isAsyncIterable6(resolvedDataResult)) {
47381
+ if (isAsyncIterable7(resolvedDataResult)) {
46539
47382
  return resolvedDataResult;
46540
47383
  }
46541
47384
  if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
@@ -49583,6 +50426,7 @@ export {
49583
50426
  braintrustStreamChunkSchema,
49584
50427
  buildLocalSummary,
49585
50428
  collectAnthropicSession,
50429
+ completeOpenAIBatchTrace,
49586
50430
  configureInstrumentation,
49587
50431
  constructLogs3OverflowRequest,
49588
50432
  createFinalValuePassThroughStream,
@@ -49622,6 +50466,8 @@ export {
49622
50466
  loginToState,
49623
50467
  logs3OverflowUploadSchema,
49624
50468
  newId,
50469
+ openaiBatchesRetrieveTraced,
50470
+ openaiFilesCreateTraced,
49625
50471
  parseCachedHeader,
49626
50472
  parseTemplateFormat,
49627
50473
  permalink,