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.
- package/dev/dist/index.js +1465 -881
- package/dev/dist/index.mjs +846 -262
- package/dist/apply-auto-instrumentation.js +217 -217
- package/dist/apply-auto-instrumentation.mjs +2 -2
- package/dist/auto-instrumentations/bundler/esbuild.cjs +13 -1
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +13 -1
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +13 -1
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +13 -1
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +13 -1
- package/dist/auto-instrumentations/bundler/webpack.cjs +13 -1
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-DKTGDNA7.mjs → chunk-LW4HDHXT.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-OMCZ3MV2.mjs → chunk-OXINGIEZ.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-AOIYCVEL.mjs → chunk-U64OYU4Q.mjs} +13 -1
- package/dist/auto-instrumentations/hook.mjs +16 -4
- package/dist/auto-instrumentations/index.cjs +13 -1
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +133 -2
- package/dist/browser.d.ts +133 -2
- package/dist/browser.js +1143 -297
- package/dist/browser.mjs +1143 -297
- package/dist/{chunk-6Z5S7VOU.js → chunk-2XDW3UCG.js} +13 -1
- package/dist/{chunk-M6XPNJC4.mjs → chunk-BU6SM54N.mjs} +687 -115
- package/dist/{chunk-7FA6VP2S.mjs → chunk-N3JKQ3D3.mjs} +13 -1
- package/dist/{chunk-XLLGRXGR.js → chunk-TWCDSYJN.js} +1803 -1231
- package/dist/cli.js +819 -235
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +1143 -297
- package/dist/edge-light.mjs +1143 -297
- package/dist/index.d.mts +133 -2
- package/dist/index.d.ts +133 -2
- package/dist/index.js +902 -640
- package/dist/index.mjs +336 -74
- package/dist/instrumentation/index.d.mts +15 -0
- package/dist/instrumentation/index.d.ts +15 -0
- package/dist/instrumentation/index.js +857 -262
- package/dist/instrumentation/index.mjs +857 -262
- package/dist/vitest-evals-reporter.js +16 -16
- package/dist/vitest-evals-reporter.mjs +2 -2
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +1143 -297
- package/dist/workerd.mjs +1143 -297
- package/package.json +1 -1
package/dist/workerd.js
CHANGED
|
@@ -104,6 +104,7 @@ __export(workerd_exports, {
|
|
|
104
104
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
105
105
|
buildLocalSummary: () => buildLocalSummary,
|
|
106
106
|
collectAnthropicSession: () => collectAnthropicSession,
|
|
107
|
+
completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
|
|
107
108
|
configureInstrumentation: () => configureInstrumentation,
|
|
108
109
|
constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
|
|
109
110
|
createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
|
|
@@ -143,6 +144,8 @@ __export(workerd_exports, {
|
|
|
143
144
|
loginToState: () => loginToState,
|
|
144
145
|
logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
|
|
145
146
|
newId: () => newId,
|
|
147
|
+
openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
|
|
148
|
+
openaiFilesCreateTraced: () => openaiFilesCreateTraced,
|
|
146
149
|
parseCachedHeader: () => parseCachedHeader,
|
|
147
150
|
parseTemplateFormat: () => parseTemplateFormat,
|
|
148
151
|
permalink: () => permalink,
|
|
@@ -5880,7 +5883,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5880
5883
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5881
5884
|
"braintrust.spanInstrumentationName"
|
|
5882
5885
|
);
|
|
5883
|
-
var SDK_VERSION = true ? "3.
|
|
5886
|
+
var SDK_VERSION = true ? "3.30.0" : "0.0.0";
|
|
5884
5887
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5885
5888
|
return {
|
|
5886
5889
|
...args,
|
|
@@ -10127,6 +10130,15 @@ function _internalStartSpanWithInitialMerge(args) {
|
|
|
10127
10130
|
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
10128
10131
|
}).span;
|
|
10129
10132
|
}
|
|
10133
|
+
function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
|
|
10134
|
+
return startSpanAndIsLogger(
|
|
10135
|
+
{
|
|
10136
|
+
...args,
|
|
10137
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
10138
|
+
},
|
|
10139
|
+
{ useParentSpanIdsForObjectParent: true }
|
|
10140
|
+
).span;
|
|
10141
|
+
}
|
|
10130
10142
|
function _internalStartSpanWithContext(args, context) {
|
|
10131
10143
|
return startSpanAndIsLogger({
|
|
10132
10144
|
...args,
|
|
@@ -10140,7 +10152,7 @@ async function flush(options) {
|
|
|
10140
10152
|
function setFetch(fetch2) {
|
|
10141
10153
|
_internalGetGlobalState().setFetch(fetch2);
|
|
10142
10154
|
}
|
|
10143
|
-
function startSpanAndIsLogger(args) {
|
|
10155
|
+
function startSpanAndIsLogger(args, internalOptions) {
|
|
10144
10156
|
const state = args?.state ?? _globalState;
|
|
10145
10157
|
const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
|
|
10146
10158
|
asyncFlush: args?.asyncFlush,
|
|
@@ -10154,7 +10166,7 @@ function startSpanAndIsLogger(args) {
|
|
|
10154
10166
|
) ? {
|
|
10155
10167
|
spanId: parentObject.data.span_id,
|
|
10156
10168
|
rootSpanId: parentObject.data.root_span_id
|
|
10157
|
-
} : void 0;
|
|
10169
|
+
} : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
|
|
10158
10170
|
const { parent: _ignoredParent, ...spanArgs } = args ?? {};
|
|
10159
10171
|
const span = new SpanImpl({
|
|
10160
10172
|
state,
|
|
@@ -13632,6 +13644,131 @@ function unsubscribeAll(unsubscribers) {
|
|
|
13632
13644
|
return [];
|
|
13633
13645
|
}
|
|
13634
13646
|
|
|
13647
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
13648
|
+
function channel(spec) {
|
|
13649
|
+
return spec;
|
|
13650
|
+
}
|
|
13651
|
+
function defineChannels(pkg, channels, options) {
|
|
13652
|
+
const { instrumentationName } = options;
|
|
13653
|
+
return Object.fromEntries(
|
|
13654
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
13655
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
13656
|
+
if (spec.kind === "async") {
|
|
13657
|
+
const asyncSpec = spec;
|
|
13658
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
13659
|
+
fullChannelName
|
|
13660
|
+
);
|
|
13661
|
+
const intercept2 = (interceptor) => {
|
|
13662
|
+
const hook = tracingChannel2();
|
|
13663
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13664
|
+
};
|
|
13665
|
+
};
|
|
13666
|
+
return [
|
|
13667
|
+
key,
|
|
13668
|
+
{
|
|
13669
|
+
...asyncSpec,
|
|
13670
|
+
instrumentationName,
|
|
13671
|
+
intercept: intercept2,
|
|
13672
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13673
|
+
const hook = tracingChannel2();
|
|
13674
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13675
|
+
},
|
|
13676
|
+
tracingChannel: tracingChannel2,
|
|
13677
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
13678
|
+
fn,
|
|
13679
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13680
|
+
context
|
|
13681
|
+
)
|
|
13682
|
+
}
|
|
13683
|
+
];
|
|
13684
|
+
}
|
|
13685
|
+
const syncSpec = spec;
|
|
13686
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
13687
|
+
fullChannelName
|
|
13688
|
+
);
|
|
13689
|
+
const intercept = (interceptor) => {
|
|
13690
|
+
const hook = tracingChannel();
|
|
13691
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13692
|
+
};
|
|
13693
|
+
};
|
|
13694
|
+
return [
|
|
13695
|
+
key,
|
|
13696
|
+
{
|
|
13697
|
+
...syncSpec,
|
|
13698
|
+
instrumentationName,
|
|
13699
|
+
intercept,
|
|
13700
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13701
|
+
const hook = tracingChannel();
|
|
13702
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13703
|
+
},
|
|
13704
|
+
tracingChannel,
|
|
13705
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
13706
|
+
fn,
|
|
13707
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13708
|
+
context
|
|
13709
|
+
)
|
|
13710
|
+
}
|
|
13711
|
+
];
|
|
13712
|
+
})
|
|
13713
|
+
);
|
|
13714
|
+
}
|
|
13715
|
+
|
|
13716
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
13717
|
+
var openAIChannels = defineChannels(
|
|
13718
|
+
"openai",
|
|
13719
|
+
{
|
|
13720
|
+
filesCreateTraced: channel({
|
|
13721
|
+
channelName: "files.create-traced",
|
|
13722
|
+
kind: "async"
|
|
13723
|
+
}),
|
|
13724
|
+
batchesRetrieveTraced: channel({
|
|
13725
|
+
channelName: "batches.retrieve-traced",
|
|
13726
|
+
kind: "async"
|
|
13727
|
+
}),
|
|
13728
|
+
batchesCompleteTrace: channel({
|
|
13729
|
+
channelName: "batches.complete-trace",
|
|
13730
|
+
kind: "async"
|
|
13731
|
+
}),
|
|
13732
|
+
chatCompletionsCreate: channel({
|
|
13733
|
+
channelName: "chat.completions.create",
|
|
13734
|
+
kind: "async"
|
|
13735
|
+
}),
|
|
13736
|
+
embeddingsCreate: channel({
|
|
13737
|
+
channelName: "embeddings.create",
|
|
13738
|
+
kind: "async"
|
|
13739
|
+
}),
|
|
13740
|
+
betaChatCompletionsParse: channel({
|
|
13741
|
+
channelName: "beta.chat.completions.parse",
|
|
13742
|
+
kind: "async"
|
|
13743
|
+
}),
|
|
13744
|
+
betaChatCompletionsStream: channel({
|
|
13745
|
+
channelName: "beta.chat.completions.stream",
|
|
13746
|
+
kind: "sync-stream"
|
|
13747
|
+
}),
|
|
13748
|
+
moderationsCreate: channel({
|
|
13749
|
+
channelName: "moderations.create",
|
|
13750
|
+
kind: "async"
|
|
13751
|
+
}),
|
|
13752
|
+
responsesCreate: channel({
|
|
13753
|
+
channelName: "responses.create",
|
|
13754
|
+
kind: "async"
|
|
13755
|
+
}),
|
|
13756
|
+
responsesStream: channel({
|
|
13757
|
+
channelName: "responses.stream",
|
|
13758
|
+
kind: "sync-stream"
|
|
13759
|
+
}),
|
|
13760
|
+
responsesParse: channel({
|
|
13761
|
+
channelName: "responses.parse",
|
|
13762
|
+
kind: "async"
|
|
13763
|
+
}),
|
|
13764
|
+
responsesCompact: channel({
|
|
13765
|
+
channelName: "responses.compact",
|
|
13766
|
+
kind: "async"
|
|
13767
|
+
})
|
|
13768
|
+
},
|
|
13769
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
13770
|
+
);
|
|
13771
|
+
|
|
13635
13772
|
// src/wrappers/attachment-utils.ts
|
|
13636
13773
|
function getExtensionFromMediaType(mediaType) {
|
|
13637
13774
|
const extensionMap = {
|
|
@@ -13807,118 +13944,91 @@ function processInputAttachments(input) {
|
|
|
13807
13944
|
return processNode(input);
|
|
13808
13945
|
}
|
|
13809
13946
|
|
|
13810
|
-
// src/instrumentation/
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
...asyncSpec,
|
|
13833
|
-
instrumentationName,
|
|
13834
|
-
intercept: intercept2,
|
|
13835
|
-
invoke: (target, thisArg, args, additional) => {
|
|
13836
|
-
const hook = tracingChannel2();
|
|
13837
|
-
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13838
|
-
},
|
|
13839
|
-
tracingChannel: tracingChannel2,
|
|
13840
|
-
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
13841
|
-
fn,
|
|
13842
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13843
|
-
context
|
|
13844
|
-
)
|
|
13845
|
-
}
|
|
13846
|
-
];
|
|
13947
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
13948
|
+
var OPENAI_METADATA_KEYS = [
|
|
13949
|
+
"model",
|
|
13950
|
+
"temperature",
|
|
13951
|
+
"top_p",
|
|
13952
|
+
"max_tokens",
|
|
13953
|
+
"frequency_penalty",
|
|
13954
|
+
"presence_penalty",
|
|
13955
|
+
"stop",
|
|
13956
|
+
"response_format",
|
|
13957
|
+
"tools",
|
|
13958
|
+
"tool_choice",
|
|
13959
|
+
"parallel_tool_calls",
|
|
13960
|
+
"max_tool_calls"
|
|
13961
|
+
];
|
|
13962
|
+
function batchMetadata(params) {
|
|
13963
|
+
const metadata = { provider: "openai" };
|
|
13964
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
13965
|
+
try {
|
|
13966
|
+
const value = Reflect.get(params, key);
|
|
13967
|
+
if (value !== void 0) {
|
|
13968
|
+
metadata[key] = value;
|
|
13847
13969
|
}
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13970
|
+
} catch {
|
|
13971
|
+
}
|
|
13972
|
+
}
|
|
13973
|
+
return metadata;
|
|
13974
|
+
}
|
|
13975
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
13976
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
13977
|
+
return {
|
|
13978
|
+
input: processInputAttachments(input),
|
|
13979
|
+
metadata: batchMetadata(params)
|
|
13980
|
+
};
|
|
13981
|
+
}
|
|
13982
|
+
function extractOpenAIChatInput(params) {
|
|
13983
|
+
const { messages, ...metadata } = params;
|
|
13984
|
+
return {
|
|
13985
|
+
input: processInputAttachments(messages),
|
|
13986
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13987
|
+
};
|
|
13988
|
+
}
|
|
13989
|
+
function extractOpenAIResponsesInput(params) {
|
|
13990
|
+
const { input, ...metadata } = params;
|
|
13991
|
+
return {
|
|
13992
|
+
input: processInputAttachments(input),
|
|
13993
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13994
|
+
};
|
|
13995
|
+
}
|
|
13996
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
13997
|
+
if (!result) {
|
|
13998
|
+
return void 0;
|
|
13999
|
+
}
|
|
14000
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14001
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14002
|
+
}
|
|
14003
|
+
function processImagesInOutput(output) {
|
|
14004
|
+
if (Array.isArray(output)) {
|
|
14005
|
+
return output.map(processImagesInOutput);
|
|
14006
|
+
}
|
|
14007
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
14008
|
+
const fileExtension = output.output_format || "png";
|
|
14009
|
+
const contentType = `image/${fileExtension}`;
|
|
14010
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
14011
|
+
let binaryString;
|
|
14012
|
+
try {
|
|
14013
|
+
binaryString = atob(output.result);
|
|
14014
|
+
} catch {
|
|
14015
|
+
return output;
|
|
14016
|
+
}
|
|
14017
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
14018
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
14019
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
14020
|
+
}
|
|
14021
|
+
return {
|
|
14022
|
+
...output,
|
|
14023
|
+
result: new Attachment({
|
|
14024
|
+
data: new Blob([bytes], { type: contentType }),
|
|
14025
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
14026
|
+
contentType
|
|
14027
|
+
})
|
|
14028
|
+
};
|
|
14029
|
+
}
|
|
14030
|
+
return output;
|
|
13877
14031
|
}
|
|
13878
|
-
|
|
13879
|
-
// src/instrumentation/plugins/openai-channels.ts
|
|
13880
|
-
var openAIChannels = defineChannels(
|
|
13881
|
-
"openai",
|
|
13882
|
-
{
|
|
13883
|
-
chatCompletionsCreate: channel({
|
|
13884
|
-
channelName: "chat.completions.create",
|
|
13885
|
-
kind: "async"
|
|
13886
|
-
}),
|
|
13887
|
-
embeddingsCreate: channel({
|
|
13888
|
-
channelName: "embeddings.create",
|
|
13889
|
-
kind: "async"
|
|
13890
|
-
}),
|
|
13891
|
-
betaChatCompletionsParse: channel({
|
|
13892
|
-
channelName: "beta.chat.completions.parse",
|
|
13893
|
-
kind: "async"
|
|
13894
|
-
}),
|
|
13895
|
-
betaChatCompletionsStream: channel({
|
|
13896
|
-
channelName: "beta.chat.completions.stream",
|
|
13897
|
-
kind: "sync-stream"
|
|
13898
|
-
}),
|
|
13899
|
-
moderationsCreate: channel({
|
|
13900
|
-
channelName: "moderations.create",
|
|
13901
|
-
kind: "async"
|
|
13902
|
-
}),
|
|
13903
|
-
responsesCreate: channel({
|
|
13904
|
-
channelName: "responses.create",
|
|
13905
|
-
kind: "async"
|
|
13906
|
-
}),
|
|
13907
|
-
responsesStream: channel({
|
|
13908
|
-
channelName: "responses.stream",
|
|
13909
|
-
kind: "sync-stream"
|
|
13910
|
-
}),
|
|
13911
|
-
responsesParse: channel({
|
|
13912
|
-
channelName: "responses.parse",
|
|
13913
|
-
kind: "async"
|
|
13914
|
-
}),
|
|
13915
|
-
responsesCompact: channel({
|
|
13916
|
-
channelName: "responses.compact",
|
|
13917
|
-
kind: "async"
|
|
13918
|
-
})
|
|
13919
|
-
},
|
|
13920
|
-
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
13921
|
-
);
|
|
13922
14032
|
|
|
13923
14033
|
// src/openai-utils.ts
|
|
13924
14034
|
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
@@ -13975,23 +14085,573 @@ function getCachedMetricFromHeaders(headers) {
|
|
|
13975
14085
|
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
13976
14086
|
}
|
|
13977
14087
|
|
|
14088
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
14089
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
14090
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
14091
|
+
"completed",
|
|
14092
|
+
"failed",
|
|
14093
|
+
"expired",
|
|
14094
|
+
"cancelled"
|
|
14095
|
+
]);
|
|
14096
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
14097
|
+
function read(value, key) {
|
|
14098
|
+
if (!isObject(value)) {
|
|
14099
|
+
return void 0;
|
|
14100
|
+
}
|
|
14101
|
+
try {
|
|
14102
|
+
return Reflect.get(value, key);
|
|
14103
|
+
} catch {
|
|
14104
|
+
return void 0;
|
|
14105
|
+
}
|
|
14106
|
+
}
|
|
14107
|
+
function isBatchRecordIterable(value) {
|
|
14108
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
14109
|
+
return false;
|
|
14110
|
+
}
|
|
14111
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
14112
|
+
}
|
|
14113
|
+
function validCustomId(value) {
|
|
14114
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
14115
|
+
}
|
|
14116
|
+
function logBatchInstrumentationError(context, error) {
|
|
14117
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
14118
|
+
}
|
|
14119
|
+
async function exportParent(parent) {
|
|
14120
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
14121
|
+
return parent.toStr();
|
|
14122
|
+
}
|
|
14123
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
14124
|
+
return await parent.export();
|
|
14125
|
+
}
|
|
14126
|
+
return void 0;
|
|
14127
|
+
}
|
|
14128
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
14129
|
+
const encoded = new TextEncoder().encode(
|
|
14130
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
14131
|
+
);
|
|
14132
|
+
return new Uint8Array(
|
|
14133
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
14134
|
+
);
|
|
14135
|
+
}
|
|
14136
|
+
function digestHex(bytes, length) {
|
|
14137
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
14138
|
+
}
|
|
14139
|
+
function digestUuid(bytes) {
|
|
14140
|
+
const hex = digestHex(bytes, 16);
|
|
14141
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
14142
|
+
}
|
|
14143
|
+
async function batchSpanIds(inputFileId) {
|
|
14144
|
+
const [row, span, root] = await Promise.all([
|
|
14145
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
14146
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
14147
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
14148
|
+
]);
|
|
14149
|
+
return {
|
|
14150
|
+
rowId: digestUuid(row),
|
|
14151
|
+
spanId: digestHex(span, 8),
|
|
14152
|
+
rootSpanId: digestHex(root, 16)
|
|
14153
|
+
};
|
|
14154
|
+
}
|
|
14155
|
+
async function childSpanIds(inputFileId, customId) {
|
|
14156
|
+
const [row, span] = await Promise.all([
|
|
14157
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
14158
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
14159
|
+
]);
|
|
14160
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
14161
|
+
}
|
|
14162
|
+
async function startBatchSpan(context) {
|
|
14163
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
14164
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
14165
|
+
const hasParentSpan = Boolean(
|
|
14166
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
14167
|
+
);
|
|
14168
|
+
return withCurrent(
|
|
14169
|
+
NOOP_SPAN,
|
|
14170
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
14171
|
+
withSpanInstrumentationName(
|
|
14172
|
+
{
|
|
14173
|
+
name: "openai.batch",
|
|
14174
|
+
type: "task" /* TASK */,
|
|
14175
|
+
parent: context.parent,
|
|
14176
|
+
...!hasParentSpan ? {
|
|
14177
|
+
parentSpanIds: {
|
|
14178
|
+
parentSpanIds: [],
|
|
14179
|
+
rootSpanId: ids.rootSpanId
|
|
14180
|
+
}
|
|
14181
|
+
} : {},
|
|
14182
|
+
spanId: ids.spanId,
|
|
14183
|
+
startTime: context.taskStartTime,
|
|
14184
|
+
event: {
|
|
14185
|
+
id: ids.rowId,
|
|
14186
|
+
metadata: {
|
|
14187
|
+
endpoint: context.endpoint,
|
|
14188
|
+
input_file_id: context.inputFileId,
|
|
14189
|
+
provider: "openai"
|
|
14190
|
+
}
|
|
14191
|
+
}
|
|
14192
|
+
},
|
|
14193
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14194
|
+
)
|
|
14195
|
+
)
|
|
14196
|
+
);
|
|
14197
|
+
}
|
|
14198
|
+
async function startBatchChild(context, taskParent, input) {
|
|
14199
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
14200
|
+
return withCurrent(
|
|
14201
|
+
NOOP_SPAN,
|
|
14202
|
+
() => _internalStartSpanWithInitialMerge(
|
|
14203
|
+
withSpanInstrumentationName(
|
|
14204
|
+
{
|
|
14205
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
14206
|
+
type: "llm" /* LLM */,
|
|
14207
|
+
parent: taskParent,
|
|
14208
|
+
spanId: ids.spanId,
|
|
14209
|
+
startTime: context.childStartTime,
|
|
14210
|
+
event: {
|
|
14211
|
+
id: ids.rowId,
|
|
14212
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
14213
|
+
metadata: {
|
|
14214
|
+
...input.spanData?.metadata,
|
|
14215
|
+
custom_id: input.customId,
|
|
14216
|
+
provider: "openai"
|
|
14217
|
+
}
|
|
14218
|
+
}
|
|
14219
|
+
},
|
|
14220
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14221
|
+
)
|
|
14222
|
+
)
|
|
14223
|
+
);
|
|
14224
|
+
}
|
|
14225
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
14226
|
+
}) {
|
|
14227
|
+
const resolvedFile = await file;
|
|
14228
|
+
if (typeof resolvedFile === "string") {
|
|
14229
|
+
for (const line of resolvedFile.split("\n")) {
|
|
14230
|
+
if (!line.trim()) {
|
|
14231
|
+
continue;
|
|
14232
|
+
}
|
|
14233
|
+
try {
|
|
14234
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
14235
|
+
} catch (error) {
|
|
14236
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14237
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14238
|
+
}
|
|
14239
|
+
}
|
|
14240
|
+
return;
|
|
14241
|
+
}
|
|
14242
|
+
const body = read(resolvedFile, "body");
|
|
14243
|
+
const getReader = read(body, "getReader");
|
|
14244
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
14245
|
+
let reader;
|
|
14246
|
+
try {
|
|
14247
|
+
reader = Reflect.apply(getReader, body, []);
|
|
14248
|
+
const decoder2 = new TextDecoder();
|
|
14249
|
+
let pending = "";
|
|
14250
|
+
while (true) {
|
|
14251
|
+
const readChunk = read(reader, "read");
|
|
14252
|
+
if (typeof readChunk !== "function") {
|
|
14253
|
+
throw new Error("Response body stream has no read method");
|
|
14254
|
+
}
|
|
14255
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
14256
|
+
if (!isObject(chunk)) {
|
|
14257
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
14258
|
+
}
|
|
14259
|
+
if (chunk.done === true) {
|
|
14260
|
+
pending += decoder2.decode();
|
|
14261
|
+
break;
|
|
14262
|
+
}
|
|
14263
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
14264
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
14265
|
+
}
|
|
14266
|
+
pending += decoder2.decode(chunk.value, { stream: true });
|
|
14267
|
+
let newline = pending.indexOf("\n");
|
|
14268
|
+
while (newline !== -1) {
|
|
14269
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
14270
|
+
pending = pending.slice(newline + 1);
|
|
14271
|
+
if (line.trim()) {
|
|
14272
|
+
try {
|
|
14273
|
+
yield JSON.parse(line);
|
|
14274
|
+
} catch (error) {
|
|
14275
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14276
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14277
|
+
}
|
|
14278
|
+
}
|
|
14279
|
+
newline = pending.indexOf("\n");
|
|
14280
|
+
}
|
|
14281
|
+
}
|
|
14282
|
+
if (pending.trim()) {
|
|
14283
|
+
try {
|
|
14284
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
14285
|
+
} catch (error) {
|
|
14286
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14287
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14288
|
+
}
|
|
14289
|
+
}
|
|
14290
|
+
} catch (error) {
|
|
14291
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
14292
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
14293
|
+
} finally {
|
|
14294
|
+
const releaseLock = read(reader, "releaseLock");
|
|
14295
|
+
if (typeof releaseLock === "function") {
|
|
14296
|
+
try {
|
|
14297
|
+
Reflect.apply(releaseLock, reader, []);
|
|
14298
|
+
} catch (error) {
|
|
14299
|
+
logBatchInstrumentationError(
|
|
14300
|
+
"could not release stream reader",
|
|
14301
|
+
error
|
|
14302
|
+
);
|
|
14303
|
+
}
|
|
14304
|
+
}
|
|
14305
|
+
}
|
|
14306
|
+
return;
|
|
14307
|
+
}
|
|
14308
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
14309
|
+
for await (const record of resolvedFile) {
|
|
14310
|
+
yield record;
|
|
14311
|
+
}
|
|
14312
|
+
return;
|
|
14313
|
+
}
|
|
14314
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
14315
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
14316
|
+
}
|
|
14317
|
+
async function readBatchInputs(file) {
|
|
14318
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
14319
|
+
const issues = [];
|
|
14320
|
+
let endpoint;
|
|
14321
|
+
try {
|
|
14322
|
+
for await (const value of jsonlRecords(
|
|
14323
|
+
file,
|
|
14324
|
+
(issue) => issues.push(issue)
|
|
14325
|
+
)) {
|
|
14326
|
+
const customId = read(value, "custom_id");
|
|
14327
|
+
const url = read(value, "url");
|
|
14328
|
+
const body = read(value, "body");
|
|
14329
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
14330
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
14331
|
+
continue;
|
|
14332
|
+
}
|
|
14333
|
+
endpoint = url;
|
|
14334
|
+
let spanData;
|
|
14335
|
+
try {
|
|
14336
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
14337
|
+
} catch (error) {
|
|
14338
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
14339
|
+
}
|
|
14340
|
+
inputs.set(customId, { customId, spanData });
|
|
14341
|
+
}
|
|
14342
|
+
} catch (error) {
|
|
14343
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
14344
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
14345
|
+
}
|
|
14346
|
+
if (!endpoint || inputs.size === 0) {
|
|
14347
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
14348
|
+
}
|
|
14349
|
+
return { endpoint, inputs, issues };
|
|
14350
|
+
}
|
|
14351
|
+
async function writePendingSpans(trace, endTime) {
|
|
14352
|
+
const task = await startBatchSpan(trace.context);
|
|
14353
|
+
const taskParent = await task.export();
|
|
14354
|
+
for (const input of trace.inputs.values()) {
|
|
14355
|
+
try {
|
|
14356
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14357
|
+
if (endTime !== void 0) {
|
|
14358
|
+
child.end({ endTime });
|
|
14359
|
+
}
|
|
14360
|
+
} catch (error) {
|
|
14361
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
14362
|
+
}
|
|
14363
|
+
}
|
|
14364
|
+
if (endTime !== void 0) {
|
|
14365
|
+
if (trace.status && trace.status !== "completed") {
|
|
14366
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14367
|
+
}
|
|
14368
|
+
task.end({ endTime });
|
|
14369
|
+
}
|
|
14370
|
+
}
|
|
14371
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
14372
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14373
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
14374
|
+
const parentPromise = exportParent(args[0].parent);
|
|
14375
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
14376
|
+
try {
|
|
14377
|
+
const inputFileId = read(file, "id");
|
|
14378
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
14379
|
+
inputPromise,
|
|
14380
|
+
parentPromise
|
|
14381
|
+
]);
|
|
14382
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
14383
|
+
if (inputData.issues[0]) {
|
|
14384
|
+
logBatchInstrumentationError(
|
|
14385
|
+
"skipped invalid input file",
|
|
14386
|
+
inputData.issues[0]
|
|
14387
|
+
);
|
|
14388
|
+
}
|
|
14389
|
+
return file;
|
|
14390
|
+
}
|
|
14391
|
+
const trace = {
|
|
14392
|
+
context: {
|
|
14393
|
+
inputFileId,
|
|
14394
|
+
endpoint: inputData.endpoint,
|
|
14395
|
+
parent: exportedParent2,
|
|
14396
|
+
taskStartTime: startTime,
|
|
14397
|
+
childStartTime: startTime
|
|
14398
|
+
},
|
|
14399
|
+
inputs: inputData.inputs
|
|
14400
|
+
};
|
|
14401
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
14402
|
+
await writePendingSpans(trace);
|
|
14403
|
+
} catch (error) {
|
|
14404
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
14405
|
+
}
|
|
14406
|
+
return file;
|
|
14407
|
+
};
|
|
14408
|
+
function validTimestamp(value) {
|
|
14409
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
14410
|
+
}
|
|
14411
|
+
function terminalEndTime(batch, startTime) {
|
|
14412
|
+
let timestamp;
|
|
14413
|
+
switch (batch.status) {
|
|
14414
|
+
case "completed":
|
|
14415
|
+
timestamp = batch.completed_at;
|
|
14416
|
+
break;
|
|
14417
|
+
case "failed":
|
|
14418
|
+
timestamp = batch.failed_at;
|
|
14419
|
+
break;
|
|
14420
|
+
case "expired":
|
|
14421
|
+
timestamp = batch.expired_at;
|
|
14422
|
+
break;
|
|
14423
|
+
default:
|
|
14424
|
+
timestamp = batch.cancelled_at;
|
|
14425
|
+
}
|
|
14426
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
14427
|
+
}
|
|
14428
|
+
async function updateBatchTimestamps(batch) {
|
|
14429
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
14430
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
14431
|
+
return;
|
|
14432
|
+
}
|
|
14433
|
+
if (validTimestamp(batch.created_at)) {
|
|
14434
|
+
trace.context.taskStartTime = batch.created_at;
|
|
14435
|
+
}
|
|
14436
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
14437
|
+
trace.status = batch.status;
|
|
14438
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
14439
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
14440
|
+
}
|
|
14441
|
+
await writePendingSpans(trace, trace.endTime);
|
|
14442
|
+
}
|
|
14443
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
14444
|
+
try {
|
|
14445
|
+
await updateBatchTimestamps(batch);
|
|
14446
|
+
} catch (error) {
|
|
14447
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
14448
|
+
}
|
|
14449
|
+
return batch;
|
|
14450
|
+
});
|
|
14451
|
+
function errorFromResult(result) {
|
|
14452
|
+
const error = read(result.value, "error");
|
|
14453
|
+
if (isObject(error)) {
|
|
14454
|
+
const message = read(error, "message");
|
|
14455
|
+
return new Error(
|
|
14456
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14457
|
+
);
|
|
14458
|
+
}
|
|
14459
|
+
const response = read(result.value, "response");
|
|
14460
|
+
const statusCode = read(response, "status_code");
|
|
14461
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
14462
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
14463
|
+
return new Error(
|
|
14464
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14465
|
+
);
|
|
14466
|
+
}
|
|
14467
|
+
return void 0;
|
|
14468
|
+
}
|
|
14469
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
14470
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
14471
|
+
try {
|
|
14472
|
+
const resultError = errorFromResult(result);
|
|
14473
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
14474
|
+
if (resultError) {
|
|
14475
|
+
child.log({ error: resultError });
|
|
14476
|
+
} else if (isObject(responseBody)) {
|
|
14477
|
+
const model = read(responseBody, "model");
|
|
14478
|
+
child.log({
|
|
14479
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
14480
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
14481
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
14482
|
+
});
|
|
14483
|
+
} else {
|
|
14484
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
14485
|
+
}
|
|
14486
|
+
} catch (error) {
|
|
14487
|
+
child.log({ error });
|
|
14488
|
+
} finally {
|
|
14489
|
+
child.end({ endTime });
|
|
14490
|
+
}
|
|
14491
|
+
}
|
|
14492
|
+
async function completeResultFile({
|
|
14493
|
+
context,
|
|
14494
|
+
endTime,
|
|
14495
|
+
file,
|
|
14496
|
+
inputs,
|
|
14497
|
+
issues,
|
|
14498
|
+
seen,
|
|
14499
|
+
source,
|
|
14500
|
+
taskParent
|
|
14501
|
+
}) {
|
|
14502
|
+
if (file === void 0) {
|
|
14503
|
+
return;
|
|
14504
|
+
}
|
|
14505
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
14506
|
+
const customId = read(value, "custom_id");
|
|
14507
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
14508
|
+
issues.push(
|
|
14509
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
14510
|
+
);
|
|
14511
|
+
continue;
|
|
14512
|
+
}
|
|
14513
|
+
if (seen.has(customId)) {
|
|
14514
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
14515
|
+
continue;
|
|
14516
|
+
}
|
|
14517
|
+
const input = inputs.get(customId);
|
|
14518
|
+
if (!input) {
|
|
14519
|
+
issues.push(
|
|
14520
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
14521
|
+
);
|
|
14522
|
+
continue;
|
|
14523
|
+
}
|
|
14524
|
+
seen.add(customId);
|
|
14525
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
14526
|
+
value,
|
|
14527
|
+
source
|
|
14528
|
+
});
|
|
14529
|
+
}
|
|
14530
|
+
}
|
|
14531
|
+
function sameInputs(first, second) {
|
|
14532
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
14533
|
+
}
|
|
14534
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
14535
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
14536
|
+
return void 0;
|
|
14537
|
+
}
|
|
14538
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
14539
|
+
if (existing) {
|
|
14540
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
14541
|
+
return void 0;
|
|
14542
|
+
}
|
|
14543
|
+
return { ...existing, inputs: inputData.inputs };
|
|
14544
|
+
}
|
|
14545
|
+
const parent = await exportParent(getSpanParentObject());
|
|
14546
|
+
if (!parent) {
|
|
14547
|
+
return void 0;
|
|
14548
|
+
}
|
|
14549
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14550
|
+
return {
|
|
14551
|
+
context: {
|
|
14552
|
+
inputFileId,
|
|
14553
|
+
endpoint: inputData.endpoint,
|
|
14554
|
+
parent,
|
|
14555
|
+
taskStartTime: startTime,
|
|
14556
|
+
childStartTime: startTime
|
|
14557
|
+
},
|
|
14558
|
+
inputs: inputData.inputs
|
|
14559
|
+
};
|
|
14560
|
+
}
|
|
14561
|
+
async function completeBatch(args) {
|
|
14562
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
14563
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
14564
|
+
if (!trace) {
|
|
14565
|
+
logBatchInstrumentationError(
|
|
14566
|
+
"left batch spans pending",
|
|
14567
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
14568
|
+
);
|
|
14569
|
+
return;
|
|
14570
|
+
}
|
|
14571
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
14572
|
+
const task = await startBatchSpan(trace.context);
|
|
14573
|
+
const taskParent = await task.export();
|
|
14574
|
+
const issues = [];
|
|
14575
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14576
|
+
await Promise.all([
|
|
14577
|
+
completeResultFile({
|
|
14578
|
+
context: trace.context,
|
|
14579
|
+
endTime,
|
|
14580
|
+
file: args.outputFileContent,
|
|
14581
|
+
inputs: trace.inputs,
|
|
14582
|
+
issues,
|
|
14583
|
+
seen,
|
|
14584
|
+
source: "output",
|
|
14585
|
+
taskParent
|
|
14586
|
+
}),
|
|
14587
|
+
completeResultFile({
|
|
14588
|
+
context: trace.context,
|
|
14589
|
+
endTime,
|
|
14590
|
+
file: args.errorFileContent,
|
|
14591
|
+
inputs: trace.inputs,
|
|
14592
|
+
issues,
|
|
14593
|
+
seen,
|
|
14594
|
+
source: "error",
|
|
14595
|
+
taskParent
|
|
14596
|
+
})
|
|
14597
|
+
]);
|
|
14598
|
+
if (issues.length > 0) {
|
|
14599
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
14600
|
+
return;
|
|
14601
|
+
}
|
|
14602
|
+
const missing = [...trace.inputs.values()].filter(
|
|
14603
|
+
({ customId }) => !seen.has(customId)
|
|
14604
|
+
);
|
|
14605
|
+
if (!trace.status || trace.status === "completed") {
|
|
14606
|
+
if (missing.length > 0) {
|
|
14607
|
+
logBatchInstrumentationError(
|
|
14608
|
+
"left batch spans pending",
|
|
14609
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
14610
|
+
);
|
|
14611
|
+
return;
|
|
14612
|
+
}
|
|
14613
|
+
} else {
|
|
14614
|
+
for (const input of missing) {
|
|
14615
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14616
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14617
|
+
child.end({ endTime });
|
|
14618
|
+
}
|
|
14619
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14620
|
+
}
|
|
14621
|
+
task.end({ endTime });
|
|
14622
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
14623
|
+
}
|
|
14624
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
14625
|
+
try {
|
|
14626
|
+
await completeBatch(args[0]);
|
|
14627
|
+
} catch (error) {
|
|
14628
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
14629
|
+
}
|
|
14630
|
+
return result;
|
|
14631
|
+
});
|
|
14632
|
+
|
|
13978
14633
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
13979
14634
|
var OpenAIPlugin = class extends BasePlugin {
|
|
13980
14635
|
constructor() {
|
|
13981
14636
|
super();
|
|
13982
14637
|
}
|
|
13983
14638
|
onEnable() {
|
|
14639
|
+
this.unsubscribers.push(
|
|
14640
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
14641
|
+
interceptOpenAIFilesCreateTraced
|
|
14642
|
+
),
|
|
14643
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
14644
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
14645
|
+
),
|
|
14646
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
14647
|
+
interceptOpenAIBatchTraceComplete
|
|
14648
|
+
)
|
|
14649
|
+
);
|
|
13984
14650
|
this.unsubscribers.push(
|
|
13985
14651
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
13986
14652
|
name: "Chat Completion",
|
|
13987
14653
|
type: "llm" /* LLM */,
|
|
13988
|
-
extractInput: ([params]) =>
|
|
13989
|
-
const { messages, ...metadata } = params;
|
|
13990
|
-
return {
|
|
13991
|
-
input: processInputAttachments(messages),
|
|
13992
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13993
|
-
};
|
|
13994
|
-
},
|
|
14654
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
13995
14655
|
extractOutput: (result) => {
|
|
13996
14656
|
return result?.choices;
|
|
13997
14657
|
},
|
|
@@ -14037,13 +14697,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14037
14697
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
14038
14698
|
name: "Chat Completion",
|
|
14039
14699
|
type: "llm" /* LLM */,
|
|
14040
|
-
extractInput: ([params]) =>
|
|
14041
|
-
const { messages, ...metadata } = params;
|
|
14042
|
-
return {
|
|
14043
|
-
input: processInputAttachments(messages),
|
|
14044
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14045
|
-
};
|
|
14046
|
-
},
|
|
14700
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
14047
14701
|
extractOutput: (result) => {
|
|
14048
14702
|
return result?.choices;
|
|
14049
14703
|
},
|
|
@@ -14065,13 +14719,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14065
14719
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
14066
14720
|
name: "Chat Completion",
|
|
14067
14721
|
type: "llm" /* LLM */,
|
|
14068
|
-
extractInput: ([params]) =>
|
|
14069
|
-
const { messages, ...metadata } = params;
|
|
14070
|
-
return {
|
|
14071
|
-
input: processInputAttachments(messages),
|
|
14072
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14073
|
-
};
|
|
14074
|
-
}
|
|
14722
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
14075
14723
|
})
|
|
14076
14724
|
);
|
|
14077
14725
|
this.unsubscribers.push(
|
|
@@ -14101,23 +14749,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14101
14749
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
14102
14750
|
name: "openai.responses.create",
|
|
14103
14751
|
type: "llm" /* LLM */,
|
|
14104
|
-
extractInput: ([params]) =>
|
|
14105
|
-
const { input, ...metadata } = params;
|
|
14106
|
-
return {
|
|
14107
|
-
input: processInputAttachments(input),
|
|
14108
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14109
|
-
};
|
|
14110
|
-
},
|
|
14752
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14111
14753
|
extractOutput: (result) => {
|
|
14112
14754
|
return processImagesInOutput(result?.output);
|
|
14113
14755
|
},
|
|
14114
|
-
extractMetadata: (result) =>
|
|
14115
|
-
if (!result) {
|
|
14116
|
-
return void 0;
|
|
14117
|
-
}
|
|
14118
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14119
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14120
|
-
},
|
|
14756
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14121
14757
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14122
14758
|
const metrics = withCachedMetric(
|
|
14123
14759
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14136,13 +14772,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14136
14772
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
14137
14773
|
name: "openai.responses.create",
|
|
14138
14774
|
type: "llm" /* LLM */,
|
|
14139
|
-
extractInput: ([params]) =>
|
|
14140
|
-
const { input, ...metadata } = params;
|
|
14141
|
-
return {
|
|
14142
|
-
input: processInputAttachments(input),
|
|
14143
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14144
|
-
};
|
|
14145
|
-
},
|
|
14775
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14146
14776
|
extractFromEvent: (event) => {
|
|
14147
14777
|
if (event.type !== "response.completed" || !event.response) {
|
|
14148
14778
|
return {};
|
|
@@ -14165,23 +14795,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14165
14795
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
14166
14796
|
name: "openai.responses.parse",
|
|
14167
14797
|
type: "llm" /* LLM */,
|
|
14168
|
-
extractInput: ([params]) =>
|
|
14169
|
-
const { input, ...metadata } = params;
|
|
14170
|
-
return {
|
|
14171
|
-
input: processInputAttachments(input),
|
|
14172
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14173
|
-
};
|
|
14174
|
-
},
|
|
14798
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14175
14799
|
extractOutput: (result) => {
|
|
14176
14800
|
return processImagesInOutput(result?.output);
|
|
14177
14801
|
},
|
|
14178
|
-
extractMetadata: (result) =>
|
|
14179
|
-
if (!result) {
|
|
14180
|
-
return void 0;
|
|
14181
|
-
}
|
|
14182
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14183
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14184
|
-
},
|
|
14802
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14185
14803
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14186
14804
|
const metrics = withCachedMetric(
|
|
14187
14805
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14200,23 +14818,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14200
14818
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
14201
14819
|
name: "openai.responses.compact",
|
|
14202
14820
|
type: "llm" /* LLM */,
|
|
14203
|
-
extractInput: ([params]) =>
|
|
14204
|
-
const { input, ...metadata } = params;
|
|
14205
|
-
return {
|
|
14206
|
-
input: processInputAttachments(input),
|
|
14207
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14208
|
-
};
|
|
14209
|
-
},
|
|
14821
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14210
14822
|
extractOutput: (result) => {
|
|
14211
14823
|
return processImagesInOutput(result?.output);
|
|
14212
14824
|
},
|
|
14213
|
-
extractMetadata: (result) =>
|
|
14214
|
-
if (!result) {
|
|
14215
|
-
return void 0;
|
|
14216
|
-
}
|
|
14217
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14218
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14219
|
-
},
|
|
14825
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14220
14826
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14221
14827
|
const metrics = withCachedMetric(
|
|
14222
14828
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14272,35 +14878,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
14272
14878
|
cached
|
|
14273
14879
|
};
|
|
14274
14880
|
}
|
|
14275
|
-
function processImagesInOutput(output) {
|
|
14276
|
-
if (Array.isArray(output)) {
|
|
14277
|
-
return output.map(processImagesInOutput);
|
|
14278
|
-
}
|
|
14279
|
-
if (isObject(output)) {
|
|
14280
|
-
if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
|
|
14281
|
-
const fileExtension = output.output_format || "png";
|
|
14282
|
-
const contentType = `image/${fileExtension}`;
|
|
14283
|
-
const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
14284
|
-
const filename = `${baseFilename}.${fileExtension}`;
|
|
14285
|
-
const binaryString = atob(output.result);
|
|
14286
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
14287
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
14288
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
14289
|
-
}
|
|
14290
|
-
const blob = new Blob([bytes], { type: contentType });
|
|
14291
|
-
const attachment = new Attachment({
|
|
14292
|
-
data: blob,
|
|
14293
|
-
filename,
|
|
14294
|
-
contentType
|
|
14295
|
-
});
|
|
14296
|
-
return {
|
|
14297
|
-
...output,
|
|
14298
|
-
result: attachment
|
|
14299
|
-
};
|
|
14300
|
-
}
|
|
14301
|
-
}
|
|
14302
|
-
return output;
|
|
14303
|
-
}
|
|
14304
14881
|
function mergeLogprobTokens(existing, incoming) {
|
|
14305
14882
|
if (incoming === void 0) {
|
|
14306
14883
|
return existing;
|
|
@@ -34333,7 +34910,7 @@ function extractSession(event) {
|
|
|
34333
34910
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
34334
34911
|
}
|
|
34335
34912
|
function isPiAgent(value) {
|
|
34336
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
34913
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
34337
34914
|
}
|
|
34338
34915
|
function promptContextStore() {
|
|
34339
34916
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -34343,17 +34920,21 @@ function currentPiPromptState() {
|
|
|
34343
34920
|
return promptContextStore().getStore();
|
|
34344
34921
|
}
|
|
34345
34922
|
function installPiAgentInstrumentation(agent) {
|
|
34923
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
34924
|
+
const streamFunction = agent[property];
|
|
34346
34925
|
const existing = piAgentPatchStates.get(agent);
|
|
34347
|
-
if (!existing ||
|
|
34926
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
34348
34927
|
const patchState = {
|
|
34349
|
-
|
|
34350
|
-
|
|
34928
|
+
originalStreamFunction: streamFunction,
|
|
34929
|
+
property,
|
|
34930
|
+
wrappedStreamFunction: streamFunction
|
|
34351
34931
|
};
|
|
34352
|
-
patchState.
|
|
34932
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
34353
34933
|
agent,
|
|
34354
|
-
patchState.
|
|
34934
|
+
patchState.originalStreamFunction,
|
|
34935
|
+
property
|
|
34355
34936
|
);
|
|
34356
|
-
agent
|
|
34937
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
34357
34938
|
piAgentPatchStates.set(agent, patchState);
|
|
34358
34939
|
}
|
|
34359
34940
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -34378,15 +34959,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
34378
34959
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
34379
34960
|
}
|
|
34380
34961
|
}
|
|
34381
|
-
function
|
|
34382
|
-
return async function
|
|
34383
|
-
const invokeOriginal = () => Reflect.apply(
|
|
34962
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
34963
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
34964
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
34384
34965
|
const state = currentPiPromptState();
|
|
34385
34966
|
if (!state || state.agent !== agent || state.finalized) {
|
|
34386
34967
|
return invokeOriginal();
|
|
34387
34968
|
}
|
|
34388
34969
|
wrapPiToolExecutors(context.tools);
|
|
34389
|
-
const llmState = await startPiLlmSpan(
|
|
34970
|
+
const llmState = await startPiLlmSpan(
|
|
34971
|
+
state,
|
|
34972
|
+
model,
|
|
34973
|
+
context,
|
|
34974
|
+
property,
|
|
34975
|
+
options
|
|
34976
|
+
);
|
|
34390
34977
|
try {
|
|
34391
34978
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
34392
34979
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -34423,12 +35010,12 @@ function wrapPiToolExecutors(tools) {
|
|
|
34423
35010
|
}
|
|
34424
35011
|
}
|
|
34425
35012
|
}
|
|
34426
|
-
async function startPiLlmSpan(state, model, context, options) {
|
|
35013
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
34427
35014
|
const metadata = {
|
|
34428
35015
|
...extractModelMetadata2(model),
|
|
34429
35016
|
...extractStreamOptionsMetadata(options),
|
|
34430
35017
|
...extractToolMetadata(context.tools),
|
|
34431
|
-
"pi_coding_agent.operation":
|
|
35018
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
34432
35019
|
};
|
|
34433
35020
|
const span = startSpan(
|
|
34434
35021
|
withSpanInstrumentationName(
|
|
@@ -37444,6 +38031,7 @@ __export(exports_exports, {
|
|
|
37444
38031
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
37445
38032
|
buildLocalSummary: () => buildLocalSummary,
|
|
37446
38033
|
collectAnthropicSession: () => collectAnthropicSession,
|
|
38034
|
+
completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
|
|
37447
38035
|
configureInstrumentation: () => configureInstrumentation,
|
|
37448
38036
|
constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
|
|
37449
38037
|
createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
|
|
@@ -37482,6 +38070,8 @@ __export(exports_exports, {
|
|
|
37482
38070
|
loginToState: () => loginToState,
|
|
37483
38071
|
logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
|
|
37484
38072
|
newId: () => newId,
|
|
38073
|
+
openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
|
|
38074
|
+
openaiFilesCreateTraced: () => openaiFilesCreateTraced,
|
|
37485
38075
|
parseCachedHeader: () => parseCachedHeader,
|
|
37486
38076
|
parseTemplateFormat: () => parseTemplateFormat,
|
|
37487
38077
|
permalink: () => permalink,
|
|
@@ -37646,6 +38236,260 @@ async function registerSandbox(options) {
|
|
|
37646
38236
|
};
|
|
37647
38237
|
}
|
|
37648
38238
|
|
|
38239
|
+
// src/wrappers/openai-promise-utils.ts
|
|
38240
|
+
function splitSpanInfo(allParams) {
|
|
38241
|
+
const { span_info, ...params } = allParams;
|
|
38242
|
+
return {
|
|
38243
|
+
params,
|
|
38244
|
+
span_info
|
|
38245
|
+
};
|
|
38246
|
+
}
|
|
38247
|
+
function createChannelContext(_channel, params, span_info) {
|
|
38248
|
+
return {
|
|
38249
|
+
arguments: (
|
|
38250
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38251
|
+
[params]
|
|
38252
|
+
),
|
|
38253
|
+
span_info
|
|
38254
|
+
};
|
|
38255
|
+
}
|
|
38256
|
+
async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
|
|
38257
|
+
let enhancedResponse;
|
|
38258
|
+
const tracePromise = (
|
|
38259
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38260
|
+
channel2.tracePromise
|
|
38261
|
+
);
|
|
38262
|
+
const data = await tracePromise(async () => {
|
|
38263
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38264
|
+
traceContext.response = enhancedResponse.response;
|
|
38265
|
+
return enhancedResponse.data;
|
|
38266
|
+
}, traceContext);
|
|
38267
|
+
if (!enhancedResponse) {
|
|
38268
|
+
throw new Error("Expected withResponse() to provide response");
|
|
38269
|
+
}
|
|
38270
|
+
return {
|
|
38271
|
+
data,
|
|
38272
|
+
response: enhancedResponse.response,
|
|
38273
|
+
request_id: enhancedResponse.request_id
|
|
38274
|
+
};
|
|
38275
|
+
}
|
|
38276
|
+
async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
|
|
38277
|
+
const tracePromise = (
|
|
38278
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38279
|
+
channel2.tracePromise
|
|
38280
|
+
);
|
|
38281
|
+
let response;
|
|
38282
|
+
await tracePromise(async () => {
|
|
38283
|
+
response = await apiPromise.asResponse();
|
|
38284
|
+
traceContext.response = response;
|
|
38285
|
+
return void 0;
|
|
38286
|
+
}, traceContext);
|
|
38287
|
+
if (!response) {
|
|
38288
|
+
throw new Error("Expected asResponse() to provide response");
|
|
38289
|
+
}
|
|
38290
|
+
return response;
|
|
38291
|
+
}
|
|
38292
|
+
function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
|
|
38293
|
+
let firstConsumption;
|
|
38294
|
+
let enhancedResponsePromise;
|
|
38295
|
+
let dataPromise;
|
|
38296
|
+
let responsePromise;
|
|
38297
|
+
const withResponse = () => {
|
|
38298
|
+
firstConsumption ??= "data";
|
|
38299
|
+
enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
|
|
38300
|
+
return enhancedResponsePromise;
|
|
38301
|
+
};
|
|
38302
|
+
const asResponse = () => {
|
|
38303
|
+
firstConsumption ??= "response";
|
|
38304
|
+
responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
|
|
38305
|
+
return responsePromise;
|
|
38306
|
+
};
|
|
38307
|
+
return new Proxy({}, {
|
|
38308
|
+
get(target, prop, receiver) {
|
|
38309
|
+
if (prop === "withResponse") {
|
|
38310
|
+
return withResponse;
|
|
38311
|
+
}
|
|
38312
|
+
if (prop === "asResponse") {
|
|
38313
|
+
return asResponse;
|
|
38314
|
+
}
|
|
38315
|
+
if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
|
|
38316
|
+
dataPromise ??= withResponse().then((result) => result.data);
|
|
38317
|
+
const value = Reflect.get(dataPromise, prop, receiver);
|
|
38318
|
+
return typeof value === "function" ? value.bind(dataPromise) : value;
|
|
38319
|
+
}
|
|
38320
|
+
return Reflect.get(target, prop, receiver);
|
|
38321
|
+
}
|
|
38322
|
+
});
|
|
38323
|
+
}
|
|
38324
|
+
|
|
38325
|
+
// src/openai-batch.ts
|
|
38326
|
+
function read2(value, key) {
|
|
38327
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
38328
|
+
return void 0;
|
|
38329
|
+
}
|
|
38330
|
+
try {
|
|
38331
|
+
return Reflect.get(value, key);
|
|
38332
|
+
} catch {
|
|
38333
|
+
return void 0;
|
|
38334
|
+
}
|
|
38335
|
+
}
|
|
38336
|
+
function isAsyncIterable5(value) {
|
|
38337
|
+
return typeof read2(value, Symbol.asyncIterator) === "function";
|
|
38338
|
+
}
|
|
38339
|
+
function teeAsyncIterable(source) {
|
|
38340
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
38341
|
+
const stream = new ReadableStream({
|
|
38342
|
+
async pull(controller) {
|
|
38343
|
+
try {
|
|
38344
|
+
const result = await iterator.next();
|
|
38345
|
+
if (result.done) {
|
|
38346
|
+
controller.close();
|
|
38347
|
+
return;
|
|
38348
|
+
}
|
|
38349
|
+
if (!(result.value instanceof Uint8Array)) {
|
|
38350
|
+
throw new TypeError(
|
|
38351
|
+
"OpenAI upload streams must yield Uint8Array chunks"
|
|
38352
|
+
);
|
|
38353
|
+
}
|
|
38354
|
+
controller.enqueue(result.value);
|
|
38355
|
+
} catch (error) {
|
|
38356
|
+
controller.error(error);
|
|
38357
|
+
}
|
|
38358
|
+
},
|
|
38359
|
+
async cancel(reason) {
|
|
38360
|
+
await iterator.return?.(reason);
|
|
38361
|
+
}
|
|
38362
|
+
});
|
|
38363
|
+
const [uploadStream, trace] = stream.tee();
|
|
38364
|
+
const upload = {
|
|
38365
|
+
async *[Symbol.asyncIterator]() {
|
|
38366
|
+
const reader = uploadStream.getReader();
|
|
38367
|
+
try {
|
|
38368
|
+
while (true) {
|
|
38369
|
+
const result = await reader.read();
|
|
38370
|
+
if (result.done) {
|
|
38371
|
+
return;
|
|
38372
|
+
}
|
|
38373
|
+
yield result.value;
|
|
38374
|
+
}
|
|
38375
|
+
} finally {
|
|
38376
|
+
reader.releaseLock();
|
|
38377
|
+
}
|
|
38378
|
+
}
|
|
38379
|
+
};
|
|
38380
|
+
const path = read2(source, "path");
|
|
38381
|
+
if (typeof path === "string") {
|
|
38382
|
+
Object.defineProperty(upload, "path", { value: path });
|
|
38383
|
+
}
|
|
38384
|
+
return { upload, trace: new Response(trace) };
|
|
38385
|
+
}
|
|
38386
|
+
function teeUpload(upload) {
|
|
38387
|
+
if (upload instanceof Blob) {
|
|
38388
|
+
return { upload, trace: new Response(upload) };
|
|
38389
|
+
}
|
|
38390
|
+
if (upload instanceof Response) {
|
|
38391
|
+
return { upload, trace: upload.clone() };
|
|
38392
|
+
}
|
|
38393
|
+
if (isAsyncIterable5(upload)) {
|
|
38394
|
+
return teeAsyncIterable(upload);
|
|
38395
|
+
}
|
|
38396
|
+
return void 0;
|
|
38397
|
+
}
|
|
38398
|
+
function openaiFilesCreateTraced(files) {
|
|
38399
|
+
return (params, options) => {
|
|
38400
|
+
const parent = getSpanParentObject();
|
|
38401
|
+
const purpose = read2(params, "purpose");
|
|
38402
|
+
const file = read2(params, "file");
|
|
38403
|
+
if (purpose !== "batch") {
|
|
38404
|
+
return files.create(params, options);
|
|
38405
|
+
}
|
|
38406
|
+
let branches;
|
|
38407
|
+
try {
|
|
38408
|
+
branches = teeUpload(file);
|
|
38409
|
+
} catch {
|
|
38410
|
+
return files.create(params, options);
|
|
38411
|
+
}
|
|
38412
|
+
if (!branches) {
|
|
38413
|
+
return files.create(params, options);
|
|
38414
|
+
}
|
|
38415
|
+
const tracedParams = {
|
|
38416
|
+
...Object(params),
|
|
38417
|
+
file: branches.upload
|
|
38418
|
+
};
|
|
38419
|
+
const apiPromise = files.create(tracedParams, options);
|
|
38420
|
+
let enhancedResponse;
|
|
38421
|
+
const tracedResponse = openAIChannels.filesCreateTraced.invoke(
|
|
38422
|
+
async () => {
|
|
38423
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38424
|
+
return enhancedResponse.data;
|
|
38425
|
+
},
|
|
38426
|
+
files,
|
|
38427
|
+
[{ params, inputFileContent: branches.trace, parent }],
|
|
38428
|
+
{}
|
|
38429
|
+
).then((data) => {
|
|
38430
|
+
if (!enhancedResponse) {
|
|
38431
|
+
throw new Error(
|
|
38432
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38433
|
+
);
|
|
38434
|
+
}
|
|
38435
|
+
return { ...enhancedResponse, data };
|
|
38436
|
+
});
|
|
38437
|
+
return createLazyAPIPromise(
|
|
38438
|
+
() => tracedResponse,
|
|
38439
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38440
|
+
() => apiPromise
|
|
38441
|
+
);
|
|
38442
|
+
};
|
|
38443
|
+
}
|
|
38444
|
+
function openaiBatchesRetrieveTraced(batches) {
|
|
38445
|
+
return (batchId, options) => {
|
|
38446
|
+
const apiPromise = batches.retrieve(batchId, options);
|
|
38447
|
+
let enhancedResponse;
|
|
38448
|
+
const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
|
|
38449
|
+
async () => {
|
|
38450
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38451
|
+
return enhancedResponse.data;
|
|
38452
|
+
},
|
|
38453
|
+
batches,
|
|
38454
|
+
[{ batchId }],
|
|
38455
|
+
{}
|
|
38456
|
+
).then((data) => {
|
|
38457
|
+
if (!enhancedResponse) {
|
|
38458
|
+
throw new Error(
|
|
38459
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38460
|
+
);
|
|
38461
|
+
}
|
|
38462
|
+
return { ...enhancedResponse, data };
|
|
38463
|
+
});
|
|
38464
|
+
return createLazyAPIPromise(
|
|
38465
|
+
() => tracedResponse,
|
|
38466
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38467
|
+
() => apiPromise
|
|
38468
|
+
);
|
|
38469
|
+
};
|
|
38470
|
+
}
|
|
38471
|
+
async function completeOpenAIBatchTrace(args) {
|
|
38472
|
+
const inputFileContent = Promise.resolve(args.inputFileContent);
|
|
38473
|
+
const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
|
|
38474
|
+
const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
|
|
38475
|
+
void inputFileContent.catch(() => void 0);
|
|
38476
|
+
void outputFileContent?.catch(() => void 0);
|
|
38477
|
+
void errorFileContent?.catch(() => void 0);
|
|
38478
|
+
await openAIChannels.batchesCompleteTrace.invoke(
|
|
38479
|
+
async () => void 0,
|
|
38480
|
+
void 0,
|
|
38481
|
+
[
|
|
38482
|
+
{
|
|
38483
|
+
...args,
|
|
38484
|
+
inputFileContent,
|
|
38485
|
+
outputFileContent,
|
|
38486
|
+
errorFileContent
|
|
38487
|
+
}
|
|
38488
|
+
],
|
|
38489
|
+
{}
|
|
38490
|
+
);
|
|
38491
|
+
}
|
|
38492
|
+
|
|
37649
38493
|
// src/functions/invoke.ts
|
|
37650
38494
|
async function invoke(args) {
|
|
37651
38495
|
const {
|
|
@@ -37748,58 +38592,6 @@ function initFunction({
|
|
|
37748
38592
|
return f;
|
|
37749
38593
|
}
|
|
37750
38594
|
|
|
37751
|
-
// src/wrappers/openai-promise-utils.ts
|
|
37752
|
-
function splitSpanInfo(allParams) {
|
|
37753
|
-
const { span_info, ...params } = allParams;
|
|
37754
|
-
return {
|
|
37755
|
-
params,
|
|
37756
|
-
span_info
|
|
37757
|
-
};
|
|
37758
|
-
}
|
|
37759
|
-
function createChannelContext(_channel, params, span_info) {
|
|
37760
|
-
return {
|
|
37761
|
-
arguments: (
|
|
37762
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37763
|
-
[params]
|
|
37764
|
-
),
|
|
37765
|
-
span_info
|
|
37766
|
-
};
|
|
37767
|
-
}
|
|
37768
|
-
async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
|
|
37769
|
-
let enhancedResponse;
|
|
37770
|
-
const tracePromise = (
|
|
37771
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37772
|
-
channel2.tracePromise
|
|
37773
|
-
);
|
|
37774
|
-
const data = await tracePromise(async () => {
|
|
37775
|
-
enhancedResponse = await apiPromise.withResponse();
|
|
37776
|
-
traceContext.response = enhancedResponse.response;
|
|
37777
|
-
return enhancedResponse.data;
|
|
37778
|
-
}, traceContext);
|
|
37779
|
-
if (!enhancedResponse) {
|
|
37780
|
-
throw new Error("Expected withResponse() to provide response");
|
|
37781
|
-
}
|
|
37782
|
-
return { data, response: enhancedResponse.response };
|
|
37783
|
-
}
|
|
37784
|
-
function createLazyAPIPromise(ensureExecuted) {
|
|
37785
|
-
let dataPromise = null;
|
|
37786
|
-
return new Proxy({}, {
|
|
37787
|
-
get(target, prop, receiver) {
|
|
37788
|
-
if (prop === "withResponse") {
|
|
37789
|
-
return () => ensureExecuted();
|
|
37790
|
-
}
|
|
37791
|
-
if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
|
|
37792
|
-
if (!dataPromise) {
|
|
37793
|
-
dataPromise = ensureExecuted().then((result) => result.data);
|
|
37794
|
-
}
|
|
37795
|
-
const value = Reflect.get(dataPromise, prop, receiver);
|
|
37796
|
-
return typeof value === "function" ? value.bind(dataPromise) : value;
|
|
37797
|
-
}
|
|
37798
|
-
return Reflect.get(target, prop, receiver);
|
|
37799
|
-
}
|
|
37800
|
-
});
|
|
37801
|
-
}
|
|
37802
|
-
|
|
37803
38595
|
// src/wrappers/oai_responses.ts
|
|
37804
38596
|
function responsesProxy(openai) {
|
|
37805
38597
|
if (!openai.responses) {
|
|
@@ -37836,17 +38628,33 @@ function wrapResponsesAsync(target, channel2) {
|
|
|
37836
38628
|
return (allParams, options) => {
|
|
37837
38629
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
37838
38630
|
let executionPromise = null;
|
|
38631
|
+
let apiPromise = null;
|
|
38632
|
+
const getAPIPromise = () => {
|
|
38633
|
+
apiPromise ??= target(params, options);
|
|
38634
|
+
return apiPromise;
|
|
38635
|
+
};
|
|
37839
38636
|
const ensureExecuted = () => {
|
|
37840
38637
|
if (!executionPromise) {
|
|
37841
38638
|
executionPromise = (async () => {
|
|
37842
38639
|
const traceContext = createChannelContext(channel2, params, span_info);
|
|
37843
|
-
|
|
37844
|
-
|
|
38640
|
+
return tracePromiseWithResponse(
|
|
38641
|
+
channel2,
|
|
38642
|
+
traceContext,
|
|
38643
|
+
getAPIPromise()
|
|
38644
|
+
);
|
|
37845
38645
|
})();
|
|
37846
38646
|
}
|
|
37847
38647
|
return executionPromise;
|
|
37848
38648
|
};
|
|
37849
|
-
return createLazyAPIPromise(
|
|
38649
|
+
return createLazyAPIPromise(
|
|
38650
|
+
ensureExecuted,
|
|
38651
|
+
() => tracePromiseAsResponse(
|
|
38652
|
+
channel2,
|
|
38653
|
+
createChannelContext(channel2, params, span_info),
|
|
38654
|
+
getAPIPromise()
|
|
38655
|
+
),
|
|
38656
|
+
getAPIPromise
|
|
38657
|
+
);
|
|
37850
38658
|
};
|
|
37851
38659
|
}
|
|
37852
38660
|
function wrapResponsesSyncStream(target, channel2) {
|
|
@@ -37992,6 +38800,11 @@ function wrapChatCompletion(completion) {
|
|
|
37992
38800
|
allParams
|
|
37993
38801
|
);
|
|
37994
38802
|
let executionPromise = null;
|
|
38803
|
+
let apiPromise = null;
|
|
38804
|
+
const getAPIPromise = () => {
|
|
38805
|
+
apiPromise ??= completion(params, options);
|
|
38806
|
+
return apiPromise;
|
|
38807
|
+
};
|
|
37995
38808
|
const ensureExecuted = () => {
|
|
37996
38809
|
if (!executionPromise) {
|
|
37997
38810
|
executionPromise = (async () => {
|
|
@@ -38001,32 +38814,44 @@ function wrapChatCompletion(completion) {
|
|
|
38001
38814
|
span_info
|
|
38002
38815
|
);
|
|
38003
38816
|
if (params.stream) {
|
|
38004
|
-
const completionPromise =
|
|
38005
|
-
|
|
38006
|
-
|
|
38817
|
+
const completionPromise = (
|
|
38818
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38819
|
+
getAPIPromise()
|
|
38007
38820
|
);
|
|
38008
|
-
const { data: data2, response: response2 } = await tracePromiseWithResponse(
|
|
38821
|
+
const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
|
|
38009
38822
|
openAIChannels.chatCompletionsCreate,
|
|
38010
38823
|
traceContext,
|
|
38011
38824
|
completionPromise
|
|
38012
38825
|
);
|
|
38013
|
-
return { data: data2, response: response2 };
|
|
38826
|
+
return { data: data2, response: response2, request_id: request_id2 };
|
|
38014
38827
|
}
|
|
38015
|
-
const completionResponse =
|
|
38016
|
-
|
|
38017
|
-
|
|
38828
|
+
const completionResponse = (
|
|
38829
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38830
|
+
getAPIPromise()
|
|
38018
38831
|
);
|
|
38019
|
-
const { data, response } = await tracePromiseWithResponse(
|
|
38832
|
+
const { data, response, request_id } = await tracePromiseWithResponse(
|
|
38020
38833
|
openAIChannels.chatCompletionsCreate,
|
|
38021
38834
|
traceContext,
|
|
38022
38835
|
completionResponse
|
|
38023
38836
|
);
|
|
38024
|
-
return { data, response };
|
|
38837
|
+
return { data, response, request_id };
|
|
38025
38838
|
})();
|
|
38026
38839
|
}
|
|
38027
38840
|
return executionPromise;
|
|
38028
38841
|
};
|
|
38029
|
-
return createLazyAPIPromise(
|
|
38842
|
+
return createLazyAPIPromise(
|
|
38843
|
+
ensureExecuted,
|
|
38844
|
+
() => tracePromiseAsResponse(
|
|
38845
|
+
openAIChannels.chatCompletionsCreate,
|
|
38846
|
+
createChannelContext(
|
|
38847
|
+
openAIChannels.chatCompletionsCreate,
|
|
38848
|
+
params,
|
|
38849
|
+
span_info
|
|
38850
|
+
),
|
|
38851
|
+
getAPIPromise()
|
|
38852
|
+
),
|
|
38853
|
+
getAPIPromise
|
|
38854
|
+
);
|
|
38030
38855
|
};
|
|
38031
38856
|
}
|
|
38032
38857
|
function createEndpointProxy(target, wrapperFn) {
|
|
@@ -38044,6 +38869,11 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38044
38869
|
return (allParams, options) => {
|
|
38045
38870
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
38046
38871
|
let executionPromise = null;
|
|
38872
|
+
let apiPromise = null;
|
|
38873
|
+
const getAPIPromise = () => {
|
|
38874
|
+
apiPromise ??= create(params, options);
|
|
38875
|
+
return apiPromise;
|
|
38876
|
+
};
|
|
38047
38877
|
const ensureExecuted = () => {
|
|
38048
38878
|
if (!executionPromise) {
|
|
38049
38879
|
executionPromise = (async () => {
|
|
@@ -38051,13 +38881,21 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38051
38881
|
return tracePromiseWithResponse(
|
|
38052
38882
|
channel2,
|
|
38053
38883
|
traceContext,
|
|
38054
|
-
|
|
38884
|
+
getAPIPromise()
|
|
38055
38885
|
);
|
|
38056
38886
|
})();
|
|
38057
38887
|
}
|
|
38058
38888
|
return executionPromise;
|
|
38059
38889
|
};
|
|
38060
|
-
return createLazyAPIPromise(
|
|
38890
|
+
return createLazyAPIPromise(
|
|
38891
|
+
ensureExecuted,
|
|
38892
|
+
() => tracePromiseAsResponse(
|
|
38893
|
+
channel2,
|
|
38894
|
+
createChannelContext(channel2, params, span_info),
|
|
38895
|
+
getAPIPromise()
|
|
38896
|
+
),
|
|
38897
|
+
getAPIPromise
|
|
38898
|
+
);
|
|
38061
38899
|
};
|
|
38062
38900
|
}
|
|
38063
38901
|
var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
|
|
@@ -40752,7 +41590,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
|
|
|
40752
41590
|
function createEveInstrumentationProvider(options = {}) {
|
|
40753
41591
|
const bridge = new EveProviderBridge(options.metadata);
|
|
40754
41592
|
return {
|
|
41593
|
+
// Eve versions before tracePolicy use capture to decide whether provider
|
|
41594
|
+
// events include content. Newer versions prefer tracePolicy when both are
|
|
41595
|
+
// present, so keep the deprecated field for backwards compatibility.
|
|
40755
41596
|
capture: "content",
|
|
41597
|
+
tracePolicy: () => ({
|
|
41598
|
+
emit: true,
|
|
41599
|
+
recordInputs: true,
|
|
41600
|
+
recordOutputs: true
|
|
41601
|
+
}),
|
|
40756
41602
|
events: {
|
|
40757
41603
|
"action.completed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
40758
41604
|
"action.failed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
@@ -45181,7 +46027,7 @@ function isAsync(fn) {
|
|
|
45181
46027
|
function isAsyncGenerator2(fn) {
|
|
45182
46028
|
return fn[Symbol.toStringTag] === "AsyncGenerator";
|
|
45183
46029
|
}
|
|
45184
|
-
function
|
|
46030
|
+
function isAsyncIterable6(obj) {
|
|
45185
46031
|
return typeof obj[Symbol.asyncIterator] === "function";
|
|
45186
46032
|
}
|
|
45187
46033
|
function wrapAsync(asyncFn) {
|
|
@@ -45353,7 +46199,7 @@ var eachOfLimit$2 = (limit) => {
|
|
|
45353
46199
|
if (isAsyncGenerator2(obj)) {
|
|
45354
46200
|
return asyncEachOfLimit(obj, limit, iteratee, callback);
|
|
45355
46201
|
}
|
|
45356
|
-
if (
|
|
46202
|
+
if (isAsyncIterable6(obj)) {
|
|
45357
46203
|
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
|
|
45358
46204
|
}
|
|
45359
46205
|
var nextElem = createIterator(obj);
|
|
@@ -46708,7 +47554,7 @@ function callEvaluatorData(data) {
|
|
|
46708
47554
|
baseExperiment
|
|
46709
47555
|
};
|
|
46710
47556
|
}
|
|
46711
|
-
function
|
|
47557
|
+
function isAsyncIterable7(value) {
|
|
46712
47558
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
46713
47559
|
}
|
|
46714
47560
|
function isIterable(value) {
|
|
@@ -46743,7 +47589,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
|
46743
47589
|
}).asDataset();
|
|
46744
47590
|
}
|
|
46745
47591
|
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
46746
|
-
if (
|
|
47592
|
+
if (isAsyncIterable7(resolvedDataResult)) {
|
|
46747
47593
|
return resolvedDataResult;
|
|
46748
47594
|
}
|
|
46749
47595
|
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|