braintrust 3.29.0 → 3.31.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.d.mts +4 -1
- package/dev/dist/index.d.ts +4 -1
- package/dev/dist/index.js +1492 -887
- package/dev/dist/index.mjs +836 -231
- 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 +22 -4
- package/dist/auto-instrumentations/bundler/next.mjs +12 -6
- 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 +18 -4
- package/dist/auto-instrumentations/index.cjs +13 -1
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +614 -480
- package/dist/browser.d.ts +614 -480
- package/dist/browser.js +1172 -305
- package/dist/browser.mjs +1172 -305
- package/dist/{chunk-6Z5S7VOU.js → chunk-4AQGZS6X.js} +13 -1
- package/dist/{chunk-M6XPNJC4.mjs → chunk-AJT4FR25.mjs} +703 -120
- package/dist/{chunk-7FA6VP2S.mjs → chunk-CE3BLB2L.mjs} +13 -1
- package/dist/{chunk-XLLGRXGR.js → chunk-V32LW47Z.js} +1819 -1236
- package/dist/cli.js +846 -241
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +1172 -305
- package/dist/edge-light.mjs +1172 -305
- package/dist/index.d.mts +614 -480
- package/dist/index.d.ts +614 -480
- package/dist/index.js +915 -643
- package/dist/index.mjs +349 -77
- package/dist/instrumentation/index.d.mts +15 -0
- package/dist/instrumentation/index.d.ts +15 -0
- package/dist/instrumentation/index.js +836 -230
- package/dist/instrumentation/index.mjs +836 -230
- 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 +1172 -305
- package/dist/workerd.mjs +1172 -305
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -104,6 +104,7 @@ __export(browser_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(browser_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,
|
|
@@ -4028,6 +4031,7 @@ var ProjectSettings = import_v36.z.union([
|
|
|
4028
4031
|
]),
|
|
4029
4032
|
disable_realtime_queries: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
|
|
4030
4033
|
monitor_charts_use_metrics_start: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
|
|
4034
|
+
blind_reviews: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
|
|
4031
4035
|
default_preprocessor: NullableSavedFunctionId
|
|
4032
4036
|
}).partial(),
|
|
4033
4037
|
import_v36.z.null()
|
|
@@ -4089,6 +4093,7 @@ var WindowedAutomationConfig = import_v36.z.object({
|
|
|
4089
4093
|
auto_approve_tools: import_v36.z.array(import_v36.z.string().min(1)).optional().default([]),
|
|
4090
4094
|
harness: import_v36.z.enum(["native", "codex", "claude-code"]).optional(),
|
|
4091
4095
|
model: import_v36.z.string().min(1).optional(),
|
|
4096
|
+
endpoint_name: import_v36.z.string().min(1).optional(),
|
|
4092
4097
|
reasoning_effort: import_v36.z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
|
|
4093
4098
|
}).optional(),
|
|
4094
4099
|
actions: import_v36.z.array(
|
|
@@ -5880,7 +5885,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5880
5885
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5881
5886
|
"braintrust.spanInstrumentationName"
|
|
5882
5887
|
);
|
|
5883
|
-
var SDK_VERSION = true ? "3.
|
|
5888
|
+
var SDK_VERSION = true ? "3.31.0" : "0.0.0";
|
|
5884
5889
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5885
5890
|
return {
|
|
5886
5891
|
...args,
|
|
@@ -10127,6 +10132,15 @@ function _internalStartSpanWithInitialMerge(args) {
|
|
|
10127
10132
|
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
10128
10133
|
}).span;
|
|
10129
10134
|
}
|
|
10135
|
+
function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
|
|
10136
|
+
return startSpanAndIsLogger(
|
|
10137
|
+
{
|
|
10138
|
+
...args,
|
|
10139
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
10140
|
+
},
|
|
10141
|
+
{ useParentSpanIdsForObjectParent: true }
|
|
10142
|
+
).span;
|
|
10143
|
+
}
|
|
10130
10144
|
function _internalStartSpanWithContext(args, context) {
|
|
10131
10145
|
return startSpanAndIsLogger({
|
|
10132
10146
|
...args,
|
|
@@ -10140,7 +10154,7 @@ async function flush(options) {
|
|
|
10140
10154
|
function setFetch(fetch2) {
|
|
10141
10155
|
_internalGetGlobalState().setFetch(fetch2);
|
|
10142
10156
|
}
|
|
10143
|
-
function startSpanAndIsLogger(args) {
|
|
10157
|
+
function startSpanAndIsLogger(args, internalOptions) {
|
|
10144
10158
|
const state = args?.state ?? _globalState;
|
|
10145
10159
|
const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
|
|
10146
10160
|
asyncFlush: args?.asyncFlush,
|
|
@@ -10154,7 +10168,7 @@ function startSpanAndIsLogger(args) {
|
|
|
10154
10168
|
) ? {
|
|
10155
10169
|
spanId: parentObject.data.span_id,
|
|
10156
10170
|
rootSpanId: parentObject.data.root_span_id
|
|
10157
|
-
} : void 0;
|
|
10171
|
+
} : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
|
|
10158
10172
|
const { parent: _ignoredParent, ...spanArgs } = args ?? {};
|
|
10159
10173
|
const span = new SpanImpl({
|
|
10160
10174
|
state,
|
|
@@ -13598,6 +13612,131 @@ function unsubscribeAll(unsubscribers) {
|
|
|
13598
13612
|
return [];
|
|
13599
13613
|
}
|
|
13600
13614
|
|
|
13615
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
13616
|
+
function channel(spec) {
|
|
13617
|
+
return spec;
|
|
13618
|
+
}
|
|
13619
|
+
function defineChannels(pkg, channels, options) {
|
|
13620
|
+
const { instrumentationName } = options;
|
|
13621
|
+
return Object.fromEntries(
|
|
13622
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
13623
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
13624
|
+
if (spec.kind === "async") {
|
|
13625
|
+
const asyncSpec = spec;
|
|
13626
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
13627
|
+
fullChannelName
|
|
13628
|
+
);
|
|
13629
|
+
const intercept2 = (interceptor) => {
|
|
13630
|
+
const hook = tracingChannel2();
|
|
13631
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13632
|
+
};
|
|
13633
|
+
};
|
|
13634
|
+
return [
|
|
13635
|
+
key,
|
|
13636
|
+
{
|
|
13637
|
+
...asyncSpec,
|
|
13638
|
+
instrumentationName,
|
|
13639
|
+
intercept: intercept2,
|
|
13640
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13641
|
+
const hook = tracingChannel2();
|
|
13642
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13643
|
+
},
|
|
13644
|
+
tracingChannel: tracingChannel2,
|
|
13645
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
13646
|
+
fn,
|
|
13647
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13648
|
+
context
|
|
13649
|
+
)
|
|
13650
|
+
}
|
|
13651
|
+
];
|
|
13652
|
+
}
|
|
13653
|
+
const syncSpec = spec;
|
|
13654
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
13655
|
+
fullChannelName
|
|
13656
|
+
);
|
|
13657
|
+
const intercept = (interceptor) => {
|
|
13658
|
+
const hook = tracingChannel();
|
|
13659
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13660
|
+
};
|
|
13661
|
+
};
|
|
13662
|
+
return [
|
|
13663
|
+
key,
|
|
13664
|
+
{
|
|
13665
|
+
...syncSpec,
|
|
13666
|
+
instrumentationName,
|
|
13667
|
+
intercept,
|
|
13668
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13669
|
+
const hook = tracingChannel();
|
|
13670
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13671
|
+
},
|
|
13672
|
+
tracingChannel,
|
|
13673
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
13674
|
+
fn,
|
|
13675
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13676
|
+
context
|
|
13677
|
+
)
|
|
13678
|
+
}
|
|
13679
|
+
];
|
|
13680
|
+
})
|
|
13681
|
+
);
|
|
13682
|
+
}
|
|
13683
|
+
|
|
13684
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
13685
|
+
var openAIChannels = defineChannels(
|
|
13686
|
+
"openai",
|
|
13687
|
+
{
|
|
13688
|
+
filesCreateTraced: channel({
|
|
13689
|
+
channelName: "files.create-traced",
|
|
13690
|
+
kind: "async"
|
|
13691
|
+
}),
|
|
13692
|
+
batchesRetrieveTraced: channel({
|
|
13693
|
+
channelName: "batches.retrieve-traced",
|
|
13694
|
+
kind: "async"
|
|
13695
|
+
}),
|
|
13696
|
+
batchesCompleteTrace: channel({
|
|
13697
|
+
channelName: "batches.complete-trace",
|
|
13698
|
+
kind: "async"
|
|
13699
|
+
}),
|
|
13700
|
+
chatCompletionsCreate: channel({
|
|
13701
|
+
channelName: "chat.completions.create",
|
|
13702
|
+
kind: "async"
|
|
13703
|
+
}),
|
|
13704
|
+
embeddingsCreate: channel({
|
|
13705
|
+
channelName: "embeddings.create",
|
|
13706
|
+
kind: "async"
|
|
13707
|
+
}),
|
|
13708
|
+
betaChatCompletionsParse: channel({
|
|
13709
|
+
channelName: "beta.chat.completions.parse",
|
|
13710
|
+
kind: "async"
|
|
13711
|
+
}),
|
|
13712
|
+
betaChatCompletionsStream: channel({
|
|
13713
|
+
channelName: "beta.chat.completions.stream",
|
|
13714
|
+
kind: "sync-stream"
|
|
13715
|
+
}),
|
|
13716
|
+
moderationsCreate: channel({
|
|
13717
|
+
channelName: "moderations.create",
|
|
13718
|
+
kind: "async"
|
|
13719
|
+
}),
|
|
13720
|
+
responsesCreate: channel({
|
|
13721
|
+
channelName: "responses.create",
|
|
13722
|
+
kind: "async"
|
|
13723
|
+
}),
|
|
13724
|
+
responsesStream: channel({
|
|
13725
|
+
channelName: "responses.stream",
|
|
13726
|
+
kind: "sync-stream"
|
|
13727
|
+
}),
|
|
13728
|
+
responsesParse: channel({
|
|
13729
|
+
channelName: "responses.parse",
|
|
13730
|
+
kind: "async"
|
|
13731
|
+
}),
|
|
13732
|
+
responsesCompact: channel({
|
|
13733
|
+
channelName: "responses.compact",
|
|
13734
|
+
kind: "async"
|
|
13735
|
+
})
|
|
13736
|
+
},
|
|
13737
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
13738
|
+
);
|
|
13739
|
+
|
|
13601
13740
|
// src/wrappers/attachment-utils.ts
|
|
13602
13741
|
function getExtensionFromMediaType(mediaType) {
|
|
13603
13742
|
const extensionMap = {
|
|
@@ -13773,118 +13912,91 @@ function processInputAttachments(input) {
|
|
|
13773
13912
|
return processNode(input);
|
|
13774
13913
|
}
|
|
13775
13914
|
|
|
13776
|
-
// src/instrumentation/
|
|
13777
|
-
|
|
13778
|
-
|
|
13779
|
-
|
|
13780
|
-
|
|
13781
|
-
|
|
13782
|
-
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13791
|
-
|
|
13792
|
-
|
|
13793
|
-
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
...asyncSpec,
|
|
13799
|
-
instrumentationName,
|
|
13800
|
-
intercept: intercept2,
|
|
13801
|
-
invoke: (target, thisArg, args, additional) => {
|
|
13802
|
-
const hook = tracingChannel2();
|
|
13803
|
-
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13804
|
-
},
|
|
13805
|
-
tracingChannel: tracingChannel2,
|
|
13806
|
-
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
13807
|
-
fn,
|
|
13808
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13809
|
-
context
|
|
13810
|
-
)
|
|
13811
|
-
}
|
|
13812
|
-
];
|
|
13915
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
13916
|
+
var OPENAI_METADATA_KEYS = [
|
|
13917
|
+
"model",
|
|
13918
|
+
"temperature",
|
|
13919
|
+
"top_p",
|
|
13920
|
+
"max_tokens",
|
|
13921
|
+
"frequency_penalty",
|
|
13922
|
+
"presence_penalty",
|
|
13923
|
+
"stop",
|
|
13924
|
+
"response_format",
|
|
13925
|
+
"tools",
|
|
13926
|
+
"tool_choice",
|
|
13927
|
+
"parallel_tool_calls",
|
|
13928
|
+
"max_tool_calls"
|
|
13929
|
+
];
|
|
13930
|
+
function batchMetadata(params) {
|
|
13931
|
+
const metadata = { provider: "openai" };
|
|
13932
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
13933
|
+
try {
|
|
13934
|
+
const value = Reflect.get(params, key);
|
|
13935
|
+
if (value !== void 0) {
|
|
13936
|
+
metadata[key] = value;
|
|
13813
13937
|
}
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13938
|
+
} catch {
|
|
13939
|
+
}
|
|
13940
|
+
}
|
|
13941
|
+
return metadata;
|
|
13942
|
+
}
|
|
13943
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
13944
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
13945
|
+
return {
|
|
13946
|
+
input: processInputAttachments(input),
|
|
13947
|
+
metadata: batchMetadata(params)
|
|
13948
|
+
};
|
|
13949
|
+
}
|
|
13950
|
+
function extractOpenAIChatInput(params) {
|
|
13951
|
+
const { messages, ...metadata } = params;
|
|
13952
|
+
return {
|
|
13953
|
+
input: processInputAttachments(messages),
|
|
13954
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13955
|
+
};
|
|
13956
|
+
}
|
|
13957
|
+
function extractOpenAIResponsesInput(params) {
|
|
13958
|
+
const { input, ...metadata } = params;
|
|
13959
|
+
return {
|
|
13960
|
+
input: processInputAttachments(input),
|
|
13961
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13962
|
+
};
|
|
13963
|
+
}
|
|
13964
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
13965
|
+
if (!result) {
|
|
13966
|
+
return void 0;
|
|
13967
|
+
}
|
|
13968
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
13969
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13970
|
+
}
|
|
13971
|
+
function processImagesInOutput(output) {
|
|
13972
|
+
if (Array.isArray(output)) {
|
|
13973
|
+
return output.map(processImagesInOutput);
|
|
13974
|
+
}
|
|
13975
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
13976
|
+
const fileExtension = output.output_format || "png";
|
|
13977
|
+
const contentType = `image/${fileExtension}`;
|
|
13978
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
13979
|
+
let binaryString;
|
|
13980
|
+
try {
|
|
13981
|
+
binaryString = atob(output.result);
|
|
13982
|
+
} catch {
|
|
13983
|
+
return output;
|
|
13984
|
+
}
|
|
13985
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
13986
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
13987
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
13988
|
+
}
|
|
13989
|
+
return {
|
|
13990
|
+
...output,
|
|
13991
|
+
result: new Attachment({
|
|
13992
|
+
data: new Blob([bytes], { type: contentType }),
|
|
13993
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
13994
|
+
contentType
|
|
13995
|
+
})
|
|
13996
|
+
};
|
|
13997
|
+
}
|
|
13998
|
+
return output;
|
|
13843
13999
|
}
|
|
13844
|
-
|
|
13845
|
-
// src/instrumentation/plugins/openai-channels.ts
|
|
13846
|
-
var openAIChannels = defineChannels(
|
|
13847
|
-
"openai",
|
|
13848
|
-
{
|
|
13849
|
-
chatCompletionsCreate: channel({
|
|
13850
|
-
channelName: "chat.completions.create",
|
|
13851
|
-
kind: "async"
|
|
13852
|
-
}),
|
|
13853
|
-
embeddingsCreate: channel({
|
|
13854
|
-
channelName: "embeddings.create",
|
|
13855
|
-
kind: "async"
|
|
13856
|
-
}),
|
|
13857
|
-
betaChatCompletionsParse: channel({
|
|
13858
|
-
channelName: "beta.chat.completions.parse",
|
|
13859
|
-
kind: "async"
|
|
13860
|
-
}),
|
|
13861
|
-
betaChatCompletionsStream: channel({
|
|
13862
|
-
channelName: "beta.chat.completions.stream",
|
|
13863
|
-
kind: "sync-stream"
|
|
13864
|
-
}),
|
|
13865
|
-
moderationsCreate: channel({
|
|
13866
|
-
channelName: "moderations.create",
|
|
13867
|
-
kind: "async"
|
|
13868
|
-
}),
|
|
13869
|
-
responsesCreate: channel({
|
|
13870
|
-
channelName: "responses.create",
|
|
13871
|
-
kind: "async"
|
|
13872
|
-
}),
|
|
13873
|
-
responsesStream: channel({
|
|
13874
|
-
channelName: "responses.stream",
|
|
13875
|
-
kind: "sync-stream"
|
|
13876
|
-
}),
|
|
13877
|
-
responsesParse: channel({
|
|
13878
|
-
channelName: "responses.parse",
|
|
13879
|
-
kind: "async"
|
|
13880
|
-
}),
|
|
13881
|
-
responsesCompact: channel({
|
|
13882
|
-
channelName: "responses.compact",
|
|
13883
|
-
kind: "async"
|
|
13884
|
-
})
|
|
13885
|
-
},
|
|
13886
|
-
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
13887
|
-
);
|
|
13888
14000
|
|
|
13889
14001
|
// src/openai-utils.ts
|
|
13890
14002
|
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
@@ -13941,23 +14053,573 @@ function getCachedMetricFromHeaders(headers) {
|
|
|
13941
14053
|
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
13942
14054
|
}
|
|
13943
14055
|
|
|
14056
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
14057
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
14058
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
14059
|
+
"completed",
|
|
14060
|
+
"failed",
|
|
14061
|
+
"expired",
|
|
14062
|
+
"cancelled"
|
|
14063
|
+
]);
|
|
14064
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
14065
|
+
function read(value, key) {
|
|
14066
|
+
if (!isObject(value)) {
|
|
14067
|
+
return void 0;
|
|
14068
|
+
}
|
|
14069
|
+
try {
|
|
14070
|
+
return Reflect.get(value, key);
|
|
14071
|
+
} catch {
|
|
14072
|
+
return void 0;
|
|
14073
|
+
}
|
|
14074
|
+
}
|
|
14075
|
+
function isBatchRecordIterable(value) {
|
|
14076
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
14077
|
+
return false;
|
|
14078
|
+
}
|
|
14079
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
14080
|
+
}
|
|
14081
|
+
function validCustomId(value) {
|
|
14082
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
14083
|
+
}
|
|
14084
|
+
function logBatchInstrumentationError(context, error) {
|
|
14085
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
14086
|
+
}
|
|
14087
|
+
async function exportParent(parent) {
|
|
14088
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
14089
|
+
return parent.toStr();
|
|
14090
|
+
}
|
|
14091
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
14092
|
+
return await parent.export();
|
|
14093
|
+
}
|
|
14094
|
+
return void 0;
|
|
14095
|
+
}
|
|
14096
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
14097
|
+
const encoded = new TextEncoder().encode(
|
|
14098
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
14099
|
+
);
|
|
14100
|
+
return new Uint8Array(
|
|
14101
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
14102
|
+
);
|
|
14103
|
+
}
|
|
14104
|
+
function digestHex(bytes, length) {
|
|
14105
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
14106
|
+
}
|
|
14107
|
+
function digestUuid(bytes) {
|
|
14108
|
+
const hex = digestHex(bytes, 16);
|
|
14109
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
14110
|
+
}
|
|
14111
|
+
async function batchSpanIds(inputFileId) {
|
|
14112
|
+
const [row, span, root] = await Promise.all([
|
|
14113
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
14114
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
14115
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
14116
|
+
]);
|
|
14117
|
+
return {
|
|
14118
|
+
rowId: digestUuid(row),
|
|
14119
|
+
spanId: digestHex(span, 8),
|
|
14120
|
+
rootSpanId: digestHex(root, 16)
|
|
14121
|
+
};
|
|
14122
|
+
}
|
|
14123
|
+
async function childSpanIds(inputFileId, customId) {
|
|
14124
|
+
const [row, span] = await Promise.all([
|
|
14125
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
14126
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
14127
|
+
]);
|
|
14128
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
14129
|
+
}
|
|
14130
|
+
async function startBatchSpan(context) {
|
|
14131
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
14132
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
14133
|
+
const hasParentSpan = Boolean(
|
|
14134
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
14135
|
+
);
|
|
14136
|
+
return withCurrent(
|
|
14137
|
+
NOOP_SPAN,
|
|
14138
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
14139
|
+
withSpanInstrumentationName(
|
|
14140
|
+
{
|
|
14141
|
+
name: "openai.batch",
|
|
14142
|
+
type: "task" /* TASK */,
|
|
14143
|
+
parent: context.parent,
|
|
14144
|
+
...!hasParentSpan ? {
|
|
14145
|
+
parentSpanIds: {
|
|
14146
|
+
parentSpanIds: [],
|
|
14147
|
+
rootSpanId: ids.rootSpanId
|
|
14148
|
+
}
|
|
14149
|
+
} : {},
|
|
14150
|
+
spanId: ids.spanId,
|
|
14151
|
+
startTime: context.taskStartTime,
|
|
14152
|
+
event: {
|
|
14153
|
+
id: ids.rowId,
|
|
14154
|
+
metadata: {
|
|
14155
|
+
endpoint: context.endpoint,
|
|
14156
|
+
input_file_id: context.inputFileId,
|
|
14157
|
+
provider: "openai"
|
|
14158
|
+
}
|
|
14159
|
+
}
|
|
14160
|
+
},
|
|
14161
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14162
|
+
)
|
|
14163
|
+
)
|
|
14164
|
+
);
|
|
14165
|
+
}
|
|
14166
|
+
async function startBatchChild(context, taskParent, input) {
|
|
14167
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
14168
|
+
return withCurrent(
|
|
14169
|
+
NOOP_SPAN,
|
|
14170
|
+
() => _internalStartSpanWithInitialMerge(
|
|
14171
|
+
withSpanInstrumentationName(
|
|
14172
|
+
{
|
|
14173
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
14174
|
+
type: "llm" /* LLM */,
|
|
14175
|
+
parent: taskParent,
|
|
14176
|
+
spanId: ids.spanId,
|
|
14177
|
+
startTime: context.childStartTime,
|
|
14178
|
+
event: {
|
|
14179
|
+
id: ids.rowId,
|
|
14180
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
14181
|
+
metadata: {
|
|
14182
|
+
...input.spanData?.metadata,
|
|
14183
|
+
custom_id: input.customId,
|
|
14184
|
+
provider: "openai"
|
|
14185
|
+
}
|
|
14186
|
+
}
|
|
14187
|
+
},
|
|
14188
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14189
|
+
)
|
|
14190
|
+
)
|
|
14191
|
+
);
|
|
14192
|
+
}
|
|
14193
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
14194
|
+
}) {
|
|
14195
|
+
const resolvedFile = await file;
|
|
14196
|
+
if (typeof resolvedFile === "string") {
|
|
14197
|
+
for (const line of resolvedFile.split("\n")) {
|
|
14198
|
+
if (!line.trim()) {
|
|
14199
|
+
continue;
|
|
14200
|
+
}
|
|
14201
|
+
try {
|
|
14202
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
14203
|
+
} catch (error) {
|
|
14204
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14205
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14206
|
+
}
|
|
14207
|
+
}
|
|
14208
|
+
return;
|
|
14209
|
+
}
|
|
14210
|
+
const body = read(resolvedFile, "body");
|
|
14211
|
+
const getReader = read(body, "getReader");
|
|
14212
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
14213
|
+
let reader;
|
|
14214
|
+
try {
|
|
14215
|
+
reader = Reflect.apply(getReader, body, []);
|
|
14216
|
+
const decoder2 = new TextDecoder();
|
|
14217
|
+
let pending = "";
|
|
14218
|
+
while (true) {
|
|
14219
|
+
const readChunk = read(reader, "read");
|
|
14220
|
+
if (typeof readChunk !== "function") {
|
|
14221
|
+
throw new Error("Response body stream has no read method");
|
|
14222
|
+
}
|
|
14223
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
14224
|
+
if (!isObject(chunk)) {
|
|
14225
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
14226
|
+
}
|
|
14227
|
+
if (chunk.done === true) {
|
|
14228
|
+
pending += decoder2.decode();
|
|
14229
|
+
break;
|
|
14230
|
+
}
|
|
14231
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
14232
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
14233
|
+
}
|
|
14234
|
+
pending += decoder2.decode(chunk.value, { stream: true });
|
|
14235
|
+
let newline = pending.indexOf("\n");
|
|
14236
|
+
while (newline !== -1) {
|
|
14237
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
14238
|
+
pending = pending.slice(newline + 1);
|
|
14239
|
+
if (line.trim()) {
|
|
14240
|
+
try {
|
|
14241
|
+
yield JSON.parse(line);
|
|
14242
|
+
} catch (error) {
|
|
14243
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14244
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14245
|
+
}
|
|
14246
|
+
}
|
|
14247
|
+
newline = pending.indexOf("\n");
|
|
14248
|
+
}
|
|
14249
|
+
}
|
|
14250
|
+
if (pending.trim()) {
|
|
14251
|
+
try {
|
|
14252
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
14253
|
+
} catch (error) {
|
|
14254
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14255
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14256
|
+
}
|
|
14257
|
+
}
|
|
14258
|
+
} catch (error) {
|
|
14259
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
14260
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
14261
|
+
} finally {
|
|
14262
|
+
const releaseLock = read(reader, "releaseLock");
|
|
14263
|
+
if (typeof releaseLock === "function") {
|
|
14264
|
+
try {
|
|
14265
|
+
Reflect.apply(releaseLock, reader, []);
|
|
14266
|
+
} catch (error) {
|
|
14267
|
+
logBatchInstrumentationError(
|
|
14268
|
+
"could not release stream reader",
|
|
14269
|
+
error
|
|
14270
|
+
);
|
|
14271
|
+
}
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
return;
|
|
14275
|
+
}
|
|
14276
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
14277
|
+
for await (const record of resolvedFile) {
|
|
14278
|
+
yield record;
|
|
14279
|
+
}
|
|
14280
|
+
return;
|
|
14281
|
+
}
|
|
14282
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
14283
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
14284
|
+
}
|
|
14285
|
+
async function readBatchInputs(file) {
|
|
14286
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
14287
|
+
const issues = [];
|
|
14288
|
+
let endpoint;
|
|
14289
|
+
try {
|
|
14290
|
+
for await (const value of jsonlRecords(
|
|
14291
|
+
file,
|
|
14292
|
+
(issue) => issues.push(issue)
|
|
14293
|
+
)) {
|
|
14294
|
+
const customId = read(value, "custom_id");
|
|
14295
|
+
const url = read(value, "url");
|
|
14296
|
+
const body = read(value, "body");
|
|
14297
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
14298
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
14299
|
+
continue;
|
|
14300
|
+
}
|
|
14301
|
+
endpoint = url;
|
|
14302
|
+
let spanData;
|
|
14303
|
+
try {
|
|
14304
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
14305
|
+
} catch (error) {
|
|
14306
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
14307
|
+
}
|
|
14308
|
+
inputs.set(customId, { customId, spanData });
|
|
14309
|
+
}
|
|
14310
|
+
} catch (error) {
|
|
14311
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
14312
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
14313
|
+
}
|
|
14314
|
+
if (!endpoint || inputs.size === 0) {
|
|
14315
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
14316
|
+
}
|
|
14317
|
+
return { endpoint, inputs, issues };
|
|
14318
|
+
}
|
|
14319
|
+
async function writePendingSpans(trace, endTime) {
|
|
14320
|
+
const task = await startBatchSpan(trace.context);
|
|
14321
|
+
const taskParent = await task.export();
|
|
14322
|
+
for (const input of trace.inputs.values()) {
|
|
14323
|
+
try {
|
|
14324
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14325
|
+
if (endTime !== void 0) {
|
|
14326
|
+
child.end({ endTime });
|
|
14327
|
+
}
|
|
14328
|
+
} catch (error) {
|
|
14329
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
14330
|
+
}
|
|
14331
|
+
}
|
|
14332
|
+
if (endTime !== void 0) {
|
|
14333
|
+
if (trace.status && trace.status !== "completed") {
|
|
14334
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14335
|
+
}
|
|
14336
|
+
task.end({ endTime });
|
|
14337
|
+
}
|
|
14338
|
+
}
|
|
14339
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
14340
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14341
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
14342
|
+
const parentPromise = exportParent(args[0].parent);
|
|
14343
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
14344
|
+
try {
|
|
14345
|
+
const inputFileId = read(file, "id");
|
|
14346
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
14347
|
+
inputPromise,
|
|
14348
|
+
parentPromise
|
|
14349
|
+
]);
|
|
14350
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
14351
|
+
if (inputData.issues[0]) {
|
|
14352
|
+
logBatchInstrumentationError(
|
|
14353
|
+
"skipped invalid input file",
|
|
14354
|
+
inputData.issues[0]
|
|
14355
|
+
);
|
|
14356
|
+
}
|
|
14357
|
+
return file;
|
|
14358
|
+
}
|
|
14359
|
+
const trace = {
|
|
14360
|
+
context: {
|
|
14361
|
+
inputFileId,
|
|
14362
|
+
endpoint: inputData.endpoint,
|
|
14363
|
+
parent: exportedParent2,
|
|
14364
|
+
taskStartTime: startTime,
|
|
14365
|
+
childStartTime: startTime
|
|
14366
|
+
},
|
|
14367
|
+
inputs: inputData.inputs
|
|
14368
|
+
};
|
|
14369
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
14370
|
+
await writePendingSpans(trace);
|
|
14371
|
+
} catch (error) {
|
|
14372
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
14373
|
+
}
|
|
14374
|
+
return file;
|
|
14375
|
+
};
|
|
14376
|
+
function validTimestamp(value) {
|
|
14377
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
14378
|
+
}
|
|
14379
|
+
function terminalEndTime(batch, startTime) {
|
|
14380
|
+
let timestamp;
|
|
14381
|
+
switch (batch.status) {
|
|
14382
|
+
case "completed":
|
|
14383
|
+
timestamp = batch.completed_at;
|
|
14384
|
+
break;
|
|
14385
|
+
case "failed":
|
|
14386
|
+
timestamp = batch.failed_at;
|
|
14387
|
+
break;
|
|
14388
|
+
case "expired":
|
|
14389
|
+
timestamp = batch.expired_at;
|
|
14390
|
+
break;
|
|
14391
|
+
default:
|
|
14392
|
+
timestamp = batch.cancelled_at;
|
|
14393
|
+
}
|
|
14394
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
14395
|
+
}
|
|
14396
|
+
async function updateBatchTimestamps(batch) {
|
|
14397
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
14398
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
14399
|
+
return;
|
|
14400
|
+
}
|
|
14401
|
+
if (validTimestamp(batch.created_at)) {
|
|
14402
|
+
trace.context.taskStartTime = batch.created_at;
|
|
14403
|
+
}
|
|
14404
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
14405
|
+
trace.status = batch.status;
|
|
14406
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
14407
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
14408
|
+
}
|
|
14409
|
+
await writePendingSpans(trace, trace.endTime);
|
|
14410
|
+
}
|
|
14411
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
14412
|
+
try {
|
|
14413
|
+
await updateBatchTimestamps(batch);
|
|
14414
|
+
} catch (error) {
|
|
14415
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
14416
|
+
}
|
|
14417
|
+
return batch;
|
|
14418
|
+
});
|
|
14419
|
+
function errorFromResult(result) {
|
|
14420
|
+
const error = read(result.value, "error");
|
|
14421
|
+
if (isObject(error)) {
|
|
14422
|
+
const message = read(error, "message");
|
|
14423
|
+
return new Error(
|
|
14424
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14425
|
+
);
|
|
14426
|
+
}
|
|
14427
|
+
const response = read(result.value, "response");
|
|
14428
|
+
const statusCode = read(response, "status_code");
|
|
14429
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
14430
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
14431
|
+
return new Error(
|
|
14432
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14433
|
+
);
|
|
14434
|
+
}
|
|
14435
|
+
return void 0;
|
|
14436
|
+
}
|
|
14437
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
14438
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
14439
|
+
try {
|
|
14440
|
+
const resultError = errorFromResult(result);
|
|
14441
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
14442
|
+
if (resultError) {
|
|
14443
|
+
child.log({ error: resultError });
|
|
14444
|
+
} else if (isObject(responseBody)) {
|
|
14445
|
+
const model = read(responseBody, "model");
|
|
14446
|
+
child.log({
|
|
14447
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
14448
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
14449
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
14450
|
+
});
|
|
14451
|
+
} else {
|
|
14452
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
14453
|
+
}
|
|
14454
|
+
} catch (error) {
|
|
14455
|
+
child.log({ error });
|
|
14456
|
+
} finally {
|
|
14457
|
+
child.end({ endTime });
|
|
14458
|
+
}
|
|
14459
|
+
}
|
|
14460
|
+
async function completeResultFile({
|
|
14461
|
+
context,
|
|
14462
|
+
endTime,
|
|
14463
|
+
file,
|
|
14464
|
+
inputs,
|
|
14465
|
+
issues,
|
|
14466
|
+
seen,
|
|
14467
|
+
source,
|
|
14468
|
+
taskParent
|
|
14469
|
+
}) {
|
|
14470
|
+
if (file === void 0) {
|
|
14471
|
+
return;
|
|
14472
|
+
}
|
|
14473
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
14474
|
+
const customId = read(value, "custom_id");
|
|
14475
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
14476
|
+
issues.push(
|
|
14477
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
14478
|
+
);
|
|
14479
|
+
continue;
|
|
14480
|
+
}
|
|
14481
|
+
if (seen.has(customId)) {
|
|
14482
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
14483
|
+
continue;
|
|
14484
|
+
}
|
|
14485
|
+
const input = inputs.get(customId);
|
|
14486
|
+
if (!input) {
|
|
14487
|
+
issues.push(
|
|
14488
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
14489
|
+
);
|
|
14490
|
+
continue;
|
|
14491
|
+
}
|
|
14492
|
+
seen.add(customId);
|
|
14493
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
14494
|
+
value,
|
|
14495
|
+
source
|
|
14496
|
+
});
|
|
14497
|
+
}
|
|
14498
|
+
}
|
|
14499
|
+
function sameInputs(first, second) {
|
|
14500
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
14501
|
+
}
|
|
14502
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
14503
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
14504
|
+
return void 0;
|
|
14505
|
+
}
|
|
14506
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
14507
|
+
if (existing) {
|
|
14508
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
14509
|
+
return void 0;
|
|
14510
|
+
}
|
|
14511
|
+
return { ...existing, inputs: inputData.inputs };
|
|
14512
|
+
}
|
|
14513
|
+
const parent = await exportParent(getSpanParentObject());
|
|
14514
|
+
if (!parent) {
|
|
14515
|
+
return void 0;
|
|
14516
|
+
}
|
|
14517
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14518
|
+
return {
|
|
14519
|
+
context: {
|
|
14520
|
+
inputFileId,
|
|
14521
|
+
endpoint: inputData.endpoint,
|
|
14522
|
+
parent,
|
|
14523
|
+
taskStartTime: startTime,
|
|
14524
|
+
childStartTime: startTime
|
|
14525
|
+
},
|
|
14526
|
+
inputs: inputData.inputs
|
|
14527
|
+
};
|
|
14528
|
+
}
|
|
14529
|
+
async function completeBatch(args) {
|
|
14530
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
14531
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
14532
|
+
if (!trace) {
|
|
14533
|
+
logBatchInstrumentationError(
|
|
14534
|
+
"left batch spans pending",
|
|
14535
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
14536
|
+
);
|
|
14537
|
+
return;
|
|
14538
|
+
}
|
|
14539
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
14540
|
+
const task = await startBatchSpan(trace.context);
|
|
14541
|
+
const taskParent = await task.export();
|
|
14542
|
+
const issues = [];
|
|
14543
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14544
|
+
await Promise.all([
|
|
14545
|
+
completeResultFile({
|
|
14546
|
+
context: trace.context,
|
|
14547
|
+
endTime,
|
|
14548
|
+
file: args.outputFileContent,
|
|
14549
|
+
inputs: trace.inputs,
|
|
14550
|
+
issues,
|
|
14551
|
+
seen,
|
|
14552
|
+
source: "output",
|
|
14553
|
+
taskParent
|
|
14554
|
+
}),
|
|
14555
|
+
completeResultFile({
|
|
14556
|
+
context: trace.context,
|
|
14557
|
+
endTime,
|
|
14558
|
+
file: args.errorFileContent,
|
|
14559
|
+
inputs: trace.inputs,
|
|
14560
|
+
issues,
|
|
14561
|
+
seen,
|
|
14562
|
+
source: "error",
|
|
14563
|
+
taskParent
|
|
14564
|
+
})
|
|
14565
|
+
]);
|
|
14566
|
+
if (issues.length > 0) {
|
|
14567
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
14568
|
+
return;
|
|
14569
|
+
}
|
|
14570
|
+
const missing = [...trace.inputs.values()].filter(
|
|
14571
|
+
({ customId }) => !seen.has(customId)
|
|
14572
|
+
);
|
|
14573
|
+
if (!trace.status || trace.status === "completed") {
|
|
14574
|
+
if (missing.length > 0) {
|
|
14575
|
+
logBatchInstrumentationError(
|
|
14576
|
+
"left batch spans pending",
|
|
14577
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
14578
|
+
);
|
|
14579
|
+
return;
|
|
14580
|
+
}
|
|
14581
|
+
} else {
|
|
14582
|
+
for (const input of missing) {
|
|
14583
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14584
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14585
|
+
child.end({ endTime });
|
|
14586
|
+
}
|
|
14587
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14588
|
+
}
|
|
14589
|
+
task.end({ endTime });
|
|
14590
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
14591
|
+
}
|
|
14592
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
14593
|
+
try {
|
|
14594
|
+
await completeBatch(args[0]);
|
|
14595
|
+
} catch (error) {
|
|
14596
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
14597
|
+
}
|
|
14598
|
+
return result;
|
|
14599
|
+
});
|
|
14600
|
+
|
|
13944
14601
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
13945
14602
|
var OpenAIPlugin = class extends BasePlugin {
|
|
13946
14603
|
constructor() {
|
|
13947
14604
|
super();
|
|
13948
14605
|
}
|
|
13949
14606
|
onEnable() {
|
|
14607
|
+
this.unsubscribers.push(
|
|
14608
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
14609
|
+
interceptOpenAIFilesCreateTraced
|
|
14610
|
+
),
|
|
14611
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
14612
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
14613
|
+
),
|
|
14614
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
14615
|
+
interceptOpenAIBatchTraceComplete
|
|
14616
|
+
)
|
|
14617
|
+
);
|
|
13950
14618
|
this.unsubscribers.push(
|
|
13951
14619
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
13952
14620
|
name: "Chat Completion",
|
|
13953
14621
|
type: "llm" /* LLM */,
|
|
13954
|
-
extractInput: ([params]) =>
|
|
13955
|
-
const { messages, ...metadata } = params;
|
|
13956
|
-
return {
|
|
13957
|
-
input: processInputAttachments(messages),
|
|
13958
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13959
|
-
};
|
|
13960
|
-
},
|
|
14622
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
13961
14623
|
extractOutput: (result) => {
|
|
13962
14624
|
return result?.choices;
|
|
13963
14625
|
},
|
|
@@ -14003,13 +14665,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14003
14665
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
14004
14666
|
name: "Chat Completion",
|
|
14005
14667
|
type: "llm" /* LLM */,
|
|
14006
|
-
extractInput: ([params]) =>
|
|
14007
|
-
const { messages, ...metadata } = params;
|
|
14008
|
-
return {
|
|
14009
|
-
input: processInputAttachments(messages),
|
|
14010
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14011
|
-
};
|
|
14012
|
-
},
|
|
14668
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
14013
14669
|
extractOutput: (result) => {
|
|
14014
14670
|
return result?.choices;
|
|
14015
14671
|
},
|
|
@@ -14031,13 +14687,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14031
14687
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
14032
14688
|
name: "Chat Completion",
|
|
14033
14689
|
type: "llm" /* LLM */,
|
|
14034
|
-
extractInput: ([params]) =>
|
|
14035
|
-
const { messages, ...metadata } = params;
|
|
14036
|
-
return {
|
|
14037
|
-
input: processInputAttachments(messages),
|
|
14038
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14039
|
-
};
|
|
14040
|
-
}
|
|
14690
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
14041
14691
|
})
|
|
14042
14692
|
);
|
|
14043
14693
|
this.unsubscribers.push(
|
|
@@ -14067,23 +14717,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14067
14717
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
14068
14718
|
name: "openai.responses.create",
|
|
14069
14719
|
type: "llm" /* LLM */,
|
|
14070
|
-
extractInput: ([params]) =>
|
|
14071
|
-
const { input, ...metadata } = params;
|
|
14072
|
-
return {
|
|
14073
|
-
input: processInputAttachments(input),
|
|
14074
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14075
|
-
};
|
|
14076
|
-
},
|
|
14720
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14077
14721
|
extractOutput: (result) => {
|
|
14078
14722
|
return processImagesInOutput(result?.output);
|
|
14079
14723
|
},
|
|
14080
|
-
extractMetadata: (result) =>
|
|
14081
|
-
if (!result) {
|
|
14082
|
-
return void 0;
|
|
14083
|
-
}
|
|
14084
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14085
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14086
|
-
},
|
|
14724
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14087
14725
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14088
14726
|
const metrics = withCachedMetric(
|
|
14089
14727
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14102,13 +14740,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14102
14740
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
14103
14741
|
name: "openai.responses.create",
|
|
14104
14742
|
type: "llm" /* LLM */,
|
|
14105
|
-
extractInput: ([params]) =>
|
|
14106
|
-
const { input, ...metadata } = params;
|
|
14107
|
-
return {
|
|
14108
|
-
input: processInputAttachments(input),
|
|
14109
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14110
|
-
};
|
|
14111
|
-
},
|
|
14743
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14112
14744
|
extractFromEvent: (event) => {
|
|
14113
14745
|
if (event.type !== "response.completed" || !event.response) {
|
|
14114
14746
|
return {};
|
|
@@ -14131,23 +14763,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14131
14763
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
14132
14764
|
name: "openai.responses.parse",
|
|
14133
14765
|
type: "llm" /* LLM */,
|
|
14134
|
-
extractInput: ([params]) =>
|
|
14135
|
-
const { input, ...metadata } = params;
|
|
14136
|
-
return {
|
|
14137
|
-
input: processInputAttachments(input),
|
|
14138
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14139
|
-
};
|
|
14140
|
-
},
|
|
14766
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14141
14767
|
extractOutput: (result) => {
|
|
14142
14768
|
return processImagesInOutput(result?.output);
|
|
14143
14769
|
},
|
|
14144
|
-
extractMetadata: (result) =>
|
|
14145
|
-
if (!result) {
|
|
14146
|
-
return void 0;
|
|
14147
|
-
}
|
|
14148
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14149
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14150
|
-
},
|
|
14770
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14151
14771
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14152
14772
|
const metrics = withCachedMetric(
|
|
14153
14773
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14166,23 +14786,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14166
14786
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
14167
14787
|
name: "openai.responses.compact",
|
|
14168
14788
|
type: "llm" /* LLM */,
|
|
14169
|
-
extractInput: ([params]) =>
|
|
14170
|
-
const { input, ...metadata } = params;
|
|
14171
|
-
return {
|
|
14172
|
-
input: processInputAttachments(input),
|
|
14173
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14174
|
-
};
|
|
14175
|
-
},
|
|
14789
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14176
14790
|
extractOutput: (result) => {
|
|
14177
14791
|
return processImagesInOutput(result?.output);
|
|
14178
14792
|
},
|
|
14179
|
-
extractMetadata: (result) =>
|
|
14180
|
-
if (!result) {
|
|
14181
|
-
return void 0;
|
|
14182
|
-
}
|
|
14183
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14184
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14185
|
-
},
|
|
14793
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14186
14794
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14187
14795
|
const metrics = withCachedMetric(
|
|
14188
14796
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14238,35 +14846,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
14238
14846
|
cached
|
|
14239
14847
|
};
|
|
14240
14848
|
}
|
|
14241
|
-
function processImagesInOutput(output) {
|
|
14242
|
-
if (Array.isArray(output)) {
|
|
14243
|
-
return output.map(processImagesInOutput);
|
|
14244
|
-
}
|
|
14245
|
-
if (isObject(output)) {
|
|
14246
|
-
if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
|
|
14247
|
-
const fileExtension = output.output_format || "png";
|
|
14248
|
-
const contentType = `image/${fileExtension}`;
|
|
14249
|
-
const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
14250
|
-
const filename = `${baseFilename}.${fileExtension}`;
|
|
14251
|
-
const binaryString = atob(output.result);
|
|
14252
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
14253
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
14254
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
14255
|
-
}
|
|
14256
|
-
const blob = new Blob([bytes], { type: contentType });
|
|
14257
|
-
const attachment = new Attachment({
|
|
14258
|
-
data: blob,
|
|
14259
|
-
filename,
|
|
14260
|
-
contentType
|
|
14261
|
-
});
|
|
14262
|
-
return {
|
|
14263
|
-
...output,
|
|
14264
|
-
result: attachment
|
|
14265
|
-
};
|
|
14266
|
-
}
|
|
14267
|
-
}
|
|
14268
|
-
return output;
|
|
14269
|
-
}
|
|
14270
14849
|
function mergeLogprobTokens(existing, incoming) {
|
|
14271
14850
|
if (incoming === void 0) {
|
|
14272
14851
|
return existing;
|
|
@@ -19423,6 +20002,12 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19423
20002
|
if (!activeEntry) {
|
|
19424
20003
|
return result;
|
|
19425
20004
|
}
|
|
20005
|
+
const executionOptions = args[1];
|
|
20006
|
+
const toolCallId = isObject(executionOptions) ? executionOptions.toolCallId : void 0;
|
|
20007
|
+
const toolInput = {
|
|
20008
|
+
input: serializeToolExecutionInput(args),
|
|
20009
|
+
...typeof toolCallId === "string" ? { metadata: { toolCallId } } : {}
|
|
20010
|
+
};
|
|
19426
20011
|
if (isAsyncGenerator(result)) {
|
|
19427
20012
|
return (async function* () {
|
|
19428
20013
|
const span = activeEntry.parentSpan.startSpan(
|
|
@@ -19436,7 +20021,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19436
20021
|
INSTRUMENTATION_NAMES.AI_SDK
|
|
19437
20022
|
)
|
|
19438
20023
|
);
|
|
19439
|
-
span.log(
|
|
20024
|
+
span.log(toolInput);
|
|
19440
20025
|
try {
|
|
19441
20026
|
let lastValue;
|
|
19442
20027
|
for await (const value of result) {
|
|
@@ -19454,7 +20039,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19454
20039
|
}
|
|
19455
20040
|
return activeEntry.parentSpan.traced(
|
|
19456
20041
|
async (span) => {
|
|
19457
|
-
span.log(
|
|
20042
|
+
span.log(toolInput);
|
|
19458
20043
|
const awaitedResult = await result;
|
|
19459
20044
|
span.log({ output: awaitedResult });
|
|
19460
20045
|
return awaitedResult;
|
|
@@ -33576,14 +34161,17 @@ function getMetricsFromResponse(response) {
|
|
|
33576
34161
|
if (!isRecord(usageMetadata)) {
|
|
33577
34162
|
continue;
|
|
33578
34163
|
}
|
|
33579
|
-
const inputTokenDetails = usageMetadata.input_token_details;
|
|
34164
|
+
const inputTokenDetails = isRecord(usageMetadata.input_token_details) ? usageMetadata.input_token_details : {};
|
|
33580
34165
|
const outputTokenDetails = usageMetadata.output_token_details;
|
|
33581
34166
|
return normalizeTokenMetrics({
|
|
33582
34167
|
total_tokens: usageMetadata.total_tokens,
|
|
33583
34168
|
prompt_tokens: usageMetadata.input_tokens,
|
|
33584
34169
|
completion_tokens: usageMetadata.output_tokens,
|
|
33585
|
-
|
|
33586
|
-
|
|
34170
|
+
// Prefer TTL-specific cache writes over the aggregate when available.
|
|
34171
|
+
prompt_cache_creation_tokens: inputTokenDetails.ephemeral_5m_input_tokens == null && inputTokenDetails.ephemeral_1h_input_tokens == null ? inputTokenDetails.cache_creation : void 0,
|
|
34172
|
+
prompt_cache_creation_5m_tokens: inputTokenDetails.ephemeral_5m_input_tokens,
|
|
34173
|
+
prompt_cache_creation_1h_tokens: inputTokenDetails.ephemeral_1h_input_tokens,
|
|
34174
|
+
prompt_cached_tokens: inputTokenDetails.cache_read,
|
|
33587
34175
|
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
33588
34176
|
});
|
|
33589
34177
|
}
|
|
@@ -34299,7 +34887,7 @@ function extractSession(event) {
|
|
|
34299
34887
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
34300
34888
|
}
|
|
34301
34889
|
function isPiAgent(value) {
|
|
34302
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
34890
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
34303
34891
|
}
|
|
34304
34892
|
function promptContextStore() {
|
|
34305
34893
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -34309,17 +34897,21 @@ function currentPiPromptState() {
|
|
|
34309
34897
|
return promptContextStore().getStore();
|
|
34310
34898
|
}
|
|
34311
34899
|
function installPiAgentInstrumentation(agent) {
|
|
34900
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
34901
|
+
const streamFunction = agent[property];
|
|
34312
34902
|
const existing = piAgentPatchStates.get(agent);
|
|
34313
|
-
if (!existing ||
|
|
34903
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
34314
34904
|
const patchState = {
|
|
34315
|
-
|
|
34316
|
-
|
|
34905
|
+
originalStreamFunction: streamFunction,
|
|
34906
|
+
property,
|
|
34907
|
+
wrappedStreamFunction: streamFunction
|
|
34317
34908
|
};
|
|
34318
|
-
patchState.
|
|
34909
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
34319
34910
|
agent,
|
|
34320
|
-
patchState.
|
|
34911
|
+
patchState.originalStreamFunction,
|
|
34912
|
+
property
|
|
34321
34913
|
);
|
|
34322
|
-
agent
|
|
34914
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
34323
34915
|
piAgentPatchStates.set(agent, patchState);
|
|
34324
34916
|
}
|
|
34325
34917
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -34344,15 +34936,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
34344
34936
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
34345
34937
|
}
|
|
34346
34938
|
}
|
|
34347
|
-
function
|
|
34348
|
-
return async function
|
|
34349
|
-
const invokeOriginal = () => Reflect.apply(
|
|
34939
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
34940
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
34941
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
34350
34942
|
const state = currentPiPromptState();
|
|
34351
34943
|
if (!state || state.agent !== agent || state.finalized) {
|
|
34352
34944
|
return invokeOriginal();
|
|
34353
34945
|
}
|
|
34354
34946
|
wrapPiToolExecutors(context.tools);
|
|
34355
|
-
const llmState = await startPiLlmSpan(
|
|
34947
|
+
const llmState = await startPiLlmSpan(
|
|
34948
|
+
state,
|
|
34949
|
+
model,
|
|
34950
|
+
context,
|
|
34951
|
+
property,
|
|
34952
|
+
options
|
|
34953
|
+
);
|
|
34356
34954
|
try {
|
|
34357
34955
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
34358
34956
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -34389,12 +34987,12 @@ function wrapPiToolExecutors(tools) {
|
|
|
34389
34987
|
}
|
|
34390
34988
|
}
|
|
34391
34989
|
}
|
|
34392
|
-
async function startPiLlmSpan(state, model, context, options) {
|
|
34990
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
34393
34991
|
const metadata = {
|
|
34394
34992
|
...extractModelMetadata2(model),
|
|
34395
34993
|
...extractStreamOptionsMetadata(options),
|
|
34396
34994
|
...extractToolMetadata(context.tools),
|
|
34397
|
-
"pi_coding_agent.operation":
|
|
34995
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
34398
34996
|
};
|
|
34399
34997
|
const span = startSpan(
|
|
34400
34998
|
withSpanInstrumentationName(
|
|
@@ -37412,6 +38010,7 @@ __export(exports_exports, {
|
|
|
37412
38010
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
37413
38011
|
buildLocalSummary: () => buildLocalSummary,
|
|
37414
38012
|
collectAnthropicSession: () => collectAnthropicSession,
|
|
38013
|
+
completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
|
|
37415
38014
|
configureInstrumentation: () => configureInstrumentation,
|
|
37416
38015
|
constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
|
|
37417
38016
|
createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
|
|
@@ -37450,6 +38049,8 @@ __export(exports_exports, {
|
|
|
37450
38049
|
loginToState: () => loginToState,
|
|
37451
38050
|
logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
|
|
37452
38051
|
newId: () => newId,
|
|
38052
|
+
openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
|
|
38053
|
+
openaiFilesCreateTraced: () => openaiFilesCreateTraced,
|
|
37453
38054
|
parseCachedHeader: () => parseCachedHeader,
|
|
37454
38055
|
parseTemplateFormat: () => parseTemplateFormat,
|
|
37455
38056
|
permalink: () => permalink,
|
|
@@ -37614,6 +38215,260 @@ async function registerSandbox(options) {
|
|
|
37614
38215
|
};
|
|
37615
38216
|
}
|
|
37616
38217
|
|
|
38218
|
+
// src/wrappers/openai-promise-utils.ts
|
|
38219
|
+
function splitSpanInfo(allParams) {
|
|
38220
|
+
const { span_info, ...params } = allParams;
|
|
38221
|
+
return {
|
|
38222
|
+
params,
|
|
38223
|
+
span_info
|
|
38224
|
+
};
|
|
38225
|
+
}
|
|
38226
|
+
function createChannelContext(_channel, params, span_info) {
|
|
38227
|
+
return {
|
|
38228
|
+
arguments: (
|
|
38229
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38230
|
+
[params]
|
|
38231
|
+
),
|
|
38232
|
+
span_info
|
|
38233
|
+
};
|
|
38234
|
+
}
|
|
38235
|
+
async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
|
|
38236
|
+
let enhancedResponse;
|
|
38237
|
+
const tracePromise = (
|
|
38238
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38239
|
+
channel2.tracePromise
|
|
38240
|
+
);
|
|
38241
|
+
const data = await tracePromise(async () => {
|
|
38242
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38243
|
+
traceContext.response = enhancedResponse.response;
|
|
38244
|
+
return enhancedResponse.data;
|
|
38245
|
+
}, traceContext);
|
|
38246
|
+
if (!enhancedResponse) {
|
|
38247
|
+
throw new Error("Expected withResponse() to provide response");
|
|
38248
|
+
}
|
|
38249
|
+
return {
|
|
38250
|
+
data,
|
|
38251
|
+
response: enhancedResponse.response,
|
|
38252
|
+
request_id: enhancedResponse.request_id
|
|
38253
|
+
};
|
|
38254
|
+
}
|
|
38255
|
+
async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
|
|
38256
|
+
const tracePromise = (
|
|
38257
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38258
|
+
channel2.tracePromise
|
|
38259
|
+
);
|
|
38260
|
+
let response;
|
|
38261
|
+
await tracePromise(async () => {
|
|
38262
|
+
response = await apiPromise.asResponse();
|
|
38263
|
+
traceContext.response = response;
|
|
38264
|
+
return void 0;
|
|
38265
|
+
}, traceContext);
|
|
38266
|
+
if (!response) {
|
|
38267
|
+
throw new Error("Expected asResponse() to provide response");
|
|
38268
|
+
}
|
|
38269
|
+
return response;
|
|
38270
|
+
}
|
|
38271
|
+
function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
|
|
38272
|
+
let firstConsumption;
|
|
38273
|
+
let enhancedResponsePromise;
|
|
38274
|
+
let dataPromise;
|
|
38275
|
+
let responsePromise;
|
|
38276
|
+
const withResponse = () => {
|
|
38277
|
+
firstConsumption ??= "data";
|
|
38278
|
+
enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
|
|
38279
|
+
return enhancedResponsePromise;
|
|
38280
|
+
};
|
|
38281
|
+
const asResponse = () => {
|
|
38282
|
+
firstConsumption ??= "response";
|
|
38283
|
+
responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
|
|
38284
|
+
return responsePromise;
|
|
38285
|
+
};
|
|
38286
|
+
return new Proxy({}, {
|
|
38287
|
+
get(target, prop, receiver) {
|
|
38288
|
+
if (prop === "withResponse") {
|
|
38289
|
+
return withResponse;
|
|
38290
|
+
}
|
|
38291
|
+
if (prop === "asResponse") {
|
|
38292
|
+
return asResponse;
|
|
38293
|
+
}
|
|
38294
|
+
if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
|
|
38295
|
+
dataPromise ??= withResponse().then((result) => result.data);
|
|
38296
|
+
const value = Reflect.get(dataPromise, prop, receiver);
|
|
38297
|
+
return typeof value === "function" ? value.bind(dataPromise) : value;
|
|
38298
|
+
}
|
|
38299
|
+
return Reflect.get(target, prop, receiver);
|
|
38300
|
+
}
|
|
38301
|
+
});
|
|
38302
|
+
}
|
|
38303
|
+
|
|
38304
|
+
// src/openai-batch.ts
|
|
38305
|
+
function read2(value, key) {
|
|
38306
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
38307
|
+
return void 0;
|
|
38308
|
+
}
|
|
38309
|
+
try {
|
|
38310
|
+
return Reflect.get(value, key);
|
|
38311
|
+
} catch {
|
|
38312
|
+
return void 0;
|
|
38313
|
+
}
|
|
38314
|
+
}
|
|
38315
|
+
function isAsyncIterable5(value) {
|
|
38316
|
+
return typeof read2(value, Symbol.asyncIterator) === "function";
|
|
38317
|
+
}
|
|
38318
|
+
function teeAsyncIterable(source) {
|
|
38319
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
38320
|
+
const stream = new ReadableStream({
|
|
38321
|
+
async pull(controller) {
|
|
38322
|
+
try {
|
|
38323
|
+
const result = await iterator.next();
|
|
38324
|
+
if (result.done) {
|
|
38325
|
+
controller.close();
|
|
38326
|
+
return;
|
|
38327
|
+
}
|
|
38328
|
+
if (!(result.value instanceof Uint8Array)) {
|
|
38329
|
+
throw new TypeError(
|
|
38330
|
+
"OpenAI upload streams must yield Uint8Array chunks"
|
|
38331
|
+
);
|
|
38332
|
+
}
|
|
38333
|
+
controller.enqueue(result.value);
|
|
38334
|
+
} catch (error) {
|
|
38335
|
+
controller.error(error);
|
|
38336
|
+
}
|
|
38337
|
+
},
|
|
38338
|
+
async cancel(reason) {
|
|
38339
|
+
await iterator.return?.(reason);
|
|
38340
|
+
}
|
|
38341
|
+
});
|
|
38342
|
+
const [uploadStream, trace] = stream.tee();
|
|
38343
|
+
const upload = {
|
|
38344
|
+
async *[Symbol.asyncIterator]() {
|
|
38345
|
+
const reader = uploadStream.getReader();
|
|
38346
|
+
try {
|
|
38347
|
+
while (true) {
|
|
38348
|
+
const result = await reader.read();
|
|
38349
|
+
if (result.done) {
|
|
38350
|
+
return;
|
|
38351
|
+
}
|
|
38352
|
+
yield result.value;
|
|
38353
|
+
}
|
|
38354
|
+
} finally {
|
|
38355
|
+
reader.releaseLock();
|
|
38356
|
+
}
|
|
38357
|
+
}
|
|
38358
|
+
};
|
|
38359
|
+
const path = read2(source, "path");
|
|
38360
|
+
if (typeof path === "string") {
|
|
38361
|
+
Object.defineProperty(upload, "path", { value: path });
|
|
38362
|
+
}
|
|
38363
|
+
return { upload, trace: new Response(trace) };
|
|
38364
|
+
}
|
|
38365
|
+
function teeUpload(upload) {
|
|
38366
|
+
if (upload instanceof Blob) {
|
|
38367
|
+
return { upload, trace: new Response(upload) };
|
|
38368
|
+
}
|
|
38369
|
+
if (upload instanceof Response) {
|
|
38370
|
+
return { upload, trace: upload.clone() };
|
|
38371
|
+
}
|
|
38372
|
+
if (isAsyncIterable5(upload)) {
|
|
38373
|
+
return teeAsyncIterable(upload);
|
|
38374
|
+
}
|
|
38375
|
+
return void 0;
|
|
38376
|
+
}
|
|
38377
|
+
function openaiFilesCreateTraced(files) {
|
|
38378
|
+
return (params, options) => {
|
|
38379
|
+
const parent = getSpanParentObject();
|
|
38380
|
+
const purpose = read2(params, "purpose");
|
|
38381
|
+
const file = read2(params, "file");
|
|
38382
|
+
if (purpose !== "batch") {
|
|
38383
|
+
return files.create(params, options);
|
|
38384
|
+
}
|
|
38385
|
+
let branches;
|
|
38386
|
+
try {
|
|
38387
|
+
branches = teeUpload(file);
|
|
38388
|
+
} catch {
|
|
38389
|
+
return files.create(params, options);
|
|
38390
|
+
}
|
|
38391
|
+
if (!branches) {
|
|
38392
|
+
return files.create(params, options);
|
|
38393
|
+
}
|
|
38394
|
+
const tracedParams = {
|
|
38395
|
+
...Object(params),
|
|
38396
|
+
file: branches.upload
|
|
38397
|
+
};
|
|
38398
|
+
const apiPromise = files.create(tracedParams, options);
|
|
38399
|
+
let enhancedResponse;
|
|
38400
|
+
const tracedResponse = openAIChannels.filesCreateTraced.invoke(
|
|
38401
|
+
async () => {
|
|
38402
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38403
|
+
return enhancedResponse.data;
|
|
38404
|
+
},
|
|
38405
|
+
files,
|
|
38406
|
+
[{ params, inputFileContent: branches.trace, parent }],
|
|
38407
|
+
{}
|
|
38408
|
+
).then((data) => {
|
|
38409
|
+
if (!enhancedResponse) {
|
|
38410
|
+
throw new Error(
|
|
38411
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38412
|
+
);
|
|
38413
|
+
}
|
|
38414
|
+
return { ...enhancedResponse, data };
|
|
38415
|
+
});
|
|
38416
|
+
return createLazyAPIPromise(
|
|
38417
|
+
() => tracedResponse,
|
|
38418
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38419
|
+
() => apiPromise
|
|
38420
|
+
);
|
|
38421
|
+
};
|
|
38422
|
+
}
|
|
38423
|
+
function openaiBatchesRetrieveTraced(batches) {
|
|
38424
|
+
return (batchId, options) => {
|
|
38425
|
+
const apiPromise = batches.retrieve(batchId, options);
|
|
38426
|
+
let enhancedResponse;
|
|
38427
|
+
const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
|
|
38428
|
+
async () => {
|
|
38429
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38430
|
+
return enhancedResponse.data;
|
|
38431
|
+
},
|
|
38432
|
+
batches,
|
|
38433
|
+
[{ batchId }],
|
|
38434
|
+
{}
|
|
38435
|
+
).then((data) => {
|
|
38436
|
+
if (!enhancedResponse) {
|
|
38437
|
+
throw new Error(
|
|
38438
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38439
|
+
);
|
|
38440
|
+
}
|
|
38441
|
+
return { ...enhancedResponse, data };
|
|
38442
|
+
});
|
|
38443
|
+
return createLazyAPIPromise(
|
|
38444
|
+
() => tracedResponse,
|
|
38445
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38446
|
+
() => apiPromise
|
|
38447
|
+
);
|
|
38448
|
+
};
|
|
38449
|
+
}
|
|
38450
|
+
async function completeOpenAIBatchTrace(args) {
|
|
38451
|
+
const inputFileContent = Promise.resolve(args.inputFileContent);
|
|
38452
|
+
const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
|
|
38453
|
+
const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
|
|
38454
|
+
void inputFileContent.catch(() => void 0);
|
|
38455
|
+
void outputFileContent?.catch(() => void 0);
|
|
38456
|
+
void errorFileContent?.catch(() => void 0);
|
|
38457
|
+
await openAIChannels.batchesCompleteTrace.invoke(
|
|
38458
|
+
async () => void 0,
|
|
38459
|
+
void 0,
|
|
38460
|
+
[
|
|
38461
|
+
{
|
|
38462
|
+
...args,
|
|
38463
|
+
inputFileContent,
|
|
38464
|
+
outputFileContent,
|
|
38465
|
+
errorFileContent
|
|
38466
|
+
}
|
|
38467
|
+
],
|
|
38468
|
+
{}
|
|
38469
|
+
);
|
|
38470
|
+
}
|
|
38471
|
+
|
|
37617
38472
|
// src/functions/invoke.ts
|
|
37618
38473
|
async function invoke(args) {
|
|
37619
38474
|
const {
|
|
@@ -37716,58 +38571,6 @@ function initFunction({
|
|
|
37716
38571
|
return f;
|
|
37717
38572
|
}
|
|
37718
38573
|
|
|
37719
|
-
// src/wrappers/openai-promise-utils.ts
|
|
37720
|
-
function splitSpanInfo(allParams) {
|
|
37721
|
-
const { span_info, ...params } = allParams;
|
|
37722
|
-
return {
|
|
37723
|
-
params,
|
|
37724
|
-
span_info
|
|
37725
|
-
};
|
|
37726
|
-
}
|
|
37727
|
-
function createChannelContext(_channel, params, span_info) {
|
|
37728
|
-
return {
|
|
37729
|
-
arguments: (
|
|
37730
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37731
|
-
[params]
|
|
37732
|
-
),
|
|
37733
|
-
span_info
|
|
37734
|
-
};
|
|
37735
|
-
}
|
|
37736
|
-
async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
|
|
37737
|
-
let enhancedResponse;
|
|
37738
|
-
const tracePromise = (
|
|
37739
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37740
|
-
channel2.tracePromise
|
|
37741
|
-
);
|
|
37742
|
-
const data = await tracePromise(async () => {
|
|
37743
|
-
enhancedResponse = await apiPromise.withResponse();
|
|
37744
|
-
traceContext.response = enhancedResponse.response;
|
|
37745
|
-
return enhancedResponse.data;
|
|
37746
|
-
}, traceContext);
|
|
37747
|
-
if (!enhancedResponse) {
|
|
37748
|
-
throw new Error("Expected withResponse() to provide response");
|
|
37749
|
-
}
|
|
37750
|
-
return { data, response: enhancedResponse.response };
|
|
37751
|
-
}
|
|
37752
|
-
function createLazyAPIPromise(ensureExecuted) {
|
|
37753
|
-
let dataPromise = null;
|
|
37754
|
-
return new Proxy({}, {
|
|
37755
|
-
get(target, prop, receiver) {
|
|
37756
|
-
if (prop === "withResponse") {
|
|
37757
|
-
return () => ensureExecuted();
|
|
37758
|
-
}
|
|
37759
|
-
if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
|
|
37760
|
-
if (!dataPromise) {
|
|
37761
|
-
dataPromise = ensureExecuted().then((result) => result.data);
|
|
37762
|
-
}
|
|
37763
|
-
const value = Reflect.get(dataPromise, prop, receiver);
|
|
37764
|
-
return typeof value === "function" ? value.bind(dataPromise) : value;
|
|
37765
|
-
}
|
|
37766
|
-
return Reflect.get(target, prop, receiver);
|
|
37767
|
-
}
|
|
37768
|
-
});
|
|
37769
|
-
}
|
|
37770
|
-
|
|
37771
38574
|
// src/wrappers/oai_responses.ts
|
|
37772
38575
|
function responsesProxy(openai) {
|
|
37773
38576
|
if (!openai.responses) {
|
|
@@ -37804,17 +38607,33 @@ function wrapResponsesAsync(target, channel2) {
|
|
|
37804
38607
|
return (allParams, options) => {
|
|
37805
38608
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
37806
38609
|
let executionPromise = null;
|
|
38610
|
+
let apiPromise = null;
|
|
38611
|
+
const getAPIPromise = () => {
|
|
38612
|
+
apiPromise ??= target(params, options);
|
|
38613
|
+
return apiPromise;
|
|
38614
|
+
};
|
|
37807
38615
|
const ensureExecuted = () => {
|
|
37808
38616
|
if (!executionPromise) {
|
|
37809
38617
|
executionPromise = (async () => {
|
|
37810
38618
|
const traceContext = createChannelContext(channel2, params, span_info);
|
|
37811
|
-
|
|
37812
|
-
|
|
38619
|
+
return tracePromiseWithResponse(
|
|
38620
|
+
channel2,
|
|
38621
|
+
traceContext,
|
|
38622
|
+
getAPIPromise()
|
|
38623
|
+
);
|
|
37813
38624
|
})();
|
|
37814
38625
|
}
|
|
37815
38626
|
return executionPromise;
|
|
37816
38627
|
};
|
|
37817
|
-
return createLazyAPIPromise(
|
|
38628
|
+
return createLazyAPIPromise(
|
|
38629
|
+
ensureExecuted,
|
|
38630
|
+
() => tracePromiseAsResponse(
|
|
38631
|
+
channel2,
|
|
38632
|
+
createChannelContext(channel2, params, span_info),
|
|
38633
|
+
getAPIPromise()
|
|
38634
|
+
),
|
|
38635
|
+
getAPIPromise
|
|
38636
|
+
);
|
|
37818
38637
|
};
|
|
37819
38638
|
}
|
|
37820
38639
|
function wrapResponsesSyncStream(target, channel2) {
|
|
@@ -37960,6 +38779,11 @@ function wrapChatCompletion(completion) {
|
|
|
37960
38779
|
allParams
|
|
37961
38780
|
);
|
|
37962
38781
|
let executionPromise = null;
|
|
38782
|
+
let apiPromise = null;
|
|
38783
|
+
const getAPIPromise = () => {
|
|
38784
|
+
apiPromise ??= completion(params, options);
|
|
38785
|
+
return apiPromise;
|
|
38786
|
+
};
|
|
37963
38787
|
const ensureExecuted = () => {
|
|
37964
38788
|
if (!executionPromise) {
|
|
37965
38789
|
executionPromise = (async () => {
|
|
@@ -37969,32 +38793,44 @@ function wrapChatCompletion(completion) {
|
|
|
37969
38793
|
span_info
|
|
37970
38794
|
);
|
|
37971
38795
|
if (params.stream) {
|
|
37972
|
-
const completionPromise =
|
|
37973
|
-
|
|
37974
|
-
|
|
38796
|
+
const completionPromise = (
|
|
38797
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38798
|
+
getAPIPromise()
|
|
37975
38799
|
);
|
|
37976
|
-
const { data: data2, response: response2 } = await tracePromiseWithResponse(
|
|
38800
|
+
const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
|
|
37977
38801
|
openAIChannels.chatCompletionsCreate,
|
|
37978
38802
|
traceContext,
|
|
37979
38803
|
completionPromise
|
|
37980
38804
|
);
|
|
37981
|
-
return { data: data2, response: response2 };
|
|
38805
|
+
return { data: data2, response: response2, request_id: request_id2 };
|
|
37982
38806
|
}
|
|
37983
|
-
const completionResponse =
|
|
37984
|
-
|
|
37985
|
-
|
|
38807
|
+
const completionResponse = (
|
|
38808
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38809
|
+
getAPIPromise()
|
|
37986
38810
|
);
|
|
37987
|
-
const { data, response } = await tracePromiseWithResponse(
|
|
38811
|
+
const { data, response, request_id } = await tracePromiseWithResponse(
|
|
37988
38812
|
openAIChannels.chatCompletionsCreate,
|
|
37989
38813
|
traceContext,
|
|
37990
38814
|
completionResponse
|
|
37991
38815
|
);
|
|
37992
|
-
return { data, response };
|
|
38816
|
+
return { data, response, request_id };
|
|
37993
38817
|
})();
|
|
37994
38818
|
}
|
|
37995
38819
|
return executionPromise;
|
|
37996
38820
|
};
|
|
37997
|
-
return createLazyAPIPromise(
|
|
38821
|
+
return createLazyAPIPromise(
|
|
38822
|
+
ensureExecuted,
|
|
38823
|
+
() => tracePromiseAsResponse(
|
|
38824
|
+
openAIChannels.chatCompletionsCreate,
|
|
38825
|
+
createChannelContext(
|
|
38826
|
+
openAIChannels.chatCompletionsCreate,
|
|
38827
|
+
params,
|
|
38828
|
+
span_info
|
|
38829
|
+
),
|
|
38830
|
+
getAPIPromise()
|
|
38831
|
+
),
|
|
38832
|
+
getAPIPromise
|
|
38833
|
+
);
|
|
37998
38834
|
};
|
|
37999
38835
|
}
|
|
38000
38836
|
function createEndpointProxy(target, wrapperFn) {
|
|
@@ -38012,6 +38848,11 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38012
38848
|
return (allParams, options) => {
|
|
38013
38849
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
38014
38850
|
let executionPromise = null;
|
|
38851
|
+
let apiPromise = null;
|
|
38852
|
+
const getAPIPromise = () => {
|
|
38853
|
+
apiPromise ??= create(params, options);
|
|
38854
|
+
return apiPromise;
|
|
38855
|
+
};
|
|
38015
38856
|
const ensureExecuted = () => {
|
|
38016
38857
|
if (!executionPromise) {
|
|
38017
38858
|
executionPromise = (async () => {
|
|
@@ -38019,13 +38860,21 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38019
38860
|
return tracePromiseWithResponse(
|
|
38020
38861
|
channel2,
|
|
38021
38862
|
traceContext,
|
|
38022
|
-
|
|
38863
|
+
getAPIPromise()
|
|
38023
38864
|
);
|
|
38024
38865
|
})();
|
|
38025
38866
|
}
|
|
38026
38867
|
return executionPromise;
|
|
38027
38868
|
};
|
|
38028
|
-
return createLazyAPIPromise(
|
|
38869
|
+
return createLazyAPIPromise(
|
|
38870
|
+
ensureExecuted,
|
|
38871
|
+
() => tracePromiseAsResponse(
|
|
38872
|
+
channel2,
|
|
38873
|
+
createChannelContext(channel2, params, span_info),
|
|
38874
|
+
getAPIPromise()
|
|
38875
|
+
),
|
|
38876
|
+
getAPIPromise
|
|
38877
|
+
);
|
|
38029
38878
|
};
|
|
38030
38879
|
}
|
|
38031
38880
|
var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
|
|
@@ -40720,7 +41569,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
|
|
|
40720
41569
|
function createEveInstrumentationProvider(options = {}) {
|
|
40721
41570
|
const bridge = new EveProviderBridge(options.metadata);
|
|
40722
41571
|
return {
|
|
41572
|
+
// Eve versions before tracePolicy use capture to decide whether provider
|
|
41573
|
+
// events include content. Newer versions prefer tracePolicy when both are
|
|
41574
|
+
// present, so keep the deprecated field for backwards compatibility.
|
|
40723
41575
|
capture: "content",
|
|
41576
|
+
tracePolicy: () => ({
|
|
41577
|
+
emit: true,
|
|
41578
|
+
recordInputs: true,
|
|
41579
|
+
recordOutputs: true
|
|
41580
|
+
}),
|
|
40724
41581
|
events: {
|
|
40725
41582
|
"action.completed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
40726
41583
|
"action.failed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
@@ -44328,8 +45185,8 @@ function normalizeScores(result) {
|
|
|
44328
45185
|
(s) => s !== null && s !== void 0 && typeof s === "object" && isScore(s)
|
|
44329
45186
|
);
|
|
44330
45187
|
}
|
|
44331
|
-
if (typeof result === "object" && result !== null &&
|
|
44332
|
-
return [result];
|
|
45188
|
+
if (typeof result === "object" && result !== null && "score" in result) {
|
|
45189
|
+
return [{ ...result, name: result.name ?? "score" }];
|
|
44333
45190
|
}
|
|
44334
45191
|
return [];
|
|
44335
45192
|
}
|
|
@@ -45149,7 +46006,7 @@ function isAsync(fn) {
|
|
|
45149
46006
|
function isAsyncGenerator2(fn) {
|
|
45150
46007
|
return fn[Symbol.toStringTag] === "AsyncGenerator";
|
|
45151
46008
|
}
|
|
45152
|
-
function
|
|
46009
|
+
function isAsyncIterable6(obj) {
|
|
45153
46010
|
return typeof obj[Symbol.asyncIterator] === "function";
|
|
45154
46011
|
}
|
|
45155
46012
|
function wrapAsync(asyncFn) {
|
|
@@ -45321,7 +46178,7 @@ var eachOfLimit$2 = (limit) => {
|
|
|
45321
46178
|
if (isAsyncGenerator2(obj)) {
|
|
45322
46179
|
return asyncEachOfLimit(obj, limit, iteratee, callback);
|
|
45323
46180
|
}
|
|
45324
|
-
if (
|
|
46181
|
+
if (isAsyncIterable6(obj)) {
|
|
45325
46182
|
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
|
|
45326
46183
|
}
|
|
45327
46184
|
var nextElem = createIterator(obj);
|
|
@@ -46676,7 +47533,7 @@ function callEvaluatorData(data) {
|
|
|
46676
47533
|
baseExperiment
|
|
46677
47534
|
};
|
|
46678
47535
|
}
|
|
46679
|
-
function
|
|
47536
|
+
function isAsyncIterable7(value) {
|
|
46680
47537
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
46681
47538
|
}
|
|
46682
47539
|
function isIterable(value) {
|
|
@@ -46711,7 +47568,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
|
46711
47568
|
}).asDataset();
|
|
46712
47569
|
}
|
|
46713
47570
|
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
46714
|
-
if (
|
|
47571
|
+
if (isAsyncIterable7(resolvedDataResult)) {
|
|
46715
47572
|
return resolvedDataResult;
|
|
46716
47573
|
}
|
|
46717
47574
|
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
@@ -46912,19 +47769,29 @@ function buildSpanScores(results) {
|
|
|
46912
47769
|
function _internalPrepareEvaluatorScore(scoreValue, name) {
|
|
46913
47770
|
if (scoreValue === null) return { results: null };
|
|
46914
47771
|
if (Array.isArray(scoreValue)) {
|
|
47772
|
+
const names = /* @__PURE__ */ new Set();
|
|
46915
47773
|
for (const score of scoreValue) {
|
|
46916
47774
|
if (!(typeof score === "object" && !isEmpty2(score))) {
|
|
46917
47775
|
throw new Error(
|
|
46918
47776
|
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(score)}`
|
|
46919
47777
|
);
|
|
46920
47778
|
}
|
|
47779
|
+
if (typeof score.name !== "string") {
|
|
47780
|
+
throw new Error(
|
|
47781
|
+
`When returning an array of scores, each score must have a name. Got: ${JSON.stringify(score)}`
|
|
47782
|
+
);
|
|
47783
|
+
}
|
|
47784
|
+
if (names.has(score.name)) {
|
|
47785
|
+
throw new Error(`Duplicate score name '${score.name}' in score array`);
|
|
47786
|
+
}
|
|
47787
|
+
names.add(score.name);
|
|
46921
47788
|
}
|
|
46922
47789
|
}
|
|
46923
47790
|
let results;
|
|
46924
47791
|
if (Array.isArray(scoreValue)) {
|
|
46925
47792
|
results = scoreValue;
|
|
46926
47793
|
} else if (typeof scoreValue === "object" && !isEmpty2(scoreValue)) {
|
|
46927
|
-
results = [scoreValue];
|
|
47794
|
+
results = [{ ...scoreValue, name: scoreValue.name ?? name }];
|
|
46928
47795
|
} else {
|
|
46929
47796
|
results = [{ name, score: scoreValue }];
|
|
46930
47797
|
}
|